int TA_MACDFIX_Lookback( TA_Integer optInSignalPeriod_0, /* From 1 to TA_INTEGER_MAX */ TA_Integer optInCompatibility_1 ) /**** END GENCODE SECTION 1 - DO NOT DELETE THIS LINE ****/ { /* insert lookback code here. */ /* The lookback is driven by the signal line output. * * (must also account for the initial data consume * by the fix 26 period EMA). */ return TA_EMA_Lookback( 26, optInCompatibility_1 ) + TA_EMA_Lookback( optInSignalPeriod_0, optInCompatibility_1 ); }
int TA_TEMA_Lookback( TA_Integer optInTimePeriod_0, /* From 1 to TA_INTEGER_MAX */ TA_Integer optInCompatibility_1 ) /**** END GENCODE SECTION 1 - DO NOT DELETE THIS LINE ****/ { /* insert lookback code here. */ /* Get lookack for one EMA. */ int retValue = TA_EMA_Lookback( optInTimePeriod_0, optInCompatibility_1 ); return retValue * 3; }
int TA_MA_Lookback( TA_Integer optInTimePeriod_0, /* From 2 to TA_INTEGER_MAX */ TA_MAType optInMAType_1 ) /**** END GENCODE SECTION 1 - DO NOT DELETE THIS LINE ****/ { /* insert lookback code here. */ switch( optInMAType_1 ) { case TA_MAType_SMA: return TA_SMA_Lookback( optInTimePeriod_0 ); break; case TA_MAType_EMA: return TA_EMA_Lookback( optInTimePeriod_0 ); break; case TA_MAType_WMA: return TA_WMA_Lookback( optInTimePeriod_0 ); break; case TA_MAType_DEMA: return TA_DEMA_Lookback( optInTimePeriod_0 ); break; case TA_MAType_TEMA: return TA_TEMA_Lookback( optInTimePeriod_0 ); break; case TA_MAType_TRIMA: return TA_TRIMA_Lookback( optInTimePeriod_0 ); break; case TA_MAType_KAMA: return TA_KAMA_Lookback( optInTimePeriod_0 ); break; case TA_MAType_MAMA: return TA_MAMA_Lookback( 0.5, 0.05 ); break; case TA_MAType_T3: return TA_T3_Lookback( optInTimePeriod_0, 0.7 ); break; } return 0; }
/* Generated */ TA_RetCode TA_PREFIX(INT_MACD)( int startIdx, /* Generated */ int endIdx, /* Generated */ const INPUT_TYPE inReal[], /* Generated */ int optInFastPeriod, /* Generated */ int optInSlowPeriod, /* Generated */ int optInSignalPeriod_2, /* Generated */ int *outBegIdx, /* Generated */ int *outNbElement, /* Generated */ double outMACD[], /* Generated */ double outMACDSignal[], /* Generated */ double outMACDHist[] ) /* Generated */ #endif /* Generated */ { /* Generated */ ARRAY_REF(slowEMABuffer); /* Generated */ ARRAY_REF(fastEMABuffer); /* Generated */ double k1, k2; /* Generated */ TA_RetCode retCode; /* Generated */ int tempInteger, outBegIdx1, outNbElement1; /* Generated */ int outBegIdx2, outNbElement2; /* Generated */ int lookbackTotal, lookbackSignal; /* Generated */ int i; /* Generated */ if( optInSlowPeriod < optInFastPeriod ) /* Generated */ { /* Generated */ tempInteger = optInSlowPeriod; /* Generated */ optInSlowPeriod = optInFastPeriod; /* Generated */ optInFastPeriod = tempInteger; /* Generated */ } /* Generated */ if( optInSlowPeriod != 0 ) /* Generated */ k1 = PER_TO_K(optInSlowPeriod); /* Generated */ else /* Generated */ { /* Generated */ optInSlowPeriod = 26; /* Generated */ k1 = (double)0.075; /* Generated */ } /* Generated */ if( optInFastPeriod != 0 ) /* Generated */ k2 = PER_TO_K(optInFastPeriod); /* Generated */ else /* Generated */ { /* Generated */ optInFastPeriod = 12; /* Generated */ k2 = (double)0.15; /* Generated */ } /* Generated */ lookbackSignal = TA_EMA_Lookback( optInSignalPeriod_2 ); /* Generated */ lookbackTotal = lookbackSignal; /* Generated */ lookbackTotal += TA_EMA_Lookback( optInSlowPeriod ); /* 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( fastEMABuffer, tempInteger ); /* Generated */ if( !fastEMABuffer ) /* Generated */ { /* Generated */ *outBegIdx = 0; /* Generated */ *outNbElement = 0; /* Generated */ return TA_ALLOC_ERR; /* Generated */ } /* Generated */ ARRAY_ALLOC( slowEMABuffer, tempInteger ); /* Generated */ if( !slowEMABuffer ) /* Generated */ { /* Generated */ *outBegIdx = 0; /* Generated */ *outNbElement = 0; /* Generated */ ARRAY_FREE( fastEMABuffer ); /* Generated */ return TA_ALLOC_ERR; /* Generated */ } /* Generated */ tempInteger = startIdx-lookbackSignal; /* Generated */ retCode = TA_PREFIX(INT_EMA)( tempInteger, endIdx, /* Generated */ inReal, optInSlowPeriod, k1, /* Generated */ &outBegIdx1, &outNbElement1, slowEMABuffer ); /* Generated */ if( retCode != TA_SUCCESS ) /* Generated */ { /* Generated */ *outBegIdx = 0; /* Generated */ *outNbElement = 0; /* Generated */ ARRAY_FREE( fastEMABuffer ); /* Generated */ ARRAY_FREE( slowEMABuffer ); /* Generated */ return retCode; /* Generated */ } /* Generated */ retCode = TA_PREFIX(INT_EMA)( tempInteger, endIdx, /* Generated */ inReal, optInFastPeriod, k2, /* Generated */ &outBegIdx2, &outNbElement2, fastEMABuffer ); /* Generated */ if( retCode != TA_SUCCESS ) /* Generated */ { /* Generated */ *outBegIdx = 0; /* Generated */ *outNbElement = 0; /* Generated */ ARRAY_FREE( fastEMABuffer ); /* Generated */ ARRAY_FREE( slowEMABuffer ); /* 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( fastEMABuffer ); /* Generated */ ARRAY_FREE( slowEMABuffer ); /* Generated */ return TA_INTERNAL_ERROR(119); /* Generated */ } /* Generated */ for( i=0; i < outNbElement1; i++ ) /* Generated */ fastEMABuffer[i] = fastEMABuffer[i] - slowEMABuffer[i]; /* Generated */ ARRAY_MEMMOVE( outMACD, 0, fastEMABuffer, lookbackSignal, (endIdx-startIdx)+1 ); /* Generated */ retCode = TA_INT_EMA( 0, outNbElement1-1, /* Generated */ fastEMABuffer, optInSignalPeriod_2, PER_TO_K(optInSignalPeriod_2), /* Generated */ &outBegIdx2, &outNbElement2, outMACDSignal ); /* Generated */ ARRAY_FREE( fastEMABuffer ); /* Generated */ ARRAY_FREE( slowEMABuffer ); /* 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 */ }
TA_RetCode TA_TEMA( TA_Libc *libHandle, TA_Integer startIdx, TA_Integer endIdx, const TA_Real inReal_0[], TA_Integer optInTimePeriod_0, /* From 1 to TA_INTEGER_MAX */ TA_Integer optInCompatibility_1, TA_Integer *outBegIdx, TA_Integer *outNbElement, TA_Real outReal_0[] ) /**** END GENCODE SECTION 2 - DO NOT DELETE THIS LINE ****/ { /* Insert local variables here. */ TA_Real *firstEMA, *secondEMA; TA_Real k; TA_Integer firstEMABegIdx, firstEMANbElement; TA_Integer secondEMABegIdx, secondEMANbElement; TA_Integer thirdEMABegIdx, thirdEMANbElement; TA_Integer tempInt, outIdx, lookbackTotal, lookbackEMA; TA_Integer firstEMAIdx, secondEMAIdx; TA_RetCode retCode; /**** START GENCODE SECTION 3 - DO NOT DELETE THIS LINE ****/ (void)libHandle; /* Get ride of warning if unused. */ #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. */ if( !inReal_0 ) return TA_BAD_PARAM; /* min/max are checked for optInTimePeriod_0. */ if( optInTimePeriod_0 == TA_INTEGER_DEFAULT ) optInTimePeriod_0 = 30; else if( (optInTimePeriod_0 < 1) || (optInTimePeriod_0 > 2147483647) ) return TA_BAD_PARAM; if( optInCompatibility_1 == TA_INTEGER_DEFAULT ) optInCompatibility_1 = 0; else if( (optInCompatibility_1 < 0) || (optInCompatibility_1 > 1) ) return TA_BAD_PARAM; if( outReal_0 == 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. */ /* For an explanation of this function, please read: * * Stocks & Commodities V. 12:1 (11-19): * Smoothing Data With Faster Moving Averages * Stocks & Commodities V. 12:2 (72-80): * Smoothing Data With Less Lag * * Both magazine articles written by Patrick G. Mulloy * * Essentially, a TEMA of time serie 't' is: * EMA1 = EMA(t,period) * EMA2 = EMA(EMA(t,period),period) * EMA3 = EMA(EMA(EMA(t,period),period)) * TEMA = 3*EMA1 - 3*EMA2 + EMA3 * * TEMA offers a moving average with less lags then the * traditional EMA. * * Do not confuse a TEMA with EMA3. Both are called "Triple EMA" * in the litterature. * * DEMA is very similar (and from the same author). */ /* Will change only on success. */ *outNbElement = 0; *outBegIdx = 0; /* Adjust startIdx to account for the lookback period. */ lookbackEMA = TA_EMA_Lookback( optInTimePeriod_0, optInCompatibility_1 ); lookbackTotal = lookbackEMA * 3; if( startIdx < lookbackTotal ) startIdx = lookbackTotal; /* Make sure there is still something to evaluate. */ if( startIdx > endIdx ) return TA_SUCCESS; /* Allocate a temporary buffer for the firstEMA. */ tempInt = lookbackTotal+(endIdx-startIdx)+1; firstEMA = (TA_Real *)TA_Malloc( libHandle, tempInt * sizeof( TA_Real) ); if( !firstEMA ) return TA_ALLOC_ERR; /* Calculate the first EMA */ k = PER_TO_K(optInTimePeriod_0); retCode = TA_INT_EMA( startIdx-(lookbackEMA*2), endIdx, inReal_0, optInTimePeriod_0, k, optInCompatibility_1, &firstEMABegIdx, &firstEMANbElement, firstEMA ); /* Verify for failure or if not enough data after * calculating the first EMA. */ if( (retCode != TA_SUCCESS) || (firstEMANbElement == 0) ) { TA_Free( libHandle, firstEMA ); return retCode; } /* Allocate a temporary buffer for storing the EMA2 */ secondEMA = (TA_Real *)TA_Malloc( libHandle, firstEMANbElement * sizeof( TA_Real) ); if( !secondEMA ) { TA_Free( libHandle, firstEMA ); return TA_ALLOC_ERR; } retCode = TA_INT_EMA( 0, firstEMANbElement-1, firstEMA, optInTimePeriod_0, k, optInCompatibility_1, &secondEMABegIdx, &secondEMANbElement, secondEMA ); /* Return empty output on failure or if not enough data after * calculating the second EMA. */ if( (retCode != TA_SUCCESS) || (secondEMANbElement == 0) ) { TA_Free( libHandle, firstEMA ); TA_Free( libHandle, secondEMA ); return retCode; } /* Calculate the EMA3 into the caller provided output. */ retCode = TA_INT_EMA( 0, secondEMANbElement-1, secondEMA, optInTimePeriod_0, k, optInCompatibility_1, &thirdEMABegIdx, &thirdEMANbElement, outReal_0 ); /* Return empty output on failure or if not enough data after * calculating the third EMA. */ if( (retCode != TA_SUCCESS) || (thirdEMANbElement == 0) ) { TA_Free( libHandle, firstEMA ); TA_Free( libHandle, secondEMA ); return retCode; } /* Indicate where the output starts relative to * the caller input. */ firstEMAIdx = thirdEMABegIdx + secondEMABegIdx; secondEMAIdx = thirdEMABegIdx; *outBegIdx = firstEMAIdx + firstEMABegIdx; /* Do the TEMA: * Iterate through the EMA3 (output buffer) and adjust * the value by using the EMA2 and EMA1. */ outIdx = 0; while( outIdx < thirdEMANbElement ) { outReal_0[outIdx] += (3.0*firstEMA[firstEMAIdx++]) - (3.0*secondEMA[secondEMAIdx++]); outIdx++; } TA_Free( libHandle, firstEMA ); TA_Free( libHandle, secondEMA ); /* Indicates to the caller the number of output * successfully calculated. */ *outNbElement = outIdx; return TA_SUCCESS; }
/* Internal implementation can be called from any other TA function. * * Faster because there is no parameter check, but it is a double * edge sword. * * The optInK_1 and optInTimePeriod_0 are usually tightly coupled: * * optInK_1 = 2 / (optInTimePeriod_0 + 1). * * These values are going to be related by this equation 99.9% of the * time... but there is some exception, this is why both must be provided. * * The macro PER_TO_K is equivalent to the above formula. */ TA_RetCode TA_INT_EMA( TA_Integer startIdx, TA_Integer endIdx, const TA_Real *inReal_0, TA_Integer optInTimePeriod_0, /* From 1 to TA_INTEGER_MAX */ TA_Real optInK_1, /* Ratio for calculation of EMA. */ TA_Integer optInCompatibility_1, TA_Integer *outBegIdx, TA_Integer *outNbElement, TA_Real *outReal_0 ) { TA_Real tempReal, prevMA; int i, today, outIdx, lookbackTotal; /* Ususally, optInK_1 = 2 / (optInTimePeriod_0 + 1), * but sometime there is exception. This * is why both value are parameters. */ /* Identify the minimum number of price bar needed * to calculate at least one output. */ lookbackTotal = TA_EMA_Lookback( optInTimePeriod_0, optInCompatibility_1 ); /* 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 ) { *outBegIdx = 0; *outNbElement = 0; return TA_SUCCESS; } /* Do the EMA calculation using tight loops. */ /* The first EMA is calculated differently. It * then become the seed for subsequent EMA. * * The algorithm for this seed vary widely. * Only 3 are implemented here: * * TA_MA_CLASSIC: * Use a simple MA of the first 'period'. * This is the approach most widely documented. * * TA_MA_METASTOCK: * Use first price bar value as a seed * from the begining of all the available * data. * * TA_MA_TRADESTATION: * Use 4th price bar as a seed, except when * period is 1 who use 2th price bar or something * like that... (not an obvious one...). */ switch( optInCompatibility_1 ) { case TA_MA_CLASSIC: today = startIdx-lookbackTotal; i = optInTimePeriod_0; tempReal = 0.0; while( i-- > 0 ) tempReal += inReal_0[today++]; prevMA = tempReal / optInTimePeriod_0; break; case TA_MA_METASTOCK: prevMA = inReal_0[0]; today = 1; break; /* !!! Tradestation not supported yet. case TA_MA_TRADESTATION: prevMA = inReal_0[startIdx-1]; if( optInTimePeriod_0 == 1 ) *outBegIdx_0 = 1; else *outBegIdx_0 = 3; */ default: return TA_UNKNOWN_ERR; } /* At this point, prevMA is the first EMA (the seed for * the rest). * 'today' keep track of where the processing is within the * input. */ /* Skip the unstable period. Do the processing * but do not write it in the output. */ while( today <= startIdx ) prevMA = ((inReal_0[today++]-prevMA)*optInK_1) + prevMA; /* Write the first value. */ outReal_0[0] = prevMA; outIdx = 1; *outBegIdx = today-1; /* Calculate the remaining range. */ while( today <= endIdx ) { prevMA = ((inReal_0[today++]-prevMA)*optInK_1) + prevMA; outReal_0[outIdx++] = prevMA; } *outNbElement = outIdx; return TA_SUCCESS; }
/* Generated */ TA_RetCode TA_S_TEMA( int startIdx, /* Generated */ int endIdx, /* Generated */ const float inReal_0[], /* Generated */ int optInTimePeriod_0, /* From 2 to 100000 */ /* Generated */ int *outBegIdx, /* Generated */ int *outNbElement, /* Generated */ double outReal_0[] ) /* Generated */ #endif /* Generated */ { /* Generated */ ARRAY_REF(firstEMA); /* Generated */ ARRAY_REF(secondEMA); /* Generated */ double k; /* Generated */ int firstEMABegIdx, firstEMANbElement; /* Generated */ int secondEMABegIdx, secondEMANbElement; /* Generated */ int thirdEMABegIdx, thirdEMANbElement; /* Generated */ int tempInt, outIdx, lookbackTotal, lookbackEMA; /* Generated */ int firstEMAIdx, secondEMAIdx; /* Generated */ TA_RetCode retCode; /* 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_0 ) return TA_BAD_PARAM; /* Generated */ if( (int)optInTimePeriod_0 == TA_INTEGER_DEFAULT ) /* Generated */ optInTimePeriod_0 = 30; /* Generated */ else if( ((int)optInTimePeriod_0 < 2) || ((int)optInTimePeriod_0 > 100000) ) /* Generated */ return TA_BAD_PARAM; /* Generated */ if( outReal_0 == NULL ) /* Generated */ return TA_BAD_PARAM; /* Generated */ #endif /* Generated */ *outNbElement = 0; /* Generated */ *outBegIdx = 0; /* Generated */ lookbackEMA = TA_EMA_Lookback( optInTimePeriod_0 ); /* Generated */ lookbackTotal = lookbackEMA * 3; /* Generated */ if( startIdx < lookbackTotal ) /* Generated */ startIdx = lookbackTotal; /* Generated */ if( startIdx > endIdx ) /* Generated */ return TA_SUCCESS; /* Generated */ tempInt = lookbackTotal+(endIdx-startIdx)+1; /* Generated */ ARRAY_ALLOC(firstEMA,tempInt); /* Generated */ if( !firstEMA ) /* Generated */ return TA_ALLOC_ERR; /* Generated */ k = PER_TO_K(optInTimePeriod_0); /* Generated */ retCode = TA_PREFIX(INT_EMA)( startIdx-(lookbackEMA*2), endIdx, inReal_0, /* Generated */ optInTimePeriod_0, k, /* Generated */ &firstEMABegIdx, &firstEMANbElement, firstEMA ); /* Generated */ if( (retCode != TA_SUCCESS) || (firstEMANbElement == 0) ) /* Generated */ { /* Generated */ ARRAY_FREE( firstEMA ); /* Generated */ return retCode; /* Generated */ } /* Generated */ ARRAY_ALLOC(secondEMA,firstEMANbElement); /* Generated */ if( !secondEMA ) /* Generated */ { /* Generated */ ARRAY_FREE( firstEMA ); /* Generated */ return TA_ALLOC_ERR; /* Generated */ } /* Generated */ retCode = TA_INT_EMA( 0, firstEMANbElement-1, firstEMA, /* Generated */ optInTimePeriod_0, k, /* Generated */ &secondEMABegIdx, &secondEMANbElement, secondEMA ); /* Generated */ if( (retCode != TA_SUCCESS) || (secondEMANbElement == 0) ) /* Generated */ { /* Generated */ ARRAY_FREE( firstEMA ); /* Generated */ ARRAY_FREE( secondEMA ); /* Generated */ return retCode; /* Generated */ } /* Generated */ retCode = TA_INT_EMA( 0, secondEMANbElement-1, secondEMA, /* Generated */ optInTimePeriod_0, k, /* Generated */ &thirdEMABegIdx, &thirdEMANbElement, /* Generated */ outReal_0 ); /* Generated */ if( (retCode != TA_SUCCESS) || (thirdEMANbElement == 0) ) /* Generated */ { /* Generated */ ARRAY_FREE( firstEMA ); /* Generated */ ARRAY_FREE( secondEMA ); /* Generated */ return retCode; /* Generated */ } /* Generated */ firstEMAIdx = thirdEMABegIdx + secondEMABegIdx; /* Generated */ secondEMAIdx = thirdEMABegIdx; /* Generated */ *outBegIdx = firstEMAIdx + firstEMABegIdx; /* Generated */ outIdx = 0; /* Generated */ while( outIdx < thirdEMANbElement ) /* Generated */ { /* Generated */ outReal_0[outIdx] += (3.0*firstEMA[firstEMAIdx++]) - (3.0*secondEMA[secondEMAIdx++]); /* Generated */ outIdx++; /* Generated */ } /* Generated */ ARRAY_FREE( firstEMA ); /* Generated */ ARRAY_FREE( secondEMA ); /* Generated */ *outNbElement = outIdx; /* Generated */ return TA_SUCCESS; /* Generated */ }
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; }