Exemple #1
0
//-----------------------------------------------------------------------------------------------
void calc_volatility(int param_bars, int param_counted_bars)   {

   // Output: vols[] array
   // Compute volatility using log price differences.

   // Adapted by E Farrell 2013
   // from code supplied by J Blackledge 2012

   for (int i = param_counted_bars; i >= 0; i--)
   {
      double sumHat1 = 0;
      double sumHat2 = 0;

      if( i >= param_bars - Lookback ){
         Print("setting vols to zero!");
         vols[i] = 0;
         continue;
      }

      for (int j = i + Lookback - 2; j >= i; j--){
         sumHat1 += MathPow( MathAbs( MathLog( Close[j] / Close[j+1] ) ), 2);
         sumHat2 += MathLog(Close[j]/Close[j+1]);
      }

      // Calculate Volatility
      sumHat1 = MathSqrt(sumHat1);
      sumHat2 = sumHat2 / MathSqrt(Lookback-1);
      vols[i] = sumHat1- sumHat2;

      if (DEBUG == 1) {
         // Output array values to Expert Log
         //Print("\t vols[\t", DoubleToStr(i,0), "\t] \t", DoubleToStr(vols[i],6));
         //Print("\t Close[\t", DoubleToStr(i,0), "\t] \t", DoubleToStr(Close[i],6));

         // Write values to debug file
         file_result = FileWrite (file_handle, "close", i, Close[i], "vols", i, vols[i]);
      }

   }

}
// LCOV_EXCL_STOP
ex_expr::exp_return_type ExFunctionMath::eval(char *op_data[],
					      CollHeap *heap,
					      ComDiagsArea** diagsArea)
{
  ex_expr::exp_return_type retcode = ex_expr::EXPR_OK;

  short err = 0;
  errno = 0;

  if ((getOperand()) &&
      (getOperand(0)->getDatatype() != REC_FLOAT64))
    {
      return evalUnsupportedOperations(op_data, heap, diagsArea);
    }

  switch (getOperType())
    {
    case ITM_DEGREES:
      // radians to degrees
      *(double *)op_data[0] = (*(double *)op_data[1] * 180E0) / PIVALUE;
      break;

    case ITM_PI:
      *(double *)op_data[0] = PIVALUE;
      break;

    case ITM_RADIANS:
      // degrees to radians
      *(double *)op_data[0] = (*(double *)op_data[1] / 180E0) * PIVALUE;
      break;

    case ITM_ROUND:
    {
      double op, res;
      short err1 = 0, err2 = 0, err3 = 0;
      Int32 roundTo;

      roundTo = (getNumOperands() > 2) ? (Int32)(*((double*)op_data[2])) : 0;

      switch (getOperand(1)->getDatatype()) {
        case REC_IEEE_FLOAT32:
          op = *((float*)op_data[1]);
          break;
        case REC_IEEE_FLOAT64:
          op = *((double*)op_data[1]);
          break;
        default:
            // LCOV_EXCL_START
          ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
          **diagsArea << DgString0("ROUND");
          return ex_expr::EXPR_ERROR;
          // LCOV_EXCL_STOP
      }

      //
      // For commenting purposes, assume the following:
      //
      // op      = -12.58
      // roundTo = 0
      //
      //

      double pow1 = MathPow(10.0, roundTo, err1);             // = 1
      double pow2 = MathPow(10.0, -roundTo, err2);            // = 1
      double pow3 = MathPow(10.0, roundTo+1, err3);           // = 10


      double abs1 = (op < 0.0) ? -op : op;                    // = 12.58
      double sign = (op < 0.0) ? -1.0 : 1.0;                  // = -1.0

      double floor1 = MathFloor(abs1*pow3, err);              // = 125
      double floor2 = 10.0 * MathFloor(floor1 / 10.0, err);   // = 120
      double floor3 = floor1 - floor2;                        // = 5

      double floor4 = MathFloor(abs1*pow1, err);              // = 12
      double floor5 = pow2 * sign;                            // = -1.0

      // Is digit at rounding position less than 5?
      if (floor3 < 5.0) {
        res = floor4 * floor5;                                // = -12.0
      }
      // Is digit at rounding position greater than 5?
      else if (floor3 > 5.0) {
        res = (floor4 + 1.0) * floor5;                        // = -13.0
      }
      else {
        // Are digits after rounding position greater than 0?
        if (((abs1*pow3) - floor1) > 0.0)
          res = (floor4 + 1.0) * floor5;                      // = -13.0
        else {
          double floor6 = 2.0 * MathFloor(floor4 / 2.0, err); // = 12.0

          // Now round to even
          if ((floor4 - floor6) == 1.0)
            res = (floor4 + 1.0) * floor5;                    // = -13.0
          else
            res = floor4 * floor5;                            // = -12.0
        }
      }

      *(double *)op_data[0] = res;

      break;
    }

    case ITM_SCALE_TRUNC:
      {
          // LCOV_EXCL_START
	ExRaiseSqlError(heap, diagsArea, EXE_MATH_FUNC_NOT_SUPPORTED);
	if (getOperType() == ITM_ROUND)
	  **diagsArea << DgString0("ROUND");
	else
	  **diagsArea << DgString0("TRUNCATE");
	  
	retcode = ex_expr::EXPR_ERROR;
      }
     break;
     // LCOV_EXCL_STOP

    case ITM_ACOS:
      if ((*(double *)op_data[1] < -1) ||
	  (*(double *)op_data[1] > 1))
	{
	  ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
	  **diagsArea << DgString0("ACOS");
	  return ex_expr::EXPR_ERROR;
	}

      *(double *)op_data[0] = MathAcos(*(double *)op_data[1], err);
      break;

    case ITM_ASIN:
      if ((*(double *)op_data[1] < -1) ||
	  (*(double *)op_data[1] > 1))
	{
	  ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
	  **diagsArea << DgString0("ASIN");

	  return ex_expr::EXPR_ERROR;
	}

      *(double *)op_data[0] = MathAsin(*(double *)op_data[1], err);
      break;

    case ITM_ATAN:
      // No error checks, all numeric values allowed.

      *(double *)op_data[0] = MathAtan(*(double *)op_data[1], err);
      break;
      
    case ITM_ATAN2:
      // No error checks, all numeric values allowed.

      *(double *)op_data[0] = MathAtan2(*(double *)op_data[1],
				    *(double *)op_data[2], err);
      break;

    case ITM_CEIL:
      // No error checks, all numeric values allowed.

      *(double *)op_data[0] = MathCeil(*(double *)op_data[1], err);
      break;

    case ITM_COS:

       *(double *)op_data[0] = MathCos(*(double *)op_data[1], err);
      break;

    case ITM_COSH:
      *(double *)op_data[0] = MathCosh(*(double *)op_data[1], err);
      if (*(double *)op_data[0] == HUGE_VAL)
	{
	  ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
	  **diagsArea << DgString0("COSH");
	  return ex_expr::EXPR_ERROR;
	}
      break;

    case ITM_EXP:
      *(double *)op_data[0] = MathExp(*(double *)op_data[1], err);

      // Check for overflow. 
      if (err) 
	// if  (*(double *)op_data[0] == HUGE_VAL_REAL64)
	{
	  // Overflow

	  ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
	  **diagsArea << DgString0("EXP");
	  return ex_expr::EXPR_ERROR;
	}

      break;

    case ITM_FLOOR:
      // No error checks, all numeric values allowed.

      *(double *)op_data[0] = MathFloor(*(double *)op_data[1], err);
      break;

    case ITM_LOG:
      if (*(double *)op_data[1] <= 0)
	{
	  ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
	  **diagsArea << DgString0("LOG");
	  return ex_expr::EXPR_ERROR;
	}
      
      *(double *)op_data[0] = MathLog(*(double *)op_data[1], err);
      break;

    case ITM_LOG10:
      if (*(double *)op_data[1] <= 0)
	{
	  ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
	  **diagsArea << DgString0("LOG10");
	  return ex_expr::EXPR_ERROR;
	}
      
      *(double *)op_data[0] = MathLog10(*(double *)op_data[1], err);
      break;

    case ITM_SIN:

      *(double *)op_data[0] = MathSin(*(double *)op_data[1], err);
      break;

    case ITM_SINH:
      *(double *)op_data[0] = MathSinh(*(double *)op_data[1], err);
      if (*(double *)op_data[0] == HUGE_VAL)
	{
	  ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
	  **diagsArea << DgString0("SINH");
	  return ex_expr::EXPR_ERROR;
	}
	
      break;

    case ITM_SQRT:
      if (*(double *)op_data[1] < 0)
	{
	  ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
	  **diagsArea << DgString0("SQRT");
	  return ex_expr::EXPR_ERROR;
	}
      
      *(double *)op_data[0] = MathSqrt(*(double *)op_data[1], err);
      break;

    case ITM_TAN:

      *(double *)op_data[0] = MathTan(*(double *)op_data[1], err);
      break;

    case ITM_TANH:
      // No error checks, all numeric values allowed.

      *(double *)op_data[0] = MathTanh(*(double *)op_data[1], err);
      break;
     
    case ITM_EXPONENT:
    case ITM_POWER:
      if (((*(double *)op_data[1] == 0) &&
	   (*(double *)op_data[2] <= 0)) ||
	  ((*(double *)op_data[1] < 0) &&
	   (MathFloor(*(double *)op_data[2], err) != *(double *)op_data[2])))
	{
	  ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
	  **diagsArea << DgString0("POWER");
	  return ex_expr::EXPR_ERROR;
	}

      *(double *)op_data[0] = MathPow(*(double *)op_data[1],
				  *(double *)op_data[2], err);
        if (errno == ERANGE)	
	{
	  // Overflow

	  ExRaiseSqlError(heap, diagsArea, EXE_BAD_ARG_TO_MATH_FUNC);
	  **diagsArea << DgString0("POWER");
	  return ex_expr::EXPR_ERROR;
	}
	

      break;

    default:
      {
	ExRaiseSqlError(heap, diagsArea, EXE_INTERNAL_ERROR);
	retcode = ex_expr::EXPR_ERROR;
      }
      break;
     }
  
  return retcode;
}