Martingale Amibroker AFL Strategy

This is advanced template with position sizing used for strategies where Buy (LE) and Cover (SX) are same; Sell (LX) and Short (SE) are same. It is basically addon version of Intraday Trading AFL.

Parameters:

  1. Color of Modified Signals: This AFL displays on chart both original signals and modified signals, you can set colors. The stoploss, trail stop and target lines are also drawn on chart with same color.
  2. Exposure  and Quantity both parameters are available. If exposure is 0, it will take the defined Quantity. Exposure example: If you want to buy/sell each stock with Rs. 100,000, you can se the exposure =100000 and run the AFL on multiple stocks. It will automatically trade 1000 share for a 100 rs. stock, and 250 shares of a 400 rs. stock.
  3. Qty Using SL: If this is given non-zero value, it calculates quantity based on SL as defined in percentage. It will ignore Quantity given in parameter or Quantity calculated from Exposure.
  4. Day Profit Limit: Strategy will squareoff and stop trading when profit limit reached (example 5000)
  5. Day Loss Limit: Strategy will squareoff and stop trading when loss limit reached (example 2000)
  6. Apply Intraday Martingale: Select NO or Arithmetic or Geometric

A. This works only when Intraday mode is activated
B. If selected Arithmetic, it adds the trading quantity on every losing trade. Example trade quantity is 1, after every losing trading it adds 1 to new trade. So progression is like 1, 2, 3, 4, 5….
C. If selected Geometric, it multiplies the trading quantity on every losing trade with 2. Example trade quantity is 1, after every losing trading it multiplies 2 to new trade. So progression is like 1, 2, 4, 8, 16….

How to Use:

This is not a AFL strategy but simply template for automatic trading. Take the following steps to start automatic trading with your own strategy:

  1. In Amibroker, go to Analysis, then Formula Editor
  2. In Formula Editor window, go to File -> Open and open your strategy with buy/sell code.
  3. Scroll down to bottom of code. Copy-paste here code from this strategy template.
  4. Save this file in your computer at location which you easily remember. Now this file is ready for auto trading from both Amibroker charts and Scanner.

Download Link:

Direct Code for Copy-Paste

_SECTION_BEGIN( "AutoTrade-Intraday-Martingale.afl" );
intra = ParamToggle( "Activate Intraday Mode", "NO|YES" );
per10 = Param( "Trade Entry From(HHMM)", 920, 900, 2400, 1 );
per11 = Param( "Trade Entry Upto(HHMM)", 1445, 900, 2400, 1 );
per12 = Param( "Trade Exit(HHMM)", 1515, 900, 2300, 100 );
slp = Param( "StopLoss(%)", 0, 0, 1000, 0.1 );
tsl= Param("Trail Stop(%)", 0, 0, 100, 0.1);
tgtp = Param( "Target(%)", 0, 0, 1000, 0.1 );
Col = ParamColor( "Color of Modified Signals", colorYellow );
instr= ParamList("Instrument Name","EQ|FUTIDX|FUTSTK|OPTIDX|OPTSTK|FUTCOM"); 
delay= ParamToggle("Trade Intrabar?", "YES|Candle Completion");
stag= ParamStr("Strategy Tag", "STG1");
dlong= ParamToggle("Disable Long?", "NO|YES");
dshort= ParamToggle("Disable Short?", "NO|YES");

if(dlong){Buy=Sell=0;}
if(dshort){Short=Cover=0;}
dd= DaysSince1900();
d=prof= 0;
basicprice= LastValue(ValueWhen(Day()!=Ref(Day(),-1), C));



if(delay)
{Buy=Ref(Buy,-1); Sell=Ref(Sell,-1); Short= Ref(Short,-1); Cover= Ref(Cover,-1);}

qt= Param("Trade Quantity", 0, 0, 1000000) ;
exposure= Param("Qty using Exposure", 0, 0, 1000000) ;
maxl= Param("Qty using SL",0,0,100000 );


if(slp>0)
sln= LastValue(slp*basicprice/100);


if(exposure>0)
qt= round(exposure/basicprice);

if(maxl>0)
qt= round(maxl/sln);

mt= ParamList("Apply Intraday Martingale", "NO|Arithmetic|Geometric");
dt= Param("Day Profit Limit", 0, 0, 100000, 1);
dl= Param("Day Loss Limit", 0, -100000, 0, 1);

mtl=0;
if(mt=="Arithmetic" AND intra) mtl=1;
if(mt=="Geometric" AND intra) mtl=2;

intraex = intra AND (TimeNum() > per12 * 100);
intraen = !intra OR ( TimeNum() <= per11 * 100 AND TimeNum() >= per10 * 100 );


Buy1 = Buy;
Sell1 = Sell;
Short1 = Short;
Cover1 = Cover;
Buy=Sell=Short=Cover=0;
bflag = sflag = sp=bp = 0;
slarr = tgtarr = Null;
profarr= qtarr= 0;
/*for updated afl code always check https://algoji.com/amibroker-autotrade-afl-toolkit/ */
for ( i = 10; i < BarCount; i++ )
{
	if(d==dd[i]) profarr[i]= profarr[i-1];
    if ( ( Cover1[i] OR intraex[i]OR( H[i] > slarr[i-1] AND (sl>0 OR tsl>0) )  OR ( L[i] < tgtarr[i-1] AND tgt > 0 )   OR (dt>0 AND (profarr[i-1]+ (sp-C[i])*qtarr[i-1])>=dt) OR (dl<0 AND (profarr[i-1]+ (sp-C[i])*qtarr[i-1])<=dl) ) AND sflag )
    {
        Cover[i] = 1;
        CoverPrice[i]= C[i];
        sflag = 0;
        d= dd[i]; prof= sp-C[i];
        if(d==dd[i]) profarr[i]= (prof*qtarr[i-1] + profarr[i-1]);        
    }

    if ( ( Sell1[i] OR intraex[i] OR( L[i] < slarr[i-1] AND (sl>0 OR tsl>0) ) OR ( H[i] > tgtarr[i-1] AND tgt > 0 )   OR (dt>0 AND (profarr[i-1]+ (C[i]-bp)*qtarr[i-1])>=dt) OR (dl<0 AND (profarr[i-1]+ (C[i]-bp)*qtarr[i-1])<=dl) ) AND bflag )
    {
        Sell[i] = 1;
        SellPrice[i]= C[i];
        bflag = 0;
        d= dd[i]; prof= C[i]- bp;
        if(d==dd[i]) profarr[i]= (prof*qtarr[i-1] + profarr[i-1]);
    }

    if ( Buy1[i] AND intraen[i] AND !bflag AND  ( ((dt>0 AND profarr[i]<=dt) OR dt==0) AND  ((dl<0 AND profarr[i]>=dl) OR dl==0) ) )
    {
        Buy[i] = 1;
        bflag = 1;
		bp= C[i];
		qtarr[i]= qt;
		if(prof<0 AND d==dd[i] AND mtl==1) qtarr[i]= qtarr[i-1]+qt; 
		if(prof<0 AND d==dd[i] AND mtl==2) qtarr[i]= qtarr[i-1]*2; 
		sl= slp*bp/100;
		tgt= tgtp*bp/100;
        if ( slp )
            slarr[i] = (1-slp/100)*bp; 

        if ( tgtp )
            tgtarr[i] = (1+tgtp/100)*bp;
    }

    if ( bflag AND !Buy[i] )
    {
        slarr[i] = slarr[i-1];
        tgtarr[i] = tgtarr[i-1];
        qtarr[i]= qtarr[i-1];
        if(tsl>0)
        slarr[i] = Max(slarr[i-1], H[i]*(1-tsl/100));
    }



    if ( Short1[i] AND intraen[i] AND !sflag AND  ( ((dt>0 AND profarr[i]<=dt) OR dt==0) AND  ((dl<0 AND profarr[i]>=dl) OR dl==0) ) )
    {
        Short[i] = 1;
        sflag = 1;
        Sp= C[i];
		sl= slp*Sp/100;
		tgt= tgtp*Sp/100;
		qtarr[i]= qt;
		if(prof<0 AND d==dd[i] AND mtl==1) qtarr[i]= qtarr[i-1]+qt; 
		if(prof<0 AND d==dd[i] AND mtl==2) qtarr[i]= qtarr[i-1]*2; 
        if ( slp )
            slarr[i] = C[i] + sl;
		if(tsl)
			slarr[i]= L[i]*(1+tsl/100);
        if ( tgtp )
            tgtarr[i] = C[i] - tgt;
    }

    if ( sflag AND !Short[i] )
    {
        slarr[i] = slarr[i-1];
        tgtarr[i] = tgtarr[i-1];
        qtarr[i]= qtarr[i-1];
        if(tsl>0)
        slarr[i] = Min(slarr[i-1], L[i]*(1+tsl/100));
    }


}

Plot( slarr, "SL", Col, styleLine );
Plot( tgtarr, "TGT", Col, styleLine );
PlotShapes( IIf( Buy, shapeUpArrow, shapeNone ), Col, 0, L, Offset = -45 );
PlotShapes( IIf( Short, shapeDownArrow, shapeNone ), Col, 0, H, Offset = -45 );
PlotShapes( IIf( Cover, shapeStar, shapeNone ), Col, 0, L, Offset = -55 );
PlotShapes( IIf( Sell, shapeStar, shapeNone ), Col, 0, H, Offset = -55 );

sig = IIf( BarsSince( Buy ) < BarsSince( Short ), 1, 0 );
messageboard = ParamToggle( "Message Board", "Show|Hide", 1 );

if ( messageboard == 1 )
{
    GfxSelectFont( "Tahoma", 13, 100 );
    GfxSetBkMode( 1 );
    GfxSetTextColor( colorWhite );

    GfxSelectSolidBrush( colorDarkTeal ); // this is the box background color


    pxHeight = Status( "pxchartheight" ) ;

    xx = Status( "pxchartwidth" );
    Left = 1100;
    width = 310;
    x = 5;
    x2 = 310;

    y = pxHeight;

    GfxSelectPen( colorGreen, 1 ); // broader color
    GfxRoundRect( x, y - 180, x2, y , 7, 7 ) ;
    GfxTextOut( ""+WriteIf(intra, "Intraday Mode Activated", "Intraday Mode Not Activated" ), 13, y-180 );    
    GfxTextOut( ( "Current Qty "+qtarr ), 13, y-160 );
    GfxTextOut( ( "Last" + " Signal came " + ( BarsSince( Buy OR Short ) ) * Interval() / 60 + " mins ago" ), 13, y - 140 ) ; // The text format location
    GfxTextOut( ( "" + WriteIf( sig == 1, "BUY @ " + ValueWhen(Buy,C) , "SHORT @ " + ValueWhen(Short,C) ) ), 13, y - 120 );
    GfxTextOut( "Stop Loss : " + WriteIf(slp==0, "Not Activated", ""+slarr), 13, y - 100 );
    GfxTextOut( "Target : " + WriteIf(tgtp==0, "Not Activated", ""+tgtarr), 13, y - 80 );
    GfxTextOut( ( "Current P/L~ " + WriteVal( IIf( sig == 1, (C-ValueWhen(Buy,C))*qtarr, (ValueWhen(Short,C)-C)*qtarr ), 2.2 ) ), 13, y-60 );
    GfxTextOut( ( "Booked Profit for Day~ "+ WriteIf(intra, NumToStr(profarr, 1.2), "N/A") ), 13, y-40 );
}

/*for updated afl code always check https://algoji.com/amibroker-autotrade-afl-toolkit/ */

global algoji;
algoji = "k" +Name() + NumToStr( Interval() / 60, 1.0, False ) ;

procedure aStaticVarSet( SName, Svalue )
{
    global algoji;

        StaticVarSet( Sname + algoji, Svalue );
}

function aStaticVarGet( SName )
{
    global algoji;
    Var = StaticVarGet( Sname + algoji );

    if ( IsNull( Var = StaticVarGet( Sname + algoji ) ) )
        Var = 0;

    return Var;
}

sym = Name();

//_TRACE("t"+t);

Checkdt=Nz(aStaticVarGet("lastdt"));
dt = LastValue( DateTime() );
Checkdtss=Nz(aStaticVarGet("lastdtss"));
dtss = LastValue( DateTime() );
Checkdtc=Nz(aStaticVarGet("lastdtc"));
dtc = LastValue( DateTime() );
Checkdts=Nz(aStaticVarGet("lastdts"));
dts = LastValue( DateTime() );
RTBuy = LastValue( Buy) AND Checkdt != dt;
RTShort = LastValue( Short) AND Checkdtss != dtss;
RTCover = LastValue( Cover) AND Checkdtc != dtc;
RTSell = LastValue( Sell) AND Checkdts != dts;

if ( RTCover)
{
	 aStaticVarSet("lastdtc",dtc );
	 StaticVarSet("counter", Nz(StaticVarGet("counter"))+1 );
    bp= NumToStr(Close[BarCount-1],1.2, False);
	qty= NumToStr(qtarr[BarCount-2], 1.0, False);
            _TRACE( "#"+Nz(StaticVarGet("counter"))+",SX,"+sym+",,," +bp +","+qty+","+instr+",,");
	AlgoJi_Signal(NumToStr(Nz(StaticVarGet("counter")),0,False), "SX",sym,"M","",bp,qty,instr,stag);
}

if ( RTSell )
{
	 aStaticVarSet("lastdts",dts );
	 StaticVarSet("counter", Nz(StaticVarGet("counter"))+1 );
    sp= NumToStr(Close[BarCount-1],1.2, False);
	qty= NumToStr(qtarr[BarCount-2], 1.0, False);
            _TRACE( "#"+Nz(StaticVarGet("counter"))+",LX,"+sym+",,," +sp +","+qty+",,,");
	AlgoJi_Signal(NumToStr(Nz(StaticVarGet("counter")),0,False), "LX",sym,"M","",sp,qty,instr,stag);
}
//https://algoji.com/
if ( RTBuy )
{
	 aStaticVarSet("lastdt",dt );
	 StaticVarSet("counter", Nz(StaticVarGet("counter"))+1 );
    bp= NumToStr(Close[BarCount-1],1.2, False);
	qty= NumToStr(qtarr[BarCount-1], 1.0, False);
            _TRACE( "#"+Nz(StaticVarGet("counter"))+",LE,"+sym+",,," +bp +","+qty+","+instr+",,");
	AlgoJi_Signal(NumToStr(Nz(StaticVarGet("counter")),0,False), "LE",sym,"M","",bp,qty,instr,stag);
}
//https://algoji.com/
if ( RTShort )
{
	 aStaticVarSet("lastdtss",dtss );
	 StaticVarSet("counter", Nz(StaticVarGet("counter"))+1 );
    sp= NumToStr(Close[BarCount-1],1.2, False);
	qty= NumToStr(qtarr[BarCount-1], 1.0, False);
            _TRACE( "#"+Nz(StaticVarGet("counter"))+",SE,"+sym+",,," +sp +","+qty+","+instr+",,");
	AlgoJi_Signal(NumToStr(Nz(StaticVarGet("counter")),0,False), "SE",sym,"M","",sp,qty,instr,stag);
}

_SECTION_END();

_SECTION_BEGIN( "Button Trading" );
Button = ParamToggle( "Enable Button Trading", "YES|NO" );
expiry= ParamStr("Expiry","");
strike= ParamStr("Strike","");
type= ParamStr("Option Type", "");
	qty= NumToStr(qtarr[BarCount-1], 1.0, False);
	sp= NumToStr(Close[BarCount-1], 1.2, False);
sym = Name()+ "|"+expiry+ "|" +strike+ "|" +type;


function GetSecondNum()
{
    Time = Now( 4 );
    Seconds = int( Time % 100 );
    Minutes = int( Time / 100 % 100 );
    Hours = int( Time / 10000 % 100 );
    SecondNum = int( Hours * 60 * 60 + Minutes * 60 + Seconds );
    return SecondNum;
}
 
function PopupWindowEx( popupID, bodytext, captiontext, timeout, left, top )
{
    displayText = bodytext + captiontext;
    if ( ( StaticVarGetText( "prevPopup" + popupID ) != displayText) OR ( StaticVarGet( "prevPopupTime" + popupID ) < GetSecondNum() ) )
    {
        StaticVarSetText( "prevPopup" + popupID, displayText);
        StaticVarSet( "prevPopupTime" + popupID, GetSecondNum() + timeout );
        PopupWindow( bodytext, Captiontext + popupID, timeout, Left, top );
    }
}



x1= Status( "pxchartleft" )+10;
y1= Status( "pxcharttop" )+20;

if ( Button == 0 )
{
    click = GetCursorMouseButtons() == 9;
    Px = GetCursorXPosition( 1 );
    Py = GetCursorYPosition( 1 );

    x2 = x1 + 60;
    y2 = y1 + 60;
    GfxSelectSolidBrush(  ColorRGB( 0, 102, 0 ) ); //buy
    GfxSelectFont( "Tahoma", 13, 100 );
    GfxSetBkMode( 1 );
    GfxSetTextColor( colorWhite );
    GfxRoundRect( x1, y1, x2, y2 , 7, 7 ) ;
    GfxTextOut( "LE", x1 + 20, y1 + 20 );

    sx1 = x2;
    sy1 = y1;
    sx2 = sx1 + 60;
    sy2 = sy1 + 60;
    GfxSelectSolidBrush(  ColorRGB( 255, 204, 204 ) );//sell
    GfxRoundRect( sx1, sy1, sx2, sy2 , 7, 7 ) ;
    GfxSetTextColor( ColorRGB( 153, 0, 0 ) );
    GfxTextOut( "SE", sx1 + 20, sy1 + 20 );

    ex1 = x1;
    ey1 = y1+60;
    ex2 = ex1 + 60;
    ey2 = ey1 + 60;
    GfxSelectSolidBrush(  ColorRGB( 255, 204, 204 ) );//sell
    GfxRoundRect( ex1, ey1, ex2, ey2 , 7, 7 ) ;
    GfxSetTextColor( ColorRGB( 153, 0, 0 ) );
    GfxTextOut( "LX", ex1 + 20, ey1 + 20 );

    GfxSelectSolidBrush(  ColorRGB( 0, 102, 0 ) );//sell
    GfxRoundRect( ex2, ey1, ex2+60, ey2 , 7, 7 ) ;
    GfxSetTextColor( colorWhite );
    GfxTextOut( "SX", ex2 + 20, ey1 + 20 );

    if ( px > x1 AND px<x2 AND py>y1 AND py < y2 AND Click )
    {
        _TRACE( "# ," + NumToStr(Nz(StaticVarGet("counter")),0,False) + ", BUY triggered from button, "  );
		AlertIf( 1, "SOUND C:\\Windows\\Media\\tada.wav", "Audio alert", 1, 2, 1 );    
    StaticVarSet("counter", Nz(StaticVarGet("counter"))+1 );
    	PopupWindowEx( "ID:1", "BUY", "Buy Triggered from Button "+Name(), 1, -1, -1 );
	AlgoJi_Signal(NumToStr(Nz(StaticVarGet("counter")),0,False), "LE",sym,"M","",sp,qty,instr,stag);
	}
//https://algoji.com/
    if ( px > sx1 AND px<sx2 AND py>sy1 AND py < sy2 AND Click )
    {
        _TRACE( "# ," + NumToStr( DateTime(), formatDateTime ) + ", SHORT triggered from button, " );
		AlertIf( 2, "SOUND C:\\Windows\\Media\\tada.wav", "Audio alert", 2, 2, 1 );
    StaticVarSet("counter", Nz(StaticVarGet("counter"))+1 );
	PopupWindowEx( "ID:3", "SHORT", "Short Triggered from Button "+Name(), 1, -1, -1 );
	AlgoJi_Signal(NumToStr(Nz(StaticVarGet("counter")),0,False), "SE",sym,"M","",sp,qty,instr,stag);
    }
//https://algoji.com/
    if ( px > ex1 AND px<ex2 AND py>ey1 AND py<ey2 AND Click )
    {
        _TRACE( "# ," + NumToStr( DateTime(), formatDateTime ) + ", SELL triggered from button, " );
		AlertIf( 3, "SOUND C:\\Windows\\Media\\tada.wav", "Audio alert", 2, 2, 1 );
    StaticVarSet("counter", Nz(StaticVarGet("counter"))+1 );    
	PopupWindowEx( "ID:3", "SELL", "Sell Triggered from Button "+Name(), 1, -1, -1 );
	AlgoJi_Signal(NumToStr(Nz(StaticVarGet("counter")),0,False), "LX",sym,"M","",sp,qty,instr,stag);
    }
//https://algoji.com/
    if ( px > ex2 AND px<(ex2+60) AND py>ey1 AND py < ey2 AND Click )
    {
        _TRACE( "# ," + NumToStr( DateTime(), formatDateTime ) + ", Cover triggered from button, " );
		AlertIf( 4, "SOUND C:\\Windows\\Media\\tada.wav", "Audio alert", 2, 2, 1 );
    StaticVarSet("counter", Nz(StaticVarGet("counter"))+1 );
	PopupWindowEx( "ID:3", "Cover", "Cover  Triggered from Button "+Name(), 1, -1, -1 );
	AlgoJi_Signal(NumToStr(Nz(StaticVarGet("counter")),0,False), "SX",sym,"M","",sp,qty,instr,stag);
    }

}
_SECTION_END();

/*
//AlgojiBroadcastSignal(ID,Type,Symbol,OrderType,TrigPrice,Price,Qty,InstrumentName,StrategyTag)
            //Symbol = Symbol | Expiry | Strike | OptionType 
            //TrigPrice = TrigPrice | StopLoss | SquareOff | TrailingTicks
            //StrategyTag = StrategyTag | Port
            
            AlgojiBroadcastSignal("7", "LE","EURINR","M","","","300","NCD","","","","","STRAT1","");