Printf error when backtesting

i get a wierd printf error when backtesting. Never seen it before.
where is it coming from?

Here is my full code and i am testing it against eur.usd on 5 minutes

#include_once <commonFunctions.afl>
LONGSIDE = 1;
SHORTSIDE = 2;
ABOVECLOUD = 1;
BELOWCLOUD = 2;
BETWEENCLOUD = 3;
function returnState( st )
{
    str = "";

    switch( st )
    {
        case ABOVECLOUD:
            str = "ABOVECLOUD";
            break;

        case BELOWCLOUD:
            str = "BELOWCLOUD";
            break;

        case BETWEENCLOUD:
            str = "BETWEENCLOUD";
            break;

    }

    return str;



}

//SetBarsRequired( -2, -2 ); // require all bars.
_N( Title = StrFormat( "{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) Vol   " + WriteVal( V, 1.0 ) + " {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ) + " \n "     + " \n " );
//https://www.raoufx.com/trading%20with%20ichimoku%20clouds%20the%20essential%20guide%20to%20ichimoku%20kinko%20hyo%20technical%20analysis.pdf
Plot( C, "Close", colorDefault, styleNoTitle | GetPriceStyle() );
_SECTION_BEGIN( "Tenkan-Sen" );
TenkanPer = Param( "Tenkan-Sen Period", 9, 1, 100, 1 );
TenkanCol = ParamColor( "Tenkan-Sen Color", colorRed );
TenkanSty = ParamStyle( "Tenkan-Sen Style", styleLine | styleThick );
Tenkan = ( HHV( H, TenkanPer ) + LLV( L, TenkanPer ) ) / 2;
//Plot( Tenkan, "Tenkan", TenkanCol, TenkanSty );
_SECTION_END();

_SECTION_BEGIN( "Kijun-Sen" );
KijunPer = Param( "Kijun-Sen Period", 22, 1, 100, 1 ); // using 22 instead of 26 as there are only 22 trading days in a month.
KijunCol = ParamColor( "Kijun-Sen Color", colorBlue );
KijunSty = ParamStyle( "Kijun-Sen Style", styleLine | styleThick );
Kijun = ( HHV( H, KijunPer ) + LLV( L, KijunPer ) ) / 2;
//Plot( Kijun, "Kijun", KijunCol, KijunSty );
_SECTION_END();

_SECTION_BEGIN( "Chikou Span" );
ChikouShft = Param( "Chikou Span Shift", 22, 1, 100, 1 ); // using 22 instead of 26 as there are only 22 trading days in a month.
ChikouCol = ParamColor( "Chikou Span Color", colorViolet );
ChikouSty = ParamStyle( "Chikou Span Style", styleLine | styleNoLabel );
Chikou = C;
//Plot( Chikou, "", ChikouCol, ChikouSty, Null, Null, -ChikouShft );
_SECTION_END();

_SECTION_BEGIN( "Senkou-Kumo" );
SenkouKumoShft = Param( "Senkou-Kumo Shift", 21, 0, 100, 1 );
_SECTION_END();

_SECTION_BEGIN( "Senkou Span A" );
SenkouACol = ParamColor( "Senkou Span A Color", colorSeaGreen );
SenkouASty = ParamStyle( "Senkou Span A Style", styleLine );
SenkouA = ( Tenkan + Kijun ) / 2;
SenkouA_values = Ref( SenkouA, -1 * SenkouKumoShft );


_SECTION_END();

_SECTION_BEGIN( "Senkou Span B" );
SenkouBPer = Param( "Senkou Span B Period", 42, 1, 200, 1 );
SenkouBCol = ParamColor( "Senkou Span B Color", colorPink );
SenkouBSty = ParamStyle( "Senkou Span B Style", styleLine );
SenkouB = ( HHV( H, SenkouBPer ) + LLV( L, SenkouBPer ) ) / 2;
//Plot( SenkouB, "Senkou B", SenkouBCol, SenkouBSty, Null, Null, SenkouKumoShft ) ;
SenkouB_values = Ref( SenkouB, -1 * SenkouKumoShft );
_SECTION_END();
Title = Title +  " SenkouA_values  " + SenkouA_values + "SenkouB_values" + SenkouB_values ;
_SECTION_BEGIN( "Kumo" );
KumoUpCol = ParamColor( "Kumo UP Color", colorSeaGreen );
KumoDnCol = ParamColor( "Kumo DN Color", colorPink );
//PlotOHLC( SenkouA, SenkouA, SenkouB, SenkouB, "", IIf( SenkouA > SenkouB, KumoUpCol, KumoDnCol ), styleCloud | styleNoLabel, Null, Null, SenkouKumoShft );
_SECTION_END();

TrendingLong = SenkouA_values > SenkouB_values AND L > SenkouA_values;
TrendingShort = SenkouA_values < SenkouB_values AND H < SenkouA_values;
cloudHigh = Max( SenkouA_values, SenkouB_values );
cloudLow = Min( SenkouA_values, SenkouB_values );
MovedAboveCloudTop = L > cloudHigh;
MovedIntoCloudTop = L < cloudHigh;
MovedIntoCloudBotton = H > cloudLow;
MovedBelowCloudBotton = L < cloudLow;
_SECTION_BEGIN( "Price" );
SetChartOptions( 0, chartShowArrows | chartShowDates );

Plot( C, "Close", ParamColor( "Color", colorBlack ), styleNoTitle | ParamStyle( "Style" ) | GetPriceStyle() );

_SECTION_BEGIN( " moving averages" );

Periods_35 = 35;
EMA35 = EMA( C, Periods_35 );
Plot( EMA35, "9 ema" , colorBlue, ParamStyle( "Style" ) );

Periods_50 = 50;
EMA50 = EMA( C, Periods_50 );
Plot( EMA50, "50 ema" , colorGreen, ParamStyle( "Style" ) );




/*
Periods_5 = 5;
EMA5= EMA( C, Periods_5 );
Plot( EMA5,  "5 ema", colorGreen, ParamStyle( "Style" ) );
*/



//PlotShapes(IIf(Cross(EMA9,EMA20),shapeStar,shapeNone),colorGreen,0);


_SECTION_END();

LongSignal_Case1 = Cross( RSI( 9 ), 50 ) AND EMA35 > EMA50 AND TrendingLong;
ShortSignal_Case1 = Cross( 50, RSI( 9 ) ) AND EMA35 < EMA50 AND TrendingShort;

LongEntry_Case1 = Ref( LongSignal_Case1, -1 )  AND H > Ref( H, -1 );

ShortEntry_Case1 = Ref( ShortSignal_Case1, -1 )  AND L < Ref( l, -1 );
atrvalue = ATR( 14 );
/* backtest system 1: */
Buy = LongEntry_Case1;
Sell = BarsSince( Buy ) > 2;
Short = ShortSignal_Case1;
Cover = BarsSince( Short ) > 2;

reallyHigh = H > Ref( HHV( H, 150 ), -1 );
reallyLow = L < Ref( llV( l, 150 ), -1 );
LineThickness = Param( "LineThickness", 2, 1, 8, 1 );
EuropeColor = ParamColor( "Europe Session", colorGreen );
Plot( IIf( reallyHigh OR reallyLow , LineThickness, -1e10 ), "", IIf( reallyHigh, colorGreen, IIf( reallyLow, colorRed, colorPaleBlue ) )  , styleOwnScale | styleArea | styleNoLabel, -1, 90 );
//Plot( IIf(reallyHigh ,LineThickness,-1e10),"",EuropeColor ,styleOwnScale|styleArea|styleNoLabel, -1, 90);
lastSide = 0;
currentState = 0;
//currentState = IIf( Low > cloudHigh, ABOVECLOUD, IIf( High < cloudLow, BELOWCLOUD,currentState ) );

touchedCloudLongTimes = touchedCloudShortTimes = 0;
countMovedAboveCloudLong = countMovedintoCloudLong =  countMovedBelowCloudShort = countMovedIntoCloudShort = 0;
MovedLongbar = MovedShortbar = BarCount;;

for( i = 1; i < BarCount - 1; i++ )

{
// INITIALIZE
    currentState[i] = currentState[i - 1];

// basically, i want to check if it crossed above the cloud or below the cloud. i want to mark the first time it touched the cloud after price broke above it.
// i will take the rsi turn only if it never touched cloud again after first breakout.
    if( ( lastSide != LONGSIDE )  AND l[i] > cloudHigh[i] )
    {
        lastSide = LONGSIDE;
        MovedShortbar = BarCount;
        MovedLongbar = i;
        //currentState[i]=ABOVECLOUD;
        countMovedintoCloudLong = countMovedAboveCloudLong = 0;
        PlotText( "Moving Long" , i, Status( "axismaxy" ) - 1.5 * atrvalue[i],  colorwhite, colorgreen, yoffset = 0 ) ;

    }

    if( lastSide != SHORTSIDE  AND h[i] < cloudLow[i] )
    {
        lastSide = SHORTSIDE;
        MovedShortbar = i;
        MovedLongbar = BarCount;

        // currentState[i]=BELOWCLOUD;
        countMovedintoCloudShort = countMovedBelowCloudShort = 0;
        PlotText( "Moving sHORT" , i, Status( "axismaxy" ) - 1.5 * atrvalue[i],  colorwhite, colorred, yoffset = 0 ) ;
    }

    if( ( Low[i]<CloudHigh[i] AND Low[i]>CloudLow[i] ) OR( High[i] > CloudLow[i] AND High[i] < CloudHigh[i] ) ) // MAKE SURE ITS BETWEEN THE CLOUD PRICES.
    {
//currentState[i]=BETWEENCLOUD;
    }

    switch( lastSide )
    {
        case 1:// if last bar above cloud and this bar into cloud, it did a transition and so add

            if( i > MovedLongbar )
            {
                if( MovedAboveCloudTop[i - 1] AND 	MovedIntoCloudTop[i] )
                {
                    countMovedintoCloudLong += 1;;
                    PlotText( "MIC" + countMovedintoCloudLong, i, Status( "axismaxy" ) - 2.5 * atrvalue[i],  colorwhite, colorred, yoffset = 0 ) ;
                }

                if( MovedAboveCloudTop[i] AND 	MovedIntoCloudTop[i - 1] )
                {
                    countMovedAboveCloudLong += 1;;
                    PlotText( "MAC" + countMovedAboveCloudLong, i, Status( "axismaxy" ) - 2.5 * atrvalue[i],  colorwhite, colorred, yoffset = 0 ) ;
                }

                if( LongEntry_Case1[i - 1] AND H[i] > H[i - 1] AND  countMovedintoCloudLong <= 5 ) // i need to only do rsi if it never touched cloud after first breakout.
                {
                    PlotText( "LongRSI"   , i, Status( "axisminy" ) + 1.5 * atrvalue[i],  colorwhite, colorred, yoffset = 0 ) ;
                    Buy[i] = True;
                }


            }

            break;

        case 2:
            if( MovedBelowCloudBotton[i - 1] AND 	MovedIntoCloudBotton[i] )
            {
                countMovedintoCloudShort += 1;;
                PlotText( "MIC" + countMovedintoCloudShort, i, Status( "axismaxy" ) - 1.5 * atrvalue[i],  colorwhite, colorred, yoffset = 0 ) ;
            }

            if( MovedBelowCloudBotton[i  ] AND 	MovedIntoCloudBotton[i - 1] )
            {
                countMovedBelowCloudShort += 1;;
                PlotText( "MBC" +  countMovedBelowCloudShort, i, Status( "axismaxy" ) - 1.5 * atrvalue[i],  colorwhite, colorred, yoffset = 0 ) ;
            }

            if( ShortEntry_Case1[i - 1] AND L[i] < l[i - 1] AND  countMovedintoCloudShort <= 5 ) // i need to only do rsi if it never touched cloud after first breakout.
            {
                PlotText( "ShortRSI"   , i, Status( "axisminy" ) + 1.5 * atrvalue[i],  colorwhite, colorred, yoffset = 0 ) ;
                short[i] = True;
            }

            break;
    }



}





PlotShapes( IIf( Cross( EMA35, EMA50 ), shapeDigit1, shapeNone ), colorWhite, graph0 );
PlotShapes( IIf( Cross( EMA50, EMA35 ), shapeDigit1, shapeNone ), colorYellow, graph0 );
PlotShapes( IIf( Cross( EMA50, EMA35 ), shapedownArrow, shapeNone ), colorWhite, graph0 );
PlotShapes( IIf( Cross( EMA50, EMA35 ), shapedownArrow, shapeNone ), colorYellow, graph0 );

PlotShapes( IIf( LongSignal_Case1, shapeDigit2, shapeNone ), colorWhite, graph0 );
PlotShapes( IIf( ShortSignal_Case1, shapeDigit2, shapeNone ), colorYellow, graph0 );

PlotShapes( shapeHollowUpArrow*LongEntry_Case1, IIf( touchedCloudLongTimes == 0, colorWhite, colorYellow ), 0, Graph0 );
PlotShapes( shapeHollowdownArrow*ShortEntry_Case1, colorYellow, 0, Graph0 );


Sell = BarsSince( Buy ) > 2;
Cover = BarsSince( Short ) > 2;
//Buy = LongSignal; //=h>ValueWhen(LongSignal,High,1);// AND LowestSince(LongSignal,Low,1)>ValueWhen(LongSignal,Low,1);
Title = Title +  "cloudHigh  " + cloudHigh + "cloudLow" + cloudLow  + " currentState  " + currentState ;
Filter = true;

//AddColumn( LongSignal, "LongSignal" );
//AddColumn( countLongHH7SinceCrossedShort, "countLongHH7SinceCrossedShort" );
//AddColumn( countLongHH7SinceCrossedLong, "countLongHH7SinceCrossedLong" );

//AddColumn(C>ValueWhen(LongSignal,High,1) ,"buysignal");
//AddColumn(LowestSince(Ref(LongSignal,1),Low,1),"lowestlow");

SetCustomBacktestProc( "" );

Check in this file as well
#include_once <commonFunctions.afl>

By habit, I never use Charting code and run it blindly in Analysis window.
Ideally, Charts and Analysis ignore irrelevant function calls but improper code will cause this.

Rewrite some parts of code and post the results that are fit for an Analysis.

Unless its an internal issue which in unlikely, Tomasz will know more. What version of AB are you running?

1 Like

@suresh I have seen this error frequently when there was something wrong in my CBT procedures (I mean that the error dialog was displayed when I did not invoke the functions in the proper sequence and/or I was using some wrong parameters)

In your code, you wrote (last line):

SetCustomBacktestProc( "" );

Just commenting out this line solves the issue, since you did not include any custom backtest procedure in your code:

See the documentation:

SetCustomBacktestProc( filename, enable = True )

filename parameter instructs backtester to use external formula file as custom backtest procedure, if empty - it means use current formula

Since you invoked it with no filename, you are supposed to include in this same formula a backtest procedure. I do not see it!

If needed, please, review the Porfolio Backtester Interface Reference Guide.

1 Like

There is no error if you do this one

period = 20; // number of averaging periods 
m = MA( Close, period ); // simple moving average
Buy = Cross( Close, m ); // buy when close crosses ABOVE moving average
Sell = Cross( m, Close ); // sell when closes crosses BELOW moving average
Short = Cover = 0;

SetCustomBacktestProc(""); // enable custom backtest

It just shows no results then. That is all.

Also there is no error if running "his" code with

#include_once <commonFunctions.afl>

being commented.


His error comes from the fact that his second printf line (seen in his picture) has wrong format specifier or too many format specifiers which are not in line with number of variables inserted as 2nd, 3rd 4th,.... argument of printf. Simply look at the upper picture. It already tells everything. The number of variables does not (seem to) match.

@suresh,
SImply post the complete 2nd printf line that is part of your commonFunctions.afl function! Or better post the complete function.


Starting from version 6.10, printf/StrFormat now implement a check for correct formatting string as sometimes users passed strings with % that is special marker for formatting string instead of %% to print actual percent sign. When check failes, "Error 61. The number of % formatting specifier(s) does not match the number of arguments passed." is displayed

Long story short... it is not weird error. It is normal standard error.

2 Likes

@suresh - just ask Google. It is that simple. Newbies need to realize that answers to ALL their questions are already there - in the manual, in the Knowledge base and in the forum. And that getting answers from Google is much faster than asking the same question over and over and waiting for somebody to write the very same reply again and again.

If you just used GOOGLE https://www.google.com/search?q=error+61+amibroker

you would find this (first answer):

http://www.amibroker.com/kb/2016/01/18/how-to-fix-error-61-in-printfstrformat-calls/

If you do not know where is the formula that generates the error -- then -- use text search ! AFL Editor has "Find in files" functionality. Just copy paste code fragment and you will see that it comes from Backtest Report code (formulas that are "Report charts" subfolder). This one is likely to be Profit table.afl as it generates HTML tags as can be seen in the screenshot. But you are using some OLD (or modified) version of the formula from somewhere and that is the problem.

But the easiest way is just to display LOG window (Window->Log menu). It will display file and exact location of error like this (I simulated the error for illustration purposes):

image

Then just double click on error line would open up AFL Editor automatically and point the cursor to the location of the error. What can be easier than this?

5 Likes