Exemple #1
0
PlotLine * TALIB::getMA (PlotLine *in, int type, int period)
{
  PlotLine *ma = new PlotLine;

  TA_Real input[in->getSize()];
  TA_Real out[in->getSize()];
  TA_Integer outBeg;
  TA_Integer count;
  TA_RetCode rc = TA_SUCCESS;

  int loop;
  for (loop = 0; loop < in->getSize(); loop++)
    input[loop] = (TA_Real) in->getData(loop);

  switch (type)
  {
    case 0:
      rc = TA_MA(0, in->getSize()- 1, &input[0], period, TA_MAType_SMA, &outBeg, &count, &out[0]);
      break;
    case 1:
      rc = TA_MA(0, in->getSize()- 1, &input[0], period, TA_MAType_EMA, &outBeg, &count, &out[0]);
      break;
    case 2:
      rc = TA_MA(0, in->getSize()- 1, &input[0], period, TA_MAType_WMA, &outBeg, &count, &out[0]);
      break;
    case 3:
      rc = TA_MA(0, in->getSize()- 1, &input[0], period, TA_MAType_DEMA, &outBeg, &count, &out[0]);
      break;
    case 4:
      rc = TA_MA(0, in->getSize()- 1, &input[0], period, TA_MAType_TEMA, &outBeg, &count, &out[0]);
      break;
    case 5:
      rc = TA_MA(0, in->getSize()- 1, &input[0], period, TA_MAType_TRIMA, &outBeg, &count, &out[0]);
      break;
    case 6:
      rc = TA_MA(0, in->getSize()- 1, &input[0], period, TA_MAType_KAMA, &outBeg, &count, &out[0]);
      break;
    case 7:
      rc = TA_MA(0, in->getSize()- 1, &input[0], period, TA_MAType_MAMA, &outBeg, &count, &out[0]);
      break;
    case 8:
      rc = TA_MA(0, in->getSize()- 1, &input[0], period, TA_MAType_T3, &outBeg, &count, &out[0]);
      break;
    default:
      break;    
  }

  if (rc != TA_SUCCESS)
  {
    qDebug("TALIB::getMA:error on TALIB function call");
    return ma;
  }

  for (loop = 0; loop < count; loop++)
    ma->append((double) out[loop]);

  return ma;  
}
Exemple #2
0
int
RSI::getMA (QString inKey, QString outKey, int type, int period)
{
  if (! g_symbol)
    return 0;
  
  TA_RetCode rc = TA_Initialize();
  if (rc != TA_SUCCESS)
    qDebug() << "RSI::getMA: error on TA_Initialize";

  QList<int> keys = g_symbol->keys();

  TA_Real input[MAX_SIZE];
  TA_Real out[MAX_SIZE];
  TA_Integer outBeg;
  TA_Integer outNb;

  int dpos = 0;
  for (int kpos = 0; kpos < keys.size(); kpos++)
  {
    CBar *bar = g_symbol->bar(keys.at(kpos));
    
    double v;
    if (! bar->get(inKey, v))
      continue;
    
    input[dpos++] = (TA_Real) v;
  }

  rc = TA_MA(0, dpos - 1, &input[0], period, (TA_MAType) type, &outBeg, &outNb, &out[0]);
  
  if (rc != TA_SUCCESS)
  {
    qDebug() << "RSI::getMA: TA-Lib error" << rc;
    return 0;
  }

  int keyLoop = keys.size() - 1;
  int outLoop = outNb - 1;
  while (keyLoop > -1 && outLoop > -1)
  {
    CBar *bar = g_symbol->bar(keys.at(keyLoop));
    bar->set(outKey, out[outLoop]);
    keyLoop--;
    outLoop--;
  }
  
  return 1;
}
Exemple #3
0
/* Generated */ TA_RetCode TA_S_STOCHF( int    startIdx,
/* Generated */                         int    endIdx,
/* Generated */                         const float  inHigh_0[],
/* Generated */                         const float  inLow_0[],
/* Generated */                         const float  inClose_0[],
/* Generated */                         int           optInFastK_Period_0, /* From 1 to 100000 */
/* Generated */                         int           optInFastD_Period_1, /* From 1 to 100000 */
/* Generated */                         TA_MAType     optInFastD_MAType_2,
/* Generated */                         int          *outBegIdx,
/* Generated */                         int          *outNbElement,
/* Generated */                         double        outFastK_0[],
/* Generated */                         double        outFastD_1[] )
/* Generated */ #endif
/* Generated */ {
/* Generated */    TA_RetCode retCode;
/* Generated */    double lowest, highest, tmp, diff;
/* Generated */    ARRAY_REF( tempBuffer );
/* Generated */    int outIdx, lowestIdx, highestIdx;
/* Generated */    int lookbackTotal, lookbackK, lookbackFastD;
/* Generated */    int trailingIdx, today, i;
/* Generated */    #if !defined( _MANAGED ) && !defined(USE_SINGLE_PRECISION_INPUT)
/* Generated */    int bufferIsAllocated;
/* Generated */    #endif
/* Generated */  #ifndef TA_FUNC_NO_RANGE_CHECK
/* Generated */     if( startIdx < 0 )
/* Generated */        return TA_OUT_OF_RANGE_START_INDEX;
/* Generated */     if( (endIdx < 0) || (endIdx < startIdx))
/* Generated */        return TA_OUT_OF_RANGE_END_INDEX;
/* Generated */     if(!inHigh_0||!inLow_0||!inClose_0)
/* Generated */        return TA_BAD_PARAM;
/* Generated */     if( (int)optInFastK_Period_0 == TA_INTEGER_DEFAULT )
/* Generated */        optInFastK_Period_0 = 5;
/* Generated */     else if( ((int)optInFastK_Period_0 < 1) || ((int)optInFastK_Period_0 > 100000) )
/* Generated */        return TA_BAD_PARAM;
/* Generated */     if( (int)optInFastD_Period_1 == TA_INTEGER_DEFAULT )
/* Generated */        optInFastD_Period_1 = 3;
/* Generated */     else if( ((int)optInFastD_Period_1 < 1) || ((int)optInFastD_Period_1 > 100000) )
/* Generated */        return TA_BAD_PARAM;
/* Generated */     #if !defined(_MANAGED)
/* Generated */     if( (int)optInFastD_MAType_2 == TA_INTEGER_DEFAULT )
/* Generated */        optInFastD_MAType_2 = 0;
/* Generated */     else if( ((int)optInFastD_MAType_2 < 0) || ((int)optInFastD_MAType_2 > 8) )
/* Generated */        return TA_BAD_PARAM;
/* Generated */     #endif 
/* Generated */     if( outFastK_0 == NULL )
/* Generated */        return TA_BAD_PARAM;
/* Generated */     if( outFastD_1 == NULL )
/* Generated */        return TA_BAD_PARAM;
/* Generated */  #endif 
/* Generated */    lookbackK      = optInFastK_Period_0-1;
/* Generated */    lookbackFastD  = TA_MA_Lookback( optInFastD_Period_1, optInFastD_MAType_2 );
/* Generated */    lookbackTotal  = lookbackK + lookbackFastD;
/* Generated */    if( startIdx < lookbackTotal )
/* Generated */       startIdx = lookbackTotal;
/* Generated */    if( startIdx > endIdx )
/* Generated */    {
/* Generated */       *outBegIdx    = 0;
/* Generated */       *outNbElement = 0;
/* Generated */       return TA_SUCCESS;
/* Generated */    }
/* Generated */    outIdx = 0;
/* Generated */    trailingIdx = startIdx-lookbackTotal;
/* Generated */    today       = trailingIdx+lookbackK;
/* Generated */    lowestIdx   = highestIdx = -1;
/* Generated */    diff = highest = lowest  = 0.0;
/* Generated */    #if !defined( _MANAGED ) && !defined(USE_SINGLE_PRECISION_INPUT)
/* Generated */       bufferIsAllocated = 0;
/* Generated */    #endif
/* Generated */    #if defined(USE_SINGLE_PRECISION_INPUT)
/* Generated */       ARRAY_ALLOC( tempBuffer, endIdx-today+1 );
/* Generated */    #else
/* Generated */       if( (outFastK_0 == inHigh_0) || 
/* Generated */           (outFastK_0 == inLow_0)  || 
/* Generated */           (outFastK_0 == inClose_0) )
/* Generated */       {
/* Generated */          tempBuffer = outFastK_0;
/* Generated */       }
/* Generated */       else if( (outFastD_1 == inHigh_0) ||
/* Generated */                (outFastD_1 == inLow_0)  ||
/* Generated */                (outFastD_1 == inClose_0) )
/* Generated */       {
/* Generated */          tempBuffer = outFastD_1;
/* Generated */       }
/* Generated */       else
/* Generated */       {
/* Generated */          #if !defined( _MANAGED )
/* Generated */             bufferIsAllocated = 1;
/* Generated */          #endif
/* Generated */          ARRAY_ALLOC(tempBuffer, endIdx-today+1 );
/* Generated */       }
/* Generated */    #endif
/* Generated */    while( today <= endIdx )
/* Generated */    {
/* Generated */       tmp = inLow_0[today];
/* Generated */       if( lowestIdx < trailingIdx )
/* Generated */       {
/* Generated */          lowestIdx = trailingIdx;
/* Generated */          lowest = inLow_0[lowestIdx];
/* Generated */          i = lowestIdx;
/* Generated */          while( ++i<=today )
/* Generated */          {
/* Generated */             tmp = inLow_0[i];
/* Generated */             if( tmp < lowest )
/* Generated */             {
/* Generated */                lowestIdx = i;
/* Generated */                lowest = tmp;
/* Generated */             }
/* Generated */          }
/* Generated */          diff = (highest - lowest)/100.0;
/* Generated */       }
/* Generated */       else if( tmp <= lowest )
/* Generated */       {
/* Generated */          lowestIdx = today;
/* Generated */          lowest = tmp;
/* Generated */          diff = (highest - lowest)/100.0;
/* Generated */       }
/* Generated */       tmp = inHigh_0[today];
/* Generated */       if( highestIdx < trailingIdx )
/* Generated */       {
/* Generated */          highestIdx = trailingIdx;
/* Generated */          highest = inHigh_0[highestIdx];
/* Generated */          i = highestIdx;
/* Generated */          while( ++i<=today )
/* Generated */          {
/* Generated */             tmp = inHigh_0[i];
/* Generated */             if( tmp > highest )
/* Generated */             {
/* Generated */                highestIdx = i;
/* Generated */                highest = tmp;
/* Generated */             }
/* Generated */          }
/* Generated */          diff = (highest - lowest)/100.0;
/* Generated */       }
/* Generated */       else if( tmp >= highest )
/* Generated */       {
/* Generated */          highestIdx = today;
/* Generated */          highest = tmp;
/* Generated */          diff = (highest - lowest)/100.0;
/* Generated */       }
/* Generated */       if( diff != 0.0 )
/* Generated */         tempBuffer[outIdx++] = (inClose_0[today]-lowest)/diff;
/* Generated */       else
/* Generated */         tempBuffer[outIdx++] = 0.0;
/* Generated */       trailingIdx++;
/* Generated */       today++; 
/* Generated */    }
/* Generated */    retCode = TA_MA( 0, outIdx-1,
/* Generated */                     tempBuffer, optInFastD_Period_1,
/* Generated */                     optInFastD_MAType_2, 
/* Generated */                     outBegIdx, outNbElement, outFastD_1 );
/* Generated */    if( (retCode != TA_SUCCESS) || (*outNbElement == 0) )
/* Generated */    {
/* Generated */       #if defined(USE_SINGLE_PRECISION_INPUT)
/* Generated */          ARRAY_FREE( tempBuffer ); 
/* Generated */       #else
/* Generated */          ARRAY_FREE_COND( bufferIsAllocated, tempBuffer ); 
/* Generated */       #endif
/* Generated */       *outBegIdx    = 0;
/* Generated */       *outNbElement = 0;
/* Generated */       return retCode; 
/* Generated */    }
/* Generated */    ARRAY_MEMMOVE( outFastK_0, 0, tempBuffer, lookbackFastD, *outNbElement );
/* Generated */    #if defined(USE_SINGLE_PRECISION_INPUT)
/* Generated */       ARRAY_FREE( tempBuffer ); 
/* Generated */    #else
/* Generated */       ARRAY_FREE_COND( bufferIsAllocated, tempBuffer ); 
/* Generated */    #endif
/* Generated */    if( retCode != TA_SUCCESS )
/* Generated */    {
/* Generated */       *outBegIdx    = 0;
/* Generated */       *outNbElement = 0;
/* Generated */       return retCode;
/* Generated */    }
/* Generated */    *outBegIdx = startIdx;
/* Generated */    return TA_SUCCESS;
/* Generated */ }
Exemple #4
0
/* Generated */ TA_RetCode TA_S_MACDEXT( int    startIdx,
/* Generated */                          int    endIdx,
/* Generated */                          const float  inReal[],
/* Generated */                          int           optInFastPeriod, /* From 2 to 100000 */
/* Generated */                          TA_MAType     optInFastMAType,
/* Generated */                          int           optInSlowPeriod, /* From 2 to 100000 */
/* Generated */                          TA_MAType     optInSlowMAType,
/* Generated */                          int           optInSignalPeriod, /* From 1 to 100000 */
/* Generated */                          TA_MAType     optInSignalMAType,
/* Generated */                          int          *outBegIdx,
/* Generated */                          int          *outNbElement,
/* Generated */                          double        outMACD[],
/* Generated */                          double        outMACDSignal[],
/* Generated */                          double        outMACDHist[] )
/* Generated */ #endif
/* Generated */ {
/* Generated */    ARRAY_REF( slowMABuffer );
/* Generated */    ARRAY_REF( fastMABuffer );
/* Generated */    TA_RetCode retCode;
/* Generated */    int tempInteger, outBegIdx1, outNbElement1;
/* Generated */    int outBegIdx2, outNbElement2;
/* Generated */    int lookbackTotal, lookbackSignal, lookbackLargest;
/* Generated */    int i;
/* Generated */    TA_MAType tempMAType;
/* Generated */  #ifndef TA_FUNC_NO_RANGE_CHECK
/* Generated */     if( startIdx < 0 )
/* Generated */        return TA_OUT_OF_RANGE_START_INDEX;
/* Generated */     if( (endIdx < 0) || (endIdx < startIdx))
/* Generated */        return TA_OUT_OF_RANGE_END_INDEX;
/* Generated */     if( !inReal ) return TA_BAD_PARAM;
/* Generated */     if( (int)optInFastPeriod == TA_INTEGER_DEFAULT )
/* Generated */        optInFastPeriod = 12;
/* Generated */     else if( ((int)optInFastPeriod < 2) || ((int)optInFastPeriod > 100000) )
/* Generated */        return TA_BAD_PARAM;
/* Generated */     #if !defined(_MANAGED)
/* Generated */     if( (int)optInFastMAType == TA_INTEGER_DEFAULT )
/* Generated */        optInFastMAType = 0;
/* Generated */     else if( ((int)optInFastMAType < 0) || ((int)optInFastMAType > 8) )
/* Generated */        return TA_BAD_PARAM;
/* Generated */     #endif 
/* Generated */     if( (int)optInSlowPeriod == TA_INTEGER_DEFAULT )
/* Generated */        optInSlowPeriod = 26;
/* Generated */     else if( ((int)optInSlowPeriod < 2) || ((int)optInSlowPeriod > 100000) )
/* Generated */        return TA_BAD_PARAM;
/* Generated */     #if !defined(_MANAGED)
/* Generated */     if( (int)optInSlowMAType == TA_INTEGER_DEFAULT )
/* Generated */        optInSlowMAType = 0;
/* Generated */     else if( ((int)optInSlowMAType < 0) || ((int)optInSlowMAType > 8) )
/* Generated */        return TA_BAD_PARAM;
/* Generated */     #endif 
/* Generated */     if( (int)optInSignalPeriod == TA_INTEGER_DEFAULT )
/* Generated */        optInSignalPeriod = 9;
/* Generated */     else if( ((int)optInSignalPeriod < 1) || ((int)optInSignalPeriod > 100000) )
/* Generated */        return TA_BAD_PARAM;
/* Generated */     #if !defined(_MANAGED)
/* Generated */     if( (int)optInSignalMAType == TA_INTEGER_DEFAULT )
/* Generated */        optInSignalMAType = 0;
/* Generated */     else if( ((int)optInSignalMAType < 0) || ((int)optInSignalMAType > 8) )
/* Generated */        return TA_BAD_PARAM;
/* Generated */     #endif 
/* Generated */     if( outMACD == NULL )
/* Generated */        return TA_BAD_PARAM;
/* Generated */     if( outMACDSignal == NULL )
/* Generated */        return TA_BAD_PARAM;
/* Generated */     if( outMACDHist == NULL )
/* Generated */        return TA_BAD_PARAM;
/* Generated */  #endif 
/* Generated */    if( optInSlowPeriod < optInFastPeriod )
/* Generated */    {
/* Generated */        tempInteger     = optInSlowPeriod;
/* Generated */        optInSlowPeriod = optInFastPeriod;
/* Generated */        optInFastPeriod = tempInteger;
/* Generated */        tempMAType      = optInSlowMAType;
/* Generated */        optInSlowMAType = optInFastMAType;
/* Generated */        optInFastMAType = tempMAType;
/* Generated */    }
/* Generated */    lookbackLargest = TA_MA_Lookback( optInFastPeriod, optInFastMAType );
/* Generated */    tempInteger     = TA_MA_Lookback( optInSlowPeriod, optInSlowMAType );
/* Generated */    if( tempInteger > lookbackLargest )
/* Generated */       lookbackLargest = tempInteger;
/* Generated */    lookbackSignal = TA_MA_Lookback( optInSignalPeriod, optInSignalMAType ); 
/* Generated */    lookbackTotal  = lookbackSignal+lookbackLargest;
/* Generated */    if( startIdx < lookbackTotal )
/* Generated */       startIdx = lookbackTotal;
/* Generated */    if( startIdx > endIdx )
/* Generated */    {
/* Generated */       *outBegIdx = 0;
/* Generated */       *outNbElement = 0;
/* Generated */       return TA_SUCCESS;
/* Generated */    }
/* Generated */    tempInteger = (endIdx-startIdx)+1+lookbackSignal;
/* Generated */    ARRAY_ALLOC( fastMABuffer, tempInteger );
/* Generated */    if( !fastMABuffer )
/* Generated */    {
/* Generated */       *outBegIdx = 0;
/* Generated */       *outNbElement = 0;
/* Generated */       return TA_ALLOC_ERR;
/* Generated */    }
/* Generated */    ARRAY_ALLOC( slowMABuffer, tempInteger );
/* Generated */    if( !slowMABuffer )
/* Generated */    {
/* Generated */       *outBegIdx = 0;
/* Generated */       *outNbElement = 0;
/* Generated */       ARRAY_FREE( fastMABuffer );
/* Generated */       return TA_ALLOC_ERR;
/* Generated */    }
/* Generated */    tempInteger = startIdx-lookbackSignal;
/* Generated */    retCode = TA_PREFIX(MA)( tempInteger, endIdx,
/* Generated */                             inReal, optInSlowPeriod, optInSlowMAType,
/* Generated */                             &outBegIdx1, &outNbElement1, slowMABuffer );
/* Generated */    if( retCode != TA_SUCCESS )
/* Generated */    {
/* Generated */       *outBegIdx = 0;
/* Generated */       *outNbElement = 0;
/* Generated */       ARRAY_FREE( fastMABuffer );
/* Generated */       ARRAY_FREE( slowMABuffer );
/* Generated */       return retCode;
/* Generated */    }
/* Generated */    retCode = TA_PREFIX(MA)( tempInteger, endIdx,
/* Generated */                             inReal, optInFastPeriod, optInFastMAType,
/* Generated */                             &outBegIdx2, &outNbElement2, fastMABuffer );
/* Generated */    if( retCode != TA_SUCCESS )
/* Generated */    {
/* Generated */       *outBegIdx = 0;
/* Generated */       *outNbElement = 0;
/* Generated */       ARRAY_FREE( fastMABuffer );
/* Generated */       ARRAY_FREE( slowMABuffer );
/* Generated */       return retCode;
/* Generated */    }
/* Generated */    if( (outBegIdx1 != tempInteger) || 
/* Generated */        (outBegIdx2 != tempInteger) || 
/* Generated */        (outNbElement1 != outNbElement2) ||
/* Generated */        (outNbElement1 != (endIdx-startIdx)+1+lookbackSignal) )
/* Generated */    {
/* Generated */       *outBegIdx = 0;
/* Generated */       *outNbElement = 0;
/* Generated */       ARRAY_FREE( fastMABuffer );
/* Generated */       ARRAY_FREE( slowMABuffer );
/* Generated */       return TA_INTERNAL_ERROR(119);
/* Generated */    }
/* Generated */    for( i=0; i < outNbElement1; i++ )
/* Generated */       fastMABuffer[i] = fastMABuffer[i] - slowMABuffer[i];
/* Generated */    ARRAY_MEMMOVE( outMACD, 0, fastMABuffer, lookbackSignal, (endIdx-startIdx)+1 );
/* Generated */    retCode = TA_MA( 0, outNbElement1-1,
/* Generated */                     fastMABuffer, optInSignalPeriod, optInSignalMAType,
/* Generated */                     &outBegIdx2, &outNbElement2, outMACDSignal );
/* Generated */    ARRAY_FREE( fastMABuffer );
/* Generated */    ARRAY_FREE( slowMABuffer );
/* Generated */    if( retCode != TA_SUCCESS )
/* Generated */    {
/* Generated */       *outBegIdx = 0;
/* Generated */       *outNbElement = 0;
/* Generated */       return retCode;
/* Generated */    }
/* Generated */    for( i=0; i < outNbElement2; i++ )
/* Generated */       outMACDHist[i] = outMACD[i]-outMACDSignal[i];
/* Generated */    *outBegIdx     = startIdx;
/* Generated */    *outNbElement  = outNbElement2;
/* Generated */    return TA_SUCCESS;
/* Generated */ }
Exemple #5
0
TEST(TA_MA, test_ta_lib_for_ma) {
  int result =
      MQL4::mapRatesData.get_forex_data("/home/sean/projects/quants/gom/data");
  EXPECT_EQ(result, 0);

  std::string symbol_name("USDJPY");
  MQL4::RatesData *rd = MQL4::mapRatesData.getSymbol(
      MQL4::MARKET_FOREX_FURTURES, symbol_name, MQL4::PERIOD_M1);
  EXPECT_NE((void*)rd, (void*)0);

  double *outTrimaReal = new double[rd->rs.size * 4];
  double *outSmaReal = outTrimaReal + rd->rs.size;
  double *outEmaReal = outSmaReal + rd->rs.size;
  double *outWmaReal = outEmaReal + rd->rs.size;

  int outBegIdx, outNBElement;
  int period = 60;
  TA_RetCode code = TA_MA(
      0, (int)rd->rs.amount - 1, rd->rs.close, period, /* From 1 to 100000 */
      TA_MAType_TRIMA, &outBegIdx, &outNBElement, outTrimaReal);

  EXPECT_EQ(code, 0);
  EXPECT_EQ(outBegIdx, period - 1);
  EXPECT_EQ(outNBElement, (int)rd->rs.amount - outBegIdx);

  code = TA_MA(0, (int)rd->rs.amount - 1, rd->rs.close,
               period, /* From 1 to 100000 */
               TA_MAType_SMA, &outBegIdx, &outNBElement, outSmaReal);

  EXPECT_EQ(code, 0);
  EXPECT_EQ(outBegIdx, period - 1);
  EXPECT_EQ(outNBElement, (int)rd->rs.amount - outBegIdx);

  code = TA_MA(0, (int)rd->rs.amount - 1, rd->rs.close,
               period, /* From 1 to 100000 */
               TA_MAType_EMA, &outBegIdx, &outNBElement, outEmaReal);

  EXPECT_EQ(code, 0);
  EXPECT_EQ(outBegIdx, period - 1);
  EXPECT_EQ(outNBElement, (int)rd->rs.amount - outBegIdx);

  code = TA_MA(0, (int)rd->rs.amount - 1, rd->rs.close,
               period, /* From 1 to 100000 */
               TA_MAType_WMA, &outBegIdx, &outNBElement, outWmaReal);

  EXPECT_EQ(code, 0);
  EXPECT_EQ(outBegIdx, period - 1);
  EXPECT_EQ(outNBElement, (int)rd->rs.amount - outBegIdx);

  ofstream fout("test-ma.csv");
  fout << "Close Price, TRIma, Sma, Ema, Wma\n";
  for (int i = 0; i < outNBElement; ++i) {
    if (i < outBegIdx)
      fout << rd->rs.close[i] << ", "
           << ", "
           << ", "
           << ", " << endl;
    else
      fout << rd->rs.close[i] << ", " << outTrimaReal[i] << ", "
           << outSmaReal[i] << ", " << outEmaReal[i] << ", " << outWmaReal[i]
           << ", " << endl;
  }
  fout.close();

  delete[] outTrimaReal;
  MQL4::mapRatesData.releaseRatesFromMap();
}
Exemple #6
0
Datum ta_f( PG_FUNCTION_ARGS)
{

	// Declare for TA
	TA_RetCode retCode;
	TA_Real *closePrice = NULL;
	TA_Real *out;

	TA_Integer outBeg;
	TA_Integer outNbElement;

	// Declare for postgres
	FuncCallContext *funcctx;
	int call_cntr;
	int max_calls;
	Datum *result = NULL;
	int dim;
	int z;
	ArrayType *ur = PG_GETARG_ARRAYTYPE_P(0);

	if (array_contains_nulls(ur))
	{
		ereport(ERROR,
				( errcode(ERRCODE_ARRAY_ELEMENT_ERROR), errmsg("cannot work with arrays containing NULLs") ));
	}

	dim = ARRNELEMS(ur);
	closePrice = ARRPTR(ur);

	if (SRF_IS_FIRSTCALL())
	{
		MemoryContext oldcontext;

		funcctx = SRF_FIRSTCALL_INIT();
		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
		/* One-time setup code appears here: */
		retCode = TA_Initialize();
		if (retCode != TA_SUCCESS)
		{
			ereport(ERROR,
					( errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Cannot initialize TA-Lib (%d)!\n", retCode) ));
		}

		out = palloc(dim * sizeof(TA_Real));

		retCode = TA_MA(0, dim - 1, &closePrice[0], 5, TA_MAType_SMA, &outBeg,
				&outNbElement, &out[0]);

		result = palloc(outNbElement * sizeof(Datum));

		// Error log for debugging
		/*
		ereport(NOTICE,
				(errmsg("dims %d,  outBeg: %d, outNbElement %d\n", dim, outBeg, outNbElement)));
		*/
		for (z = 0; z < dim; z++)
		{
			// Error log for debugging
			//ereport(NOTICE, (errmsg("z: %d, out[z]: %5.1f", z, out[z])));
			if(z > outBeg-1) {
				result[z] = Float8GetDatum(out[z-outBeg]);
				continue;
			}
			result[z] = NULL;
		}
		TA_Shutdown();

		funcctx->max_calls = dim;
		funcctx->user_fctx = result;
		MemoryContextSwitchTo(oldcontext);
	}

	/* stuff done on every call of the function */
	funcctx = SRF_PERCALL_SETUP();

	call_cntr = funcctx->call_cntr;
	max_calls = funcctx->max_calls;

	if (call_cntr < max_calls)
	{
		if(((Datum *) funcctx->user_fctx)[call_cntr]) {
			SRF_RETURN_NEXT(funcctx, ((Datum *) funcctx->user_fctx)[call_cntr]);
		}
		SRF_RETURN_NEXT_NULL(funcctx);
	}
	SRF_RETURN_DONE(funcctx);
}
Exemple #7
0
static ErrorNumber do_test_ma( const TA_History *history,
                               const TA_Test *test )
{
   TA_RetCode retCode;
   ErrorNumber errNb;
   TA_Integer outBegIdx;
   TA_Integer outNbElement;
   TA_RangeTestParam testParam;
   TA_Integer temp, temp2;
   const TA_Real *referenceInput;

   TA_SetCompatibility( test->compatibility );

   /* Set to NAN all the elements of the gBuffers.  */
   clearAllBuffers();

   /* Build the input. */
   setInputBuffer( 0, history->close, history->nbBars );
   setInputBuffer( 1, history->close, history->nbBars );

   /* Re-initialize all the unstable period to zero. */
   TA_SetUnstablePeriod( TA_FUNC_UNST_ALL, 0 );
   
   /* Set the unstable period requested for that test. */
   switch( test->optInMAType_1 )
   {
   case TA_MAType_TEMA:
   case TA_MAType_DEMA:
   case TA_MAType_EMA:
      retCode = TA_SetUnstablePeriod( TA_FUNC_UNST_EMA, test->unstablePeriod );
      break;
   case TA_MAType_KAMA:
      retCode = TA_SetUnstablePeriod( TA_FUNC_UNST_KAMA, test->unstablePeriod );
      break;
   case TA_MAType_MAMA:
      retCode = TA_SetUnstablePeriod( TA_FUNC_UNST_MAMA, test->unstablePeriod );
      break;
   case TA_MAType_T3:
      retCode = TA_SetUnstablePeriod( TA_FUNC_UNST_T3, test->unstablePeriod );
      break;
   default:
      retCode = TA_SUCCESS;
      break;
   }

   if( retCode != TA_SUCCESS )
      return TA_TEST_TFRR_SETUNSTABLE_PERIOD_FAIL;

   /* Transform the inputs for MAMA (it is an AVGPRICE in John Ehlers book). */
   if( test->optInMAType_1 == TA_MAType_MAMA )
   {
      TA_MEDPRICE( 0, history->nbBars-1, history->high, history->low,
                   &outBegIdx, &outNbElement, gBuffer[0].in );

      TA_MEDPRICE( 0, history->nbBars-1, history->high, history->low,
                   &outBegIdx, &outNbElement, gBuffer[1].in );

      /* Will be use as reference */
      TA_MEDPRICE( 0, history->nbBars-1, history->high, history->low,
                   &outBegIdx, &outNbElement, gBuffer[2].in );
      referenceInput = gBuffer[2].in;
   }
   else
      referenceInput = history->close;

   /* Make a simple first call. */
   switch( test->id )
   {
   case TA_ANY_MA_TEST:
      retCode = TA_MA( test->startIdx,
                       test->endIdx,
                       gBuffer[0].in,
                       test->optInTimePeriod_0,
                       test->optInMAType_1,
                       &outBegIdx,
                       &outNbElement,
                       gBuffer[0].out0 );
      break;
   case TA_MAMA_TEST:
      retCode = TA_MAMA( test->startIdx,
                         test->endIdx,
                         gBuffer[0].in,
                         0.5, 0.05,                       
                         &outBegIdx,
                         &outNbElement,
                         gBuffer[0].out0,
                         gBuffer[0].out2 );

     break;
   case TA_FAMA_TEST:
      retCode = TA_MAMA( test->startIdx,
                         test->endIdx,
                         gBuffer[0].in,
                         0.5, 0.05,                       
                         &outBegIdx,
                         &outNbElement,
                         gBuffer[0].out2,
                         gBuffer[0].out0 );

     break;
   }

   errNb = checkDataSame( gBuffer[0].in, referenceInput, history->nbBars );
   if( errNb != TA_TEST_PASS )
      return errNb;

   errNb = checkExpectedValue( gBuffer[0].out0, 
                               retCode, test->expectedRetCode,
                               outBegIdx, test->expectedBegIdx,
                               outNbElement, test->expectedNbElement,
                               test->oneOfTheExpectedOutReal,
                               test->oneOfTheExpectedOutRealIndex );   
   if( errNb != TA_TEST_PASS )
      return errNb;

   outBegIdx = outNbElement = 0;

   /* Make another call where the input and the output are the
    * same buffer.
    */
   switch( test->id )
   {
   case TA_ANY_MA_TEST:
      retCode = TA_MA( test->startIdx,
                       test->endIdx,
                       gBuffer[1].in,
                       test->optInTimePeriod_0,
                       test->optInMAType_1,
                       &outBegIdx,
                       &outNbElement,
                       gBuffer[1].in );
      break;
   case TA_MAMA_TEST:
      retCode = TA_MAMA( test->startIdx,
                         test->endIdx,
                         gBuffer[1].in,
                         0.5, 0.05,                       
                         &outBegIdx,
                         &outNbElement,
                         gBuffer[1].in,
                         gBuffer[0].out2 );
     break;
   case TA_FAMA_TEST:
      retCode = TA_MAMA( test->startIdx,
                         test->endIdx,
                         gBuffer[1].in,
                         0.5, 0.05,                       
                         &outBegIdx,
                         &outNbElement,
                         gBuffer[0].out2,
                         gBuffer[1].in );
     break;
   }

   /* The previous call to TA_MA should have the same output
    * as this call.
    *
    * checkSameContent verify that all value different than NAN in
    * the first parameter is identical in the second parameter.
    */
   errNb = checkSameContent( gBuffer[0].out0, gBuffer[1].in );
   if( errNb != TA_TEST_PASS )
      return errNb;

   errNb = checkExpectedValue( gBuffer[1].in, 
                               retCode, test->expectedRetCode,
                               outBegIdx, test->expectedBegIdx,
                               outNbElement, test->expectedNbElement,
                               test->oneOfTheExpectedOutReal,
                               test->oneOfTheExpectedOutRealIndex );   
   if( errNb != TA_TEST_PASS )
      return errNb;

  /* Verify that the "all-purpose" TA_MA_Lookback is consistent
   * with the corresponding moving average lookback function.
   */
   switch( test->optInMAType_1 )
   {
   case TA_MAType_WMA:
      temp = TA_WMA_Lookback( test->optInTimePeriod_0 );
      break;

   case TA_MAType_SMA:
      temp = TA_SMA_Lookback( test->optInTimePeriod_0 );
      break;

   case TA_MAType_EMA:
      temp = TA_EMA_Lookback( test->optInTimePeriod_0 );
      break;

   case TA_MAType_DEMA:
      temp = TA_DEMA_Lookback( test->optInTimePeriod_0 );
      break;

   case TA_MAType_TEMA:
      temp = TA_TEMA_Lookback( test->optInTimePeriod_0 );
      break;

   case TA_MAType_KAMA:
      temp = TA_KAMA_Lookback( test->optInTimePeriod_0 );
      break;

   case TA_MAType_MAMA:
      temp = TA_MAMA_Lookback( 0.5, 0.05 );
      break;

   case TA_MAType_TRIMA:
      temp = TA_TRIMA_Lookback( test->optInTimePeriod_0 );
      break;

   case TA_MAType_T3:
      temp = TA_T3_Lookback( test->optInTimePeriod_0, 0.7 );
      break;

   default:
      return TA_TEST_TFRR_BAD_MA_TYPE;
   }

   temp2 = TA_MA_Lookback( test->optInTimePeriod_0, test->optInMAType_1 );

   if( temp != temp2 )
      return TA_TEST_TFFR_BAD_MA_LOOKBACK;

   /* Do a systematic test of most of the
    * possible startIdx/endIdx range.
    */
   testParam.test  = test;
   testParam.close = referenceInput;

   if( test->doRangeTestFlag )
   {
      switch( test->optInMAType_1 )
      {
      case TA_MAType_TEMA:
      case TA_MAType_DEMA:
      case TA_MAType_EMA:
         errNb = doRangeTest( rangeTestFunction, 
                              TA_FUNC_UNST_EMA,
                              (void *)&testParam, 1, 0 );
         break;
      case TA_MAType_T3:
         errNb = doRangeTest( rangeTestFunction, 
                              TA_FUNC_UNST_T3,
                              (void *)&testParam, 1, 0 );
         break;
      case TA_MAType_KAMA:
         errNb = doRangeTest( rangeTestFunction, 
                              TA_FUNC_UNST_KAMA,
                              (void *)&testParam, 1, 0 );
         break;
      case TA_MAType_MAMA:
         errNb = doRangeTest( rangeTestFunction, 
                              TA_FUNC_UNST_MAMA,
                              (void *)&testParam, 2, 0 );
         break;
      default:
         errNb = doRangeTest( rangeTestFunction, 
                              TA_FUNC_UNST_NONE,
                              (void *)&testParam, 1, 0 );
      }

      if( errNb != TA_TEST_PASS )
         return errNb;
   }

   return TA_TEST_PASS;
}
Exemple #8
0
/**** Local functions definitions.     ****/
static TA_RetCode rangeTestFunction( 
                              TA_Integer startIdx,
                              TA_Integer endIdx,
                              TA_Real *outputBuffer,
                              TA_Integer *outBegIdx,
                              TA_Integer *outNbElement,
                              TA_Integer *lookback,
                              void *opaqueData,
                              unsigned int outputNb )
{
  TA_RetCode retCode;
  TA_RangeTestParam *testParam;
  TA_Real *dummyBuffer;
    
  testParam = (TA_RangeTestParam *)opaqueData;   

  switch( testParam->test->optInMAType_1 )
  {
  case TA_MAType_MAMA:
     dummyBuffer = TA_Malloc( sizeof(TA_Real)*(endIdx-startIdx+600) );
     if( outputNb == 0 )
     {
        retCode = TA_MAMA( startIdx,
                           endIdx,
                           testParam->close,
                           0.5, 0.05,                      
                           outBegIdx,
                           outNbElement,
                           outputBuffer,
                           &dummyBuffer[300] );
     }
     else
     {
        retCode = TA_MAMA( startIdx,
                           endIdx,
                           testParam->close,
                           0.5, 0.05,                      
                           outBegIdx,
                           outNbElement,
                           &dummyBuffer[300],
                           outputBuffer );
     }
     TA_Free( dummyBuffer );
     *lookback = TA_MAMA_Lookback( 0.5, 0.05 );
     break;
  default:
     /* Test for the TA_MA function. All the MA can be done
      * through that function.
      */
     retCode = TA_MA( startIdx,
                      endIdx,
                      testParam->close,
                      testParam->test->optInTimePeriod_0,
                      testParam->test->optInMAType_1,
                      outBegIdx,
                      outNbElement,
                      outputBuffer );

     *lookback = TA_MA_Lookback( testParam->test->optInTimePeriod_0,
                                 testParam->test->optInMAType_1 );
     break;
  }

  return retCode;
}
Exemple #9
0
TA_RetCode TA_STOCH( TA_Integer    startIdx,
                     TA_Integer    endIdx,
                     const TA_Real inHigh_0[],
                     const TA_Real inLow_0[],
                     const TA_Real inClose_0[],
                     TA_Integer    optInFastK_Period_0, /* From 1 to TA_INTEGER_MAX */
                     TA_Integer    optInSlowK_Period_1, /* From 1 to TA_INTEGER_MAX */
                     TA_MAType     optInSlowK_MAType_2,
                     TA_Integer    optInSlowD_Period_3, /* From 1 to TA_INTEGER_MAX */
                     TA_MAType     optInSlowD_MAType_4,
                     TA_Integer   *outBegIdx,
                     TA_Integer   *outNbElement,
                     TA_Real       outSlowK_0[],
                     TA_Real       outSlowD_1[] )
/**** END GENCODE SECTION 2 - DO NOT DELETE THIS LINE ****/
{
   /* Insert local variables here. */
   TA_RetCode retCode;
   TA_Real lowest, highest, tmp, diff;
   TA_Real *tempBuffer;
   TA_Integer outIdx, lowestIdx, highestIdx;
   TA_Integer lookbackTotal, lookbackK, lookbackKSlow, lookbackDSlow;
   TA_Integer trailingIdx, today, i, bufferIsAllocated;

/**** START GENCODE SECTION 3 - DO NOT DELETE THIS LINE ****/

#ifndef TA_FUNC_NO_RANGE_CHECK

   /* Validate the requested output range. */
   if( startIdx < 0 )
      return TA_OUT_OF_RANGE_START_INDEX;
   if( (endIdx < 0) || (endIdx < startIdx))
      return TA_OUT_OF_RANGE_END_INDEX;

   /* Validate the parameters. */
   /* Verify required price component. */
   if(!inHigh_0||!inLow_0||!inClose_0)
      return TA_BAD_PARAM;

   /* min/max are checked for optInFastK_Period_0. */
   if( (TA_Integer)optInFastK_Period_0 == TA_INTEGER_DEFAULT )
      optInFastK_Period_0 = 5;
   else if( ((TA_Integer)optInFastK_Period_0 < 1) || ((TA_Integer)optInFastK_Period_0 > 2147483647) )
      return TA_BAD_PARAM;

   /* min/max are checked for optInSlowK_Period_1. */
   if( (TA_Integer)optInSlowK_Period_1 == TA_INTEGER_DEFAULT )
      optInSlowK_Period_1 = 3;
   else if( ((TA_Integer)optInSlowK_Period_1 < 1) || ((TA_Integer)optInSlowK_Period_1 > 2147483647) )
      return TA_BAD_PARAM;

   if( (TA_Integer)optInSlowK_MAType_2 == TA_INTEGER_DEFAULT )
      optInSlowK_MAType_2 = 0;
   else if( ((TA_Integer)optInSlowK_MAType_2 < 0) || ((TA_Integer)optInSlowK_MAType_2 > 8) )
      return TA_BAD_PARAM;

   /* min/max are checked for optInSlowD_Period_3. */
   if( (TA_Integer)optInSlowD_Period_3 == TA_INTEGER_DEFAULT )
      optInSlowD_Period_3 = 3;
   else if( ((TA_Integer)optInSlowD_Period_3 < 1) || ((TA_Integer)optInSlowD_Period_3 > 2147483647) )
      return TA_BAD_PARAM;

   if( (TA_Integer)optInSlowD_MAType_4 == TA_INTEGER_DEFAULT )
      optInSlowD_MAType_4 = 0;
   else if( ((TA_Integer)optInSlowD_MAType_4 < 0) || ((TA_Integer)optInSlowD_MAType_4 > 8) )
      return TA_BAD_PARAM;

   if( outSlowK_0 == NULL )
      return TA_BAD_PARAM;

   if( outSlowD_1 == NULL )
      return TA_BAD_PARAM;

#endif /* TA_FUNC_NO_RANGE_CHECK */

/**** END GENCODE SECTION 3 - DO NOT DELETE THIS LINE ****/

   /* Insert TA function code here. */

   /* With stochastic, there is a total of 4 different lines that
    * are defined: FASTK, FASTD, SLOWK and SLOWD.
    *
    * The D is the signal line usually drawn over its
    * corresponding K function.
    *
    *                    (Today's Close - LowestLow)
    *  FASTK(Kperiod) =  --------------------------- * 100
    *                     (HighestHigh - LowestLow)
    *   
    *  FASTD(FastDperiod, MA type) = MA Smoothed FASTK over FastDperiod
    * 
    *  SLOWK(SlowKperiod, MA type) = MA Smoothed FASTK over SlowKperiod
    *
    *  SLOWD(SlowDperiod, MA Type) = MA Smoothed SLOWK over SlowDperiod
    *
    * The HighestHigh and LowestLow are the extreme values among the
    * last 'Kperiod'.
    *  
    * SLOWK and FASTD are equivalent when using the same period.
    *
    * The following shows how these four lines are made available in TA-LIB:
    *
    *  TA_STOCH  : Returns the SLOWK and SLOWD
    *  TA_STOCHF : Returns the FASTK and FASTD
    *
    * The TA_STOCH function correspond to the more widely implemented version
    * found in many software/charting package. The TA_STOCHF is more rarely
    * used because its higher volatility cause often whipsaws.
    */

   /* Identify the lookback needed. */
   lookbackK      = optInFastK_Period_0-1;
   lookbackKSlow  = TA_MA_Lookback( optInSlowK_Period_1, optInSlowK_MAType_2 );
   lookbackDSlow  = TA_MA_Lookback( optInSlowD_Period_3, optInSlowD_MAType_4 );
   lookbackTotal  = lookbackK + lookbackDSlow + lookbackKSlow;

   /* Move up the start index if there is not
    * enough initial data.
    */
   if( startIdx < lookbackTotal )
      startIdx = lookbackTotal;

   /* Make sure there is still something to evaluate. */
   if( startIdx > endIdx )
   {
      /* Succeed... but no data in the output. */
      *outBegIdx    = 0;
      *outNbElement = 0;
      return TA_SUCCESS;
   }

   /* Do the K calculation:
    *
    *    Kt = 100 x ((Ct-Lt)/(Ht-Lt))
    *
    * Kt is today stochastic
    * Ct is today closing price.
    * Lt is the lowest price of the last K Period (including today)
    * Ht is the highest price of the last K Period (including today)
    */

   /* Proceed with the calculation for the requested range.
    * Note that this algorithm allows the input and
    * output to be the same buffer.
    */
   outIdx = 0;

   /* Calculate just enough K for ending up with the caller 
    * requested range. (The range of k must consider all
    * the lookback involve with the smoothing).
    */
   trailingIdx = startIdx-lookbackTotal;
   today       = trailingIdx+lookbackK;
   lowestIdx   = highestIdx = -1;
   diff = highest = lowest  = 0.0;

   /* Allocate a temporary buffer large enough to
    * store the K.
    *
    * If the output is the same as the input, great
    * we just save ourself one memory allocation.
    */
   bufferIsAllocated = 0;
   if( (outSlowK_0 == inHigh_0) || 
       (outSlowK_0 == inLow_0)  || 
       (outSlowK_0 == inClose_0) )
   {
      tempBuffer = outSlowK_0;
   }
   else if( (outSlowD_1 == inHigh_0) ||
            (outSlowD_1 == inLow_0)  ||
            (outSlowD_1 == inClose_0) )
   {
      tempBuffer = outSlowD_1;
   }
   else
   {
      bufferIsAllocated = 1;
      tempBuffer = TA_Malloc( (endIdx-today+1)*sizeof(TA_Real) );
   }

   /* Do the K calculation */
   while( today <= endIdx )
   {
      /* Set the lowest low */
      tmp = inLow_0[today];
      if( lowestIdx < trailingIdx )
      {
         lowestIdx = trailingIdx;
         lowest = inLow_0[lowestIdx];
         i = lowestIdx;
         while( ++i<=today )
         {
            tmp = inLow_0[i];
            if( tmp < lowest )
            {
               lowestIdx = i;
               lowest = tmp;
            }
         }
         diff = (highest - lowest)/100.0;
      }
      else if( tmp <= lowest )
      {
         lowestIdx = today;
         lowest = tmp;
         diff = (highest - lowest)/100.0;
      }

      /* Set the highest high */
      tmp = inHigh_0[today];
      if( highestIdx < trailingIdx )
      {
         highestIdx = trailingIdx;
         highest = inHigh_0[highestIdx];
         i = highestIdx;
         while( ++i<=today )
         {
            tmp = inHigh_0[i];
            if( tmp > highest )
            {
               highestIdx = i;
               highest = tmp;
            }
         }
         diff = (highest - lowest)/100.0;
      }
      else if( tmp >= highest )
      {
         highestIdx = today;
         highest = tmp;
         diff = (highest - lowest)/100.0;
      }

      /* Calculate stochastic. */
      if( diff != 0.0 )
        tempBuffer[outIdx++] = (inClose_0[today]-lowest)/diff;
      else
        tempBuffer[outIdx++] = 0.0;

      trailingIdx++;
      today++; 
   }

   /* Un-smoothed K calculation completed. This K calculation is not returned
    * to the caller. It is always smoothed and then return.
    * Some documentation will refer to the smoothed version as being 
    * "K-Slow", but often this end up to be shorten to "K".
    */
   retCode = TA_MA( 0, outIdx-1,
                    tempBuffer, optInSlowK_Period_1,
                    optInSlowK_MAType_2, 
                    outBegIdx, outNbElement, tempBuffer );


   if( (retCode != TA_SUCCESS) || (*outNbElement == 0) )
   {
      if( bufferIsAllocated )
        TA_Free(  tempBuffer ); 
      /* Something wrong happen? No further data? */
      *outBegIdx    = 0;
      *outNbElement = 0;
      return retCode; 
   }

   /* Calculate the %D which is simply a moving average of
    * the already smoothed %K.
    */
   retCode = TA_MA( 0, (*outNbElement)-1,
                    tempBuffer, optInSlowD_Period_3,
                    optInSlowD_MAType_4,
                    outBegIdx, outNbElement, outSlowD_1 );

   /* Copy tempBuffer into the caller buffer. 
    * (Calculation could not be done directly in the
    *  caller buffer because more input data then the
    *  requested range was needed for doing %D).
    */
   memmove( outSlowK_0, &tempBuffer[lookbackDSlow], (*outNbElement) * sizeof(TA_Real) );

   /* Don't need K anymore, free it if it was allocated here. */
   if( bufferIsAllocated )
      TA_Free(  tempBuffer ); 

   if( retCode != TA_SUCCESS )
   {
      /* Something wrong happen while processing %D? */
      *outBegIdx    = 0;
      *outNbElement = 0;
      return retCode;
   }

   /* Note: Keep the outBegIdx relative to the
    *       caller input before returning.
    */
   *outBegIdx = startIdx;

   return TA_SUCCESS;
}
Exemple #10
0
/* This is an un-optimized version of the STOCH function */
static TA_RetCode referenceStoch( TA_Integer    startIdx,
                     TA_Integer    endIdx,
                     const TA_Real inHigh_0[],
                     const TA_Real inLow_0[],
                     const TA_Real inClose_0[],
                     TA_Integer    optInFastK_Period_0, /* From 1 to TA_INTEGER_MAX */
                     TA_Integer    optInSlowK_Period_1, /* From 1 to TA_INTEGER_MAX */
                     TA_Integer    optInSlowK_MAType_2,
                     TA_Integer    optInSlowD_Period_3, /* From 1 to TA_INTEGER_MAX */
                     TA_Integer    optInSlowD_MAType_4,
                     TA_Integer   *outBegIdx,
                     TA_Integer   *outNbElement,
                     TA_Real       outSlowK_0[],
                     TA_Real       outSlowD_1[] )
/**** END GENCODE SECTION 2 - DO NOT DELETE THIS LINE ****/
{
   /* Insert local variables here. */
   TA_RetCode retCode;
   TA_Real Lt, Ht, tmp, *tempBuffer;
   TA_Integer outIdx;
   TA_Integer lookbackTotal, lookbackK, lookbackKSlow, lookbackDSlow;
   TA_Integer trailingIdx, today, i, bufferIsAllocated;

/**** START GENCODE SECTION 3 - DO NOT DELETE THIS LINE ****/

#ifndef TA_FUNC_NO_RANGE_CHECK

   /* Validate the requested output range. */
   if( startIdx < 0 )
      return TA_OUT_OF_RANGE_START_INDEX;
   if( (endIdx < 0) || (endIdx < startIdx))
      return TA_OUT_OF_RANGE_END_INDEX;

   /* Validate the parameters. */
   /* Verify required price component. */
   if(!inHigh_0||!inLow_0||!inClose_0)
      return TA_BAD_PARAM;

   /* min/max are checked for optInFastK_Period_0. */
   if( optInFastK_Period_0 == TA_INTEGER_DEFAULT )
      optInFastK_Period_0 = 5;
   else if( (optInFastK_Period_0 < 1) || (optInFastK_Period_0 > 2147483647) )
      return TA_BAD_PARAM;

   /* min/max are checked for optInSlowK_Period_1. */
   if( optInSlowK_Period_1 == TA_INTEGER_DEFAULT )
      optInSlowK_Period_1 = 3;
   else if( (optInSlowK_Period_1 < 1) || (optInSlowK_Period_1 > 2147483647) )
      return TA_BAD_PARAM;

   if( optInSlowK_MAType_2 == TA_INTEGER_DEFAULT )
      optInSlowK_MAType_2 = 0;
   else if( (optInSlowK_MAType_2 < 0) || (optInSlowK_MAType_2 > 4) )
      return TA_BAD_PARAM;

   /* min/max are checked for optInSlowD_Period_3. */
   if( optInSlowD_Period_3 == TA_INTEGER_DEFAULT )
      optInSlowD_Period_3 = 3;
   else if( (optInSlowD_Period_3 < 1) || (optInSlowD_Period_3 > 2147483647) )
      return TA_BAD_PARAM;

   if( optInSlowD_MAType_4 == TA_INTEGER_DEFAULT )
      optInSlowD_MAType_4 = 0;
   else if( (optInSlowD_MAType_4 < 0) || (optInSlowD_MAType_4 > 4) )
      return TA_BAD_PARAM;

   if( outSlowK_0 == NULL )
      return TA_BAD_PARAM;

   if( outSlowD_1 == NULL )
      return TA_BAD_PARAM;

#endif /* TA_FUNC_NO_RANGE_CHECK */

/**** END GENCODE SECTION 3 - DO NOT DELETE THIS LINE ****/

   /* Insert TA function code here. */

   /* Identify the lookback needed. */
   lookbackK      = optInFastK_Period_0-1;
   lookbackKSlow  = TA_MA_Lookback( optInSlowK_Period_1, optInSlowK_MAType_2 );
   lookbackDSlow  = TA_MA_Lookback( optInSlowD_Period_3, optInSlowD_MAType_4 );
   lookbackTotal  = lookbackK + lookbackDSlow + lookbackKSlow;

   /* Move up the start index if there is not
    * enough initial data.
    */
   if( startIdx < lookbackTotal )
      startIdx = lookbackTotal;

   /* Make sure there is still something to evaluate. */
   if( startIdx > endIdx )
   {
      /* Succeed... but no data in the output. */
      *outBegIdx    = 0;
      *outNbElement = 0;
      return TA_SUCCESS;
   }

   /* Do the K calculation:
    *
    *    Kt = 100 x ((Ct-Lt)/(Ht-Lt))
    *
    * Kt is today stochastic
    * Ct is today closing price.
    * Lt is the lowest price of the last K Period (including today)
    * Ht is the highest price of the last K Period (including today)
    */

   /* Proceed with the calculation for the requested range.
    * Note that this algorithm allows the input and
    * output to be the same buffer.
    */
   outIdx = 0;

   /* Calculate just enough K for ending up with the caller 
    * requested range. (The range of k must consider all
    * the lookback involve with the smoothing).
    */
   trailingIdx = startIdx-lookbackTotal;
   today       = trailingIdx+lookbackK;

   /* Allocate a temporary buffer large enough to
    * store the K.
    *
    * If the output is the same as the input, great
    * we just save ourself one memory allocation.
    */
   bufferIsAllocated = 0;
   if( (outSlowK_0 == inHigh_0) || 
       (outSlowK_0 == inLow_0)  || 
       (outSlowK_0 == inClose_0) )
   {
      tempBuffer = outSlowK_0;
   }
   else if( (outSlowD_1 == inHigh_0) ||
            (outSlowD_1 == inLow_0)  ||
            (outSlowD_1 == inClose_0) )
   {
      tempBuffer = outSlowD_1;
   }
   else
   {
      bufferIsAllocated = 1;
      tempBuffer = TA_Malloc( (endIdx-today+1)*sizeof(TA_Real) );
   }

   /* Do the K calculation */
   while( today <= endIdx )
   {
      /* Find Lt and Ht for the requested K period. */
      Lt = inLow_0 [trailingIdx];
      Ht = inHigh_0[trailingIdx];
      trailingIdx++;
      for( i=trailingIdx; i <= today; i++ )
      {
         tmp = inLow_0[i];
         if( tmp < Lt ) Lt = tmp;
         tmp = inHigh_0[i];
         if( tmp > Ht ) Ht = tmp;
      }

      /* Calculate stochastic. */
      tmp = Ht-Lt;
      if( tmp > 0.0 )
        tempBuffer[outIdx++] = 100.0*((inClose_0[today]-Lt)/tmp);
      else
        tempBuffer[outIdx++] = 100.0;

      today++;
   }

   /* Un-smoothed K calculation completed. This K calculation is not returned
    * to the caller. It is always smoothed and then return.
    * Some documentation will refer to the smoothed version as being 
    * "K-Slow", but often this end up to be shorten to "K".
    */
   retCode = TA_MA( 0, outIdx-1,
                    tempBuffer, optInSlowK_Period_1,
                    optInSlowK_MAType_2,
                    outBegIdx, outNbElement, tempBuffer );


   if( (retCode != TA_SUCCESS) || (*outNbElement == 0) )
   {
      if( bufferIsAllocated )
        TA_Free(  tempBuffer ); 
      /* Something wrong happen? No further data? */
      *outBegIdx    = 0;
      *outNbElement = 0;
      return retCode; 
   }

   /* Calculate the %D which is simply a moving average of
    * the already smoothed %K.
    */
   retCode = TA_MA( 0, (*outNbElement)-1,
                    tempBuffer, optInSlowD_Period_3,
                    optInSlowD_MAType_4,
                    outBegIdx, outNbElement, outSlowD_1 );

   /* Copy tempBuffer into the caller buffer. 
    * (Calculation could not be done directly in the
    *  caller buffer because more input data then the
    *  requested range was needed for doing %D).
    */
   memmove( outSlowK_0, &tempBuffer[lookbackDSlow], (*outNbElement) * sizeof(TA_Real) );

   /* Don't need K anymore, free it if it was allocated here. */
   if( bufferIsAllocated )
      TA_Free(  tempBuffer ); 

   if( retCode != TA_SUCCESS )
   {
      /* Something wrong happen while processing %D? */
      *outBegIdx    = 0;
      *outNbElement = 0;
      return retCode;
   }

   /* Note: Keep the outBegIdx relative to the
    *       caller input before returning.
    */
   *outBegIdx = startIdx;

   return TA_SUCCESS;
}