unsigned int TA_FileIndexIdentifyFileDepth( TA_FileIndexPriv *data )
{
   TA_List *listLocationToken;
   TA_TokenInfo *info;
   unsigned int latestPathPortionDepth;
   unsigned int currentDepth;

   /* Identify the last portion of the path where
    * the directory path is all resolved.
    *
    * It is imperative that the last token be TA_TOK_END.
    */
   listLocationToken = data->listLocationToken;

   info = TA_ListAccessHead( listLocationToken );
   latestPathPortionDepth = 1;
   currentDepth = 0;
   while( info )
   {
      currentDepth++;

      if( info->id == TA_TOK_END )
         return latestPathPortionDepth;
      if( info->id == TA_TOK_SEP )
         latestPathPortionDepth = currentDepth;

      info = TA_ListAccessNext( listLocationToken );
   }

   /* Should never get here. */
   TA_FATAL_RET( data->libHandle, NULL, currentDepth, latestPathPortionDepth, 0 );
}
Beispiel #2
0
TA_RetCode TA_PMFree( TA_PM *toBeFreed )
{
    TA_PMPriv *pmPriv;
    TA_TradeLogPriv *tradeLogPriv;

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

        /* Clearly mark this object as being unusable. */
        pmPriv->magicNb = 0;

        /* Indicate to all TA_TradeLog that they do
         * no belong to this TA_PM anymore.
         */
        tradeLogPriv = TA_ListAccessHead( &pmPriv->tradeLogList );
        while( tradeLogPriv )
        {
            tradeLogPriv->nbReferenceFromTA_PM--;
            tradeLogPriv = TA_ListAccessNext( &pmPriv->tradeLogList );
        }
        TA_ListFree( &pmPriv->tradeLogList );

        /* Free all the cached arrays. */
        FREE_IF_NOT_NULL( pmPriv->equity );
        FREE_IF_NOT_NULL( pmPriv->arrayTimestamp );

        FREE_IF_NOT_NULL( pmPriv->shortArrayCache.investment );
        FREE_IF_NOT_NULL( pmPriv->shortArrayCache.profit );

        FREE_IF_NOT_NULL( pmPriv->longArrayCache.investment );
        FREE_IF_NOT_NULL( pmPriv->longArrayCache.profit );

        FREE_IF_NOT_NULL( pmPriv->totalArrayCache.investment );
        FREE_IF_NOT_NULL( pmPriv->totalArrayCache.profit );

        /* Last thing that must be freed... */
        TA_Free( toBeFreed );
    }

    return TA_SUCCESS;
}
Beispiel #3
0
TA_RetCode TA_PMAddTradeLog( TA_PM *pm, TA_TradeLog *tradeLogToAdd )
{
    TA_TradeLogPriv *tradeLogPriv;
    TA_TradeLogPriv *tradeLogPrivIter;
    TA_PMPriv *pmPriv;
    TA_RetCode retCode;

    if( !pm || !tradeLogToAdd )
        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;

    /* Make sure this TA_TradeLog is a valid object. */
    tradeLogPriv = (TA_TradeLogPriv *)tradeLogToAdd->hiddenData;
    if( !tradeLogPriv || (tradeLogPriv->magicNb != TA_TRADELOGPRIV_MAGIC_NB) )
        return TA_BAD_OBJECT;

    /* Make sure it was not already added */
    tradeLogPrivIter = TA_ListAccessHead( &pmPriv->tradeLogList );
    while( tradeLogPrivIter )
    {
        if( tradeLogPrivIter == tradeLogPriv )
            return TA_TRADELOG_ALREADY_ADDED;
        tradeLogPrivIter = TA_ListAccessNext( &pmPriv->tradeLogList );
    }

    /* Add it to the list and bump the reference count of the TA_TradeLog */
    retCode = TA_ListAddTail( &pmPriv->tradeLogList, tradeLogPriv );
    if( retCode != TA_SUCCESS )
        return retCode;

    tradeLogPriv->nbReferenceFromTA_PM++;

    /* Invalidate cached calculation. */
    pmPriv->flags &= ~TA_PMVALUECACHE_CALCULATED;

    return TA_SUCCESS;
}
Beispiel #4
0
/**** Global functions definitions.   ****/
TA_RetCode TA_PMValue( TA_PM *pm,
                       TA_PMValueId valueId,
                       TA_PMGroup grp,
                       TA_Real *value )
{
    TA_PMPriv         *pmPriv;
    TA_RetCode         retCode;
    TA_List           *tradeLogList;
    TA_TradeLogPriv   *tradeLogPriv;
    unsigned int tempInt, tempInt2;
    TA_Real tempReal, tempReal2, tempReal3;

    /* Validate parameters. */
    if( !pm || !value )
        return TA_BAD_PARAM;

    if( (valueId >= TA_PM_NB_VALUEID ) ||
            (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 || (pmPriv->magicNb != TA_PMPRIV_MAGIC_NB) )
        return TA_BAD_OBJECT;

    /* Process ALL the basic calculation if not already done. */
    tradeLogList = &pmPriv->tradeLogList;
    tradeLogPriv = TA_ListAccessHead( tradeLogList );

    if( !(pmPriv->flags & TA_PMVALUECACHE_CALCULATED) )
    {
        initValueCache( &pmPriv->longValueCache  );
        initValueCache( &pmPriv->shortValueCache );
        if( !tradeLogPriv )
            return TA_NO_TRADE_LOG;
        else
        {
            do
            {
                if( !(tradeLogPriv->flags & TA_PMVALUECACHE_CALCULATED) )
                {
                    retCode = processTradeLog_BasicCalculation( &pmPriv->startDate,
                              &pmPriv->endDate,
                              tradeLogPriv );
                }

                mergeValueCache( &pmPriv->longValueCache, &tradeLogPriv->longValueCache );
                mergeValueCache( &pmPriv->shortValueCache, &tradeLogPriv->shortValueCache );
                tradeLogPriv = TA_ListAccessNext( tradeLogList );
            } while( tradeLogPriv );
        }
        pmPriv->flags |= TA_PMVALUECACHE_CALCULATED;
    }

    switch( valueId )
    {
    case TA_PM_TOTAL_NB_OF_TRADE:
        switch( grp )
        {
        case TA_PM_ALL_TRADES:
            tempInt  = pmPriv->shortValueCache.nbWinningTrade;
            tempInt += pmPriv->shortValueCache.nbLosingTrade;
            tempInt += pmPriv->longValueCache.nbWinningTrade;
            tempInt += pmPriv->longValueCache.nbLosingTrade;
            break;
        case TA_PM_LONG_TRADES:
            tempInt  = pmPriv->longValueCache.nbWinningTrade;
            tempInt += pmPriv->longValueCache.nbLosingTrade;
            break;
        case TA_PM_SHORT_TRADES:
            tempInt  = pmPriv->shortValueCache.nbWinningTrade;
            tempInt += pmPriv->shortValueCache.nbLosingTrade;
            break;
        default:
            return TA_BAD_PARAM;
        }
        *value = (TA_Real)tempInt;
        break;

    case TA_PM_NB_WINNING_TRADE:
        switch( grp )
        {
        case TA_PM_ALL_TRADES:
            tempInt  = pmPriv->shortValueCache.nbWinningTrade;
            tempInt += pmPriv->longValueCache.nbWinningTrade;
            break;
        case TA_PM_LONG_TRADES:
            tempInt  = pmPriv->longValueCache.nbWinningTrade;
            break;
        case TA_PM_SHORT_TRADES:
            tempInt  = pmPriv->shortValueCache.nbWinningTrade;
            break;
        default:
            return TA_BAD_PARAM;
        }
        *value = (TA_Real)tempInt;
        break;

    case TA_PM_NB_LOSING_TRADE:
        switch( grp )
        {
        case TA_PM_ALL_TRADES:
            tempInt  = pmPriv->shortValueCache.nbLosingTrade;
            tempInt += pmPriv->longValueCache.nbLosingTrade;
            break;
        case TA_PM_LONG_TRADES:
            tempInt  = pmPriv->longValueCache.nbLosingTrade;
            break;
        case TA_PM_SHORT_TRADES:
            tempInt  = pmPriv->shortValueCache.nbLosingTrade;
            break;
        default:
            return TA_BAD_PARAM;
        }
        *value = (TA_Real)tempInt;
        break;

    case TA_PM_TOTAL_NET_PROFIT:
        switch( grp )
        {
        case TA_PM_ALL_TRADES:
            tempInt  = pmPriv->shortValueCache.nbWinningTrade;
            tempInt += pmPriv->shortValueCache.nbLosingTrade;
            tempInt += pmPriv->longValueCache.nbWinningTrade;
            tempInt += pmPriv->longValueCache.nbLosingTrade;
            tempReal  = pmPriv->shortValueCache.sumProfit;
            tempReal += pmPriv->shortValueCache.sumLoss; /* loss are negative */
            tempReal += pmPriv->longValueCache.sumProfit;
            tempReal += pmPriv->longValueCache.sumLoss;
            break;
        case TA_PM_LONG_TRADES:
            tempInt  = pmPriv->longValueCache.nbWinningTrade;
            tempInt += pmPriv->longValueCache.nbLosingTrade;
            tempReal  = pmPriv->longValueCache.sumProfit;
            tempReal += pmPriv->longValueCache.sumLoss;
            break;
        case TA_PM_SHORT_TRADES:
            tempInt  = pmPriv->shortValueCache.nbWinningTrade;
            tempInt += pmPriv->shortValueCache.nbLosingTrade;
            tempReal  = pmPriv->shortValueCache.sumProfit;
            tempReal += pmPriv->shortValueCache.sumLoss;
            break;
        default:
            return TA_BAD_PARAM;
        }
        if( tempInt == 0 )
        {
            *value = 0.0;
            return TA_VALUE_NOT_APPLICABLE;
        }
        else
            *value = tempReal;
        break;

    case TA_PM_STARTING_CAPITAL:
        *value = pmPriv->initialCapital;
        switch( grp )
        {
        case TA_PM_ALL_TRADES:
            break;
        case TA_PM_LONG_TRADES:
        case TA_PM_SHORT_TRADES:
            return TA_VALUE_NOT_APPLICABLE;
        default:
            return TA_BAD_PARAM;
        }
        break;

    case TA_PM_ENDING_CAPITAL:
        tempReal  = pmPriv->shortValueCache.sumProfit;
        tempReal += pmPriv->shortValueCache.sumLoss; /* loss are negative */
        tempReal += pmPriv->longValueCache.sumProfit;
        tempReal += pmPriv->longValueCache.sumLoss;
        *value = pmPriv->initialCapital + tempReal;
        switch( grp )
        {
        case TA_PM_ALL_TRADES:
            break;
        case TA_PM_LONG_TRADES:
        case TA_PM_SHORT_TRADES:
            return TA_VALUE_NOT_APPLICABLE;
        default:
            return TA_BAD_PARAM;
        }
        break;

    case TA_PM_GROSS_PROFIT:
        switch( grp )
        {
        case TA_PM_ALL_TRADES:
            tempInt   = pmPriv->shortValueCache.nbWinningTrade;
            tempInt  += pmPriv->longValueCache.nbWinningTrade;
            tempReal  = pmPriv->shortValueCache.sumProfit;
            tempReal += pmPriv->longValueCache.sumProfit;
            break;
        case TA_PM_LONG_TRADES:
            tempInt  = pmPriv->longValueCache.nbWinningTrade;
            tempReal = pmPriv->longValueCache.sumProfit;
            break;
        case TA_PM_SHORT_TRADES:
            tempInt  = pmPriv->shortValueCache.nbWinningTrade;
            tempReal = pmPriv->shortValueCache.sumProfit;
            break;
        default:
            return TA_BAD_PARAM;
        }

        if( tempInt == 0 )
        {
            *value = 0.0;
            return TA_VALUE_NOT_APPLICABLE;
        }
        else
            *value = tempReal;
        break;

    case TA_PM_GROSS_LOSS:
        /* loss are negative */
        switch( grp )
        {
        case TA_PM_ALL_TRADES:
            tempInt   = pmPriv->shortValueCache.nbLosingTrade;
            tempInt  += pmPriv->longValueCache.nbLosingTrade;
            tempReal  = pmPriv->shortValueCache.sumLoss;
            tempReal += pmPriv->longValueCache.sumLoss;
            break;
        case TA_PM_LONG_TRADES:
            tempInt  = pmPriv->longValueCache.nbLosingTrade;
            tempReal = pmPriv->longValueCache.sumLoss;
            break;
        case TA_PM_SHORT_TRADES:
            tempInt  = pmPriv->shortValueCache.nbLosingTrade;
            tempReal = pmPriv->shortValueCache.sumLoss;
            break;
        default:
            return TA_BAD_PARAM;
        }
        if( tempInt == 0 )
        {
            *value = 0.0;
            return TA_VALUE_NOT_APPLICABLE;
        }
        else
            *value = tempReal;
        break;

    case TA_PM_PROFIT_FACTOR:
        switch( grp )
        {
        case TA_PM_ALL_TRADES:
            tempInt  = pmPriv->shortValueCache.nbWinningTrade;
            tempInt += pmPriv->shortValueCache.nbLosingTrade;
            tempInt += pmPriv->longValueCache.nbWinningTrade;
            tempInt += pmPriv->longValueCache.nbLosingTrade;
            tempReal   = pmPriv->shortValueCache.sumProfit;
            tempReal  += pmPriv->longValueCache.sumProfit;
            tempReal2  = pmPriv->shortValueCache.sumLoss;
            tempReal2 += pmPriv->longValueCache.sumLoss;
            break;
        case TA_PM_LONG_TRADES:
            tempInt  = pmPriv->longValueCache.nbWinningTrade;
            tempInt += pmPriv->longValueCache.nbLosingTrade;
            tempReal   = pmPriv->longValueCache.sumProfit;
            tempReal2  = pmPriv->longValueCache.sumLoss;
            break;
        case TA_PM_SHORT_TRADES:
            tempInt  = pmPriv->shortValueCache.nbWinningTrade;
            tempInt += pmPriv->shortValueCache.nbLosingTrade;
            tempReal   = pmPriv->shortValueCache.sumProfit;
            tempReal2  = pmPriv->shortValueCache.sumLoss;
            break;
        default:
            return TA_BAD_PARAM;
        }
        if( (tempReal2 >= 0.0) || (tempReal <= 0.0) )
        {
            *value = 0.0;
            return TA_VALUE_NOT_APPLICABLE;
        }
        else
            *value = tempReal/(-tempReal2);
        break;

    case TA_PM_AVG_PROFIT:
        switch( grp )
        {
        case TA_PM_ALL_TRADES:
            tempInt   = pmPriv->shortValueCache.nbWinningTrade;
            tempInt  += pmPriv->longValueCache.nbWinningTrade;
            tempReal  = pmPriv->shortValueCache.sumProfit;
            tempReal += pmPriv->longValueCache.sumProfit;
            break;
        case TA_PM_LONG_TRADES:
            tempInt   = pmPriv->longValueCache.nbWinningTrade;
            tempReal  = pmPriv->longValueCache.sumProfit;
            break;
        case TA_PM_SHORT_TRADES:
            tempInt   = pmPriv->shortValueCache.nbWinningTrade;
            tempReal  = pmPriv->shortValueCache.sumProfit;
            break;
        default:
            return TA_BAD_PARAM;
        }
        if( tempInt <= 0 )
        {
            *value = 0.0;
            return TA_VALUE_NOT_APPLICABLE;
        }
        else
            *value = tempReal/((TA_Real)tempInt);
        break;

    case TA_PM_PERCENT_PROFITABLE:

        switch( grp )
        {
        case TA_PM_ALL_TRADES:
            tempInt2  = pmPriv->shortValueCache.nbWinningTrade;
            tempInt2 += pmPriv->longValueCache.nbWinningTrade;
            tempInt   = pmPriv->shortValueCache.nbLosingTrade;
            tempInt  += pmPriv->longValueCache.nbLosingTrade;
            break;
        case TA_PM_LONG_TRADES:
            tempInt2 = pmPriv->longValueCache.nbWinningTrade;
            tempInt  = pmPriv->longValueCache.nbLosingTrade;
            break;
        case TA_PM_SHORT_TRADES:
            tempInt2 = pmPriv->shortValueCache.nbWinningTrade;
            tempInt  = pmPriv->shortValueCache.nbLosingTrade;
            break;
        default:
            return TA_BAD_PARAM;
        }
        if( tempInt == 0 )
        {
            /* No losing trades. */
            if( tempInt2 == 0 )
            {
                /* No trades at all */
                *value = (TA_Real)0.0;
                return TA_VALUE_NOT_APPLICABLE;
            }
            /* All trades are winning trades. */
            *value = (TA_Real)100.0;
        }
        else
        {
            tempInt += tempInt2;
            *value = ((TA_Real)tempInt2)/((TA_Real)tempInt)*100.0;
        }
        break;

    case TA_PM_AVG_PROFIT_PERCENT:
        switch( grp )
        {
        case TA_PM_ALL_TRADES:
            tempInt   = pmPriv->shortValueCache.nbWinningTrade;
            tempInt  += pmPriv->longValueCache.nbWinningTrade;
            tempReal  = pmPriv->shortValueCache.sumProfitPercent;
            tempReal += pmPriv->longValueCache.sumProfitPercent;
            break;
        case TA_PM_LONG_TRADES:
            tempInt   = pmPriv->longValueCache.nbWinningTrade;
            tempReal  = pmPriv->longValueCache.sumProfitPercent;
            break;
        case TA_PM_SHORT_TRADES:
            tempInt   = pmPriv->shortValueCache.nbWinningTrade;
            tempReal  = pmPriv->shortValueCache.sumProfitPercent;
            break;
        default:
            return TA_BAD_PARAM;
        }
        if( tempInt <= 0 )
        {
            *value = 0.0;
            return TA_VALUE_NOT_APPLICABLE;
        }
        else
            *value = (tempReal*100.0)/((TA_Real)tempInt);
        break;

    case TA_PM_AVG_LOSS:
        switch( grp )
        {
        case TA_PM_ALL_TRADES:
            tempInt   = pmPriv->shortValueCache.nbLosingTrade;
            tempInt  += pmPriv->longValueCache.nbLosingTrade;
            tempReal  = pmPriv->shortValueCache.sumLoss;
            tempReal += pmPriv->longValueCache.sumLoss;
            break;
        case TA_PM_LONG_TRADES:
            tempInt   = pmPriv->longValueCache.nbLosingTrade;
            tempReal  = pmPriv->longValueCache.sumLoss;
            break;
        case TA_PM_SHORT_TRADES:
            tempInt   = pmPriv->shortValueCache.nbLosingTrade;
            tempReal  = pmPriv->shortValueCache.sumLoss;
            break;
        default:
            return TA_BAD_PARAM;
        }
        if( tempInt <= 0 )
        {
            *value = 0.0;
            return TA_VALUE_NOT_APPLICABLE;
        }
        else
            *value = tempReal/((TA_Real)tempInt);
        break;

    case TA_PM_AVG_LOSS_PERCENT:
        switch( grp )
        {
        case TA_PM_ALL_TRADES:
            tempInt   = pmPriv->shortValueCache.nbLosingTrade;
            tempInt  += pmPriv->longValueCache.nbLosingTrade;
            tempReal  = pmPriv->shortValueCache.sumLossPercent;
            tempReal += pmPriv->longValueCache.sumLossPercent;
            break;
        case TA_PM_LONG_TRADES:
            tempInt   = pmPriv->longValueCache.nbLosingTrade;
            tempReal  = pmPriv->longValueCache.sumLossPercent;
            break;
        case TA_PM_SHORT_TRADES:
            tempInt   = pmPriv->shortValueCache.nbLosingTrade;
            tempReal  = pmPriv->shortValueCache.sumLossPercent;
            break;
        default:
            return TA_BAD_PARAM;
        }
        if( tempInt <= 0 )
        {
            *value = 0.0;
            return TA_VALUE_NOT_APPLICABLE;
        }
        else
            *value = (tempReal*100.0)/((TA_Real)tempInt);
        break;

    case TA_PM_LARGEST_PROFIT:
        switch( grp )
        {
        case TA_PM_ALL_TRADES:
            tempReal = MAX( pmPriv->shortValueCache.largestProfit,
                            pmPriv->longValueCache.largestProfit );
            break;
        case TA_PM_LONG_TRADES:
            tempReal = pmPriv->longValueCache.largestProfit;
            break;
        case TA_PM_SHORT_TRADES:
            tempReal = pmPriv->shortValueCache.largestProfit;
            break;
        default:
            return TA_BAD_PARAM;
        }
        if( tempReal == TA_REAL_MIN )
        {
            *value = 0.0;
            return TA_VALUE_NOT_APPLICABLE;
        }
        else
            *value = tempReal;
        break;

    case TA_PM_LARGEST_LOSS:
        switch( grp )
        {
        case TA_PM_ALL_TRADES:
            tempReal = MIN( pmPriv->shortValueCache.largestLoss,
                            pmPriv->longValueCache.largestLoss );
            break;
        case TA_PM_LONG_TRADES:
            tempReal = pmPriv->longValueCache.largestLoss;
            break;
        case TA_PM_SHORT_TRADES:
            tempReal = pmPriv->shortValueCache.largestLoss;
            break;
        default:
            return TA_BAD_PARAM;
        }

        if( tempReal == TA_REAL_MAX )
        {
            *value = 0.0;
            return TA_VALUE_NOT_APPLICABLE;
        }
        else
            *value = tempReal;
        break;

    case TA_PM_LARGEST_PROFIT_PERCENT:
        switch( grp )
        {
        case TA_PM_ALL_TRADES:
            tempReal = MAX( pmPriv->shortValueCache.largestProfitPercent,
                            pmPriv->longValueCache.largestProfitPercent );
            break;
        case TA_PM_LONG_TRADES:
            tempReal = pmPriv->longValueCache.largestProfitPercent;
            break;
        case TA_PM_SHORT_TRADES:
            tempReal = pmPriv->shortValueCache.largestProfitPercent;
            break;
        default:
            return TA_BAD_PARAM;
        }
        if( tempReal == TA_REAL_MIN )
        {
            *value = 0.0;
            return TA_VALUE_NOT_APPLICABLE;
        }
        else
            *value = tempReal*100.0;
        break;

    case TA_PM_LARGEST_LOSS_PERCENT:
        switch( grp )
        {
        case TA_PM_ALL_TRADES:
            tempReal = MIN( pmPriv->shortValueCache.largestLossPercent,
                            pmPriv->longValueCache.largestLossPercent );
            break;
        case TA_PM_LONG_TRADES:
            tempReal = pmPriv->longValueCache.largestLossPercent;
            break;
        case TA_PM_SHORT_TRADES:
            tempReal = pmPriv->shortValueCache.largestLossPercent;
            break;
        default:
            return TA_BAD_PARAM;
        }

        if( tempReal == TA_REAL_MAX )
        {
            *value = 0.0;
            return TA_VALUE_NOT_APPLICABLE;
        }
        else
            *value = tempReal*100.0;
        break;

    case TA_PM_RATE_OF_RETURN:
        /* One-period rate of return: (profit / initialCapital) */
        tempReal3 = pmPriv->initialCapital;
        if( tempReal3 <= 0.0 )
        {
            *value = 0.0;
            return TA_BAD_STARTING_CAPITAL;
        }

        switch( grp )
        {
        case TA_PM_ALL_TRADES:
            tempReal   = pmPriv->shortValueCache.sumProfit;
            tempReal  += pmPriv->longValueCache.sumProfit;
            tempReal2  = pmPriv->shortValueCache.sumLoss; /* loss are negative */
            tempReal2 += pmPriv->longValueCache.sumLoss;
            break;
        case TA_PM_LONG_TRADES:
            tempReal  = pmPriv->longValueCache.sumProfit;
            tempReal2 = pmPriv->longValueCache.sumLoss;
            break;
        case TA_PM_SHORT_TRADES:
            tempReal  = pmPriv->shortValueCache.sumProfit;
            tempReal2 = pmPriv->shortValueCache.sumLoss;
            break;
        default:
            return TA_BAD_PARAM;
        }
        if( (tempReal <= 0.0) && (tempReal2 >= 0.0) )
        {
            *value = 0.0;
            return TA_VALUE_NOT_APPLICABLE;
        }
        else
            *value = ((tempReal+tempReal2)/tempReal3)*100.0;
        break;

    case TA_PM_ANNUALIZED_RETURN:
        /* Annualized rate of return on a simple-interest basis:
         *
         *   (Ending Value - Starting Value)     365
         *   -------------------------------  *  ---
         *           Starting Value               n
         *
         * Where 'n' is the number of day between the end and
         * start date when the TA_PM was created.
         */
        tempReal3 = pmPriv->initialCapital;
        if( tempReal3 <= 0.0 )
        {
            *value = 0.0;
            return TA_BAD_STARTING_CAPITAL;
        }

        switch( grp )
        {
        case TA_PM_ALL_TRADES:
            tempReal   = pmPriv->shortValueCache.sumProfit;
            tempReal  += pmPriv->longValueCache.sumProfit;
            tempReal2  = pmPriv->shortValueCache.sumLoss; /* loss are negative */
            tempReal2 += pmPriv->longValueCache.sumLoss;
            break;
        case TA_PM_LONG_TRADES:
            tempReal  = pmPriv->longValueCache.sumProfit;
            tempReal2 = pmPriv->longValueCache.sumLoss;
            break;
        case TA_PM_SHORT_TRADES:
            tempReal  = pmPriv->shortValueCache.sumProfit;
            tempReal2 = pmPriv->shortValueCache.sumLoss;
            break;
        default:
            return TA_BAD_PARAM;
        }

        retCode = TA_TimestampDeltaDay( &pmPriv->startDate,
                                        &pmPriv->endDate,
                                        &tempInt );
        if( retCode != TA_SUCCESS )
            return retCode;

        if( ((tempReal <= 0.0) && (tempReal2 >= 0.0)) || (tempInt == 0) )
        {
            *value = 0.0;
            return TA_VALUE_NOT_APPLICABLE;
        }
        else
        {
            tempReal += tempReal2;
            *value = (tempReal/tempReal3)*(36500.0/tempInt);
        }
        break;

    case TA_PM_ANNUALIZED_COMPOUNDED_RETURN:
        /* Annualized compounded rate of return:
         *
         * ((Ending Value / Starting Value)^(1/y)) - 1
         *
         * Where 'y' is the number of year between the end
         * and start date when the TA_PM was created.
         */
        tempReal3 = pmPriv->initialCapital;
        if( tempReal3 <= 0.0 )
        {
            *value = 0.0;
            return TA_BAD_STARTING_CAPITAL;
        }

        switch( grp )
        {
        case TA_PM_ALL_TRADES:
            tempReal   = pmPriv->shortValueCache.sumProfit;
            tempReal  += pmPriv->longValueCache.sumProfit;
            tempReal2  = pmPriv->shortValueCache.sumLoss; /* loss are negative */
            tempReal2 += pmPriv->longValueCache.sumLoss;
            break;
        case TA_PM_LONG_TRADES:
            tempReal  = pmPriv->longValueCache.sumProfit;
            tempReal2 = pmPriv->longValueCache.sumLoss;
            break;
        case TA_PM_SHORT_TRADES:
            tempReal  = pmPriv->shortValueCache.sumProfit;
            tempReal2 = pmPriv->shortValueCache.sumLoss;
            break;
        default:
            return TA_BAD_PARAM;
        }

        retCode = TA_TimestampDeltaDay( &pmPriv->startDate,
                                        &pmPriv->endDate,
                                        &tempInt );
        if( retCode != TA_SUCCESS )
            return retCode;

        if( ((tempReal <= 0.0) && (tempReal2 >= 0.0)) || (tempInt == 0) )
        {
            *value = 0.0;
            return TA_VALUE_NOT_APPLICABLE;
        }
        else
        {
            tempReal += (tempReal2+tempReal3);
            *value = (pow(tempReal/tempReal3,1.0/(tempInt/365.0)) - 1.0)*100.0;
        }
        break;

    default:
        return TA_INVALID_VALUE_ID;
    }

    return TA_SUCCESS;
}
Beispiel #5
0
/* Perform the very first level of calculation among all
 * the trades allocated.
 *
 * Note: A trade is a TA_DataLog with the quantity > 0
 */
static TA_RetCode processTradeLog_BasicCalculation( TA_Timestamp *startDate,
        TA_Timestamp *endDate,
        TA_TradeLogPriv *tradeLog )
{
    TA_AllocatorForDataLog *allocator;
    TA_DataLogBlock *block;
    TA_List *list;
    TA_DataLog *invalidDataLog, *curDataLog;
    int i;

    TA_PMValueCache *shortValueCache, *longValueCache;

    /* Temporary values for calculation. */
    register TA_Real tempReal1, tempReal2, tempReal3;
    register int tempInt1;

    /* The following variables are all the
     * accumulators.
     *
     * Some are suggested to be kept in
     * registers, most of the others will
     * be maintain within the local TA_PMValueCache.
     *
     * All these value are then merge within the
     * tradeLog at the very end.
     */
    register int     long_nbLosingTrade;
    register int     short_nbLosingTrade;
    register int     long_nbWinningTrade;
    register int     short_nbWinningTrade;
    TA_PMValueCache  shortV, longV;

    /* Initialize all accumulators. */
    initValueCache( &shortV );
    initValueCache( &longV );

    long_nbLosingTrade    =
        short_nbLosingTrade   =
            long_nbWinningTrade   =
                short_nbWinningTrade  = 0;

    /* Simply iterate through all the TA_TradeLog
     * and update the accumulators.
     */
    allocator = &tradeLog->allocator;
    if( allocator )
    {
        list = &allocator->listOfDataLogBlock;
        block = TA_ListAccessHead( list );
        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'.
                     */
                    tempInt1 = curDataLog->u.trade.quantity;
                    if( (tempInt1 > 0) &&
                            !TA_TimestampLess( &curDataLog->u.trade.entryTimestamp, startDate ) &&
                            !TA_TimestampGreater( &curDataLog->u.trade.exitTimestamp, endDate ) )
                    {
                        tempReal1 = curDataLog->u.trade.entryPrice; /* Positive = long, negative = short */
                        tempReal2 = curDataLog->u.trade.profit; /* Positive = winning, negative = losing */
                        if( tempReal1 > 0.0 )
                        {
                            /* This is a long trade. */
                            if( tempReal2 > 0.0 )
                            {
                                /* This is a winning long trade */
                                longV.sumInvestmentProfit += tempReal1;
                                longV.sumProfit += tempReal2;
                                TA_SET_MAX(longV.largestProfit, tempReal2 );
                                tempReal1 = tempReal2/tempReal1;
                                TA_SET_MAX(longV.largestProfitPercent, tempReal1 );
                                longV.sumProfitPercent += tempReal1;
                                long_nbWinningTrade++;
                            }
                            else
                            {
                                /* This is a losing long trade */
                                longV.sumInvestmentLoss += tempReal1;
                                longV.sumLoss += tempReal2;
                                TA_SET_MIN(longV.largestLoss, tempReal2 );
                                tempReal1 = tempReal2/tempReal1;
                                TA_SET_MIN(longV.largestLossPercent, tempReal1 );
                                longV.sumLossPercent += tempReal1;
                                long_nbLosingTrade++;
                            }
                        }
                        else
                        {
                            /* This is a short trade. */
                            if( tempReal2 > 0.0 )
                            {
                                /* This is a winning short trade */
                                tempReal1 = -tempReal1;
                                shortV.sumInvestmentProfit += tempReal1;
                                shortV.sumProfit += tempReal2;
                                TA_SET_MAX(shortV.largestProfit, tempReal2 );
                                tempReal1 = tempReal2/tempReal1;
                                TA_SET_MAX(shortV.largestProfitPercent, tempReal1 );
                                shortV.sumProfitPercent += tempReal1;
                                short_nbWinningTrade++;
                            }
                            else
                            {
                                /* This is a losing short trade */
                                tempReal1 = -tempReal1;
                                shortV.sumInvestmentLoss += tempReal1;
                                shortV.sumLoss += tempReal2;
                                TA_SET_MIN(shortV.largestLoss, tempReal2 );
                                tempReal1 = tempReal2/tempReal1;
                                TA_SET_MIN(shortV.largestLossPercent, tempReal1 );
                                shortV.sumLossPercent += tempReal1;
                                short_nbLosingTrade++;
                            }
                        }
                    }
                }
                curDataLog++;
            }
            block = TA_ListAccessNext( list );
        }
    }

    /* Initialize the output with the accumulated results. */
    shortValueCache  = &tradeLog->shortValueCache;
    longValueCache   = &tradeLog->longValueCache;
    *shortValueCache = shortV;
    *longValueCache  = longV;

    shortValueCache->nbLosingTrade = short_nbLosingTrade;
    shortValueCache->nbWinningTrade = short_nbWinningTrade;
    longValueCache->nbLosingTrade = long_nbLosingTrade;
    longValueCache->nbWinningTrade = long_nbWinningTrade;

    /* Indicate that the value are now calculated and set
     * in the "cache".
     */
    tradeLog->flags |= TA_PMVALUECACHE_CALCULATED;
    return TA_SUCCESS;
}
Beispiel #6
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;
}
Beispiel #7
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;
}
Beispiel #8
0
/* Build the investment/profit time series.
 *
 * Note: A trade is a TA_DataLog with the quantity > 0
 */
static TA_RetCode processCache( TA_PMPriv *pmPriv, TA_TradeLogPriv *tradeLog )
{
   TA_AllocatorForDataLog *allocator;
   TA_DataLogBlock *block;
   TA_List *list;
   TA_DataLog *invalidDataLog, *curDataLog;
   int i, idx;

   TA_Timestamp     *exitTimestamp;
 
   /* Temporary values for calculation. */
   register TA_Real tempReal1, tempReal2;
   register int tempInt1;

   /* Simply iterate through all the 
    * TA_DataLogBlock and update the cached.
    */
   allocator = &tradeLog->allocator;
   if( allocator )
   {
      list = &allocator->listOfDataLogBlock;
      block = TA_ListAccessHead( list );
      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'.
                */
               tempInt1 = curDataLog->u.trade.quantity;
               if( tempInt1 > 0 )
               {
                  /* This is a trade. Consider only the trades that are
                   * closed within the TA_PM start/end period.
                   */
                  exitTimestamp = &curDataLog->u.trade.exitTimestamp;
                  if( findTimestampIndex( pmPriv, exitTimestamp, &idx ) )
                  {                   
                     tempReal1 = curDataLog->u.trade.entryPrice; /* Positive = long, negative = short */
                     tempReal2 = curDataLog->u.trade.profit; /* Positive = winning, negative = losing */
                     if( tempReal1 > 0.0 )
                     {
                        /* This is a long trade. */            
                        pmPriv->longArrayCache.investment[idx] += tempReal1;
                        pmPriv->longArrayCache.profit[idx] += tempReal2;
                     }
                     else
                     {
                        /* This is a short trade. */            
                        pmPriv->shortArrayCache.investment[idx] -= tempReal1;
                        pmPriv->shortArrayCache.profit[idx] += tempReal2;
                     }
                  }
               }
            }
            curDataLog++;
         }
         block = TA_ListAccessNext( list );
      }
   }

   return TA_SUCCESS;
}
TA_RetCode TA_FileIndexMoveToNextToken( TA_FileIndexPriv *data )
{
   TA_PROLOG;
   TA_Libc *libHandle;

   if( !data )
      return TA_UNKNOWN_ERR;


   libHandle = data->libHandle;
   TA_TRACE_BEGIN( libHandle, TA_FileIndexMoveToNextToken );

   if( data->curToken == NULL )
   {
      /* First time this function get called for this 'data' */
      data->curTokenDepth = 0;
      data->curDirectionForward = 1;
      data->curToken = (TA_TokenInfo *)TA_ListAccessHead( data->listLocationToken );
      data->prevToken = NULL;
      data->nextToken = (TA_TokenInfo *)TA_ListAccessNext( data->listLocationToken );

      if( !data->curToken || !data->nextToken )
      {
         TA_FATAL( data->libHandle, NULL, data->curToken, data->nextToken );
      }
   }
   else if( data->nextToken == NULL )
   {
      /* Can't go further, simply return. */
      TA_TRACE_RETURN( TA_SUCCESS );
   }
   else
   {
      if( data->curDirectionForward == 0 )
      {
         if( data->prevToken != NULL )
            TA_ListAccessNext( data->listLocationToken );
         else
            TA_ListAccessHead( data->listLocationToken );

         TA_ListAccessNext( data->listLocationToken );
         data->curDirectionForward = 1;
      }

      data->prevToken = data->curToken;
      data->curToken = data->nextToken;
      data->nextToken = (TA_TokenInfo *)TA_ListAccessNext( data->listLocationToken );

      /* Parano test: Should never happen since the code assume that
       * the 'listLocationToken' is always terminated by TA_END.
       */
      if( !data->curToken )
      {
         TA_FATAL( data->libHandle, NULL, data->curToken->id, data->curTokenDepth );
      }
   }

   data->curTokenDepth++;

   TA_TRACE_RETURN( TA_SUCCESS );
}