static void buildUIRSuffix( const UIRSuffixParsing *parsedString, TA_Timestamp *startTimestamp, TA_Timestamp *endTimestamp, char *output ) { int i; strncpy( output, parsedString->part1, parsedString->part1Length ); i = parsedString->part1Length; sprintf( output, "&a=%02d&b=%02d&c=%04d", TA_GetMonth( startTimestamp )-1, /* Yahoo! month is zero base */ TA_GetDay( startTimestamp ), TA_GetYear( startTimestamp ) ); i += 17; strncpy( &output[i], parsedString->part2, parsedString->part2Length ); i += parsedString->part2Length; sprintf( &output[i], "&d=%02d&e=%02d&f=%04d", TA_GetMonth( endTimestamp )-1, /* Yahoo! month is zero base */ TA_GetDay( endTimestamp ), TA_GetYear( endTimestamp ) ); i += 17; strncpy( &output[i], parsedString->part3, parsedString->part3Length ); i += parsedString->part3Length; output[i] = '\0'; #if DEBUG_PRINTF printf( "New UIR=[%s]\n", output ); #endif }
TA_RetCode TA_ReadOp_Do( TA_FileHandle *fileHandle, const TA_ReadOpInfo *readOpInfo, TA_Period period, const TA_Timestamp *start, const TA_Timestamp *end, unsigned int minimumNbBar, TA_Field fieldToAlloc, TA_ParamForAddData *paramForAddData, unsigned int *nbBarAdded ) { TA_PROLOG TA_RetCode retCode; TA_EstimateInfo estimationInfo; unsigned int nbElementToAllocate; unsigned int memoryNeeded; /* Boolean */ unsigned int timeNeeded; /* Boolean */ TA_Real *arrayReal[TA_REAL_ARRAY_SIZE]; TA_Integer *arrayInteger[TA_INTEGER_ARRAY_SIZE]; TA_Timestamp *timestamp; TA_Real *openBeg, *highBeg, *lowBeg, *closeBeg; TA_Integer *volumeBeg, *openInterestBeg; TA_Timestamp *timestampBeg; TA_Timestamp tmpTimestamp; TA_ReadOp op; TA_Field fieldToProcess; unsigned int year, month, day, hour, min, sec; TA_Integer curOp; unsigned int nbTotalByteDone, nbTotalBarDone; unsigned int nbBarAddedInTheBlock; char monthChar[4]; char cnvtArray[CNVT_ARRAY_SIZE]; unsigned int cnvtArrayIdx; unsigned int nbByteToAllocReal; unsigned int nbByteToAllocInteger; unsigned int fileSize; unsigned int skipField; unsigned int lineToSkip; unsigned int nbByteRead; unsigned int nbLetter; TA_Real lastValidClose; const char *car; register TA_Real tmpReal; register TA_Integer tmpInt; register unsigned int tmpIdx; register unsigned int nbCharToRead; unsigned int lastOpFieldIncremented; TA_TRACE_BEGIN( TA_PriceBarRead ); /* Initialization of local variables. */ openBeg = highBeg = lowBeg = closeBeg = NULL; timestampBeg = NULL; volumeBeg = openInterestBeg = NULL; timestamp = NULL; retCode = TA_SUCCESS; lastValidClose = 0.0; fieldToProcess = readOpInfo->fieldProvided & fieldToAlloc; if( (fieldToProcess & fieldToAlloc) != fieldToAlloc ) { /* Nothing to read because not all the requested * fields are provided by this data source! */ return TA_SUCCESS; } /* Estimate the initial amount of memory to allocate. */ fileSize = TA_FileSize( fileHandle ); retCode = TA_EstimateAllocInit( start, end, period, minimumNbBar, 2048, &estimationInfo, &nbElementToAllocate ); if( retCode != TA_SUCCESS ) { TA_TRACE_RETURN( retCode ); } if( nbElementToAllocate == 0 ) { TA_TRACE_RETURN( TA_SUCCESS ); /* Nothing to read!? Just return... */ } memset( arrayInteger, 0, sizeof( arrayInteger ) ); memset( arrayReal, 0, sizeof( arrayReal ) ); /* Set the date/time pointers to where the information will be stored. */ arrayInteger[TA_HOUR_IDX] = (TA_Integer *)&hour; arrayInteger[TA_MIN_IDX] = (TA_Integer *)&min; arrayInteger[TA_SEC_IDX] = (TA_Integer *)&sec; arrayInteger[TA_MONTH_IDX] = (TA_Integer *)&month; arrayInteger[TA_YEAR_IDX] = (TA_Integer *)&year; arrayInteger[TA_DAY_IDX] = (TA_Integer *)&day; /* Set default time/date. */ year = 1900; month = day = 1; hour = 23; min = sec = 59; /* Check if the processing of the time will be needed. */ timeNeeded = isTimeNeeded( readOpInfo->arrayReadOp); /* 'car' always point to the character being currently handled. */ nbByteRead = 0; car = TA_FileSeqRead( fileHandle, &nbByteRead ); if( (car == NULL) || (nbByteRead == 0) ) return TA_SUCCESS; /* End of file! */ --nbByteRead; nbTotalByteDone = 0; nbTotalBarDone = 0; nbBarAddedInTheBlock = 0; memoryNeeded = 1; curOp = 0; skipField = 0; monthChar[3] = '\0'; /* When requested, skip header lines. */ lineToSkip = readOpInfo->nbHeaderLineToSkip; while( lineToSkip-- ) { while( *car != '\n' ) { GET_CHAR; if( car == NULL ) goto exit_loops; } } line_loop: /* Always jump here when end-of-line is found (EOL). */ /* If curOp != 0, the last operations are canceled. */ REVERT_OPERATIONS; curOp = 0; lastOpFieldIncremented = 0; /* Start over a new line. */ if( memoryNeeded ) { /* Allocate the memory. */ nbByteToAllocReal = nbElementToAllocate * sizeof( TA_Real ); nbByteToAllocInteger = nbElementToAllocate * sizeof( TA_Integer ); timestamp = (TA_Timestamp *)TA_Malloc( nbElementToAllocate * sizeof( TA_Timestamp ) ); timestampBeg = timestamp; if( !timestampBeg ) { retCode = TA_ALLOC_ERR; goto exit_loops; } #define TA_ALLOC_MEM(upperc,lowerc,typepar) \ { \ if( fieldToProcess & TA_##upperc ) \ { \ lowerc##Beg = (TA_##typepar *)TA_Malloc( nbByteToAlloc##typepar ); \ array##typepar[TA_##upperc##_IDX] = lowerc##Beg; \ if( !lowerc##Beg ) \ { \ retCode = TA_ALLOC_ERR; \ goto exit_loops; \ } \ } \ } TA_ALLOC_MEM( OPEN, open, Real ); TA_ALLOC_MEM( HIGH, high, Real ); TA_ALLOC_MEM( LOW, low, Real ); TA_ALLOC_MEM( CLOSE, close, Real ); TA_ALLOC_MEM( VOLUME, volume, Integer ); TA_ALLOC_MEM( OPENINTEREST, openInterest, Integer ); #undef TA_ALLOC_MEM memoryNeeded = 0; } op_loop: /* Jump here when ready to proceed with the next command. */ op = readOpInfo->arrayReadOp[curOp]; if( !(op&TA_CMD_READ_MONTH_CHAR) ) { /* Skip leading non-numeric character. */ SKIP_UNTIL_NUMERIC; } /* Shall we skip this field? */ if( TA_IS_SKIP_SET(op) ) { if( (op&(TA_CMD_READ_REAL|TA_CMD_READ_INTEGER)) == 0 ) { tmpInt = TA_GET_NB_NUMERIC(op); curOp++; while( tmpInt-- ) { GET_CHAR; CHECK_EOL_EOF; } } else { if( skipField == 0 ) { skipField = TA_GET_NB_NUMERIC(op); TA_ASSERT( skipField > 0 ); } if( --skipField == 0 ) curOp++; SKIP_NUMERIC; if( (op&TA_CMD_READ_REAL) && (*car == '.') ) { GET_CHAR; CHECK_EOL_EOF; SKIP_NUMERIC; } } } else { cnvtArrayIdx = 0; if( TA_IS_REAL_CMD(op) ) { /* Extract a numeric into cnvtArray. */ READ_IN_CNVT_ARRAY; /* This is a TA_Real. */ if( car && (*car == '.') ) { /* Read rest of the float after the '.' */ READ_IN_CNVT_ARRAY; } cnvtArray[cnvtArrayIdx] = '\0'; tmpReal = atof( &cnvtArray[0] ); /* Write the TA_Real in memory. */ tmpIdx = TA_GET_IDX(op); TA_ASSERT( tmpIdx < TA_REAL_ARRAY_SIZE ); TA_ASSERT( arrayReal[tmpIdx] != NULL ); if( tmpReal != 0.0 ) { *(arrayReal[tmpIdx]) = tmpReal; if( tmpIdx == TA_CLOSE_IDX ) lastValidClose = tmpReal; } else if( TA_IS_REPLACE_ZERO(op) ) { /* Replace this zero value with the last known close. * If there is no previous close, this line is ignored. */ if( lastValidClose != 0.0 ) *(arrayReal[tmpIdx]) = lastValidClose; else { SKIP_LINE; } } else { /* Zero are not expected, consider this as a failure * and ignore all further data from this file. */ retCode = TA_PRICE_BAR_CONTAINS_ZERO; goto exit_loops; } arrayReal[tmpIdx]++; curOp++; } else { /* This is a TA_Integer. */ if( !(op&TA_CMD_READ_MONTH_CHAR) ) { nbCharToRead = TA_GET_NB_NUMERIC(op); if( nbCharToRead ) { READ_N_CHAR_IN_CNVT_ARRAY(nbCharToRead); } else { READ_IN_CNVT_ARRAY; } cnvtArray[cnvtArrayIdx] = '\0'; tmpInt = atoi( &cnvtArray[0] ); } else { /* Try to find a 3 letters month string. * Translate it to a [1..12] integer. */ nbLetter = 1; do { CHECK_EOL_EOF; monthChar[nbLetter] = (char)toupper(*car); GET_CHAR; nbLetter++; } while( nbLetter != 3 ); do { CHECK_EOL_EOF; monthChar[0] = monthChar[1]; monthChar[1] = monthChar[2]; monthChar[2] = (char)toupper(*car); if( strncmp("JAN",monthChar,3) == 0 ) tmpInt = 1; else if( strncmp("FEB",monthChar,3) == 0 ) tmpInt = 2; else if( strncmp("MAR",monthChar,3) == 0 ) tmpInt = 3; else if( strncmp("APR",monthChar,3) == 0 ) tmpInt = 4; else if( strncmp("MAY",monthChar,3) == 0 ) tmpInt = 5; else if( strncmp("JUN",monthChar,3) == 0 ) tmpInt = 6; else if( strncmp("JUL",monthChar,3) == 0 ) tmpInt = 7; else if( strncmp("AUG",monthChar,3) == 0 ) tmpInt = 8; else if( strncmp("SEP",monthChar,3) == 0 ) tmpInt = 9; else if( strncmp("OCT",monthChar,3) == 0 ) tmpInt = 10; else if( strncmp("NOV",monthChar,3) == 0 ) tmpInt = 11; else if( strncmp("DEC",monthChar,3) == 0 ) tmpInt = 12; else tmpInt = 0; GET_CHAR; } while( tmpInt == 0 ); } /* Write the TA_Integer in memory. */ tmpIdx = TA_GET_IDX(op); TA_ASSERT( tmpIdx < TA_INTEGER_ARRAY_SIZE ); TA_ASSERT( arrayInteger[tmpIdx] != NULL ); *(arrayInteger[tmpIdx]) = tmpInt; if( tmpIdx > TA_YEAR_IDX ) arrayInteger[tmpIdx]++; curOp++; if( TA_IS_TIMESTAMP_COMPLETE(op) ) { /* Build the timestamp. */ retCode = TA_SetDate( year, month, day, &tmpTimestamp ); if( retCode != TA_SUCCESS ) goto exit_loops; /* Invalid date */ if( !timeNeeded ) { /* Ignore time in comparison and use default to build the price bar. */ tmpTimestamp.time = 23595900; /* Default EOD time */ if( start && (tmpTimestamp.date < start->date) ) { /* This price bar is not needed, jump to the next line. */ retCode = TA_SUCCESS; SKIP_LINE; } if( end && (tmpTimestamp.date > end->date) ) { /* This price bar is beyond the upper limit, just exit. */ goto exit_loops; } } else { retCode = TA_SetTime( hour, min, sec, &tmpTimestamp ); if( retCode != TA_SUCCESS ) goto exit_loops; /* Invalid time */ if( start && TA_TimestampLess(&tmpTimestamp,start) ) { /* This price bar is not needed, jump to the next line. */ retCode = TA_SUCCESS; SKIP_LINE; } if( end && TA_TimestampGreater(&tmpTimestamp, end) ) { /* This price bar is beyond the upper limit, just exit. */ goto exit_loops; } } /* Write the timestamp in memory. */ *timestamp = tmpTimestamp; } } if( TA_IS_READ_STOP_FLAG_SET(op) ) { #ifdef DEBUG_PRINTF printf( "(%d%d%d,%e,%e,%e,%e,%d)\n", timestampBeg?TA_GetYear(×tampBeg[nbBarAddedInTheBlock]):0, timestampBeg?TA_GetMonth(×tampBeg[nbBarAddedInTheBlock]):0, timestampBeg?TA_GetDay(×tampBeg[nbBarAddedInTheBlock]):0, openBeg?openBeg[nbBarAddedInTheBlock]:0.0, highBeg?highBeg[nbBarAddedInTheBlock]:0.0, lowBeg?lowBeg[nbBarAddedInTheBlock]:0.0, closeBeg?closeBeg[nbBarAddedInTheBlock]:0.0, volumeBeg?volumeBeg[nbBarAddedInTheBlock]:0 ); #endif /* At this point, the price bar is completely written in memory. */ timestamp++; curOp = 0; nbBarAddedInTheBlock++; if( nbBarAddedInTheBlock < nbElementToAllocate ) { /* Go to next line. */ SKIP_LINE; } else { /* There is not enough memory for another bar, so re-allocate * some more. */ retCode = TA_HistoryAddData( paramForAddData, nbBarAddedInTheBlock, period, timestampBeg, openBeg, highBeg, lowBeg, closeBeg, volumeBeg, openInterestBeg ); /* TA_HistoryAddData is ALWAYS the owner of these memory block * when called. So we set these to NULL to make sure there will * be no attempt to free these from this function. */ openBeg = highBeg = lowBeg = closeBeg = NULL; timestampBeg = NULL; volumeBeg = openInterestBeg = NULL; nbTotalBarDone += nbBarAddedInTheBlock; nbBarAddedInTheBlock = 0; if( retCode != TA_SUCCESS ) goto exit_loops; retCode = TA_EstimateAllocNext( &estimationInfo, &nbElementToAllocate ); if( retCode != TA_SUCCESS ) goto exit_loops; memoryNeeded = 1; SKIP_LINE; } } else { /* Make sure we did not hit an EOL or EOF prematurly, if yes, * this line will be silently ignored. */ CHECK_EOL_EOF; } } goto op_loop; exit_loops: /* Jump here when the end-of-file is hit (or an error occured) */ /* On succesful exit, process possibly remaining data. */ if( (retCode == TA_SUCCESS) && (nbBarAddedInTheBlock != 0) ) { retCode = TA_HistoryAddData( paramForAddData, nbBarAddedInTheBlock, period, timestampBeg, openBeg, highBeg, lowBeg, closeBeg, volumeBeg, openInterestBeg ); openBeg = highBeg = lowBeg = closeBeg = NULL; timestampBeg = NULL; volumeBeg = openInterestBeg = NULL; nbTotalBarDone += nbBarAddedInTheBlock; } /* ALWAYS verify if locally allocated memory needs to be freed. ALWAYS. */ FREE_IF_NOT_NULL( openBeg ); FREE_IF_NOT_NULL( highBeg ); FREE_IF_NOT_NULL( lowBeg ); FREE_IF_NOT_NULL( closeBeg ); FREE_IF_NOT_NULL( volumeBeg ); FREE_IF_NOT_NULL( openInterestBeg ); FREE_IF_NOT_NULL( timestampBeg ); /* An indication that no more data needs to be provided is not a failure. */ if( retCode == TA_ENOUGH_DATA ) retCode = TA_SUCCESS; /* Return the number of added price bar to the caller. */ if( nbBarAdded ) *nbBarAdded = nbTotalBarDone; TA_TRACE_RETURN( retCode ); }
TA_RetCode TA_TradeReportToFile( TA_TradeReport *tradeReport, FILE *out ) { TA_TradeReportPriv *tradeReportPriv; const TA_Timestamp *entryTimestamp; const TA_Timestamp *exitTimestamp; unsigned int i; double tmpReal; if( !tradeReport || !out ) return TA_BAD_PARAM; /* Make sure this TA_TradeReport is a valid object */ tradeReportPriv = (TA_TradeReportPriv *)tradeReport->hiddenData; if( !tradeReportPriv || (tradeReportPriv->magicNb != TA_TRADEREPORT_MAGIC_NB) ) return TA_BAD_OBJECT; fprintf( out, "\n" ); fprintf( out, "[MM/DD/YYYY HH:MM:SS .. MM/DD/YYYY HH:MM:SS] [ID]\n" ); fprintf( out, " Quantity Entry($) Profit(%%) MinFE(%%) MaxFE(%%) MAE(%%)\n" ); fprintf( out, "============================================================\n" ); for( i=0; i < tradeReport->nbTrades; i++ ) { entryTimestamp = &tradeReport->trades[i]->entryTimestamp; exitTimestamp = &tradeReport->trades[i]->exitTimestamp; fprintf( out, "[%02d/%02d/%04d %02d:%02d:%02d .. %02d/%02d/%04d %02d:%02d:%02d] [%s]\n", TA_GetMonth(entryTimestamp), TA_GetDay (entryTimestamp), TA_GetYear (entryTimestamp), TA_GetHour (entryTimestamp), TA_GetMin (entryTimestamp), TA_GetSec (entryTimestamp), TA_GetMonth(exitTimestamp), TA_GetDay (exitTimestamp), TA_GetYear (exitTimestamp), TA_GetHour (exitTimestamp), TA_GetMin (exitTimestamp), TA_GetSec (exitTimestamp), tradeReport->trades[i]->id->symString ); fprintf( out, "%10d", tradeReport->trades[i]->quantity ); fprintf( out, "%10.2f", tradeReport->trades[i]->entryPrice ); fprintf( out, "%10.2f", tradeReport->trades[i]->profit ); tmpReal = tradeReport->trades[i]->minfe; if( tmpReal != TA_REAL_DEFAULT ) fprintf( out, "%10.2f", tmpReal ); else fprintf( out, "%10s", "N/A" ); tmpReal = tradeReport->trades[i]->maxfe; if( tmpReal != TA_REAL_DEFAULT ) fprintf( out, "%10.2f", tmpReal ); else fprintf( out, "%10s", "N/A" ); tmpReal = tradeReport->trades[i]->mae; if( tmpReal != TA_REAL_DEFAULT ) fprintf( out, "%10.2f", tmpReal ); else fprintf( out, "%10s", "N/A" ); fprintf( out, "\n\n" ); } return TA_SUCCESS; }
/**** Local functions definitions. ****/ ErrorNumber test_period( TA_UDBase *unifiedDatabase ) { TA_RetCode retCode; TA_History *history; const TA_Timestamp *timestamp; unsigned int i; ErrorNumber retValue; TA_AddDataSourceParam addParam; TA_HistoryAllocParam histParam; printf( "Testing period/timeframe conversion\n" ); /* Add access to some intra-day data. */ memset( &addParam, 0, sizeof( TA_AddDataSourceParam) ); addParam.id = TA_ASCII_FILE; addParam.location = "..\\src\\tools\\ta_regtest\\sampling\\ES.csv"; addParam.info ="[YY][MM][DD][HH][MN=5][O][H][L][C][V]"; addParam.category = "TA_SIM_REF"; retCode = TA_AddDataSource( unifiedDatabase,&addParam ); if( retCode != TA_SUCCESS ) { printf( "Can't access [%s] (%d)\n", addParam.location, retCode ); return TA_PERIOD_HISTORYALLOC_FAILED; } /* Because period transformation are very * dependend on the "delta" timestamp functions, * let's indepedently verify some of these. */ retValue = testTimestampDelta(); if( retValue != TA_TEST_PASS ) return retValue; /* Verify everything from the checkTable. */ for( i=0; i < CHECK_TABLE_SIZE; i++ ) { /* Validate by requesting all the data in a * different timeframe. */ memset( &histParam, 0, sizeof( TA_HistoryAllocParam ) ); histParam.category = "TA_SIM_REF"; histParam.symbol = checkTable[i].symbol; histParam.field = TA_ALL; histParam.period = checkTable[i].period; histParam.flags = checkTable[i].flags; retCode = TA_HistoryAlloc( unifiedDatabase, &histParam, &history ); if( retCode != TA_SUCCESS ) { printf( "%s%d.1 [%d]\n", fail_header, i, retCode ); return TA_PERIOD_HISTORYALLOC_FAILED; } if( history->nbBars != checkTable[i].nbExpectedPriceBar ) { printf( "%s%d.2 [%d != %d]\n", fail_header, i, history->nbBars, checkTable[i].nbExpectedPriceBar ); TA_HistoryFree( history ); return TA_PERIOD_NBBAR_INCORRECT; } /* If the call is expected to return an empty history, no further check are done. */ if( checkTable[i].nbExpectedPriceBar == 0 ) { retCode = TA_HistoryFree( history ); if( retCode != TA_SUCCESS ) { printf( "%s%d.16 [%d]\n", fail_header, i, retCode ); return TA_PERIOD_HISTORYFREE_FAILED; } continue; } #define CHECK_VALUE_OK(varName, subtestNo ) \ { \ if( !TA_REAL_EQ( history->varName[checkTable[i].thePriceBarToCheck], checkTable[i].expected_##varName, 0.01 ) ) \ { \ printf( "%s%d.%d [%f != %f]\n", \ fail_header, i, subtestNo, \ (TA_Real) history->varName[checkTable[i].thePriceBarToCheck], \ (TA_Real) checkTable[i].expected_##varName ); \ TA_HistoryFree( history ); \ return TA_PERIOD_PRICE_INCORRECT; \ } \ } CHECK_VALUE_OK( open, 3 ); CHECK_VALUE_OK( high, 4 ); CHECK_VALUE_OK( low, 5 ); CHECK_VALUE_OK( close, 6 ); CHECK_VALUE_OK( volume, 7 ); if( history->openInterest != NULL ) { printf( "%s%d.8\n", fail_header, i ); TA_HistoryFree( history ); return TA_PERIOD_OPENINTEREST_INCORRECT; } timestamp = &history->timestamp[checkTable[i].thePriceBarToCheck]; if( TA_GetYear( timestamp ) != checkTable[i].expected_year ) { printf( "%s%d.9 %d\n", fail_header, i, TA_GetYear(timestamp) ); TA_HistoryFree( history ); return TA_PERIOD_TIMESTAMP_YEAR_INCORRECT; } if( TA_GetMonth( timestamp ) != checkTable[i].expected_month ) { printf( "%s%d.10 %d\n", fail_header, i, TA_GetMonth(timestamp) ); TA_HistoryFree( history ); return TA_PERIOD_TIMESTAMP_MONTH_INCORRECT; } if( TA_GetDay( timestamp ) != checkTable[i].expected_day ) { printf( "%s%d.11 %d\n", fail_header, i, TA_GetDay(timestamp) ); TA_HistoryFree( history ); return TA_PERIOD_TIMESTAMP_DAY_INCORRECT; } if( TA_GetHour( timestamp ) != checkTable[i].expected_hour ) { printf( "%s%d.12 %d\n", fail_header, i, TA_GetHour(timestamp) ); TA_HistoryFree( history ); return TA_PERIOD_TIMESTAMP_DAY_INCORRECT; } if( TA_GetMin( timestamp ) != checkTable[i].expected_min ) { printf( "%s%d.13 %d\n", fail_header, i, TA_GetMin(timestamp) ); TA_HistoryFree( history ); return TA_PERIOD_TIMESTAMP_DAY_INCORRECT; } if( TA_GetSec( timestamp ) != checkTable[i].expected_sec ) { printf( "%s%d.14 %d\n", fail_header, i, TA_GetSec(timestamp) ); TA_HistoryFree( history ); return TA_PERIOD_TIMESTAMP_DAY_INCORRECT; } retCode = TA_HistoryFree( history ); if( retCode != TA_SUCCESS ) { printf( "%s%d.15 [%d]\n", fail_header, i, retCode ); return TA_PERIOD_HISTORYFREE_FAILED; } } return 0; /* Succcess. */ }
static ErrorNumber checkRangeSame( TA_UDBase *udb, const TA_History *historyRef, const TA_Timestamp *start, const TA_Timestamp *end, TA_Period period, unsigned int startIdx, unsigned int nbPriceBar ) { TA_History *history; unsigned int i; TA_RetCode retCode; TA_HistoryAllocParam histParam; int retry, again; /* Try up to 10 times to get the requested number of * price bar (sometimes Yahoo! or the Web do fail to * return the data). */ again = 1; for( retry=0; (retry < 10) && again; retry++ ) { memset( &histParam, 0, sizeof( TA_HistoryAllocParam ) ); histParam.category = "CA.TSE.STOCK"; histParam.symbol = "NT"; histParam.field = TA_ALL; histParam.start = *start; histParam.end = *end; histParam.period = period; retCode = TA_HistoryAlloc( udb, &histParam, &history ); if( (retCode == TA_SUCCESS) && (history->nbBars == nbPriceBar) ) again = 0; else { printf( "Warning: Yahoo! history alloc retry #%d of 10\n", retry+1 ); if( retCode == TA_SUCCESS ) { TA_HistoryFree( history ); } TA_Sleep( 10 /* seconds */ ); } } if( retCode != TA_SUCCESS ) { reportError( "TA_HistoryAlloc", retCode ); return TA_YAHOO_CRS_HISTORYALLOC_FAILED; } /* Check that the expected number of price bar is returned. */ if( history->nbBars != nbPriceBar ) { printf( "Failed: nbBars (received != requested)=(%d != %d)\n", history->nbBars, nbPriceBar ); TA_HistoryFree( history ); return TA_YAHOO_CRS_NBBARSBAD; } /* printf( "startIdx=%d\n", startIdx ); */ /* Check that the data is the same for the range. */ for( i=0; i < nbPriceBar; i++ ) { if( !TA_TimestampEqual( &history->timestamp[i], &historyRef->timestamp[startIdx+i] ) || (history->open[i] != historyRef->open[startIdx+i]) || (history->high[i] != historyRef->high[startIdx+i]) || (history->low[i] != historyRef->low[startIdx+i]) || (history->close[i] != historyRef->close[startIdx+i]) || (history->volume[i] != historyRef->volume[startIdx+i]) ) { printf( "Failed: Price Bar value different\n" ); printf( "Failed: Data = %d/%d/%d : %f,%f,%f,%f,%d\n", TA_GetMonth(&history->timestamp[i]), TA_GetDay(&history->timestamp[i]), TA_GetYear(&history->timestamp[i]), history->open[i], history->high[i], history->low[i], history->close[i], history->volume[i] ); printf( "Failed: Ref = %d/%d/%d : %f,%f,%f,%f,%d\n", TA_GetMonth(&historyRef->timestamp[i]), TA_GetDay(&historyRef->timestamp[i]), TA_GetYear(&historyRef->timestamp[i]), historyRef->open[startIdx+i], historyRef->high[startIdx+i], historyRef->low[startIdx+i], historyRef->close[startIdx+i], historyRef->volume[startIdx+i] ); TA_HistoryFree( history ); return TA_YAHOO_CRS_PRICEBARBAD; } } retCode = TA_HistoryFree( history ); if( retCode != TA_SUCCESS ) { reportError( "TA_HistoryFree", retCode ); return TA_YAHOO_HISTORYFREE_FAILED; } return TA_TEST_PASS; }
TA_RetCode TA_EstimateAllocInit( const TA_Timestamp *start, const TA_Timestamp *end, TA_Period period, unsigned int minimumSize, unsigned int maximumSize, TA_EstimateInfo *estimationInfo, unsigned int *nbElementToAllocate ) { unsigned int nbElement; #if 0 /* Force extrems value for testing. */ *nbElementToAllocate = 1; return TA_SUCCESS; #endif nbElement = minimumSize; /* Default */ if( start && end ) { switch( period ) { case TA_DAILY: TA_TimestampDeltaDay( start, end, &nbElement ); break; case TA_WEEKLY: TA_TimestampDeltaWeek( start, end, &nbElement ); break; case TA_MONTHLY: TA_TimestampDeltaMonth( start, end, &nbElement ); break; case TA_QUARTERLY: TA_TimestampDeltaQuarter( start, end, &nbElement ); break; case TA_YEARLY: TA_TimestampDeltaYear( start, end, &nbElement ); break; default: if( (period >= TA_1SEC) && (period <= TA_1HOUR) ) { /* Estimate the number of day */ if( (TA_GetDay (start) != TA_GetDay (end)) || (TA_GetMonth(start) != TA_GetMonth(end)) || (TA_GetYear (start) != TA_GetYear (end)) ) { /* Estimate assuming market is open for 8 hours per day * (it does not hurt to slightly under or over estimate) */ TA_TimestampDeltaDay( start, end, &nbElement ); nbElement *= (8*60*60); nbElement /= period; } else { nbElement = (8*60*60); nbElement /= period; } } break; } nbElement += 2; } /* Make the estimation fits within the max/min provided. */ estimationInfo->maximumSize = maximumSize; estimationInfo->minimumSize = minimumSize; if( nbElement > maximumSize ) nbElement = maximumSize; if( nbElement < minimumSize ) nbElement = minimumSize; *nbElementToAllocate = nbElement; return TA_SUCCESS; }