示例#1
0
static int findTimestampIndex( const TA_PMPriv *pmPriv,
                               const TA_Timestamp *exitTimestamp,
                               int *idx )
{
   const TA_Timestamp *startDate;
   const TA_Timestamp *endDate;
   TA_DayOfWeek dayOfTheWeek;

   /* Return 0 when no index can be resolved. */
   startDate = &pmPriv->startDate;
   endDate   = &pmPriv->endDate;

   /* Make sure the exitTimestamp is within the start/end date. */ 
   if( (TA_TimestampGreater(exitTimestamp,startDate)&&TA_TimestampLess(exitTimestamp,endDate)) ||
       TA_TimestampEqual(exitTimestamp, startDate) ||
       TA_TimestampEqual(exitTimestamp, endDate) )
   {
      /* Make sure the exitTimestamp is NOT on week-end. Week-end
       * trades are currently ignored.
       */
      dayOfTheWeek = TA_GetDayOfTheWeek( exitTimestamp );
      if( (dayOfTheWeek != TA_SUNDAY) && (dayOfTheWeek != TA_SATURDAY) )
      {
         TA_TimestampDeltaWeekday( startDate, exitTimestamp, (unsigned int *)idx );
         *idx -= 1;

         #ifdef TA_DEBUG
         TA_ASSERT_RET( *idx >= 0, 0 );
         TA_ASSERT_RET( (unsigned int)*idx < pmPriv->nbDailyBars, 0 );             
         TA_ASSERT_RET( TA_TimestampEqual(&pmPriv->arrayTimestamp[*idx], exitTimestamp ), 0 );
         #endif

         return 1;
      }
   }

   /* No index can be found, initialize to zero, just to
    * be safe.
    */
   *idx = 0; 

   return 0;
}
示例#2
0
/* Check if t0 is within the provided [t1..t2] range (inclusive check) */
static unsigned int TA_DateWithinRange( unsigned int year,
                                        unsigned int month,
                                        unsigned int day,
                                        const TA_Timestamp *t1,
                                        const TA_Timestamp *t2 )
{
   TA_Timestamp stamp;
   const TA_Timestamp *lowBorder;
   const TA_Timestamp *highBorder;

   /* Inverse t1 and t2 if not chronilogical order. */
   if( TA_TimestampLess( t2, t1 ) )
   {
      lowBorder = t2;
      highBorder = t1;
   }
   else
   {
      lowBorder = t1;
      highBorder = t2;
   }

   /* Build a timestamp for the date to be check */
   TA_SetDate( year, month, day, &stamp );  

   /* Check if exactly on boundary */
   if( TA_TimestampEqual( &stamp, lowBorder ) && TA_TimestampEqual( &stamp, highBorder ) )
   {
      return 1;
   }

   /* Check if within range. */
   if( TA_TimestampGreater( &stamp, lowBorder ) && TA_TimestampLess( &stamp, highBorder ) )
   {
      return 1;
   }

   return 0; /* Out-of-range */
}
示例#3
0
/**** Global functions definitions.   ****/
TA_RetCode TA_GetHistoryDataFromWeb( TA_Libc *libHandle,
                                     TA_DataSourceHandle *handle,
                                     TA_CategoryHandle   *categoryHandle,
                                     TA_SymbolHandle     *symbolHandle,
                                     TA_Period            period,
                                     const TA_Timestamp  *start,
                                     const TA_Timestamp  *end,
                                     TA_Field             fieldToAlloc,
                                     TA_ParamForAddData  *paramForAddData )
{
   TA_PROLOG;

   TA_RetCode retCode;
   TA_StringCache *stringCache;
   TA_String *yahooName;
   TA_WebPage *webPage;
   TA_PrivateYahooHandle *yahooHandle;
   TA_DecodingParam localDecodingParam;
   const TA_DecodingParam *decodingParam;
   TA_FileHandle *fileHandle;
   TA_ReadOpInfo *readOpInfo;
   UIRSuffixParsing suffixParsing;
   TA_Timestamp firstBarTimestamp, lastBarTimestamp, prevEndDate;
   TA_InfoFromAddedData infoFromAddedData;
   TA_DayOfWeek dayOfWeek;

   int nbEstimateBar;
   int nbField;
   unsigned int nbBarAdded, nbTotalBarAdded;
   int again, firstTime, nbBatch;
   int zeroBarAddedAttempt;

   TA_TRACE_BEGIN( libHandle, TA_GetHistoryDataFromWeb );

   /* Initialize some local variables. */
   stringCache   = TA_GetGlobalStringCache( libHandle );
   yahooHandle   = (TA_PrivateYahooHandle *)handle->opaqueData;
   readOpInfo    = NULL;
   nbEstimateBar = 0;

   TA_ASSERT( libHandle, categoryHandle != NULL );
   TA_ASSERT( libHandle, symbolHandle != NULL );
   TA_ASSERT( libHandle, categoryHandle->string != NULL );
   TA_ASSERT( libHandle, symbolHandle->string != NULL );

   /* Set the initial first/last timestamp */
   if( start )
      TA_TimestampCopy( &firstBarTimestamp, start );
   else
   {
      TA_SetDate( 1950, 1, 1, &firstBarTimestamp );
      TA_SetTime( 0, 0, 0, &firstBarTimestamp );
   }

   if( end )
      TA_TimestampCopy( &lastBarTimestamp, end );
   else
   {
      TA_SetDateNow( &lastBarTimestamp );
      TA_SetTime( 0, 0, 0, &lastBarTimestamp );
   }

   /* Make sure that lastBarTimestamp is a week-day. */
   dayOfWeek = TA_GetDayOfTheWeek( &lastBarTimestamp );
   if( (dayOfWeek == TA_SUNDAY) || (dayOfWeek == TA_SATURDAY) )
      TA_PrevWeekday( &lastBarTimestamp );

   /* Map the TA-Lib name into the Yahoo! name. */
   retCode = TA_AllocStringFromLibName( libHandle,
                                        categoryHandle->string,
                                        symbolHandle->string,
                                        &yahooName );  
   if( retCode != TA_SUCCESS )
   {
      TA_TRACE_RETURN( retCode );
   }

   TA_ASSERT( libHandle, yahooName != NULL );
   TA_ASSERT( libHandle, yahooHandle != NULL );

   /* Get the decoding parameter for the CSV web page. */
   decodingParam = TA_YahooIdxDecodingParam( yahooHandle->index, TA_YAHOOIDX_CVS_PAGE );
   if( !decodingParam )
   {
      TA_StringFree( stringCache, yahooName );
      TA_TRACE_RETURN( TA_INTERNAL_ERROR(103) );
   }

   /* Use a local copy of the decoding param. 
    * This is because the uirSuffix is replaced with
    * an allocated buffer (so the date field can be
    * manipulated).
    */
   localDecodingParam = *decodingParam;

   /* Parse the uirSuffix so the start/end date can be changed. */
   if( !setUIRSuffixParsing( decodingParam->uirSuffix, &suffixParsing ) )
   {
      /* This should never happen unless the
       * Yahoo! index protocol has been broken.
       */
      /* Clean-up and exit */
      TA_StringFree( stringCache, yahooName );
      TA_TRACE_RETURN( TA_INTERNAL_ERROR(104) );
   }

   /* Replace the uirSuffix with a large local buffer. */
   localDecodingParam.uirSuffix = TA_Malloc( libHandle, suffixParsing.maxTotalLength );
   if( !localDecodingParam.uirSuffix )
   {
      /* Clean-up and exit */
      TA_StringFree( stringCache, yahooName );
      TA_TRACE_RETURN( TA_ALLOC_ERR );
   }

   /* Change the dates in the uirSuffix. */
   buildUIRSuffix( &suffixParsing,
                   &firstBarTimestamp, &lastBarTimestamp,
                   (char *)localDecodingParam.uirSuffix );

   /* nbBatch is a safety net to make sure that
    * TA-Lib won't stay forever in the while loop
    * in case Yahoo! changes their protocol.
    */
   nbBatch = 0; 

   /* Sometime Yahoo! return an empty csv file. Make
    * multiple attempts in that case.
    */
   zeroBarAddedAttempt = 0;

   again = 1;
   firstTime = 1;
   nbTotalBarAdded = 0;
   while( again && (++nbBatch < 100) && (zeroBarAddedAttempt < 10) )
   {  
    
      if( TA_TimestampLess(&lastBarTimestamp,&firstBarTimestamp) )
      {
          /* Get out of this loop if all the requested data
           * has been retreived already.
           */
         again = 0;
         break;
      }   

      retCode = TA_WebPageAllocFromYahooName( libHandle,
                                              &localDecodingParam,
                                              TA_StringToChar(yahooName),
                                              &webPage );
           
      if( retCode != TA_SUCCESS )
      {
         TA_StringFree( stringCache, yahooName );
         TA_Free( libHandle, (char *)localDecodingParam.uirSuffix );
         TA_TRACE_RETURN( retCode );
      }

      /* Disguise the webPage stream into a "file". That way the speed
       * optimized ASCII decoder can be re-used (TA_ReadOp stuff).
       */
      retCode = TA_FileSeqOpenFromStream( libHandle, webPage->content, &fileHandle );
      if( retCode != TA_SUCCESS )
      {
         /* Clean-up and exit */
         TA_StringFree( stringCache, yahooName );
         TA_WebPageFree( webPage );
         TA_Free( libHandle, (char *)localDecodingParam.uirSuffix );
         TA_TRACE_RETURN( retCode );
      }

      if( firstTime )
      {
         /* Make assumption of the data provided
          * base on the number of fields in the CSV file.
          */
         nbField = nbCommaField( webPage->content );
         switch( nbField )
         {
         case 2:
            readOpInfo = yahooHandle->readOp2Fields;
            break;
         case 5:
            readOpInfo = yahooHandle->readOp5Fields;
            break;
         default:
            readOpInfo = yahooHandle->readOp6Fields;
         }

         /* User asking for all the fields? */
         if( fieldToAlloc == TA_ALL )
         {
            switch( nbField )
            {
            case 2:
               fieldToAlloc = TA_CLOSE|TA_TIMESTAMP;
               break;
            case 5:
               fieldToAlloc = TA_OPEN|TA_HIGH|TA_LOW|TA_CLOSE|TA_TIMESTAMP;
               break;
            default:
               fieldToAlloc = TA_OPEN|TA_HIGH|TA_LOW|TA_CLOSE|TA_VOLUME|TA_TIMESTAMP;
            }
         }

         /* Optimize the read op for the requested data. */
         retCode = TA_ReadOp_Optimize( libHandle,
                                       readOpInfo,
                                       period,
                                       fieldToAlloc );
         if( retCode != TA_SUCCESS )
         {
            /* Clean-up and exit */
            TA_StringFree( stringCache, yahooName );
            TA_WebPageFree( webPage );
            TA_Free( libHandle, (char *)localDecodingParam.uirSuffix );
            TA_TRACE_RETURN( retCode );
         }

         /* Make an estimation of the number of price bar. */
         nbEstimateBar  = TA_StreamCountChar( webPage->content, '\n' ) + 1;
         if( nbEstimateBar < 100 )
            nbEstimateBar = 100;
      }

      /* Interpret the CSV data. */
      retCode = TA_ReadOp_Do( libHandle, fileHandle,                           
                              readOpInfo,
                              period, &firstBarTimestamp, &lastBarTimestamp,
                              nbEstimateBar, fieldToAlloc,
                              paramForAddData,
                              &nbBarAdded );

      TA_FileSeqClose( libHandle, fileHandle );
      TA_WebPageFree( webPage );

      nbTotalBarAdded += nbBarAdded;

      if( retCode != TA_SUCCESS )
      {
         /* Clean-up and exit */
         TA_StringFree( stringCache, yahooName );
         TA_Free( libHandle, (char *)localDecodingParam.uirSuffix );
         TA_TRACE_RETURN( retCode );
      }

      /* Yahoo! does not always return all the data it could, up to
       * the requested end date. It is important to detect these occurence
       * and cancel the usage of all data accumulated up to now. 
       */      
      TA_GetInfoFromAddedData( paramForAddData, &infoFromAddedData );
      if( infoFromAddedData.barAddedSinceLastCall )
      {
         /* Do some more checking by considering holidays, week-end etc... */
         if( !isGapAcceptable(&infoFromAddedData.highestTimestampAddedSinceLastCall, &lastBarTimestamp) )
         {
            /* Clean-up and exit */
            TA_StringFree( stringCache, yahooName );
            TA_Free( libHandle, (char *)localDecodingParam.uirSuffix );
            TA_TRACE_RETURN( TA_DATA_GAP );
         }
         
         TA_TimestampCopy( &lastBarTimestamp, &infoFromAddedData.lowestTimestamp );
      }

      #if DEBUG_PRINTF
      printf( "NB BAR ADDED=%d, TOTAL=%d\n", nbBarAdded, nbTotalBarAdded );
      #endif

      /* Verify if more data should be processed. 
       * Yahoo! sometimes slice their data, in 
       * batch of 200 price bars. 
       */
      if( firstTime && (nbBarAdded > 200) )
      {
         again = 0; /* Assume all the data extracted... exit the loop. */
      }
      else if( nbBarAdded == 0 )
      {
         /* Make multiple attempts when retreiving data succeed,
          * but somehow there is zero bar returned. 
          *
          * Sometimes this might be correct when there is truly no
          * more data available, so choosing an algorithm before
          * giving up is a comprimise between reliability and
          * usability. The data source is free... and you get
          * what you pay for after all ;)
          */
         if( (nbTotalBarAdded < 1000) && (zeroBarAddedAttempt >= 1) && (zeroBarAddedAttempt < 7) )
         {
            /* I did choose to add a delay when insufficient total data is returned. When
             * there is already ~5 years of data, most likely there is "Zero" returned
             * because there is NO more data available, so just do the retry without delay.
             */
            TA_Sleep(zeroBarAddedAttempt*2);
         }

         #if DEBUG_PRINTF
         printf( "Retry %d", zeroBarAddedAttempt );
         #endif

         zeroBarAddedAttempt++;
      }
      else
      {
         zeroBarAddedAttempt = 0;

         if( TA_TimestampEqual( &lastBarTimestamp, &prevEndDate ) )
         {
            /* prevEndDate is a "safety net" to
             * exit the loop early in case Yahoo! starts
             * to return always the same batch of data.
             * Just ignore the repetitive data and exit.
             */
            TA_Free( libHandle, (char *)localDecodingParam.uirSuffix );
            TA_StringFree( stringCache, yahooName );
            TA_TRACE_RETURN( TA_SUCCESS );
         }
         TA_TimestampCopy( &prevEndDate, &lastBarTimestamp );

         /* Request the data up to the day BEFORE
          * the last batch of data received.
          */
         TA_PrevDay( &lastBarTimestamp );

         /* Make sure that lastBarTimestamp is a week-day. */
         dayOfWeek = TA_GetDayOfTheWeek( &lastBarTimestamp );
         if( (dayOfWeek == TA_SUNDAY) || (dayOfWeek == TA_SATURDAY) )
            TA_PrevWeekday( &lastBarTimestamp );

         /* Change the dates in the uirSuffix. */
         buildUIRSuffix( &suffixParsing,
                         &firstBarTimestamp, &lastBarTimestamp,
                         (char *)localDecodingParam.uirSuffix );

         /* From that point, data is expected to be most likely
          * sent in batch of 200.
          */
         nbEstimateBar = 200;
      }

      firstTime = 0;
   }

   /* Clean-up and exit */
   TA_Free( libHandle, (char *)localDecodingParam.uirSuffix );
   TA_StringFree( stringCache, yahooName );
   TA_TRACE_RETURN( retCode );
}
示例#4
0
static ErrorNumber checkRangeSame( TA_UDBase          *udb,
                                   const TA_History   *historyRef,
                                   const TA_Timestamp *start,
                                   const TA_Timestamp *end,
                                   unsigned int        startIdx,
                                   unsigned int        nbPriceBar )
{
   TA_History *history;
   unsigned int i;
   TA_RetCode retCode;

   #if 1
      /* Do not retry... no forgiveness! */
      retCode = TA_HistoryAlloc( udb, "CA.CDNX.STOCK", "MRY",
                                 TA_DAILY, start, end, TA_ALL,
                                 &history );
   #else
   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++ )
   {
      retCode = TA_HistoryAlloc( udb, "CA.CDNX.STOCK", "MRY",
                                 TA_DAILY, start, end, TA_ALL,
                                 &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 */ );
      }
   }
   #endif

   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;
   }

   /* 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 = %f,%f,%f,%f,%d\n", history->open[i],
                                             history->high[i],         
                                             history->low[i],
                                             history->close[i],
                                             history->volume[i] );
         printf( "Failed: Ref  = %f,%f,%f,%f,%d\n", 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;
}
示例#5
0
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;
}
示例#6
0
static TA_Timestamp *allocTimestampArray( const TA_Timestamp *start,
                                          const TA_Timestamp *end,
                                          int                *nbDays )
{
   TA_RetCode    retCode;
   TA_Timestamp *array;
   int outIdx;
   TA_Timestamp curDate;
   TA_DayOfWeek dayOfTheWeek;

   TA_ASSERT_RET( TA_TimestampValidate(start) == TA_SUCCESS, (TA_Timestamp *)NULL );
   TA_ASSERT_RET( TA_TimestampValidate(end  ) == TA_SUCCESS, (TA_Timestamp *)NULL );
   TA_ASSERT_RET( nbDays != NULL, (TA_Timestamp *)NULL );

   /* Calculate the exact number of week days
    * between start and end inclusive.
    * Excluding week-ends.
    */
   retCode = TA_TimestampDeltaWeekday( start, end, (unsigned int *)nbDays );
   if( retCode != TA_SUCCESS )
      return (TA_Timestamp *)NULL;

   /* Allocate the array. Add two element just to be on the safe side. */
   array = TA_Malloc( sizeof( TA_Timestamp ) * ((*nbDays)+2) );
   if( !array )
      return (TA_Timestamp *)NULL;

   /* Fill up the array. */
   TA_TimestampCopy( &curDate, start );

   /* Write the start point, if it is a weekday. */
   outIdx = 0;
   dayOfTheWeek = TA_GetDayOfTheWeek( &curDate );
   if( (dayOfTheWeek != TA_SUNDAY) && (dayOfTheWeek != TA_SATURDAY) )
   {
      TA_TimestampCopy( &array[outIdx], &curDate );
      outIdx++;
      TA_NextWeekday( &curDate );
      TA_ASSERT_RET( TA_TimestampValidate(&curDate) == TA_SUCCESS, (TA_Timestamp *)NULL );
   }

   /* Count the number of weekday */
   while( TA_TimestampLess( &curDate, end ) )
   {
      TA_TimestampCopy( &array[outIdx], &curDate );
      outIdx++;
      TA_NextWeekday( &curDate );
      TA_ASSERT_RET( TA_TimestampValidate(&curDate) == TA_SUCCESS, (TA_Timestamp *)NULL );
   } 

   /* Check if the ending point is a weekday. */
   if( TA_TimestampEqual( &curDate, end ) )
   {
      dayOfTheWeek = TA_GetDayOfTheWeek( &curDate );
      if( (dayOfTheWeek != TA_SUNDAY) && (dayOfTheWeek != TA_SATURDAY) )
         TA_TimestampCopy( &array[outIdx++], &curDate );
   }

   TA_ASSERT_RET( outIdx == (*nbDays), (TA_Timestamp *)NULL );

   return array;
}
示例#7
0
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;
}