Problem to achieve table profit to csv

I'm trying to run this explorer to get the profit table in csv but I don't know why it's not getting the data right. I don't understand where is the problem.

/*
   MonthlyTable_01.afl

   Exploration code to produce a month-by-month tabular presentation of percentage changes
   in a value.

   In this code the value is designated as "eq" (for equity), but is simply set to the 
   price Close for demonstration purposes.
   
   Original code provided by "Mike", here:

      http://finance.groups.yahoo.com/group/amibroker/message/125846

   Extra comments, _TRACE, and some changes by Progster

*/

//   Calculation of the value for which the tabular display of %Chg is desired.
//   Change this to whatever calculation you wish.
eq = Close;

//   Make the year and month available (in arrays) for every bar processed
yr = Year();      //   e.g. 2008
mo = Month();      //   i.e. 1 - 12

//   Create arrays marking new years and new months
YearChange = yr != Ref( yr, -1 );         //   TRUE on first bar of new year
MonChange = mo != Ref( mo, -1 );         //   TRUE on first bar of new month

FirstYr = 0;
LastYr = 0;

startbar = 0;
endbar = 0;

FirstBar = Status("firstbarinrange");
LastBar = Status("lastbarinrange");

////////////////////////////
// SKIP non-trading bars
////////////////////////////
for ( i = 0; i < BarCount; i++ )
{
    if ( FirstBar[ i ] )
    {
        startbar = i;         //   save the bar index of the first bar in the analysis range
    }

    if ( LastBar[ i ] )
    {
        endbar = i;            //   save the bar index of the last bar in the analysis range
        break;
    }
}

////////////////////////////
// collect yearly / monthly changes in symbol
// into dynamic variables
////////////////////////////

//   Initialize tracking variables
LastYrValue = eq[ startbar ];         //   note: initial equity was set to Close, above
LastMoValue = eq[ startbar ];

MaxYrProfit = MinYrProfit = 0;
MaxMoProfit = MinMoProfit = 0;

//   Loop the analysis range (only)
for ( i = startbar + 1; i <= endbar; i++ )
{

   //   Calculate yearly statistics on year change (and at at end of analysis range)
    if ( YearChange[ i ] || i == endbar )
    {
        // Chg = 100 * ( -1 + eq[ i ] / LastYrValue );      //   percentage change calc
        Chg = 100 * ( -1 + eq[ i - 1 ] / LastYrValue );      //   percentage change calc


        VarSet( "ChgYear" + yr[ i - 1 ], Chg );         //   save in dynamic variable for each year

      // Track max and min yearly profit across years seen
        MaxYrProfit = Max( MaxYrProfit, Chg );
        MinYrProfit = Min( MinYrProfit, Chg );

        if ( FirstYr == 0 )
            FirstYr = yr[ i - 1 ];

        // LastYr = yr[ i ];
        LastYr = yr[ i - 1 ];

        // LastYrValue = eq[ i ];
        LastYrValue = eq[ i - 1 ];
    }

   //   Calculate monthly statistics on month change (and at at end of analysis range)
    if ( MonChange [ i ] || i == endbar )
    {

      thisYr = yr[ i - 1];
        mon = mo[ i - 1 ];

        // Chg = 100 * ( -1 + eq[ i ] / LastMoValue );      //   percentage change calc
        Chg = 100 * ( -1 + eq[ i - 1 ] / LastMoValue );      //   percentage change calc

      _TRACE( "Calculations for " ) ;
      _TRACE( "Year: " +  NumToStr(thisYr, 1.0) ) ;
      _TRACE( "Month: " +  NumToStr(mon, 1.0) ) ;
      _TRACE( "LastMoValue: " +  NumToStr(LastMoValue, 1.2) ) ;
      // _TRACE( "eq[" + NumToStr(i - 1, 1.0) + "]: " +  NumToStr(eq[ i - 1], 1.2) ) ;
      _TRACE( "ThisMoValue: " +  NumToStr(eq[ i - 1], 1.2) ) ;
      _TRACE( "Chg: " +  NumToStr(Chg, 1.2) ) ;
      _TRACE( "---------------------------" ) ;

        VarSet( "ChgMon" + yr[ i - 1 ] + "-" + mon, Chg );   //   save in dynamic variable for each month

        VarSet( "SumChgMon" + mon, Chg + Nz( VarGet( "SumChgMon" + mon ) ) );
        VarSet( "SumMon" + mon, 1 + Nz( VarGet( "SumMon" + mon ) ) );

      // Track max and min monthly profit across months seen
        MaxMoProfit = Max( MaxMoProfit, Chg );
        MinMoProfit = Min( MinMoProfit, Chg );

        // LastMoValue = eq[ i ];
        LastMoValue = eq[ i - 1 ];
    }
}

////////////////////////////
// Transfer dynamic variable values into arrays and add to exploration.
////////////////////////////

Years = 0;
Jan = Feb = Mar = Apr = May = Jun = Jul = Aug = Sep = Oct = Nov = Dec = 0;
Annual = 0;
index = startbar;

for ( y = FirstYr; y <= LastYr; y++ )
{
    Years[ index ] = y;
    Jan[ index ] = VarGet( "ChgMon" + y + "-" + 1 );
    Feb[ index ] = VarGet( "ChgMon" + y + "-" + 2 );
    Mar[ index ] = VarGet( "ChgMon" + y + "-" + 3 );
    Apr[ index ] = VarGet( "ChgMon" + y + "-" + 4 );
    May[ index ] = VarGet( "ChgMon" + y + "-" + 5 );
    Jun[ index ] = VarGet( "ChgMon" + y + "-" + 6 );
    Jul[ index ] = VarGet( "ChgMon" + y + "-" + 7 );
    Aug[ index ] = VarGet( "ChgMon" + y + "-" + 8 );
    Sep[ index ] = VarGet( "ChgMon" + y + "-" + 9 );
    Oct[ index ] = VarGet( "ChgMon" + y + "-" + 10 );
    Nov[ index ] = VarGet( "ChgMon" + y + "-" + 11 );
    Dec[ index ] = VarGet( "ChgMon" + y + "-" + 12 );
    Annual[ index ] = VarGet( "ChgYear" + y );

    index++;
}

Filter = Years;

SetOption("NoDefaultColumns", True);
AddColumn(Years, "Year", 4.0);
AddColumn(Jan, "Jan%", 1.2);
AddColumn(Feb, "Feb%", 1.2);
AddColumn(Mar, "Mar%", 1.2);
AddColumn(Apr, "Apr%", 1.2);
AddColumn(May, "May%", 1.2);
AddColumn(Jun, "Jun%", 1.2);
AddColumn(Jul, "Jul%", 1.2);
AddColumn(Aug, "Aug%", 1.2);
AddColumn(Sep, "Sep%", 1.2);
AddColumn(Oct, "Oct%", 1.2);
AddColumn(Nov, "Nov%", 1.2);
AddColumn(Dec, "Dec%", 1.2);
AddColumn(Annual, "Yr. Profit%", 1.2);
AddTextColumn(Name(), "Name", 6.0);
AddTextColumn(FullName(), "FullName", 20.0);
//AddColumn(AddSummaryRows,(2) ); ===cnb found no solution hence blocked as adviced bellow.
/*
- You will need the most recent beta release for the AddSummaryRows
function to work (just remove this line if you are NOT up to that
release). http://finance.groups.yahoo.com/group/amibroker/message/125846
*/

image-profit-table

Can someone give me a hand?

Thank you very much

At a quick glance, it appears that everything is correct except the first and last months. Your Jan 2007 is blank, and your July 2021 has a different value that the profit table from the report charts.

Have you used the _TRACE output that's already included in the AFL to see what's happening with those two calculations?

@amb734 try this modification (I saw I similar issue using your posted code on my data):

startbar = 0;
endbar = BarCount-1;
////////////////////////////
// SKIP non-trading bars
////////////////////////////
FirstBar = Status( "firstbarinrange" );
FirstBarInRange	= 0;

for( i = 0; i < BarCount; i++ )
{
    if( firstBar[i] )
    {
        FirstBarInRange = i;
        break;
    }
}

for( i = FirstBarInRange; i < BarCount; i++ )
{
    if( eq[ i ] )
    {
        startbar = i;
        break;
    }
}

The check for a "startbar" that is not null is done in the calculation code section that was modified and included in the "3. Profit Table.afl" formula, which you'll find under the folder "Report charts". I suggest examining it to check the differences further.

I will probably modify the formula to be used both as an exploration and to visually display the tables (in such a case, the above code may be in a conditional based on the action executed).

3 Likes

FYI, the first half of the code is by AmiBroker.com from Report Charts folder.

BTW, what is the Report charts folder code for the backtest table (second one of your picture)?
It has been modified since few AB versions.


That whole looping code can be shortened to just

bi = BarIndex();
fbr = Status("firstbarinrange");
is_equal = SumSince(fbr,eq==0) == BarsSince(fbr);
startbar = LastValue(ValueWhen(is_equal, bi))/*+1*/;
endbar = BarCount-1;

with eq = C;


BTW, it is not that good to write two times loop as in your case.
First you look for firstbarinrange and then starting from firstbarinrange you write/copy another loop to look for bar where eq is greater zero since start of array.

So if using looping it would be just single loop then

eq = C;
bir = Status("barinrange");
startbar = 0;
for( i = 0; i < BarCount; i++ )
{    
	if( eq[ i ] AND bir[i] )
	{
		startbar = i;
		break;
    }
}
1 Like

Here is combined code for explorer and HTML report:

EnableTextOutput( 3 ); // enable HTML output into report (Version 5.84 or higher!)
/// HTML Report table AFL code copyright (C)2014 AmiBroker.com
/// Modified (08/2021) by fxshrat@gmail.com (added output to Explorer, loop replacement) 
/// @link https://forum.amibroker.com/t/problem-to-achieve-table-profit-to-csv/27325/6
eq = C;

yr = Year();
mo = Month();

YearChange = yr != Ref( yr, 1 );
MonChange = mo != Ref( mo, 1 );

FirstYr = 0;
LastYr = 0;

////////////////////////////
// SKIP non-trading bars
////////////////////////////
// Removed loop
bi = BarIndex();
fbr = Status("firstbarinrange");
is_equal = SumSince(fbr,eq==0) == BarsSince(fbr);
startbar = LastValue(ValueWhen(is_equal, bi));
endbar = BarCount - 1;

////////////////////////////
// collect yearly / monthly changes in equity
// into dynamic variables
////////////////////////////

LastYrValue = eq[ startbar ];
LastMoValue = eq[ startbar ];
MaxYrProfit = MinYrProfit = 0;
MaxMoProfit = MinMoProfit = 0;

for ( i = startbar + 1; i <= endbar; i++ )
{
    if ( YearChange[ i ] || i == endbar )
    {
        Chg = 100 * ( -1 + eq[ i ] / LastYrValue );
        VarSet( "ChgYear" + yr[ i ], Chg );

        MaxYrProfit = Max( MaxYrProfit, Chg );
        MinYrProfit = Min( MinYrProfit, Chg );

        if ( FirstYr == 0 )
            FirstYr = yr[ i ];

        LastYr = yr[ i ];

        LastYrValue = eq[ i ];
    }

    if ( MonChange [ i ] || i == endbar )
    {
        mon = mo[ i ];

        Chg = 100 * ( -1 + eq[ i ] / LastMoValue );

        VarSet( "ChgMon" + yr[ i ] + "_" + mon, Chg );
        VarSet( "SumChgMon" + mon, Chg + Nz( VarGet( "SumChgMon" + mon ) ) );
        VarSet( "SumMon" + mon, 1 + Nz( VarGet( "SumMon" + mon ) ) );

        MaxMoProfit = Max( MaxMoProfit, Chg );
        MinMoProfit = Min( MinMoProfit, Chg );

        LastMoValue = eq[ i ];
    }
}

MonthNames = "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec";

function GenProfitTableHTMLAndExplorer( )
{
    printf( "<table border='1' bordercolor='#000000' cellspacing='0' cellpadding='3'style='border-collapse:collapse;'>\n" );
    printf( "<tr bgcolor='#eeffee' >\n" );

    Header = "Year," + MonthNames + ",Yr%%";

    for ( Col = 0; ( Colname = StrExtract( Header, Col ) ) != ""; Col++ )
    {
        printf( "<td><b>" + Colname + "</b></td>" );
    }

    printf( "</tr>\n" );

    AddTextColumn("", "Ticker", 1);
    AddColumn(Null, "Year", 1);
    for ( m = 1; m <= 12; m++ )
        AddColumn(Null, StrExtract(MonthNames,m-1), 1.2);
    AddColumn(Null, "Yr%", 1.2);
	
    fmt = ".1f";

    for ( y = FirstYr; y <= LastYr; y++ )
    {
        //Color =  ColorRGB( IIf( row == 0 || col == 0 || col == 13, 220, 255 ), 255, IIf( row % 2, 255, 220 ) );

        // new row
        if ( y % 2 )
            printf( "<tr bgcolor='#ffffff'>\n<td bgcolor='#eeffff'>" );
        else
            printf( "<tr bgcolor='#ffffee'>\n<td bgcolor='#eeffee'>" );

        printf( "<b>%g</b></td>", y );

        ar_str = "";
        for ( m = 1; m <= 12; m++ )
        {
            Chg = VarGet( "ChgMon" + y + "_" + m );

            if ( NOT IsNull( Chg ) )
            {
                if ( Chg >= 0 )
                    printf( "<td nowrap>%"+fmt+"%%</td>", Chg );
                else
                    printf( "<td nowrap><font color='880000'>%"+fmt+"%%</font></td>", Chg );
                
                ar_str += StrFormat("%"+fmt+"%%\t", Chg);
            }
            else {
                printf( "<td>N/A</td>" );
                ar_str += "N/A\t";
            }
        }

        if ( y % 2 )
            printf( "<td nowrap bgcolor='#eeffff'>" );
        else
            printf( "<td nowrap bgcolor='#eeffee'>" );

        x = VarGet( "ChgYear" + y );

        if ( x >= 0 )
            printf( "<b>%"+fmt+"%%</b></td>", x );
        else
            printf( "<font color='880000'><b>%"+fmt+"%%</b></font></td>", x );
            
        AddRow(StrFormat("%s\t%g\t%s%"+fmt+"%%",Name(),y,ar_str,x));

        printf( "</tr>\n" ); // end row
    }


    printf( "<tr bgcolor='#eeffee' >\n" ); // new row
    printf( "<td><b>Avg</b></td>" );

    ar_str = "";
    for ( m = 1; m <= 12; m++ )
    {
        x = Nz( VarGet( "SumChgMon" + m ) / VarGet( "SumMon" + m ) );

        if ( x >= 0 )
            printf( "<td nowrap><b>%"+fmt+"%%</b></td>", x );
        else
            printf( "<td nowrap><font color='880000'><b>%"+fmt+"%%</b></font></td>", x );
        
        ar_str += StrFormat("%"+fmt+"%%\t", x);
    }
    AddRow(Name()+"\tAverage:\t"+ar_str);

    printf( "<td>&nbsp;</td>" );
    printf( "</tr></table>\n" );

}

///////////////////////////
// This function checks if currently selected symbol
// is portfolio equity
//////////////////////////
function CheckSymbol()
{
    if ( Name() != "~~~EQUITY" AND Name() != "~~~OSEQUITY" )
    {
        printf( "For accurate results switch to ~~~EQUITY symbol<br>" );
    }
}

CheckSymbol();

////////////////////////////
// Main program
////////////////////////////
SetOption("NoDefaultColumns", 1);
Filter = 0;

GenProfitTableHTMLAndExplorer();

26

2 Likes

Thanks @beppe I made the modification you suggested and now the final results are the same. However, there is still something in the first month that does not work as in the profit table...

WhatsApp Image 2021-08-25 at 11154.26

For the other hand, thank you too @fxshart, I tried to, the report chart create the table well like my other html report, but when I execute this in the explorer I get differents results :S

Would be great if @beppe or someone else could check it too, is very weird. According to what you comment it should give me the same result in the explorer but it is not like that...

WhatsApp Image 2021-08-26 at 022257.36

Please listen carefully,

The results of explorer and HTML are the same ones as they use same AB code!

And if you compare results then once again I told you that report chart calculation mode has been changed years ago. The new method is present in the most recent HTML report AFL (which I have used to modify). So you have to move that posted report AFL to Report Charts folder (the posted AFL includes both backtest report table and Explorer).

And what you call weird is not weird but those large numbers represent NULL!
To convert Null to something else (default zero) use NZ function in line 139

AddRow(StrFormat("%s\t%g\t%s%"+fmt+"%%",Name(),y,ar_str,Nz(x)));

Or replacing NULL by string "N/A".

x_str = WriteIf(IsNull(x), "N/A", StrFormat("%"+fmt+"%%",x));   
 AddRow(StrFormat("%s\t%g\t%s%s",Name(),y,ar_str,x_str));

And BTW if you would look at your pictures you are using two decimal places while the one I posted uses single decimal places! So it is clearly modified one on your end because original report AFL uses single decimal places. In line 93 I have added fmt = ".1f"; so to get two decimal places -> fmt = ".2f";

So you should compare apples to apples not apples to oranges.

Above I asked you what is the report charts AFL you are using. No response. No code.

Really, sometimes it is not amusing talking to newbies.

Single piece of advice for newbie, if coding is over your head, use simplest method possible. And simplest method is to copy-paste from the REPORT window.

  1. Select the table using mouse
  2. then press Ctrl+C to copy
  3. then switch to Excel and paste in Excel (Ctrl+V).

Voila. No coding and you got report in Excel.

1 Like

The advantage or let's say difference between explorer and report is that via Explorer one may output tables for multiple stored equities or tickers at once.

28

Hey, I do not get NULL in Yr% column when there is "N/A" at start.
Please upload your ~~~EQUITY symbol.

Also if I set From-To it does not output previous years rows (before "From"-year).
Have you modified something?

30

And explorer results are in line with BT table
31

What is the output on your end if you add Nz to is_equal line?

bi = BarIndex();
fbr = Status("firstbarinrange");
is_equal = SumSince(fbr,Nz(eq)==0) == BarsSince(fbr);
startbar = LastValue(ValueWhen(is_equal, bi));
endbar = BarCount - 1;

Hi,

Sorry for the delay I have been doing more tests to see if I found any patterns

The exact code I’m using is the one you put @fxshrat here Problem to achieve table profit to csv - #6 by fxshrat

I attach you the two equity curves in csv, one is a system in monthly timeframe and the other is in daily.

Sorry, I see that it does not let me paste all the content of the equity curve, I attach a link with the two complete files

Equity csv

My findings are… it seems to do well on a daily basis, but not on a weekly or monthly basis.

I attach images.

daily-vs-monthly

The system/explorer you tried was daily @fxshrat?

Could you run the explorer with the monthly equity curve?

Thank you very much

Please, I'm still stuck, could you tell me how to interpret the difference between the interpretation window and the profit table when I run a weekly system? Why are different in weekly timeframe if both are "monthly profits"?

https://ibb.co/yfFMH9q

Thank you very much