Exemplo n.º 1
0
static TA_RetCode equityPeriodTransform( TA_PMPriv     *pmPriv,
                                         TA_Period      newPeriod, /* The new desired period. */
                                         unsigned int  *nbBars,    /* Return the number of price bar */
                                         TA_Timestamp **timestamp, /* Allocate new timestamp. */
                                         TA_Real      **equity )   /* Allocate new equity. */
{
   TA_PROLOG

   /* Notice that this function is very similar to the
    * TA_PeriodTransform function in ta_period.c
    *
    * If you find a bug here, may be worth double
    * checking TA_PeriodTransform as well...
    */
   TA_RetCode retCode;

   /* Temporaries. */
   const TA_Timestamp *tempTimestamp;
   unsigned int tempInt, tempInt2;

   /* Variable used to identify period crossing. */
   unsigned int currentWeek, currentMonth, currentYear, currentQuarter;

   /* Pointer on the history being transformed. */
   const TA_Timestamp *old_timestamp;
   const TA_Real      *old_equity;
   TA_Integer          old_nbBars;

   /* Pointer on the transformed data. */
   TA_Timestamp *new_timestamp;    /* New allocated timestamp. */
   TA_Real      *new_equity;       /* New allocated open. */
   TA_Integer    new_nbBars;

   TA_Timestamp  cur_timestamp;    /* Current new timestamp of new period. */
   TA_Real       cur_equity;       /* Current new equity of new period. */

   int oldPriceBar, newPriceBar; /* Array iterators. */
   unsigned int again, periodCompleted; /* Boolean */
   int firstIteration;

   TA_TRACE_BEGIN(  TA_PeriodTransform );

   /* Validate some mandatory parameter. */
   TA_ASSERT( newPeriod != 0 );
   TA_ASSERT( nbBars  != NULL );

   /* It is assume that the caller call this function
    * when there is really a transform to do.
    */
   TA_ASSERT( newPeriod != TA_DAILY );

   /* Of course, timestamps from the source are needed. */
   TA_ASSERT( pmPriv->arrayTimestamp != NULL );

   /* Initialize all callers pointers to NULL.
    * These will be initialize only on success.
    * In the meantime, new_XXXX pointers are
    * going to be used on the new allocated data.
    */
   if( !timestamp || !equity ) 
      return TA_BAD_PARAM;

   *timestamp = NULL;
   *equity    = NULL;
   *nbBars    = 0;

   /* Validate the supported transformation. */

   /* Eliminate all the transform that
    * are currently not supported. 
    * Identify also the major steps
    * needed to perform the transformation.
    */
   switch( newPeriod )
   {
   case TA_WEEKLY:
   case TA_MONTHLY:
   case TA_QUARTERLY:
   case TA_YEARLY:
      /* These are supported. */
      break; 
   default:
      TA_TRACE_RETURN( TA_PERIOD_NOT_AVAILABLE );
   }

   /* OK.. now proceed with the transformations. 
    * The strategy is simple:
    *   The equity for the whole period will be the 
    *   equity at the last daily price bar of 
    *   that period.
    */
   old_timestamp    = &pmPriv->arrayTimestamp[0];
   old_equity       = &pmPriv->equity[0];
   old_nbBars       = pmPriv->nbDailyBars;

   new_timestamp    = NULL;
   newPriceBar      = 0;

   cur_timestamp.date = 0;    /* Current new timestamp of new period. */
   cur_timestamp.time = 0;    /* Current new timestamp of new period. */
   

   /* Overestimate the number of required new price bar. */
   switch( newPeriod )
   {
   case TA_WEEKLY:
      retCode = TA_TimestampDeltaWeek( &old_timestamp[0], &old_timestamp[old_nbBars-1], (unsigned int *)&new_nbBars );
         break;
   case TA_MONTHLY:
      retCode = TA_TimestampDeltaMonth( &old_timestamp[0], &old_timestamp[old_nbBars-1], (unsigned int *)&new_nbBars );
      break;
   case TA_QUARTERLY:
      retCode = TA_TimestampDeltaQuarter( &old_timestamp[0], &old_timestamp[old_nbBars-1], (unsigned int *)&new_nbBars );
      break;
   case TA_YEARLY:
      retCode = TA_TimestampDeltaYear( &old_timestamp[0], &old_timestamp[old_nbBars-1], (unsigned int *)&new_nbBars );
      break;
   default:
      TA_TRACE_RETURN( TA_INTERNAL_ERROR(126) );
   }

   if( retCode != TA_SUCCESS )
   {
      TA_TRACE_RETURN( retCode );
   }

   new_nbBars += 2; /* To be on the safe side */

   /* Allocate the new data. */      
   new_timestamp = TA_Malloc( new_nbBars * sizeof( TA_Timestamp ) );
   if( !new_timestamp )
   {
      TA_TRACE_RETURN( TA_ALLOC_ERR );
   }
   new_equity = TA_Malloc( new_nbBars * sizeof( TA_Real ) );
   if( !new_equity )
   {
      TA_Free(  new_timestamp );
      TA_TRACE_RETURN( TA_ALLOC_ERR );
   }
      
   /* Allows to detect crossing of the new period. */
   currentYear    = TA_GetYear ( &old_timestamp[0] );
   currentMonth   = TA_GetMonth( &old_timestamp[0] );
   currentWeek    = TA_GetWeekOfTheYear( &old_timestamp[0] );
   currentQuarter = TA_GetQuarterOfTheYear( &old_timestamp[0] );

   /* Iterate through the old price bar. */
   oldPriceBar = 0;

   /* Iterate through the new price bar. */
   newPriceBar = 0;

   again = 1; /* Becomes false when all bars are processed. */
   while( again )
   {
      /* Initialize cur_XXXXXX variables with the first bar in old timeframe. */
      cur_timestamp = old_timestamp[oldPriceBar];
      cur_equity    = old_equity   [oldPriceBar];

      /* Go through the bars and accumulate the info
       * until the end of the requested period is reach.
       */
      periodCompleted = 0;
      firstIteration = 1;
      while( (oldPriceBar < old_nbBars) && !periodCompleted )
      {
         tempTimestamp = &old_timestamp[oldPriceBar];

         /* Check if we reached an end of period. */
         switch( newPeriod )
         {
         case TA_WEEKLY:
            tempInt  = TA_GetWeekOfTheYear( tempTimestamp );

            /* Trap weeks on years boundary. */
            if( (currentWeek == 52) && (tempInt == 0) )
               currentWeek = 0;
            else if( currentWeek != tempInt )
            {
               periodCompleted = 1;
               currentWeek = tempInt;
            }
            break;
         case TA_MONTHLY:
            tempInt  = TA_GetMonth( tempTimestamp );
            tempInt2 = TA_GetYear(tempTimestamp);
            if( (currentMonth != tempInt) ||
                (currentYear  != tempInt2) )
            {
               periodCompleted = 1;
               currentMonth    = tempInt;
               currentYear     = tempInt2;
            }
            break;
         case TA_QUARTERLY:
            tempInt = TA_GetQuarterOfTheYear( tempTimestamp );
            tempInt2 = TA_GetYear(tempTimestamp);

            if( (currentQuarter != tempInt) ||
                (currentYear    != tempInt2) )
            {
                  periodCompleted = 1;
                  currentQuarter  = tempInt;
                  currentYear     = tempInt2;
            }
            break;
         case TA_YEARLY:
            tempInt = TA_GetYear( tempTimestamp );
            if( currentYear != tempInt )
            {
               periodCompleted = 1;
               currentYear = tempInt;
            }
            break;
         default:
            /* Do nothing */
            break;
         }

         /* If this is not the end of a period (in the new timeframe)
          * just accumulate the data. If this is the end of the period
          * that while loop will be exited.
          * Nothing is done on the first iteration because all the 
          * cur_XXXX variables have been already initialized.
          */
         if( !periodCompleted )
         {
            if( !firstIteration )
            {
               /* Adjust the new price bar. */
               cur_timestamp = old_timestamp[oldPriceBar];
               cur_equity    = old_equity   [oldPriceBar];
            }
            else
               firstIteration = 0;

            /* Move to next bar. */
            oldPriceBar++;
         }
      }
      /* We got all the info needed in the cur_XXXXX variables for
       * proceeding with the initialization of the new period price bar.
       */
      TA_DEBUG_ASSERT( newPriceBar < new_nbBars );

      /* If the timestamp is requested, some adjustment could be
       * needed to cur_timestamp.
       */
      switch( newPeriod )
      {
      case TA_WEEKLY:
            /* Now something a little bit tricky, we must
             * make sure that this new price bar is reported
             * as being the Friday of that week (even if there 
             * is no price bar for that Friday).
             */
            TA_JumpToDayOfWeek( &cur_timestamp, TA_FRIDAY );
            break;
      case TA_MONTHLY:
            /* Monthly timestamp always end with the last day of
             * the month. Even if there was no actual transaction
             * the last day.
             */
            TA_JumpToEndOfMonth( &cur_timestamp );
            break;
      case TA_QUARTERLY:
            /* Quarterly timestamp always end with the last day of
             * the quarter. Even if there was no actual transaction
             * the last day.
             * Quarter 1 =  3/31
             * Quarter 2 =  6/30
             * Quarter 3 =  9/30
             * Quarter 4 = 12/31
             */
            TA_JumpToEndOfQuarter( &cur_timestamp );
            break;
      case TA_YEARLY:
            /* Yearly data always end on 12/31. */
            TA_JumpToEndOfYear( &cur_timestamp );
            break;
      default:
            /* Do nothing. */
            break;
      }

      /* The new price bar is initialized here. */
      new_timestamp[newPriceBar] = cur_timestamp;
      new_equity   [newPriceBar] = cur_equity;
                     
      /* This new period bar is completed, move to the next one. */
      newPriceBar++;

      /* Any more data to process? */
      if( oldPriceBar >= old_nbBars)
         again = 0; /* All bars have been processsed. */
   }

   /* All done! Return the final result to the caller. */
   *equity    = new_equity;
   *timestamp = new_timestamp;
   *nbBars    = newPriceBar;

   TA_TRACE_RETURN( TA_SUCCESS );
}
Exemplo n.º 2
0
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;
}