Ejemplo n.º 1
0
TA_RetCode TA_TradeReportAlloc( TA_PM *pm, TA_TradeReport **tradeReportAllocated )
{
    TA_PMPriv          *pmPriv;
    TA_TradeReport     *tradeReport;
    TA_TradeReportPriv *tradeReportPriv;
    TA_List            *tradeLogList;
    TA_TradeLogPriv    *tradeLogPriv;
    TA_AllocatorForDataLog *allocator;
    TA_DataLogBlock    *block;
    TA_List            *listOfBlock;
    TA_DataLog         *invalidDataLog;
    TA_DataLog         *curDataLog;
    TA_Trade           **tradePtr;
    TA_Timestamp       *startDate;
    TA_Timestamp       *endDate;

    TA_RetCode retCode;
    TA_Real tempReal;
    int nbTrade, nbTradeAdded, i;

    if( !tradeReportAllocated )
        return TA_BAD_PARAM;

    *tradeReportAllocated = NULL;

    if( !pm )
        return TA_BAD_PARAM;

    /* Make sure this TA_PM is a valid object */
    pmPriv = (TA_PMPriv *)pm->hiddenData;
    if( !pmPriv || (pmPriv->magicNb != TA_PMPRIV_MAGIC_NB) )
        return TA_BAD_OBJECT;

    tradeReport = TA_Malloc( sizeof( TA_TradeReport ) + sizeof( TA_TradeReportPriv ) );
    if( !tradeReport )
        return TA_ALLOC_ERR;

    memset( tradeReport, 0, sizeof( TA_TradeReport ) + sizeof( TA_TradeReportPriv ) );
    tradeReportPriv = (TA_TradeReportPriv *)(((char *)tradeReport)+sizeof(TA_TradeReport));
    tradeReportPriv->magicNb = TA_TRADEREPORT_MAGIC_NB;
    tradeReport->hiddenData  = tradeReportPriv;

    /* TA_TradeReportFree can be safely called from this point. */

    /* Get the number of closed trades */
    tempReal = 0;
    retCode = TA_PMValue( pm, TA_PM_TOTAL_NB_OF_TRADE, TA_PM_ALL_TRADES, &tempReal );
    if( retCode != TA_SUCCESS )
    {
        TA_TradeReportFree( tradeReport );
        return retCode;
    }
    nbTrade = (unsigned int)tempReal;
    tradeReport->nbTrades = nbTrade;

    if( nbTrade != 0 )
    {
        startDate = &pmPriv->startDate;
        endDate   = &pmPriv->endDate;

        tradePtr = (TA_Trade **)TA_Malloc( nbTrade*sizeof(const TA_Trade *));
        tradeReport->trades = (const TA_Trade **)tradePtr;

        if( !tradePtr )
        {
            TA_TradeReportFree( tradeReport );
            return TA_ALLOC_ERR;
        }

        /* Iterate through all the closed trades. */
        nbTradeAdded = 0;
        tradeLogList = &pmPriv->tradeLogList;
        tradeLogPriv = TA_ListAccessHead( tradeLogList );
        if( !tradeLogPriv )
        {
            TA_TradeReportFree( tradeReport );
            return TA_NO_TRADE_LOG;
        }

        do
        {
            allocator = &tradeLogPriv->allocator;
            listOfBlock = &allocator->listOfDataLogBlock;
            block = TA_ListAccessHead( listOfBlock );
            while( block )
            {
                /* Process each blocks. */
                invalidDataLog = allocator->nextAvailableTrade;
                curDataLog = block->array;
                for( i=0; i < TA_TRADE_BLOCK_SIZE; i++ )
                {
                    if( curDataLog == invalidDataLog )
                    {
                        break;
                    }
                    else
                    {
                        /* Process each TA_DataLog being a trade (not an entry)
                         * An entry have a negative 'quantity'.
                         */
                        if( (curDataLog->u.trade.quantity > 0) &&
                                !TA_TimestampLess( &curDataLog->u.trade.entryTimestamp, startDate ) &&
                                !TA_TimestampGreater( &curDataLog->u.trade.exitTimestamp, endDate ) )
                        {
                            /* Make sure not to exceed array size */
                            if( nbTradeAdded >= nbTrade )
                            {
                                TA_TradeReportFree( tradeReport );
                                return TA_ALLOC_ERR;
                            }
                            tradePtr[nbTradeAdded++] = &curDataLog->u.trade;
                        }
                    }
                    curDataLog++;
                }

                block = TA_ListAccessNext( listOfBlock );
            }

            tradeLogPriv = TA_ListAccessNext( tradeLogList );
        } while( tradeLogPriv );

        /* Make sure all trades were initialized. */
        if( nbTradeAdded != nbTrade )
        {
            TA_TradeReportFree( tradeReport );
            return TA_ALLOC_ERR;
        }

        /* Sort all trades in chronological order of exit. */
        qsort( tradePtr, (size_t)nbTrade, sizeof(TA_Trade *), compareTrade );
    }

    /* All succeed. Return pointer to caller. */
    *tradeReportAllocated = tradeReport;
    return TA_SUCCESS;
}
Ejemplo n.º 2
0
static ErrorNumber checkPMvalues( TA_PM *pm, 
                                  int nbLongTrade,
                                  int nbShortTrade,
                                  TA_Real longNetProfit,
                                  TA_Real shortNetProfit )
{
   TA_RetCode retCode;
   TA_Real pmReadNbShortTrade, pmReadNbLongTrade, pmReadNbTotalTrade;
   TA_Real tempReal1, tempReal2;

   tempReal1 = tempReal2 = 0.0;

   /* Check all the TA_PM_TOTAL_NB_OF_TRADE. */
   retCode = TA_PMValue( pm,
                         TA_PM_TOTAL_NB_OF_TRADE,
                         TA_PM_LONG_TRADES,
                         &pmReadNbLongTrade );
   if( (retCode != TA_SUCCESS) && (retCode != TA_VALUE_NOT_APPLICABLE) )
   {
      printRetCode( retCode );
      printf( "Failed: TA_PMValue (valueId,grpId,retCode,value)=(%d,%d,%d,%g)\n",
               TA_PM_TOTAL_NB_OF_TRADE,
               TA_PM_LONG_TRADES,
               retCode,
               pmReadNbLongTrade );
      return TA_PM_CHECKVALUE_FAILED_0;
   }

   retCode = TA_PMValue( pm,
                         TA_PM_TOTAL_NB_OF_TRADE,
                         TA_PM_SHORT_TRADES,
                         &pmReadNbShortTrade );
   if( (retCode != TA_SUCCESS) && (retCode != TA_VALUE_NOT_APPLICABLE) )
   {
      printRetCode( retCode );
      printf( "Failed: TA_PMValue (valueId,grpId,retCode,value)=(%d,%d,%d,%g)\n",
               TA_PM_TOTAL_NB_OF_TRADE,
               TA_PM_SHORT_TRADES,
               retCode,
               pmReadNbShortTrade );
      return TA_PM_CHECKVALUE_FAILED_1;
   }

   retCode = TA_PMValue( pm,
                         TA_PM_TOTAL_NB_OF_TRADE,
                         TA_PM_ALL_TRADES,
                         &pmReadNbTotalTrade );
   if( (retCode != TA_SUCCESS) && (retCode != TA_VALUE_NOT_APPLICABLE) )
   {
      printRetCode( retCode );
      printf( "Failed: TA_PMValue (valueId,grpId,retCode,value)=(%d,%d,%d,%g)\n",
               TA_PM_TOTAL_NB_OF_TRADE,
               TA_PM_ALL_TRADES,
               retCode,
               pmReadNbTotalTrade );
      return TA_PM_CHECKVALUE_FAILED_2;
   }

   if( ((nbShortTrade+nbLongTrade) != pmReadNbTotalTrade) ||
       (nbShortTrade != pmReadNbShortTrade) ||
       (nbLongTrade != pmReadNbLongTrade) )
   {
      printRetCode( retCode );
      printf( "Failed: invalid nb of trade (short,pmshort,long,pmlong,total,pmtotal)=(%d,%d,%d,%d,%d,%d)\n",
              nbShortTrade, (int)pmReadNbShortTrade,
              nbLongTrade, (int)pmReadNbLongTrade,
              (nbShortTrade+nbLongTrade), (int)pmReadNbTotalTrade );
      return TA_PM_CHECKVALUE_FAILED_3;
   }

   /* Check all the value related to net profits.
    *  shortNetProfit+longNetProfit = (TA_PM_TOTAL_NET_PROFIT, TA_PM_ALL_TRADES)
    *  shortNetProfit               = (TA_PM_TOTAL_NET_PROFIT, TA_PM_SHORT_TRADES)
    *  longNetProfit                = (TA_PM_TOTAL_NET_PROFIT, TA_PM_LONG_TRADES)
    *  shortNetProfit = (TA_PM_PROFIT, TA_PM_SHORT_TRADES)+(TA_PM_LOSS, TA_PM_SHORT_TRADES)
    *  longNetProfit  = (TA_PM_PROFIT, TA_PM_LONG_TRADES)+(TA_PM_LOSS, TA_PM_LONG_TRADES)
    */
   retCode = TA_PMValue( pm,
                         TA_PM_TOTAL_NET_PROFIT,
                         TA_PM_ALL_TRADES,
                         &tempReal1 );
                            
   if( ((retCode != TA_SUCCESS) && (retCode != TA_VALUE_NOT_APPLICABLE)) ||
       (tempReal1 != (shortNetProfit+longNetProfit)) )
   {
      printRetCode( retCode );
      printf( "Failed: TA_PMValue (valueId,grpId,retCode,value,value)=(%d,%d,%d,%g,%g)\n",
               TA_PM_TOTAL_NET_PROFIT,
               TA_PM_ALL_TRADES,
               retCode,
               tempReal1,
               shortNetProfit+longNetProfit );

      return TA_PM_CHECKVALUE_FAILED_4;
   }
   
   retCode = TA_PMValue( pm,
                         TA_PM_TOTAL_NET_PROFIT,
                         TA_PM_LONG_TRADES,
                         &tempReal1 );
   if( ((retCode != TA_SUCCESS) && (retCode != TA_VALUE_NOT_APPLICABLE)) || (tempReal1 != longNetProfit) )
   {
      printRetCode( retCode );
      printf( "Failed: TA_PMValue (valueId,grpId,retCode,value,value)=(%d,%d,%d,%g,%g)\n",
               TA_PM_TOTAL_NET_PROFIT,
               TA_PM_LONG_TRADES,
               retCode,
               tempReal1,
               longNetProfit );

      return TA_PM_CHECKVALUE_FAILED_5;
   }

   retCode = TA_PMValue( pm,
                         TA_PM_TOTAL_NET_PROFIT,
                         TA_PM_SHORT_TRADES,
                         &tempReal2 );
   if( ((retCode != TA_SUCCESS) && (retCode != TA_VALUE_NOT_APPLICABLE)) || (tempReal2 != shortNetProfit) )
   {
      printRetCode( retCode );
      printf( "Failed: TA_PMValue (valueId,grpId,retCode,value,value)=(%d,%d,%d,%g,%g)\n",
               TA_PM_TOTAL_NET_PROFIT,
               TA_PM_SHORT_TRADES,
               retCode,
               tempReal1,
               shortNetProfit );

      return TA_PM_CHECKVALUE_FAILED_6;
   }

   retCode = TA_PMValue( pm,
                         TA_PM_GROSS_PROFIT,
                         TA_PM_SHORT_TRADES,
                         &tempReal1 );
   if( (retCode != TA_SUCCESS) && (retCode != TA_VALUE_NOT_APPLICABLE) )
   {
      printRetCode( retCode );
      printf( "Failed: TA_PMValue (valueId,grpId,retCode,value,value)=(%d,%d,%d,%g,%g)\n",
               TA_PM_GROSS_PROFIT,
               TA_PM_SHORT_TRADES,
               retCode,
               tempReal1,
               tempReal2 );

      return TA_PM_CHECKVALUE_FAILED_7;
   }

   retCode = TA_PMValue( pm,
                         TA_PM_GROSS_LOSS,
                         TA_PM_SHORT_TRADES,
                         &tempReal2 );
   if( ((retCode != TA_SUCCESS) && (retCode != TA_VALUE_NOT_APPLICABLE)) || (shortNetProfit != (tempReal1+tempReal2)))
   {
      printRetCode( retCode );
      printf( "Failed: TA_PMValue (valueId,grpId,retCode,value,value)=(%d,%d,%d,%g,%g,%g)\n",
               TA_PM_GROSS_LOSS,
               TA_PM_SHORT_TRADES,
               retCode,
               tempReal1,
               tempReal2,
               shortNetProfit );

      return TA_PM_CHECKVALUE_FAILED_8;
   }

   retCode = TA_PMValue( pm,
                         TA_PM_GROSS_PROFIT,
                         TA_PM_LONG_TRADES,
                         &tempReal1 );
   if( (retCode != TA_SUCCESS) && (retCode != TA_VALUE_NOT_APPLICABLE) )
   {
      printRetCode( retCode );
      printf( "Failed: TA_PMValue (valueId,grpId,retCode,value,value)=(%d,%d,%d,%g,%g)\n",
               TA_PM_GROSS_PROFIT,
               TA_PM_LONG_TRADES,
               retCode,
               tempReal1,
               tempReal2 );

      return TA_PM_CHECKVALUE_FAILED_9;
   }

   retCode = TA_PMValue( pm,
                         TA_PM_GROSS_LOSS,
                         TA_PM_LONG_TRADES,
                         &tempReal2 );
   if( ((retCode != TA_SUCCESS) && (retCode != TA_VALUE_NOT_APPLICABLE)) || (longNetProfit != (tempReal1+tempReal2)))
   {
      printRetCode( retCode );
      printf( "Failed: TA_PMValue (valueId,grpId,retCode,value,value)=(%d,%d,%d,%g,%g,%g)\n",
               TA_PM_GROSS_LOSS,
               TA_PM_SHORT_TRADES,
               retCode,
               tempReal1,
               tempReal2,
               longNetProfit );

      return TA_PM_CHECKVALUE_FAILED_10;
   }

   return TA_TEST_PASS;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
static ErrorNumber checkNoHang( TA_PM *pm )
{
   int i, j, k;
   TA_Real firstValue, secondValue;
   TA_RetCode retCode;

   /* Call 5 of the value at random. */
   for( k=0; k < 5; k++ )
   {
      i = rand()%TA_PM_NB_VALUEID;
      j = rand()%TA_PM_NB_GROUP;

      firstValue = 1.1111;
      retCode = TA_PMValue( pm, i, j, &firstValue );
      if( (retCode != TA_SUCCESS) && (retCode != TA_VALUE_NOT_APPLICABLE) )
      {
         printRetCode( retCode );
         printf( "checkNoHang rand return error for first call (%d,%d,%d)\n", i, j, retCode );
         return TA_PM_ERR_CHECK_NO_HANG_1;
      }
      secondValue = 2.2222;
      retCode = TA_PMValue( pm, i, j, &secondValue );
      if( (retCode != TA_SUCCESS) && (retCode != TA_VALUE_NOT_APPLICABLE) )
      {
         printRetCode( retCode );
         printf( "checkNoHang rand return error for second call (%d,%d,%d)\n", i, j, retCode );
         return TA_PM_ERR_CHECK_NO_HANG_2;
      }
      if( (retCode != TA_VALUE_NOT_APPLICABLE) && (firstValue != secondValue) )
      {
         printf( "checkNoHang rand values not consistent (%d,%d,%g,%g)\n", i, j, firstValue, secondValue );
         return TA_PM_ERR_CHECK_NO_HANG_3;
      }
   }

   /* Now systematically go through all the possible
    * values.
    *
    * The goal is just to try to break things by possibly
    * causing hanging, bad pointer access or memory leak.
    *
    * The call is done twice. The same value should be
    * always returned.
    */
   for( i=0; i < TA_PM_NB_VALUEID; i++ )
   {
      for( j=0; j < TA_PM_NB_GROUP; j++ )
      {
         firstValue = 3.3333;
         retCode = TA_PMValue( pm, i, j, &firstValue );
         if( (retCode != TA_SUCCESS) && (retCode != TA_VALUE_NOT_APPLICABLE) )
         {
            printRetCode( retCode );
            printf( "checkNoHang return error for first call (%d,%d,%d)\n", i, j, retCode );
            return TA_PM_ERR_CHECK_NO_HANG_4;
         }
         secondValue = 4.4444;
         retCode = TA_PMValue( pm, i, j, &secondValue );
         if( (retCode != TA_SUCCESS) && (retCode != TA_VALUE_NOT_APPLICABLE) )
         {
            printRetCode( retCode );
            printf( "checkNoHang return error for second call (%d,%d,%d)\n", i, j, retCode );
            return TA_PM_ERR_CHECK_NO_HANG_5;
         }
         if( (retCode != TA_VALUE_NOT_APPLICABLE) && (firstValue != secondValue) )
         {
            printf( "checkNoHang values not consistent (%d,%d,%g,%g)\n", i, j, firstValue, secondValue );
            return TA_PM_ERR_CHECK_NO_HANG_6;
         }
      }
   }

   return TA_TEST_PASS;
}
Ejemplo n.º 5
0
/**** Global functions definitions.   ****/
TA_RetCode TA_PMArrayAlloc( TA_PM        *pm,
                            TA_PMArrayId  arrayId,
                            TA_PMGroup    grp,
                            TA_Period     period,
                            TA_PMArray  **allocatedArray )
{
   TA_PMPriv       *pmPriv;
   TA_List         *tradeLogList;
   TA_TradeLogPriv *tradeLogPriv;
   int              timeSerieSize;
   TA_RetCode       retCode;
   TA_PMArray      *newPMArray;
   unsigned int     finalNbBars;
   TA_Real         *finalData;
   TA_Timestamp    *finalTimestamp;

   if( !allocatedArray )
      return TA_BAD_PARAM;

   *allocatedArray = NULL;

   if( !pm || 
       (arrayId >= TA_PM_NB_ARRAYID) ||
       (grp >= TA_PM_NB_GROUP) )
      return TA_BAD_PARAM;

   /* Make sure 'pm' is a ptr on a valid object */
   pmPriv = (TA_PMPriv *)pm->hiddenData; 
   if( pmPriv->magicNb != TA_PMPRIV_MAGIC_NB )
      return TA_BAD_OBJECT;


   #if 0
   /* Get the number of trade that applies to the period.
    * Doing so will also force the update of all
    * "basic calculation" if needed.
    */
   retCode = TA_PMValue( pm, TA_PM_TOTAL_NB_OF_TRADE,
                         TA_PM_ALL_TRADES, &nbTrade );
   if( retCode != TA_SUCCESS )
      return retCode;
   #endif


   /* Because the startDate/endDate are fix in the
    * lifetime of a TA_PM, all the cached time series
    * are allocated once here and freed only when the
    * TA_PM is freed.
    */
   if( !pmPriv->arrayTimestamp )
   {
      /* Allocate the timestamps (excluding week-end)
       * from [startDate..endDate] inclusive.
       * There is only one array of timestamps for all the
       * time series. 
       */
      pmPriv->arrayTimestamp = allocTimestampArray( &pmPriv->startDate,
                                                    &pmPriv->endDate,
                                                    (int *)&pmPriv->nbDailyBars );
      if( !pmPriv->arrayTimestamp )
         return TA_ALLOC_ERR;
   }


   if( !(pmPriv->flags & TA_PMARRAYCACHE_CALCULATED) )
   {
      /* The cached time serie needs to be recalculated
       * from scratch.
       */
      tradeLogList = &pmPriv->tradeLogList;
      tradeLogPriv = TA_ListAccessHead( tradeLogList );
      
      if( !tradeLogPriv )
         return TA_NO_TRADE_LOG;
      else
      {
         /* Make sure all required cached time series are correctly
          * allocated.
          */
         timeSerieSize = sizeof(TA_Real)*pmPriv->nbDailyBars;
         #define TRY_ALLOC_IF_NULL(x) { \
            if( !x ) \
            { \
               x = TA_Malloc( timeSerieSize ); \
               if( !x ) \
                  return TA_ALLOC_ERR; \
            } }

         TRY_ALLOC_IF_NULL( pmPriv->shortArrayCache.investment );
         TRY_ALLOC_IF_NULL( pmPriv->shortArrayCache.profit );
         TRY_ALLOC_IF_NULL( pmPriv->longArrayCache.investment );
         TRY_ALLOC_IF_NULL( pmPriv->longArrayCache.profit );
         #undef TRY_ALLOC_IF_NULL

         /* Reset to zero all the timeseries. */
         memset( pmPriv->shortArrayCache.investment, 0, timeSerieSize );
         memset( pmPriv->shortArrayCache.profit,     0, timeSerieSize );
         memset( pmPriv->longArrayCache.investment,  0, timeSerieSize );
         memset( pmPriv->longArrayCache.profit,      0, timeSerieSize );

         /* Iterate through all the TA_TradeLog */
         do
         {
            if( !(tradeLogPriv->flags & TA_PMARRAYCACHE_CALCULATED) )
               processCache( pmPriv, tradeLogPriv );

            tradeLogPriv = TA_ListAccessNext( tradeLogList );
         } while( tradeLogPriv );
      }

      pmPriv->flags |= TA_PMARRAYCACHE_CALCULATED;
   }
   
   switch( arrayId )
   {
   case TA_PM_ARRAY_EQUITY:
      if( !(pmPriv->flags & TA_EQUITY_CALCULATED) )
      {
         /* Allocate the daily equity. 
          * Keep it cached in "pmPriv->equity".
          */
         retCode = processDailyEquityArray(pmPriv,grp);
         if( retCode != TA_SUCCESS )
            return retCode;
         pmPriv->flags |= TA_EQUITY_CALCULATED;
      }

      /* If requested is not daily, translate to the
       * new period.
       */
      if( period == TA_DAILY )
      {
         finalTimestamp = pmPriv->arrayTimestamp;
         finalData      = pmPriv->equity;
         finalNbBars    = pmPriv->nbDailyBars;
      }
      else
      {
         retCode = equityPeriodTransform( pmPriv, period, &finalNbBars,
                                          &finalTimestamp, &finalData );

         if( retCode != TA_SUCCESS )
            return retCode;
      }
      break;

   /*case TA_PM_ARRAY_RETURNS:
      break;*/

   default:
      return TA_BAD_PARAM;
   }

   TA_ASSERT_RET( pmPriv->arrayTimestamp != NULL, TA_INTERNAL_ERROR(122) );
   TA_ASSERT_RET( pmPriv->equity != NULL, TA_INTERNAL_ERROR(123) );
   TA_ASSERT_RET( finalData != NULL, TA_INTERNAL_ERROR(124) );
   TA_ASSERT_RET( finalTimestamp != NULL, TA_INTERNAL_ERROR(125) );
 
   /* At last, allocate and fill up the TA_PMArray. */
   newPMArray = TA_Malloc( sizeof( TA_PMArray ) );
   if( !newPMArray )
      return TA_ALLOC_ERR;
   newPMArray->arrayId    = arrayId;
   newPMArray->grp        = grp;
   newPMArray->period     = period;
   newPMArray->data       = finalData;
   newPMArray->timestamp  = finalTimestamp;
   newPMArray->nbData     = finalNbBars;
   newPMArray->hiddenData = pm;

   *allocatedArray = newPMArray;
     
   return TA_SUCCESS;
}