📄 test_stoch.c
字号:
/* Set the unstable period requested for that test. */ switch( test->optInMAType_1 ) { 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. */ switch( test->testId ) { case TEST_STOCH: retCode = TA_STOCH( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInPeriod_0, test->optInPeriod_1, (TA_MAType)test->optInMAType_1, test->optInPeriod_2, (TA_MAType)test->optInMAType_2, &outBegIdx, &outNbElement, gBuffer[0].out0, gBuffer[0].out1 ); break; case TEST_STOCHF: retCode = TA_STOCHF( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInPeriod_0, test->optInPeriod_1, (TA_MAType)test->optInMAType_1, &outBegIdx, &outNbElement, gBuffer[0].out0, gBuffer[0].out1 ); break; case TEST_STOCHRSI: retCode = TA_STOCHRSI( test->startIdx, test->endIdx, gBuffer[2].in, test->optInPeriod_0, test->optInPeriod_1, test->optInPeriod_2, (TA_MAType)test->optInMAType_2, &outBegIdx, &outNbElement, gBuffer[0].out0, gBuffer[0].out1 ); break; } 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; if( test->testId == TEST_STOCH ) { /* 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. */ retCode = referenceStoch( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInPeriod_0, test->optInPeriod_1, test->optInMAType_1, test->optInPeriod_2, test->optInMAType_2, &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 optimized * 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. */ switch( test->testId ) { case TEST_STOCH: retCode = TA_STOCH( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInPeriod_0, test->optInPeriod_1, (TA_MAType)test->optInMAType_1, test->optInPeriod_2, (TA_MAType)test->optInMAType_2, &outBegIdx, &outNbElement, gBuffer[0].in, gBuffer[1].in ); break; case TEST_STOCHF: retCode = TA_STOCHF( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInPeriod_0, test->optInPeriod_1, (TA_MAType)test->optInMAType_1, &outBegIdx, &outNbElement, gBuffer[0].in, gBuffer[1].in ); break; case TEST_STOCHRSI: retCode = TA_STOCHRSI( test->startIdx, test->endIdx, gBuffer[2].in, test->optInPeriod_0, test->optInPeriod_1, test->optInPeriod_2, (TA_MAType)test->optInMAType_2, &outBegIdx, &outNbElement, gBuffer[0].in, gBuffer[1].in ); break; } /* 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 ) { switch( test->testId ) { case TEST_STOCH: case TEST_STOCHF: errNb = doRangeTest( rangeTestFunction, TA_FUNC_UNST_NONE, (void *)&testParam, 2, 0 ); break; case TEST_STOCHRSI: errNb = doRangeTest( rangeTestFunction, TA_FUNC_UNST_RSI, (void *)&testParam, 2, 0 ); break; } if( errNb != TA_TEST_PASS ) return errNb; } return TA_TEST_PASS;}/* This is an un-optimized version of the STOCH function */static TA_RetCode referenceStoch( TA_Integer startIdx, TA_Integer endIdx, const TA_Real inHigh[], const TA_Real inLow[], const TA_Real inClose[], TA_Integer optInPeriod_0, /* From 1 to TA_INTEGER_MAX */ TA_Integer optInPeriod_1, /* From 1 to TA_INTEGER_MAX */ TA_Integer optInMAType_1, TA_Integer optInPeriod_2, /* From 1 to TA_INTEGER_MAX */ TA_Integer optInMAType_2, TA_Integer *outBegIdx, TA_Integer *outNbElement, TA_Real outSlowK_0[], TA_Real outSlowD_1[] ){ TA_RetCode retCode; double Lt, Ht, tmp, *tempBuffer; int outIdx; int lookbackTotal, lookbackK, lookbackKSlow, lookbackDSlow; int trailingIdx, today, i, bufferIsAllocated; /* Identify the lookback needed. */ lookbackK = optInPeriod_0-1; lookbackKSlow = TA_MA_Lookback( optInPeriod_1, (TA_MAType)optInMAType_1 ); lookbackDSlow = TA_MA_Lookback( optInPeriod_2, (TA_MAType)optInMAType_2 ); 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) || (outSlowK_0 == inLow) || (outSlowK_0 == inClose) ) { tempBuffer = outSlowK_0; } else if( (outSlowD_1 == inHigh) || (outSlowD_1 == inLow) || (outSlowD_1 == inClose) ) { 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 [trailingIdx]; Ht = inHigh[trailingIdx]; trailingIdx++; for( i=trailingIdx; i <= today; i++ ) { tmp = inLow[i]; if( tmp < Lt ) Lt = tmp; tmp = inHigh[i]; if( tmp > Ht ) Ht = tmp; } /* Calculate stochastic. */ tmp = Ht-Lt; if( tmp > 0.0 ) tempBuffer[outIdx++] = 100.0*((inClose[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, optInPeriod_1, (TA_MAType)optInMAType_1, 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, optInPeriod_2, (TA_MAType)optInMAType_2, 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -