/**** Global functions definitions. ****/ ErrorNumber test_func_per_ohlc( TA_History *history ) { unsigned int i; ErrorNumber retValue; /* Re-initialize all the unstable period to zero. */ TA_SetUnstablePeriod( TA_FUNC_UNST_ALL, 0 ); for( i=0; i < NB_TEST; i++ ) { if( (int)tableTest[i].expectedNbElement > (int)history->nbBars ) { printf( "Failed Bad Parameter for Test #%d (%d,%d)\n", i, tableTest[i].expectedNbElement, history->nbBars ); return TA_TESTUTIL_TFRR_BAD_PARAM; } retValue = do_test( history, &tableTest[i] ); if( retValue != 0 ) { printf( "Failed Test #%d (Code=%d)\n", i, retValue ); return retValue; } } /* Re-initialize all the unstable period to zero. */ TA_SetUnstablePeriod( TA_FUNC_UNST_ALL, 0 ); /* All test succeed. */ return 0; }
static ErrorNumber do_test( const TA_History *history, const TA_Test *test ) { TA_RetCode retCode; ErrorNumber errNb; TA_Integer outBegIdx; TA_Integer outNbElement; TA_RangeTestParam testParam; /* Set to NAN all the elements of the gBuffers. */ clearAllBuffers(); /* Build the input. */ setInputBuffer( 0, history->high, history->nbBars ); setInputBuffer( 1, history->low, history->nbBars ); setInputBuffer( 2, history->close, history->nbBars ); /* Clear the unstable periods from previous tests. */ retCode = TA_SetUnstablePeriod( TA_FUNC_UNST_MFI, 0 ); if( retCode != TA_SUCCESS ) return TA_TEST_TFRR_SETUNSTABLE_PERIOD_FAIL; /* Make a simple first call. */ switch( test->theFunction ) { case TA_MFI_TEST: retCode = TA_MFI( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, history->volume, test->optInTimePeriod, &outBegIdx, &outNbElement, gBuffer[0].out0 ); break; case TA_AD_TEST: retCode = TA_AD( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, history->volume, &outBegIdx, &outNbElement, gBuffer[0].out0 ); break; case TA_ADOSC_3_10_TEST: retCode = TA_ADOSC( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, history->volume, 3, 10, &outBegIdx, &outNbElement, gBuffer[0].out0 ); break; case TA_ADOSC_5_2_TEST: retCode = TA_ADOSC( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, history->volume, 5, 2, &outBegIdx, &outNbElement, gBuffer[0].out0 ); break; default: retCode = TA_INTERNAL_ERROR(133); } /* Check that the input were preserved. */ errNb = checkDataSame( gBuffer[0].in, history->high,history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[1].in, history->low, history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[2].in, history->close,history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; CHECK_EXPECTED_VALUE( gBuffer[0].out0, 0 ); outBegIdx = outNbElement = 0; /* Make another call where the input and the output are the * same buffer. */ switch( test->theFunction ) { case TA_MFI_TEST: retCode = TA_MFI( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, history->volume, test->optInTimePeriod, &outBegIdx, &outNbElement, gBuffer[0].in ); break; case TA_AD_TEST: retCode = TA_AD( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, history->volume, &outBegIdx, &outNbElement, gBuffer[0].in ); break; case TA_ADOSC_3_10_TEST: retCode = TA_ADOSC( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, history->volume, 3, 10, &outBegIdx, &outNbElement, gBuffer[0].in ); break; case TA_ADOSC_5_2_TEST: retCode = TA_ADOSC( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, history->volume, 5, 2, &outBegIdx, &outNbElement, gBuffer[0].in ); break; default: retCode = TA_INTERNAL_ERROR(134); } /* Check that the input were preserved. */ errNb = checkDataSame( gBuffer[1].in, history->low, history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[2].in, history->close,history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; /* The previous call 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[0].in ); if( errNb != TA_TEST_PASS ) return errNb; CHECK_EXPECTED_VALUE( gBuffer[0].in, 0 ); setInputBuffer( 0, history->high, history->nbBars ); /* Make another call where the input and the output are the * same buffer. */ switch( test->theFunction ) { case TA_MFI_TEST: retCode = TA_MFI( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, history->volume, test->optInTimePeriod, &outBegIdx, &outNbElement, gBuffer[1].in ); break; case TA_AD_TEST: retCode = TA_AD( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, history->volume, &outBegIdx, &outNbElement, gBuffer[1].in ); break; case TA_ADOSC_3_10_TEST: retCode = TA_ADOSC( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, history->volume, 3, 10, &outBegIdx, &outNbElement, gBuffer[1].in ); break; case TA_ADOSC_5_2_TEST: retCode = TA_ADOSC( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, history->volume, 5, 2, &outBegIdx, &outNbElement, gBuffer[1].in ); break; default: retCode = TA_INTERNAL_ERROR(135); } /* Check that the input were preserved. */ errNb = checkDataSame( gBuffer[0].in, history->high,history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[2].in, history->close,history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; /* 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; CHECK_EXPECTED_VALUE( gBuffer[1].in, 0 ); setInputBuffer( 1, history->low, history->nbBars ); /* Make another call where the input and the output are the * same buffer. */ switch( test->theFunction ) { case TA_MFI_TEST: retCode = TA_MFI( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, history->volume, test->optInTimePeriod, &outBegIdx, &outNbElement, gBuffer[2].in ); break; case TA_AD_TEST: retCode = TA_AD( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, history->volume, &outBegIdx, &outNbElement, gBuffer[2].in ); break; case TA_ADOSC_3_10_TEST: retCode = TA_ADOSC( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, history->volume, 3, 10, &outBegIdx, &outNbElement, gBuffer[2].in ); break; case TA_ADOSC_5_2_TEST: retCode = TA_ADOSC( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, history->volume, 5, 2, &outBegIdx, &outNbElement, gBuffer[2].in ); break; default: retCode = TA_INTERNAL_ERROR(136); } /* Check that the input were preserved. */ errNb = checkDataSame( gBuffer[0].in, history->high,history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[1].in, history->low, history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; /* The previous call 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[2].in ); if( errNb != TA_TEST_PASS ) return errNb; CHECK_EXPECTED_VALUE( gBuffer[2].in, 0 ); setInputBuffer( 2, history->close, history->nbBars ); if( test->doRangeTestFlag ) { /* Do a systematic test of most of the * possible startIdx/endIdx range. */ testParam.test = test; testParam.high = history->high; testParam.low = history->low; testParam.close = history->close; testParam.volume = history->volume; switch( test->theFunction ) { case TA_MFI_TEST: errNb = doRangeTest( rangeTestFunction, TA_FUNC_UNST_MFI, (void *)&testParam, 1, 0 ); if( errNb != TA_TEST_PASS ) return errNb; break; case TA_AD_TEST: errNb = doRangeTest( rangeTestFunction, TA_FUNC_UNST_NONE, (void *)&testParam, 1, TA_DO_NOT_COMPARE ); if( errNb != TA_TEST_PASS ) return errNb; break; case TA_ADOSC_3_10_TEST: case TA_ADOSC_5_2_TEST: errNb = doRangeTest( rangeTestFunction, TA_FUNC_UNST_EMA, (void *)&testParam, 1, TA_DO_NOT_COMPARE ); if( errNb != TA_TEST_PASS ) return errNb; break; default: break; } } /* Check for fix #1359452 - AD RAnge not working as expected. */ if( test->theFunction == TA_AD_TEST ) { gBuffer[0].out0[0] = -1.0; gBuffer[0].out0[1] = -1.0; retCode = TA_AD( 0, 0, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, history->volume, &outBegIdx, &outNbElement, &gBuffer[0].out0[0] ); if( retCode != TA_SUCCESS ) { printf( "Failed AD call for fix #1359452 [%d]\n", retCode ); return TA_TEST_FAIL_BUG1359452_1; } if( gBuffer[0].out0[0] == -1.0 ) { printf( "Failed AD call for fix #1359452 out0[0] == -1\n" ); return TA_TEST_FAIL_BUG1359452_2; } retCode = TA_AD( 1, 1, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, history->volume, &outBegIdx, &outNbElement, &gBuffer[0].out0[1] ); if( retCode != TA_SUCCESS ) { printf( "Failed AD call for fix #1359452 [%d]\n", retCode ); return TA_TEST_FAIL_BUG1359452_3; } if( gBuffer[0].out0[1] == -1.0 ) { printf( "Failed AD call for fix #1359452 out0[1] == -1\n" ); return TA_TEST_FAIL_BUG1359452_4; } /* The two values are to be different. */ if( gBuffer[0].out0[1] == gBuffer[0].out0[0] ) { printf( "Failed AD logic for fix #1359452\n" ); return TA_TEST_FAIL_BUG1359452_5; } } return TA_TEST_PASS; }
static ErrorNumber do_test_per_ema( TA_Libc *libHandle, const TA_History *history, const TA_Test *test ) { TA_RetCode retCode; ErrorNumber errNb; TA_Integer outBegIdx; TA_Integer outNbElement; TA_RangeTestParam testParam; /* 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 ); /* Set the unstable period requested for that test. */ retCode = TA_SetUnstablePeriod( libHandle, TA_FUNC_UNST_EMA, test->unstablePeriod ); if( retCode != TA_SUCCESS ) return TA_TEST_TFRR_SETUNSTABLE_PERIOD_FAIL; /* Make a simple first call. */ switch( test->theFunction ) { case TA_TRIX_TEST: retCode = TA_TRIX( libHandle, test->startIdx, test->endIdx, gBuffer[0].in, test->optInTimePeriod_0, &outBegIdx, &outNbElement, gBuffer[0].out0 ); } errNb = checkDataSame( gBuffer[0].in, history->close,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->theFunction ) { case TA_TRIX_TEST: retCode = TA_TRIX( libHandle, test->startIdx, test->endIdx, gBuffer[1].in, test->optInTimePeriod_0, &outBegIdx, &outNbElement, gBuffer[1].in ); } /* 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; /* Do a systematic test of most of the * possible startIdx/endIdx range. */ testParam.test = test; testParam.close = history->close; if( test->doRangeTestFlag ) { errNb = doRangeTest( libHandle, rangeTestFunction, TA_FUNC_UNST_EMA, (void *)&testParam, 1, 0 ); if( errNb != TA_TEST_PASS ) return errNb; } return TA_TEST_PASS; }
static ErrorNumber do_test( TA_Libc *libHandle, const TA_History *history, const TA_Test *test ) { TA_RetCode retCode; ErrorNumber errNb; TA_Integer outBegIdx; TA_Integer outNbElement; TA_RangeTestParam testParam; /* Set to NAN all the elements of the gBuffers. */ clearAllBuffers(); /* Build the input. */ setInputBuffer( 0, history->high, history->nbBars ); setInputBuffer( 1, history->low, history->nbBars ); setInputBuffer( 2, history->close, history->nbBars ); /* Set the unstable period requested for that test. */ switch( test->optInMethod_3 ) { case TA_STOCH_EXPONENTIAL: retCode = TA_SetUnstablePeriod( libHandle, TA_FUNC_UNST_EMA, test->unstablePeriod ); if( retCode != TA_SUCCESS ) return TA_TEST_TFRR_SETUNSTABLE_PERIOD_FAIL; break; default: /* No unstable period for other methods. */ break; } /* Make a simple first call. */ retCode = TA_STOCH( libHandle, test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInKPeriod_0, test->optInKSlowPeriod_1, test->optInDPeriod_2, test->optInMethod_3, &outBegIdx, &outNbElement, gBuffer[0].out0, gBuffer[0].out1 ); errNb = checkDataSame( gBuffer[0].in, history->high,history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[1].in, history->low, history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[2].in, history->close,history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; CHECK_EXPECTED_VALUE( gBuffer[0].out0, 0 ); CHECK_EXPECTED_VALUE( gBuffer[0].out1, 1 ); outBegIdx = outNbElement = 0; /* Make another call where the input and the output are the * same buffer. */ retCode = TA_STOCH( libHandle, test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInKPeriod_0, test->optInKSlowPeriod_1, test->optInDPeriod_2, test->optInMethod_3, &outBegIdx, &outNbElement, gBuffer[0].in, gBuffer[1].in ); /* The previous call 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[0].in ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkSameContent( gBuffer[0].out1, gBuffer[1].in ); if( errNb != TA_TEST_PASS ) return errNb; CHECK_EXPECTED_VALUE( gBuffer[0].in, 0 ); CHECK_EXPECTED_VALUE( gBuffer[1].in, 1 ); if( errNb != TA_TEST_PASS ) return errNb; /* Do a systematic test of most of the * possible startIdx/endIdx range. */ testParam.test = test; testParam.high = history->high; testParam.low = history->low; testParam.close = history->close; if( test->doRangeTestFlag ) { errNb = doRangeTest( libHandle, rangeTestFunction, TA_FUNC_UNST_EMA, (void *)&testParam, 2 ); if( errNb != TA_TEST_PASS ) return errNb; } return TA_TEST_PASS; }
static ErrorNumber do_test( const TA_History *history, const TA_Test *test ) { TA_RetCode retCode; ErrorNumber errNb; TA_Integer outBegIdx; TA_Integer outNbElement; TA_RangeTestParam testParam; /* Set to NAN all the elements of the gBuffers. */ clearAllBuffers(); /* Build the input. */ setInputBuffer( 0, history->high, history->nbBars ); setInputBuffer( 1, history->low, history->nbBars ); setInputBuffer( 2, history->close, history->nbBars ); if( test->doAverage ) { TA_SetUnstablePeriod( TA_FUNC_UNST_ATR, test->unstablePeriod ); retCode = TA_ATR( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInTimePeriod_0, &outBegIdx, &outNbElement, gBuffer[0].out0 ); } else { retCode = TA_TRANGE( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, &outBegIdx, &outNbElement, gBuffer[0].out0 ); } errNb = checkDataSame( gBuffer[0].in, history->high,history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[1].in, history->low, history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[2].in, history->close, 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. */ if( test->doAverage ) { TA_SetUnstablePeriod( TA_FUNC_UNST_ATR, test->unstablePeriod ); retCode = TA_ATR( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInTimePeriod_0, &outBegIdx, &outNbElement, gBuffer[0].in ); } else { retCode = TA_TRANGE( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, &outBegIdx, &outNbElement, gBuffer[0].in ); } /* 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[0].in ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkExpectedValue( gBuffer[0].in, retCode, test->expectedRetCode, outBegIdx, test->expectedBegIdx, outNbElement, test->expectedNbElement, test->oneOfTheExpectedOutReal, test->oneOfTheExpectedOutRealIndex ); if( errNb != TA_TEST_PASS ) return errNb; /* Do a systematic test of most of the * possible startIdx/endIdx range. */ testParam.test = test; testParam.high = history->high; testParam.low = history->low; testParam.close = history->close; if( test->doRangeTestFlag ) { errNb = doRangeTest( rangeTestFunction, TA_FUNC_UNST_ATR, (void *)&testParam, 1, 0 ); if( errNb != TA_TEST_PASS ) return errNb; } return TA_TEST_PASS; }
static ErrorNumber do_test( const TA_History *history, const TA_Test *test ) { TA_RetCode retCode; ErrorNumber errNb; TA_Integer outBegIdx; TA_Integer outNbElement; TA_RangeTestParam testParam; /* Set to NAN all the elements of the gBuffers. */ clearAllBuffers(); TA_SetCompatibility( (TA_Compatibility)test->compatibility ); /* Build the input. */ setInputBuffer( 0, history->close, history->nbBars ); setInputBuffer( 1, history->close, history->nbBars ); TA_SetUnstablePeriod( TA_FUNC_UNST_EMA, 0 ); /* Make a simple first call. */ if( test->doPercentage ) { retCode = TA_PPO( test->startIdx, test->endIdx, gBuffer[0].in, test->optInFastPeriod, test->optInSlowPeriod, (TA_MAType)test->optInMethod_2, &outBegIdx, &outNbElement, gBuffer[0].out0 ); } else { retCode = TA_APO( test->startIdx, test->endIdx, gBuffer[0].in, test->optInFastPeriod, test->optInSlowPeriod, (TA_MAType)test->optInMethod_2, &outBegIdx, &outNbElement, gBuffer[0].out0 ); } errNb = checkDataSame( gBuffer[0].in, history->close, 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. */ if( test->doPercentage ) { retCode = TA_PPO( test->startIdx, test->endIdx, gBuffer[1].in, test->optInFastPeriod, test->optInSlowPeriod, (TA_MAType)test->optInMethod_2, &outBegIdx, &outNbElement, gBuffer[1].in ); } else { retCode = TA_APO( test->startIdx, test->endIdx, gBuffer[1].in, test->optInFastPeriod, test->optInSlowPeriod, (TA_MAType)test->optInMethod_2, &outBegIdx, &outNbElement, gBuffer[1].in ); } /* The previous call 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; /* Do a systematic test of most of the * possible startIdx/endIdx range. */ testParam.test = test; testParam.close = history->close; if( test->doRangeTestFlag ) { if( test->optInMethod_2 == TA_MAType_EMA ) { errNb = doRangeTest( rangeTestFunction, TA_FUNC_UNST_EMA, (void *)&testParam, 1, 0 ); if( errNb != TA_TEST_PASS ) return errNb; } else { errNb = doRangeTest( rangeTestFunction, TA_FUNC_UNST_NONE, (void *)&testParam, 1, 0 ); if( errNb != TA_TEST_PASS ) return errNb; } } return TA_TEST_PASS; }
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; }
static ErrorNumber do_test( const TA_History *history, const TA_Test *test ) { TA_RetCode retCode; ErrorNumber errNb; TA_Integer outBegIdx; TA_Integer outNbElement; TA_RangeTestParam testParam; retCode = TA_SetUnstablePeriod( TA_FUNC_UNST_EMA, 0 ); if( retCode != TA_SUCCESS ) return TA_TEST_TFRR_SETUNSTABLE_PERIOD_FAIL; /* 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 ); setInputBuffer( 2, history->close, history->nbBars ); setInputBuffer( 3, history->close, history->nbBars ); TA_SetCompatibility( (TA_Compatibility)test->compatibility ); /* Make a simple first call. */ retCode = TA_BBANDS( test->startIdx, test->endIdx, gBuffer[0].in, test->optInTimePeriod, test->optInNbDevUp, test->optInNbDevDn, (TA_MAType)test->optInMethod_3, &outBegIdx, &outNbElement, gBuffer[0].out0, gBuffer[0].out1, gBuffer[0].out2 ); errNb = checkDataSame( gBuffer[0].in, history->close, history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; CHECK_EXPECTED_VALUE( gBuffer[0].out0, 0 ); CHECK_EXPECTED_VALUE( gBuffer[0].out1, 1 ); CHECK_EXPECTED_VALUE( gBuffer[0].out2, 2 ); outBegIdx = outNbElement = 0; /* Make another call where the input and the output are the * same buffer. */ retCode = TA_BBANDS( test->startIdx, test->endIdx, gBuffer[1].in, test->optInTimePeriod, test->optInNbDevUp, test->optInNbDevDn, (TA_MAType)test->optInMethod_3, &outBegIdx, &outNbElement, gBuffer[1].in, gBuffer[1].out1, gBuffer[1].out2 ); /* The previous call 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; CHECK_EXPECTED_VALUE( gBuffer[1].in, 0 ); CHECK_EXPECTED_VALUE( gBuffer[1].out1, 1 ); CHECK_EXPECTED_VALUE( gBuffer[1].out2, 2 ); outBegIdx = outNbElement = 0; /* Make another call where the input and the output are the * same buffer. */ retCode = TA_BBANDS( test->startIdx, test->endIdx, gBuffer[2].in, test->optInTimePeriod, test->optInNbDevUp, test->optInNbDevDn, (TA_MAType)test->optInMethod_3, &outBegIdx, &outNbElement, gBuffer[2].out1, gBuffer[2].in, gBuffer[2].out2 ); /* The previous call 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[1].out1, gBuffer[2].in ); if( errNb != TA_TEST_PASS ) return errNb; CHECK_EXPECTED_VALUE( gBuffer[2].out1, 0 ); CHECK_EXPECTED_VALUE( gBuffer[2].in, 1 ); CHECK_EXPECTED_VALUE( gBuffer[2].out2, 2 ); outBegIdx = outNbElement = 0; /* Make another call where the input and the output are the * same buffer. */ retCode = TA_BBANDS( test->startIdx, test->endIdx, gBuffer[3].in, test->optInTimePeriod, test->optInNbDevUp, test->optInNbDevDn, (TA_MAType)test->optInMethod_3, &outBegIdx, &outNbElement, gBuffer[3].out0, gBuffer[3].out1, gBuffer[3].in ); /* The previous call 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[2].out2, gBuffer[3].in ); if( errNb != TA_TEST_PASS ) return errNb; CHECK_EXPECTED_VALUE( gBuffer[3].out0, 0 ); CHECK_EXPECTED_VALUE( gBuffer[3].out1, 1 ); CHECK_EXPECTED_VALUE( gBuffer[3].in, 2 ); /* Do a systematic test of most of the * possible startIdx/endIdx range. */ testParam.test = test; testParam.close = history->close; if( test->doRangeTestFlag ) { if( test->optInMethod_3 == TA_MAType_EMA ) { errNb = doRangeTest( rangeTestFunction, TA_FUNC_UNST_EMA, (void *)&testParam, 3, 0 ); } else { errNb = doRangeTest( rangeTestFunction, TA_FUNC_UNST_NONE, (void *)&testParam, 3, 0 ); } if( errNb != TA_TEST_PASS ) return errNb; } return TA_TEST_PASS; }
static ErrorNumber do_test( const TA_History *history, const TA_Test *test ) { TA_RetCode retCode; ErrorNumber errNb; TA_Integer outBegIdx; TA_Integer outNbElement; TA_RangeTestParam testParam; /* Set to NAN all the elements of the gBuffers. */ clearAllBuffers(); /* Build the input. */ setInputBuffer( 0, history->high, history->nbBars ); setInputBuffer( 1, history->low, history->nbBars ); setInputBuffer( 2, history->close, history->nbBars ); setInputBuffer( 3, history->high, history->nbBars ); /* Make a simple first call. */ switch( test->id ) { case TST_MINUS_DM: retCode = TA_SetUnstablePeriod( TA_FUNC_UNST_MINUS_DM, test->unstablePeriod ); if( retCode != TA_SUCCESS ) return TA_TEST_TFRR_SETUNSTABLE_PERIOD_FAIL; retCode = TA_MINUS_DM( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, test->optInTimePeriod, &outBegIdx, &outNbElement, gBuffer[0].out0 ); break; case TST_MINUS_DI: retCode = TA_SetUnstablePeriod( TA_FUNC_UNST_MINUS_DI, test->unstablePeriod ); if( retCode != TA_SUCCESS ) return TA_TEST_TFRR_SETUNSTABLE_PERIOD_FAIL; retCode = TA_MINUS_DI( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInTimePeriod, &outBegIdx, &outNbElement, gBuffer[0].out0 ); break; case TST_DX: retCode = TA_SetUnstablePeriod( TA_FUNC_UNST_DX, test->unstablePeriod ); if( retCode != TA_SUCCESS ) return TA_TEST_TFRR_SETUNSTABLE_PERIOD_FAIL; retCode = TA_DX( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInTimePeriod, &outBegIdx, &outNbElement, gBuffer[0].out0 ); break; case TST_ADX: retCode = TA_SetUnstablePeriod( TA_FUNC_UNST_ADX, test->unstablePeriod ); if( retCode != TA_SUCCESS ) return TA_TEST_TFRR_SETUNSTABLE_PERIOD_FAIL; retCode = TA_ADX( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInTimePeriod, &outBegIdx, &outNbElement, gBuffer[0].out0 ); break; case TST_PLUS_DM: retCode = TA_SetUnstablePeriod( TA_FUNC_UNST_PLUS_DM, test->unstablePeriod ); if( retCode != TA_SUCCESS ) return TA_TEST_TFRR_SETUNSTABLE_PERIOD_FAIL; retCode = TA_PLUS_DM( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, test->optInTimePeriod, &outBegIdx, &outNbElement, gBuffer[0].out0 ); break; case TST_PLUS_DI: retCode = TA_SetUnstablePeriod( TA_FUNC_UNST_PLUS_DI, test->unstablePeriod ); if( retCode != TA_SUCCESS ) return TA_TEST_TFRR_SETUNSTABLE_PERIOD_FAIL; retCode = TA_PLUS_DI( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInTimePeriod, &outBegIdx, &outNbElement, gBuffer[0].out0 ); break; case TST_ADXR: retCode = TA_SetUnstablePeriod( TA_FUNC_UNST_ADX, test->unstablePeriod ); if( retCode != TA_SUCCESS ) return TA_TEST_TFRR_SETUNSTABLE_PERIOD_FAIL; retCode = TA_ADXR( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInTimePeriod, &outBegIdx, &outNbElement, gBuffer[0].out0 ); break; default: retCode = TA_BAD_PARAM; } /* Verify that the inputs were preserved. */ errNb = checkDataSame( gBuffer[0].in, history->high, history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[1].in, history->low, history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[2].in, history->close, history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; CHECK_EXPECTED_VALUE( gBuffer[0].out0, 0 ); outBegIdx = outNbElement = 0; /* Make another call where the input and the output are the * same buffer. */ switch( test->id ) { case TST_MINUS_DM: retCode = TA_MINUS_DM( test->startIdx, test->endIdx, gBuffer[3].in, gBuffer[1].in, test->optInTimePeriod, &outBegIdx, &outNbElement, gBuffer[3].in ); break; case TST_MINUS_DI: retCode = TA_MINUS_DI( test->startIdx, test->endIdx, gBuffer[3].in, gBuffer[1].in, gBuffer[2].in, test->optInTimePeriod, &outBegIdx, &outNbElement, gBuffer[3].in ); break; case TST_DX: retCode = TA_DX( test->startIdx, test->endIdx, gBuffer[3].in, gBuffer[1].in, gBuffer[2].in, test->optInTimePeriod, &outBegIdx, &outNbElement, gBuffer[3].in ); break; case TST_ADX: retCode = TA_ADX( test->startIdx, test->endIdx, gBuffer[3].in, gBuffer[1].in, gBuffer[2].in, test->optInTimePeriod, &outBegIdx, &outNbElement, gBuffer[3].in ); break; case TST_PLUS_DM: retCode = TA_PLUS_DM( test->startIdx, test->endIdx, gBuffer[3].in, gBuffer[1].in, test->optInTimePeriod, &outBegIdx, &outNbElement, gBuffer[3].in ); break; case TST_PLUS_DI: retCode = TA_PLUS_DI( test->startIdx, test->endIdx, gBuffer[3].in, gBuffer[1].in, gBuffer[2].in, test->optInTimePeriod, &outBegIdx, &outNbElement, gBuffer[3].in ); break; case TST_ADXR: retCode = TA_ADXR( test->startIdx, test->endIdx, gBuffer[3].in, gBuffer[1].in, gBuffer[2].in, test->optInTimePeriod, &outBegIdx, &outNbElement, gBuffer[3].in ); break; default: retCode = TA_BAD_PARAM; } /* Verify that the inputs were preserved. */ errNb = checkDataSame( gBuffer[1].in, history->low, history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[2].in, history->close, history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; /* The previous call 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[3].in ); if( errNb != TA_TEST_PASS ) return errNb; CHECK_EXPECTED_VALUE( gBuffer[3].in, 0 ); if( errNb != TA_TEST_PASS ) return errNb; /* Do a systematic test of most of the * possible startIdx/endIdx range. */ testParam.test = test; testParam.high = history->high; testParam.low = history->low; testParam.close = history->close; if( test->doRangeTestFlag ) { switch( test->id ) { case TST_MINUS_DM: errNb = doRangeTest( rangeTestFunction, TA_FUNC_UNST_MINUS_DM, (void *)&testParam, 1, 0 ); break; case TST_MINUS_DI: errNb = doRangeTest( rangeTestFunction, TA_FUNC_UNST_MINUS_DI, (void *)&testParam, 1, 2 ); break; case TST_DX: errNb = doRangeTest( rangeTestFunction, TA_FUNC_UNST_DX, (void *)&testParam, 1, 2 ); break; case TST_ADX: errNb = doRangeTest( rangeTestFunction, TA_FUNC_UNST_ADX, (void *)&testParam, 1, 2 ); break; case TST_PLUS_DM: errNb = doRangeTest( rangeTestFunction, TA_FUNC_UNST_PLUS_DM, (void *)&testParam, 1, 0 ); break; case TST_PLUS_DI: errNb = doRangeTest( rangeTestFunction, TA_FUNC_UNST_PLUS_DI, (void *)&testParam, 1, 2 ); break; case TST_ADXR: errNb = doRangeTest( rangeTestFunction, TA_FUNC_UNST_ADX, (void *)&testParam, 1, 2 ); break; } if( errNb != TA_TEST_PASS ) return errNb; } return TA_TEST_PASS; }
static ErrorNumber do_test( const TA_History *history, const TA_Test *test ) { TA_RetCode retCode; ErrorNumber errNb; TA_Integer outBegIdx; TA_Integer outNbElement; TA_RangeTestParam testParam; /* Set to NAN all the elements of the gBuffers. */ clearAllBuffers(); /* Build the input. */ setInputBuffer( 0, history->high, history->nbBars ); setInputBuffer( 1, history->low, history->nbBars ); setInputBuffer( 2, history->close, history->nbBars ); /* Set the unstable period requested for that test. */ switch( test->optInSlowK_MAType_2 ) { case TA_MAType_EMA: retCode = TA_SetUnstablePeriod( TA_FUNC_UNST_EMA, test->unstablePeriod ); if( retCode != TA_SUCCESS ) return TA_TEST_TFRR_SETUNSTABLE_PERIOD_FAIL; break; default: /* No unstable period for other methods. */ break; } /* Make a simple first call. */ retCode = TA_STOCH( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInFastK_Period_0, test->optInSlowK_Period_1, test->optInSlowK_MAType_2, test->optInSlowD_Period_3, test->optInSlowD_MAType_4, &outBegIdx, &outNbElement, gBuffer[0].out0, gBuffer[0].out1 ); errNb = checkDataSame( gBuffer[0].in, history->high,history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[1].in, history->low, history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[2].in, history->close,history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; CHECK_EXPECTED_VALUE( gBuffer[0].out0, 0 ); CHECK_EXPECTED_VALUE( gBuffer[0].out1, 1 ); outBegIdx = outNbElement = 0; /* Compare to the non-optimized version */ retCode = referenceStoch( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInFastK_Period_0, test->optInSlowK_Period_1, test->optInSlowK_MAType_2, test->optInSlowD_Period_3, test->optInSlowD_MAType_4, &outBegIdx, &outNbElement, gBuffer[1].out0, gBuffer[1].out1 ); errNb = checkDataSame( gBuffer[0].in, history->high,history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[1].in, history->low, history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[2].in, history->close,history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; CHECK_EXPECTED_VALUE( gBuffer[1].out0, 0 ); CHECK_EXPECTED_VALUE( gBuffer[1].out1, 1 ); /* The non-optimized reference shall be identical to the optimzied TA-Lib * implementation. * * checkSameContent verify that all value different than NAN in * the first parameter is identical in the second parameter. */ errNb = checkSameContent( gBuffer[1].out0, gBuffer[0].out0 ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkSameContent( gBuffer[1].out1, gBuffer[0].out1 ); if( errNb != TA_TEST_PASS ) return errNb; /* Make another call where the input and the output are the * same buffer. */ retCode = TA_STOCH( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInFastK_Period_0, test->optInSlowK_Period_1, test->optInSlowK_MAType_2, test->optInSlowD_Period_3, test->optInSlowD_MAType_4, &outBegIdx, &outNbElement, gBuffer[0].in, gBuffer[1].in ); /* The previous call 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[0].in ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkSameContent( gBuffer[0].out1, gBuffer[1].in ); if( errNb != TA_TEST_PASS ) return errNb; CHECK_EXPECTED_VALUE( gBuffer[0].in, 0 ); CHECK_EXPECTED_VALUE( gBuffer[1].in, 1 ); if( errNb != TA_TEST_PASS ) return errNb; /* Do a systematic test of most of the * possible startIdx/endIdx range. */ testParam.test = test; testParam.high = history->high; testParam.low = history->low; testParam.close = history->close; if( test->doRangeTestFlag ) { errNb = doRangeTest( rangeTestFunction, TA_FUNC_UNST_EMA, (void *)&testParam, 2, 0 ); if( errNb != TA_TEST_PASS ) return errNb; } /* Call a local non-optimized version of the function. * This way, we make sure that the currently speed optimized * version in TA-Lib is not broken. */ return TA_TEST_PASS; }
static ErrorNumber doRangeTestForOneOutput( RangeTestFunction testFunction, TA_FuncUnstId unstId, void *opaqueData, unsigned int outputNb, unsigned int integerTolerance ) { TA_RetCode retCode; TA_Integer refOutBeg, refOutNbElement, refLookback; TA_Integer fixSize; TA_Real *refBuffer; ErrorNumber errNb; TA_Integer unstablePeriod, temp; /* Caculate the whole range. This is going * to be the reference for all subsequent test. */ refBuffer = TA_Malloc( MAX_RANGE_SIZE * sizeof( TA_Real ) ); if( !refBuffer ) return TA_TESTUTIL_DRT_ALLOC_ERR; if( unstId != TA_FUNC_UNST_NONE ) { /* Caller wish to test for a range of unstable * period values. But the reference is calculated * on the whole range by keeping that unstable period * to zero. */ TA_SetUnstablePeriod( unstId, 0 ); } retCode = testFunction( 0, MAX_RANGE_END, refBuffer, &refOutBeg, &refOutNbElement, &refLookback, opaqueData, outputNb ); if( retCode != TA_SUCCESS ) { printf( "Fail: doRangeTest whole range failed (%d)\n", retCode ); TA_Free( refBuffer ); return TA_TESTUTIL_DRT_REF_FAILED; } /* When calculating for the whole range, the lookback and the * refOutBeg are supppose to be equal. */ if( refLookback != refOutBeg ) { printf( "Fail: doRangeTest refLookback != refOutBeg (%d != %d)\n", refLookback, refOutBeg ); TA_Free( refBuffer ); return TA_TESTUTIL_DRT_LOOKBACK_INCORRECT; } temp = MAX_RANGE_SIZE-refLookback; if( temp != refOutNbElement ) { printf( "Fail: doRangeTest either refOutNbElement or refLookback bad (%d,%d)\n", temp, refOutNbElement ); TA_Free( refBuffer ); return TA_TESTUTIL_DRT_REF_OUTPUT_INCORRECT; } /* Calculate each value ONE by ONE and make sure it is identical * to the reference. * * Then repeat the test but calcualte TWO by TWO and so on... */ for( fixSize=1; fixSize <= MAX_RANGE_SIZE; fixSize++ ) { /* When a function has an unstable period, verify some * unstable period between 0 and MAX_RANGE_SIZE. */ if( unstId == TA_FUNC_UNST_NONE ) { errNb = doRangeTestFixSize( testFunction, opaqueData, refOutBeg, refOutNbElement, refLookback, refBuffer, unstId, fixSize, outputNb, integerTolerance ); if( errNb != TA_TEST_PASS) { TA_Free( refBuffer ); return errNb; } } else { for( unstablePeriod=0; unstablePeriod <= MAX_RANGE_SIZE; unstablePeriod++ ) { TA_SetUnstablePeriod( unstId, unstablePeriod ); errNb = doRangeTestFixSize( testFunction, opaqueData, refOutBeg, refOutNbElement, refLookback, refBuffer, unstId, fixSize, outputNb, integerTolerance ); if( errNb != TA_TEST_PASS) { printf( "Fail: Using unstable period %d\n", unstablePeriod ); TA_Free( refBuffer ); return errNb; } /* Randomly skip the test of some unstable period (limit case are * always tested though). */ if( (unstablePeriod > 20) && (unstablePeriod < 230) ) { /* Randomly skips from 0 to 149 tests. Never * make unstablePeriod exceed 230. */ temp = (rand() % 150); unstablePeriod += temp; if( unstablePeriod > 230 ) unstablePeriod = 230; } } /* Because the tests with an unstable period are very intensive * and kinda repetitive, skip the test of some fixSize (limit * case are always tested though). */ if( (fixSize > 30) && (fixSize < 240) ) { /* Randomly skips from 0 to 149 tests. Never * make fixSize exceed 240. */ temp = (rand() % 150); fixSize += temp; if( fixSize > 240 ) fixSize = 240; } } } TA_Free( refBuffer ); return TA_TEST_PASS; }