Profit tables are a valuable tool for traders and investors to analyze the trading strategy performance of their investments over time. However, the traditional presentation of these tables, with default colors, can be visually boring and hard to interpret. Enter dynamic color coding – a simple yet powerful way to enhance the readability and visual appeal of profit tables in Amibroker.
Why Dynamic Color Coding in Profit Tables?
Enhanced readability: Color-coded profit tables make it easier for users to identify patterns and trends in the data. The contrasting colors enable the human eye to quickly distinguish between positive and negative values, making it easier to spot high-performing and underperforming months or years.
Visual appeal: Dynamic color coding adds a layer of visual interest to the otherwise monotonous profit tables. The varying shades and colors make the table more engaging and enjoyable to analyze.
Faster decision-making: The clear visual representation of data allows traders and investors to make quicker and more informed decisions. The easy-to-understand format helps users to spot opportunities and risks at a glance, without having to spend time deciphering the raw data.
Steps to Install the Profit Table (Color Coded)
1)Copy the below AFL code. Goto Amibroker File -> New -> Formula and save the formula as 4. Profit Table (Color Coded).afl and save the file under //Amibroker//Formulas//Reports folder.
2)Backtest a Trading Strategy of your choice and now goto the Backtest Reports section -> Charts to visualize the dynamic profit table just below the plain vanilla profit table.
Dynamic Color Coding – Amibroker AFL Code
EnableTextOutput( 3 ); // enable HTML output into report (Version 5.84 or higher!)
eq = C;
yr = Year();
mo = Month();
YearChange = yr != Ref( yr, 1 );
MonChange = mo != Ref( mo, 1 );
FirstYr = 0;
LastYr = 0;
startbar = 0;
////////////////////////////
// SKIP non-trading bars
////////////////////////////
for ( i = 0; i < BarCount; i++ )
{
if ( eq[ i ] )
{
startbar = i;
break;
}
}
////////////////////////////
// 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 < BarCount; i++ )
{
if ( YearChange[ i ] || i == BarCount - 1 )
{
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 == BarCount - 1 )
{
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 NumToHex( num )
{
hexVal = "";
hexChars = "0123456789ABCDEF";
while (num > 0)
{
remainder = num % 16;
hexVal = StrMid(hexChars, remainder, 1) + hexVal;
num = int(num / 16);
}
while (StrLen(hexVal) < 2)
{
hexVal = "0" + hexVal;
}
return hexVal;
}
function ColorBasedOnPercent( Chg )
{
if (Chg > 0)
{
greenIntensity = 255-Min(255, (Chg*25));
//_TRACE("Green Intensity:"+greenIntensity);
hexColor = "#" + NumToHex(int(greenIntensity)) + "FF" + NumToHex(int(greenIntensity));
}
else if (Chg < 0)
{
redIntensity = 255-Min(255, (Chg*-25) );
hexColor = "#" + "FF" + NumToHex(int(redIntensity)) + NumToHex(int(redIntensity));
}
else
{
hexColor = "#FFFFFF";
}
//_TRACE("hexColor: "+hexColor);
return hexColor;
}
function GenProfitTableHTML( )
{
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" );
for ( y = FirstYr; y <= LastYr; y++ )
{
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 );
for ( m = 1; m <= 12; m++ )
{
Chg = VarGet( "ChgMon" + y + "-" + m );
if ( NOT IsNull( Chg ) )
{
printf( "<td nowrap bgcolor='" + ColorBasedOnPercent( Chg ) + "'>%.1f%%</td>", Chg );
}
else
printf( "<td>N/A</td>" );
}
x = VarGet( "ChgYear" + y );
if ( y % 2 )
printf( "<td nowrap bgcolor='" + ColorBasedOnPercent( x ) + "'>" );
else
printf( "<td nowrap bgcolor='" + ColorBasedOnPercent( x ) + "'>" );
printf( "<b>%.1f%%</b></td>", x );
printf( "</tr>\n" );
}
printf( "<tr bgcolor='#eeffee' >\n" );
printf( "<td><b>Avg</b></td>" );
for ( m = 1; m <= 12; m++ )
{
x = Nz( VarGet( "SumChgMon" + m ) / VarGet( "SumMon" + m ) );
printf( "<td nowrap bgcolor='" + ColorBasedOnPercent( x ) + "'><b>%.1f%%</b></td>", x );
}
printf( "<td> </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
////////////////////////////
GenProfitTableHTML();