/* Return 1 on success */ ErrorNumber checkSameContent( TA_Real *buffer1, TA_Real *buffer2 ) { const TA_Real *theBuffer1; const TA_Real *theBuffer2; unsigned int i; theBuffer1 = buffer1 - TA_BUF_PREFIX; theBuffer2 = buffer2 - TA_BUF_PREFIX; for( i=0; i < TA_BUF_SIZE; i++ ) { if( (!trio_isnan(theBuffer1[i])) && (!trio_isinf(theBuffer1[i])) && (theBuffer1[i] != RESV_PATTERN_SUFFIX) && (theBuffer1[i] != RESV_PATTERN_PREFIX) ) { if(!TA_REAL_EQ( theBuffer1[i], theBuffer2[i], 0.000001)) { printf( "Fail: Large difference found between two value expected identical (%f,%f,%d)\n", theBuffer1[i], theBuffer2[i], i ); return TA_TEST_TFRR_CHECK_SAME_CONTENT; } } } return TA_TEST_PASS; }
static ErrorNumber test_arrayId( TA_PMArrayIdTest *test ) { int i, j; TA_TradeLog *tradeLog; TA_PM *pm; TA_RetCode retCode; TA_Real theValue; TA_PMArray *pmArray; const char *tempStr; /* Allocate and build the TA_TradeLog */ retCode = TA_TradeLogAlloc( &tradeLog ); if( retCode != TA_SUCCESS ) return TA_PM_TEST_ARRAY_ID_FAILED_0; /* Add all the transaction. For simplicity, make these * all the same instrument. */ #define TA_SAFETY_NET_LIMIT 100 i = 0; while( (((void *)test->inputs[i].type) != ((void *)-1)) && (i<TA_SAFETY_NET_LIMIT) ) { retCode = TA_TradeLogAdd( tradeLog, &test->inputs[i] ); if( retCode != TA_SUCCESS ) { printRetCode( retCode ); TA_TradeLogFree( tradeLog ); return TA_PM_TEST_ARRAY_ID_FAILED_1; } i++; } if( i >= TA_SAFETY_NET_LIMIT ) { printf( "Failed: Number of transaction exceed %d limit\n", TA_SAFETY_NET_LIMIT ); return TA_PM_TEST_ARRAY_ID_FAILED_2; } #undef TA_SAFETY_NET_LIMIT /* Build the TA_PM */ retCode = TA_PMAlloc( &test->startDate, &test->endDate, test->initialCapital, &pm ); if( retCode != TA_SUCCESS ) { printRetCode( retCode ); TA_TradeLogFree( tradeLog ); return TA_PM_TEST_ARRAY_ID_FAILED_3; } /* Add the trade log to that PM */ retCode = TA_PMAddTradeLog( pm, tradeLog ); if( retCode != TA_SUCCESS ) { printRetCode( retCode ); return TA_PM_TEST_ARRAY_ID_FAILED_4; } /* Check the requested TA_PMArrayId */ #define TA_SAFETY_NET_LIMIT 30 i=0; while( (((int)test->toCheck[i].id) != -1) && (i<TA_SAFETY_NET_LIMIT) ) { switch( test->toCheck[i].grp ) { case TA_PM_ALL_TRADES: tempStr = "TA_PM_ALL_TRADES"; break; case TA_PM_SHORT_TRADES: tempStr = "TA_PM_SHORT_TRADES"; break; case TA_PM_LONG_TRADES: tempStr = "TA_PM_LONG_TRADES"; break; default: tempStr = "Invalid Group Id"; } retCode = TA_PMArrayAlloc( pm, test->toCheck[i].id, test->toCheck[i].grp, test->toCheck[i].period, &pmArray ); if( (retCode != test->toCheck[i].expectedRetCode) || (pmArray == NULL) ) { printRetCode( test->toCheck[i].expectedRetCode ); printRetCode( retCode ); printf( "Failed: TA_PMArrayAlloc expectedRetCode != retCode (%d != %d)\n", test->toCheck[i].expectedRetCode, retCode ); printf( "Failed: For %d:%s %d:%s Date[%d]\n", test->toCheck[i].id, "", test->toCheck[i].grp, tempStr, (int)test->toCheck[i].date.date ); return TA_PM_TEST_ARRAY_ID_FAILED_5; } if( retCode == TA_SUCCESS ) { /* Find the value to be verified */ for( j=0; j < pmArray->nbData; j++ ) { if( TA_TimestampEqual( &pmArray->timestamp[j], &test->toCheck[i].date ) ) { theValue = pmArray->data[j]; if( !TA_REAL_EQ(theValue,test->toCheck[i].expectedValue,0.01) ) { printf( "Failed: TA_PMArray expectedValue != theValue (%f != %f)\n", test->toCheck[i].expectedValue, theValue ); printf( "Failed: For %d:%s %d:%s, Date[%d]\n", test->toCheck[i].id, "", test->toCheck[i].grp, tempStr, (int)test->toCheck[i].date.date ); return TA_PM_TEST_ARRAY_ID_FAILED_6; } break; } } if( j >= pmArray->nbData ) { printf( "Failed: The expected date [%d] has not been found\n", (int)test->toCheck[i].date.date ); return TA_PM_TEST_ARRAY_WITH_INVALID_DATE; } TA_PMArrayFree( pmArray ); } i++; } if( i >= TA_SAFETY_NET_LIMIT ) { printf( "Failed: Number of checks exceed %d limit\n", TA_SAFETY_NET_LIMIT ); return TA_PM_TEST_ARRAY_ID_FAILED_7; } #undef TA_SAFETY_NET_LIMIT /* Free up everything */ retCode = TA_TradeLogFree( tradeLog ); if( retCode != TA_SUCCESS ) { printRetCode( retCode ); return TA_PM_TEST_ARRAY_ID_FAILED_8; } retCode = TA_PMFree( pm ); if( retCode != TA_SUCCESS ) { printRetCode( retCode ); return TA_PM_TEST_ARRAY_ID_FAILED_9; } return TA_TEST_PASS; }
static ErrorNumber test_valueId( TA_PMValueIdTest *test ) { unsigned int i; TA_TradeLog *tradeLog; TA_PM *pm; ErrorNumber errorNumber; TA_RetCode retCode; TA_Real theValue; const char *tempStr; /* Allocate and build the TA_TradeLog */ retCode = TA_TradeLogAlloc( &tradeLog ); if( retCode != TA_SUCCESS ) return TA_PM_TEST_VALUE_ID_FAILED_0; /* Add all the transaction. For simplicity, make these * all the same instrument. */ #define TA_SAFETY_NET_LIMIT 100 i = 0; while( (((void *)test->inputs[i].type) != ((void *)-1)) && (i<TA_SAFETY_NET_LIMIT) ) { retCode = TA_TradeLogAdd( tradeLog, &test->inputs[i] ); if( retCode != TA_SUCCESS ) { printRetCode( retCode ); TA_TradeLogFree( tradeLog ); return TA_PM_TEST_VALUE_ID_FAILED_1; } i++; } if( i >= TA_SAFETY_NET_LIMIT ) { printf( "Failed: Number of transaction exceed %d limit\n", TA_SAFETY_NET_LIMIT ); return TA_PM_TEST_VALUE_ID_FAILED_2; } #undef TA_SAFETY_NET_LIMIT /* Build the TA_PM */ retCode = TA_PMAlloc( &test->startDate, &test->endDate, test->initialCapital, &pm ); if( retCode != TA_SUCCESS ) { printRetCode( retCode ); TA_TradeLogFree( tradeLog ); return TA_PM_TEST_VALUE_ID_FAILED_3; } /* Add the trade log to that PM */ retCode = TA_PMAddTradeLog( pm, tradeLog ); if( retCode != TA_SUCCESS ) { printRetCode( retCode ); return TA_PM_TEST_VALUE_ID_FAILED_4; } /* Test the report feature. Again just to detect * software hanging/bad pointer. */ errorNumber = test_report( pm, 0 ); if( errorNumber != TA_TEST_PASS ) return errorNumber; /* Check the requested TA_PMArrayId */ #define TA_SAFETY_NET_LIMIT 30 i=0; while( (((int)test->toCheck[i].id) != -1) && (i<TA_SAFETY_NET_LIMIT) ) { switch( test->toCheck[i].grp ) { case TA_PM_ALL_TRADES: tempStr = "TA_PM_ALL_TRADES"; break; case TA_PM_SHORT_TRADES: tempStr = "TA_PM_SHORT_TRADES"; break; case TA_PM_LONG_TRADES: tempStr = "TA_PM_LONG_TRADES"; break; default: tempStr = "Invalid Group Id"; } retCode = TA_PMValue( pm, test->toCheck[i].id, test->toCheck[i].grp, &theValue ); if( retCode != test->toCheck[i].expectedRetCode ) { printRetCode( test->toCheck[i].expectedRetCode ); printRetCode( retCode ); printf( "Failed: TA_PMValue expectedRetCode != retCode (%d != %d)\n", test->toCheck[i].expectedRetCode, retCode ); printf( "Failed: For %d:%s %d:%s\n", test->toCheck[i].id, TA_PMValueIdString(test->toCheck[i].id), test->toCheck[i].grp, tempStr ); return TA_PM_TEST_VALUE_ID_FAILED_5; } if( !TA_REAL_EQ(theValue,test->toCheck[i].expectedValue,0.01) ) { printf( "Failed: TA_PMValue expectedValue != theValue (%f != %f)\n", test->toCheck[i].expectedValue, theValue ); printf( "Failed: For %d:%s %d:%s\n", test->toCheck[i].id, TA_PMValueIdString(test->toCheck[i].id), test->toCheck[i].grp, tempStr ); return TA_PM_TEST_VALUE_ID_FAILED_6; } i++; } if( i >= TA_SAFETY_NET_LIMIT ) { printf( "Failed: Number of checks exceed %d limit\n", TA_SAFETY_NET_LIMIT ); return TA_PM_TEST_VALUE_ID_FAILED_7; } #undef TA_SAFETY_NET_LIMIT /* Check for any potential software hanging/bad pointer. */ errorNumber = checkNoHang( pm ); if( errorNumber != TA_TEST_PASS ) return errorNumber; /* Free up everything */ retCode = TA_TradeLogFree( tradeLog ); if( retCode != TA_SUCCESS ) { printRetCode( retCode ); return TA_PM_TEST_VALUE_ID_FAILED_8; } retCode = TA_PMFree( pm ); if( retCode != TA_SUCCESS ) { printRetCode( retCode ); return TA_PM_TEST_VALUE_ID_FAILED_9; } return TA_TEST_PASS; }
/* This function compares two value. * The value is determined to be equal * if it is within a certain error range. */ static int dataWithinReasonableRange( TA_Real val1, TA_Real val2, unsigned int outputPosition, TA_FuncUnstId unstId, unsigned int integerTolerance ) { TA_Real difference, tolerance, temp; unsigned int val1_int, val2_int, tempInt, periodToIgnore; if( integerTolerance == TA_DO_NOT_COMPARE ) return 1; /* Don't compare, says that everything is fine */ /* If the function does not have an unstable period, * the compared value shall be identical. * * Because the algo may vary slightly allow for * a small epsilon error because of the nature * of floating point operations. */ if( unstId == TA_FUNC_UNST_NONE ) return TA_REAL_EQ( val1, val2, 0.000000001 ); /* In the context of the TA functions, all value * below 0.00001 are considered equal to zero and * are considered to be equal within a reasonable range. * (the percentage difference might be large, but * unsignificant at that level, so no tolerance * check is being done). */ if( (val1 < 0.00001) && (val2 < 0.00001) ) return 1; /* When the function is unstable, the comparison * tolerate at first a large difference. * * As the number of "outputPosition" is higher * the tolerance is reduced. * * In the same way, as the unstable period * increase, the tolerance is reduced (that's * what the unstable period is for... reducing * difference). * * When dealing with an unstable period, the * first 100 values are ignored. * * Following 100, the tolerance is * progressively reduced as follow: * * 1 == 0.5/1 == 50 % * 2 == 0.5/2 == 25 % * ... * 100 == 0.5/100 == 0.005 % * ... * * Overall, the following is a fair estimation: * When using a unstable period of 200, you * can expect the output to not vary more * than 0.005 % * * The logic is sligthly different if the * output are rounded integer, but it is * the same idea. * * The following describe the special meaning of * the integerTolerance: * * Value 10 -> A tolerance of 1/10 is used. * * Value 100 -> A tolerance of 1/100 is used. * * Value 1000 -> A tolerance of 1/1000 is used. * * Value 360 -> Useful when the output are * degrees. In that case, a fix * tolerance of 1 degree is used. * * Value TA_DO_NOT_COMPARE -> * Indicate that NO COMPARISON take * place. This is useful for functions * that cannot be compare when changing * the range (like the accumulative * algorithm used for TA_AD and TA_ADOSC). */ /* Some functions requires a longer unstable period. * These are trap here. */ switch( unstId ) { case TA_FUNC_UNST_T3: periodToIgnore = 200; break; default: periodToIgnore = 100; break; } if( integerTolerance == 1000 ) { /* Check for no difference of more * than 1/1000 */ if( val1 > val2 ) difference = (val1-val2); else difference = (val2-val1); difference *= 1000.0; temp = outputPosition+TA_GetUnstablePeriod(unstId)+1; if( temp <= periodToIgnore ) { /* Pretend it is fine. */ return 1; } else if( (int)difference > 1 ) { printf( "\nFail: Value diffferent by more than 1/1000 (%f)\n", difference ); return 0; } } else if( integerTolerance == 100 ) { /* Check for no difference of more * than 1/1000 */ if( val1 > val2 ) difference = (val1-val2); else difference = (val2-val1); difference *= 100.0; temp = outputPosition+TA_GetUnstablePeriod(unstId)+1; if( temp <= periodToIgnore ) { /* Pretend it is fine. */ return 1; } else if( (int)difference > 1 ) { printf( "\nFail: Value diffferent by more than 1/100 (%f)\n", difference ); return 0; } } else if( integerTolerance == 10 ) { /* Check for no difference of more * than 1/1000 */ if( val1 > val2 ) difference = (val1-val2); else difference = (val2-val1); difference *= 10.0; temp = outputPosition+TA_GetUnstablePeriod(unstId)+1; if( temp <= periodToIgnore ) { /* Pretend it is fine. */ return 1; } else if( (int)difference > 1 ) { printf( "\nFail: Value diffferent by more than 1/10 (%f)\n", difference ); return 0; } } else if( integerTolerance == 360 ) { /* Check for no difference of no more * than 10% when the value is higher than * 1 degree. * * Difference of less than 1 degree are not significant. */ val1_int = (unsigned int)val1; val2_int = (unsigned int)val2; if( val1_int > val2_int ) tempInt = val1_int - val2_int; else tempInt = val2_int - val1_int; if( val1 > val2 ) difference = (val1-val2)/val1; else difference = (val2-val1)/val2; temp = outputPosition+TA_GetUnstablePeriod(unstId)+1; if( temp <= periodToIgnore ) { /* Pretend it is fine. */ return 1; } else if( (tempInt > 1) && (difference > 0.10) ) { printf( "\nFail: Value diffferent by more than 10 percent over 1 degree (%d)\n", tempInt ); return 0; } } else if( integerTolerance ) { /* Check that the integer part of the value * is not different more than the specified * integerTolerance. */ val1_int = (unsigned int)val1; val2_int = (unsigned int)val2; if( val1_int > val2_int ) tempInt = val1_int - val2_int; else tempInt = val2_int - val1_int; temp = outputPosition+TA_GetUnstablePeriod(unstId)+1; if( temp <= periodToIgnore ) { /* Pretend it is fine. */ return 1; } else if( temp < 100 ) { if( tempInt >= 3*integerTolerance ) { printf( "\nFail: Value out of 3*tolerance range (%d,%d)\n", tempInt, integerTolerance ); return 0; /* Value considered different */ } } else if( temp < 150 ) { if( tempInt >= 2*integerTolerance ) { printf( "\nFail: Value out of 2*tolerance range (%d,%d)\n", tempInt, integerTolerance ); return 0; /* Value considered different */ } } else if( temp < 200 ) { if( tempInt >= integerTolerance ) { printf( "\nFail: Value out of tolerance range (%d,%d)\n", tempInt, integerTolerance ); return 0; /* Value considered different */ } } else if( tempInt >= 1 ) { printf( "\nFail: Value not equal (difference is %d)\n", tempInt ); return 0; /* Value considered different */ } } else { if( val1 > val2 ) difference = (val1-val2)/val1; else difference = (val2-val1)/val2; temp = outputPosition+TA_GetUnstablePeriod(unstId)+1; if( temp <= periodToIgnore ) { /* Pretend it is fine. */ return 1; } else { temp -= periodToIgnore; tolerance = 0.5/temp; } if( difference > tolerance ) { printf( "\nFail: Value out of tolerance range (%g,%g)\n", difference, tolerance ); return 0; /* Out of tolerance... values are not equal. */ } } return 1; /* Value equal within tolerance. */ }
ErrorNumber checkExpectedValue( const TA_Real *data, TA_RetCode retCode, TA_RetCode expectedRetCode, unsigned int outBegIdx, unsigned int expectedBegIdx, unsigned int outNbElement, unsigned int expectedNbElement, TA_Real oneOfTheExpectedOutReal, unsigned int oneOfTheExpectedOutRealIndex ) { unsigned int i; if( retCode != expectedRetCode ) { printf( "Fail: RetCode %d different than expected %d\n", retCode, expectedRetCode ); return TA_TESTUTIL_TFRR_BAD_RETCODE; } if( retCode != TA_SUCCESS ) { /* An error did occured, but it * was expected. No need to go * further. */ return TA_TEST_PASS; } if( outNbElement > MAX_NB_TEST_ELEMENT ) { printf( "Fail: outNbElement is out of range 2 (%d)\n", outNbElement ); return TA_TEST_TFRR_NB_ELEMENT_OUT_OF_RANGE; } /* Make sure the range of output does not contains NAN. */ for( i=0; i < outNbElement; i++ ) { if( trio_isnan(data[i]) ) { printf( "Fail: Not a number find within the data (%d,%f)\n", i, data[i] ); return TA_TEST_TFRR_OVERLAP_OR_NAN_3; } } /* Verify that the expected output is there. */ if( outNbElement != expectedNbElement ) { printf( "Fail: outNbElement expected %d but got %d\n", expectedNbElement, outNbElement ); return TA_TESTUTIL_TFRR_BAD_OUTNBELEMENT; } if( expectedNbElement > 0 ) { if( !TA_REAL_EQ( oneOfTheExpectedOutReal, data[oneOfTheExpectedOutRealIndex], 0.01 ) ) { printf( "Fail: For index %d, Expected value = %f but calculate value is %f\n", oneOfTheExpectedOutRealIndex, oneOfTheExpectedOutReal, data[oneOfTheExpectedOutRealIndex] ); return TA_TESTUTIL_TFRR_BAD_CALCULATION; } if( expectedBegIdx != outBegIdx ) { printf( "Fail: outBegIdx expected %d but got %d\n", expectedBegIdx, outBegIdx ); return TA_TESTUTIL_TFRR_BAD_BEGIDX; } } /* Succeed. */ return TA_TEST_PASS; }