Rajandran R Telecom Engineer turned Full-time Derivative Trader. Mostly Trading Nifty, Banknifty, USDINR and High Liquid Stock Derivatives. Trading the Markets Since 2006 onwards. Using Market Profile and Orderflow for more than a decade. Designed and published 100+ open source trading systems on various trading tools. Strongly believe that market understanding and robust trading frameworks are the key to the trading success. Writing about Markets, Trading System Design, Market Sentiment, Trading Softwares & Trading Nuances since 2007 onwards. Author of Marketcalls.in)

Things to Consider While Building a Bracket Order Execution Strategy for Algomojo Platform

16 min read

Building a Bracket Order Strategy is the most demanded request we got from most of the algomojo traders. This article explains the list of the key information you need to consider while building a bracket order based intraday trading strategy.

What is Bracket Order?

Bracket Orders are mostly intraday orders with immediate target and stop-loss orders. It is also called OCO (one cancels another). Means if the target level is touched by the current market profile then automatically stop-loss order is canceled and if the stop level is touched then the target order will be canceled automatically,

1)Ensure Latest Multi Broker Bridge is used

If you are deploying bracket order strategies then ensure you are using the latest bridge (Multi-Broker Bridge) from the Algomojo Portal. Ensure Proper Broker Short Code and Version is configured.

2)Get the Token ID from the Algomojo Portal

Login to the Algomojo Portal ->goto Watchlist -> Click on the symbol info as shown in the details and get the Token No

For example token no for reliance is 2885. Let this can be used as input to your trading strategy. If your broker is using NEST API then Token ID is mandatory for sending bracket orders.

3)Ensure Quick AFL is turned off

Ensure the quick AFL is turned off as you are likely to plot the target and stoploss level on the charts. you can disable the quick afl using the setbarsrequired function as shown below

SetBarsRequired(-2,-2); //diable quick AFL

4)Getting the Input Parameters

Since the Bracket Order based execution belong to pure intraday trading strategy then the following things need to be kept in the mind while getting input from the user.

1)Get the Target and Stoploss (% based stop is recommended)
2)Get the Tick size (as the stop level and target level needs to be rounded off to the nearest tick size while sending those stop and target levels to the Bracket Order
3)Use Time Based Sessions to Enter and Exit and Squareoff time for your trades.

//////////////////////////////////////////////////////////////////////
//                Trade Input Parameters          					//



//Exit Criteria
stops = Param("Stoploss %", 0.25,0,20,0.01);
target = Param("Target %", 0.5,0,20,0.01);
TickSz = Param("TickSize",0.05); //round off the stops and target to nearest tick size


sigstarttime = ParamTime("Sig Start Time", "10:00:00"); //no fresh position before signal start time
sigendtime = ParamTime("Sig End Time", "15:00:00"); //no fresh position after signal end time
sqofftime = ParamTime("Squareoff Time", "15:15:00");  //broker square off time

5)Enable Proper Logs

Ensure _Trace logs are enabled for proper trouble shooting and that will help traders to find the mistakes if any in the newly built code. And definitely helps traders to build a better trading system

6)Code only the Entry Condition and Compute Target and Stoploss Value

If you are coding for bracket orders obviously one should care about the entry logical condition as the exit is taken care of with the price either hitting the target levels or stop-loss levels.

If long only condition then ensure the sell, cover,short is maintained with zero intitalization.

Sell = Short = Cover = 0;

If the strategy contains both long and short condition then maintain the exit signals (Sell and Cover as zero)

Sell =  Cover = 0;

Here is the sample code logic with macd positive crossover stratey where only long condition is coded. And hence only Buy Entry logic is coded for the standard viable Buy and the Exit Signal is not assigned to the Sell Entry logic.

//////////////////////////////////////////////////////////////////////
//            Configure your trading condition here					//

longtradingcondition = Cross(MACD(), Signal());


//////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////
//            Trading Logic One Intraday Trade Per Day              //


Buy = longtradingcondition AND TimeNum() >= sigstarttime AND TimeNum() < sigendtime;
Buy = Buy AND Sum( Buy, BarsSince( newDay) +1 ) <= 1; //consider only the first signal for the day

entryprice = ValueWhen(Buy AND Sum( Buy, BarsSince( newDay) +1 )==1,Ref(Open,1));  //entry price at the next bar open and at the first signal
buystops1 = (100-stops)/100 * entryprice;
buytarget1 = (100+target)/100 * entryprice;


buystops = TickSz * round( buystops1 / TickSz );
buytarget = TickSz * round( buytarget1 / TickSz );


iSell = TimeNum() >= sqofftime OR Cross(High,buytarget) OR Cross(buystops,Low);

//Remove Excessive Signals
Buy = ExRem(Buy,iSell);
iSell = ExRem(iSell,Buy);


//Non Repainting  - Signals happens only after the close of the current
Buy = Ref(Buy,-1);
BuyPrice = Open;




iSellPrice = IIf(Cross(High,buytarget), buytarget, IIf( Cross(buystops,Low), buystops, Open));


buycontinue = Flip(Buy,iSell) OR isell; //look for continuation of trades

targethit = iSell AND Cross(High,buytarget);
stophit = iSell AND Cross(buystops,Low);
sqofftime = iSell AND TimeNum() >= sqofftime;


//This code place order only on Long Entry
Sell = Short = Cover = 0;


//////////////////////////////////////////////////////////////////////

7)Plot the Tick Adjusted Stoploss and Target

This helps in visualizing the target and stoplevels during intraday.

Plot(IIf(buycontinue,buystops,Null),"Stops",colorRed);
Plot(IIf(buycontinue,buytarget,Null),"Target",colorgreen);

8)Plot the Signals

Plot the Entry and Exit Signals for the Bracket order

/* Plot Buy and Sell Signal Arrows */
PlotShapes(IIf(Buy, shapeSquare, shapeNone),colorGreen, 0, L, Offset=-40);
PlotShapes(IIf(Buy, shapeSquare, shapeNone),colorLime, 0,L, Offset=-50);
PlotShapes(IIf(Buy, shapeUpArrow, shapeNone),colorWhite, 0,L, Offset=-45);
PlotShapes(IIf(iSell, shapeSquare, shapeNone),colorRed, 0, H, Offset=40);
PlotShapes(IIf(iSell, shapeSquare, shapeNone),colorOrange, 0,H, Offset=50);
PlotShapes(IIf(iSell, shapeDownArrow, shapeNone),colorWhite, 0,H, Offset=-45);

9)Ensure the Condition for Exit is displayed properly.

And Exit can happen for the following reasons

1)Target is hit
2)Stop is hit
3)Square off time is reached

Below code module is configured to get the display of Entry and Exit price values with Profit and Loss data point from that particular trade.

fntsize = 8;// font size
dist = 65;// y-offset

bi = Barindex();
fvb = FirstVisiblevalue( bi );
lvb = LastVisiblevalue( bi );

bkcolor = -1;// text background color, -1 means default color (transparent)

PlotTextSetFont( "", "ARIAL", fntsize, BarCount-1, 0, -1 );

pnl = ValueWhen(iSell,iSellPrice - entryprice);

for ( i = fvb; i <= lvb; i++ ) {
    if( Buy[i] || iSell[i] )	{
		buyvar = "\n@" + BuyPrice[i];
		sellvar = "\n@" + iSellPrice[i]+"\nPnl= "+pnl[i];
		if( Buy[i] )  PlotText( "Long Entry" + buyvar, i, L[i], colorGreen, bkcolor, -dist-2*fntsize );
		if( targethit[i] ) PlotText( "Target Hit" + sellvar, i, H[i], colorRed, bkcolor, dist+4.5*fntsize );
		if( stophit[i] ) PlotText( "Stop Hit" + sellvar, i, H[i], colorRed, bkcolor, dist+4.5*fntsize );
		if( sqofftime[i] ) PlotText( "SQoff.Time Hit" + sellvar, i, H[i], colorRed, bkcolor, dist+4.5*fntsize );
    }
}

10)Bracket Order Execution Module

Make sure only relevant information is got from the user and according to your strategy make sure all the rest of the parameters are configured default.

Refer the Algomojo Documentation for more detailed information about the parameters to be passed for PlaceBracketOrder API

It is recommended to use the Bracket Order Target and Stoploss Calculation in Absolute mode. Use Ticks mode if you are an advanced user.

It is recommended to send the Target and Stoploss information only after adjusting to the nearest tick size. Else Bracket Order could throw error while sending orders.

_SECTION_BEGIN("Algomojo Bracket Order Module");

uid = ParamStr("uid ID","TS2499"); //Enter your Trading Account Login ID
user_apikey = ParamStr("user_apikey","xxxxxxxxxxxxxxxxxxxxxx"); //Enter your API key here
api_secret = ParamStr("api_secret","xxxxxxxxxxxxxxxxxxxxxx"); //Enter your API secret key here
broker = ParamStr("Broker Code1","tj"); //Enter your Broker Short Code here
ver = ParamStr("version","1.0"); //Enter your API version here
s_prdt_ali = ParamList("s_prdt_ali","BO:BO|CNC:CNC|CO:CO|MIS:MIS|NRML:NRML",0); //Type of order
Tsym = ParamStr("Tsym","RELIANCE-EQ "); //Enter the symbol name here
exch = ParamList("Exchange","NFO|NSE|BSE|CDS|MCX|NCDEX|BFO|MCXSXFO|MCXSX",1); 
Ret = ParamList("Ret","DAY|IOC",0);
//Ttranstype = ParamList("Ttranstype","B|S",0);
prctyp = ParamList("prctyp","MKT|L|SL|SL-M",0);
Price = 0; //ParamList("Price","0");
qty = Param("Quatity",1,0,10000,1); 
discqty = "0"; //ParamList("discqty","0");
AMO = "NO"; //ParamList("AMO","NO|YES",0); //After market order
TokenNo = ParamStr("TokenNo","11184"); //Enter the token number of the symbol here. Check the Algomojo Watchlist symbol info to get the relevant symbol token no.
ltpOratp = "LTP"; //ParamList("ltpOratp","LTP|ATP",0);


 
SqrOffAbsOrticks = "Absolute";  //ParamList("SqrOffAbsOrticks","Absolute|Ticks",0); //If you select absolute then you can enter a decimal quantity. If you selected ticks you need to enter in multiples of ticks
SqrOffvalue = buytarget-entryprice; //ParamStr("SqrOffvalue","1"); 
SLAbsOrticks = "Absolute";   //ParamList("SLAbsOrticks","Absolute|Ticks",0);
SLvalue = entryprice-buystops ; //ParamStr("SLvalue","30");
trailingSL = "N"; //ParamList("trailingSL","Y|N",0); 
tSLticks = 1000; //ParamStr("tSLticks","100"); //Trailing SL value in ticks if user has opted to use trailingSL
placeordertype = "Realtime"; //ParamList("Place Order On","Realtime|CandleCompletion",0); // Place Order Type
EnableAlgo = ParamList("Algo Mode","Disable|Enable",0); // Algo Mode
stgy_name = ParamStr("Strategy Name","Test Strategy Chart"); // Strategy Name

static_name_ = Name()+GetChartID()+interval(2)+stgy_name;
static_name_algo = Name()+GetChartID()+interval(2)+stgy_name+"algostatus";
//StaticVarSet(static_name_algo, -1); 
GfxSelectFont( "BOOK ANTIQUA", 14, 100 );
GfxSetBkMode( 1 );
if(EnableAlgo == "Enable")
{
AlgoStatus = "Algo Enabled";
GfxSetTextColor( colorGreen ); 
GfxTextOut( "Algostatus : "+AlgoStatus , 20, 40); 
if(Nz(StaticVarGet(static_name_algo),0)!=1)
{
_TRACE("Algo Status : Enabled");
StaticVarSet(static_name_algo, 1);
}
}
if(EnableAlgo == "Disable")
{
AlgoStatus = "Algo Disabled";
GfxSetTextColor( colorRed ); 
GfxTextOut( "Algostatus : "+AlgoStatus , 20, 40); 
if(Nz(StaticVarGet(static_name_algo),0)!=0)
{
_TRACE("Algo Status : Disabled");
StaticVarSet(static_name_algo, 0);
}
}

if(placeordertype == "Realtime")
{
AlgoBuy = lastvalue(Ref(Buy,0));
AlgoSell = lastvalue(Ref(Sell,0));
AlgoShort = lastvalue(Ref(Short,0));
AlgoCover = lastvalue(Ref(Cover,0));
}

if(placeordertype == "CandleCompletion")
{
AlgoBuy = lastvalue(Ref(Buy,-1));
AlgoSell = lastvalue(Ref(Sell,-1));
AlgoShort = lastvalue(Ref(Short,-1));
AlgoCover = lastvalue(Ref(Cover,-1));
}


resp = "";

function bracketorder_buy(orderqty)
{
	algomojo=CreateObject("AMAMIBRIDGE.Main");
	api_data ="{\"stgy_name\":\""+stgy_name+"\",\"s_prdt_ali\":\""+s_prdt_ali+"\",\"TokenNo\":\""+TokenNo+"\",\"exch\":\""+exch+"\",\"Ttranstype\":\""+"B"+"\",\"Ret\":\""+Ret+"\",\"prctyp\":\""+prctyp+"\",\"qty\":\""+qty+"\",\"discqty\":\""+discqty+"\",\"Price\":\""+Price+"\",\"ltpOratp\":\""+ltpOratp+"\",\"SqrOffAbsOrticks\":\""+SqrOffAbsOrticks+"\",\"SqrOffvalue\":\""+SqrOffvalue+"\",\"SLAbsOrticks\":\""+SLAbsOrticks+"\",\"SLvalue\":\""+SLvalue+"\",\"trailingSL\":\""+trailingSL+"\",\"tSLticks\":\""+tSLticks+"\"}";
	resp=algomojo.AMDispatcher(user_apikey, api_secret,"PlaceBOOrder",api_data,broker,ver);
	_TRACE(resp);
}

function bracketorder_sell(orderqty)
{
	algomojo=CreateObject("AMAMIBRIDGE.Main");
	api_data ="{\"stgy_name\":\""+stgy_name+"\",\"s_prdt_ali\":\""+s_prdt_ali+"\",\"TokenNo\":\""+TokenNo+"\",\"exch\":\""+exch+"\",\"Ttranstype\":\""+"S"+"\",\"Ret\":\""+Ret+"\",\"prctyp\":\""+prctyp+"\",\"qty\":\""+qty+"\",\"discqty\":\""+discqty+"\",\"Price\":\""+Price+"\",\"ltpOratp\":\""+ltpOratp+"\",\"SqrOffAbsOrticks\":\""+SqrOffAbsOrticks+"\",\"SqrOffvalue\":\""+SqrOffvalue+"\",\"SLAbsOrticks\":\""+SLAbsOrticks+"\",\"SLvalue\":\""+SLvalue+"\",\"trailingSL\":\""+trailingSL+"\",\"tSLticks\":\""+tSLticks+"\"}";
	resp=algomojo.AMDispatcher(user_apikey, api_secret,"PlaceBOOrder",api_data,broker,ver);
	_TRACE(resp);
}


if(EnableAlgo != "Disable")
{
        lasttime = StrFormat("%0.f",LastValue(BarIndex()));
        
        SetChartBkColor(colorDarkGrey);
        if(EnableAlgo == "Enable")
        {   
            if (AlgoBuy==True AND AlgoCover == True AND StaticVarGet(static_name_+"buyCoverAlgo")==0 )
            {
            // reverse Long Entry 
                bracketorder_buy(qty*2);
                StaticVarSet(static_name_+"buyCoverAlgo",1); //Algo Order was triggered, no more order on this bar
                _TRACE("Strategy : "+ stgy_name +"AlgoStatus : "+ EnableAlgo +"Chart Symbol : "+ Name() +"  Trading Symbol : "+  Tsym +"  Quantity : "+ qty*2 +"  Signal : Buy and Cover Signal  TimeFrame : "+ Interval(2)+"  Response : "+ resp +"  ChardId : "+ GetChartID() + " Latest Price : "+LastValue(C));
        
            }
            else if ((AlgoBuy != True OR AlgoCover != True))
            {   
                StaticVarSet(static_name_+"buyCoverAlgo",0);
            }
            
            if (AlgoBuy==True AND AlgoCover != True AND StaticVarGet(static_name_+"buyAlgo")==0 )
            {
            // Long Entry 
                bracketorder_buy(qty);
                StaticVarSet(static_name_+"buyAlgo",1); //Algo Order was triggered, no more order on this bar
                _TRACE("Strategy : "+ stgy_name +"AlgoStatus : "+ EnableAlgo +"Chart Symbol : "+ Name() +"  Trading Symbol : "+  Tsym +"  Quantity : "+ qty +"  Signal : Buy Signal  TimeFrame : "+ Interval(2)+"  Response : "+ resp +"  ChardId : "+ GetChartID() + " Latest Price : "+LastValue(C));
            }
            else if (AlgoBuy != True)
            {   
                StaticVarSet(static_name_+"buyAlgo",0);
                
            }
            if (AlgoSell==true AND AlgoShort != True AND StaticVarGet(static_name_+"sellAlgo")==0 )
            {     
            // Long Exit 
                bracketorder_sell(qty);
                StaticVarSet(static_name_+"sellAlgo",1); //Algo Order was triggered, no more order on this bar
                _TRACE("Strategy : "+ stgy_name +"AlgoStatus : "+ EnableAlgo +"Chart Symbol : "+ Name() +"  Trading Symbol : "+  Tsym +"  Quantity : "+ qty +"  Signal : Sell Signal  TimeFrame : "+ Interval(2)+"  Response : "+ resp +"  ChardId : "+ GetChartID() + " Latest Price : "+LastValue(C));
            }
            else if (AlgoSell != True )
            {   
                StaticVarSet(static_name_+"sellAlgo",0);
            }
            if (AlgoShort==True AND AlgoSell==True AND  StaticVarGet(static_name_+"ShortSellAlgo")==0 )
            {
            // reverse Short Entry 
                bracketorder_sell(2*qty);
                StaticVarSet(static_name_+"ShortSellAlgo",1); //Algo Order was triggered, no more order on this bar
                _TRACE("Strategy : "+ stgy_name +"AlgoStatus : "+ EnableAlgo +"Chart Symbol : "+ Name() +"  Trading Symbol : "+  Tsym +"  Quantity : "+ qty*2 +"  Signal : Short and Sell Signal  TimeFrame : "+ Interval(2)+"  Response : "+ resp +"  ChardId : "+ GetChartID() + " Latest Price : "+LastValue(C));
            }
            else if ((AlgoShort != True OR AlgoSell != True))
            {   
                StaticVarSet(static_name_+"ShortSellAlgo",0);
            }
                
            if (AlgoShort==True  AND  AlgoSell != True AND StaticVarGet(static_name_+"ShortAlgo")==0  )
            {
            // Short Entry
                bracketorder_sell(qty);
                StaticVarSet(static_name_+"ShortAlgo",1); //Algo Order was triggered, no more order on this bar
                _TRACE("Strategy : "+ stgy_name +"AlgoStatus : "+ EnableAlgo +"Chart Symbol : "+ Name() +"  Trading Symbol : "+  Tsym +"  Quantity : "+ qty +"  Signal : Short Signal  TimeFrame : "+ Interval(2)+"  Response : "+ resp +"  ChardId : "+ GetChartID() + " Latest Price : "+LastValue(C));
            }
            else if (AlgoShort != True )
            {   
                StaticVarSet(static_name_+"ShortAlgo",0);
            }
            if (AlgoCover==true AND AlgoBuy != True AND StaticVarGet(static_name_+"CoverAlgo")==0 )
            {
            // Short Exit
                bracketorder_buy(qty);
                StaticVarSet(static_name_+"CoverAlgo",1); //Algo Order was triggered, no more order on this bar
                _TRACE("Strategy : "+ stgy_name +"AlgoStatus : "+ EnableAlgo +"Chart Symbol : "+ Name() +"  Trading Symbol : "+  Tsym +"  Quantity : "+ qty +"  Signal : Cover Signal  TimeFrame : "+ Interval(2)+"  Response : "+ resp +"  ChardId : "+ GetChartID() + " Latest Price : "+LastValue(C));
            }
            else if (AlgoCover != True )
            {   
                StaticVarSet(static_name_+"CoverAlgo",0);
            }
        }
        
}
     

Here is the complete Bracket order module for Long Only Execution with Target and Stoploss. And Trade got limited to only one trade per day. i.e only one long entry and one long exit will be triggered per trading symbol for any given day.

Here is the complete Amibroker AFL code with Bracket Order Module

_SECTION_BEGIN("Price");
SetBarsRequired(-2,-2); //diable quick AFL
SetChartOptions(0,chartShowArrows|chartShowDates);
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 
_SECTION_END();


_SECTION_BEGIN("Simple MACD Intraday Trading System");

//Buy on MACD, Signals on Positive Crossover and also trade should be executed between 10a.m and 3p.m
//Exit on MACD, Signals negative crossover and also square off the position if time is 3.15p.m

// identify new day
dn = DateNum();
newDay = dn != Ref( dn,-1);



//////////////////////////////////////////////////////////////////////
//                Trade Input Parameters          					//



//Exit Criteria
stops = Param("Stoploss %", 0.25,0,20,0.01);
target = Param("Target %", 0.5,0,20,0.01);
TickSz = Param("TickSize",0.05); //round off the stops and target to nearest tick size


sigstarttime = ParamTime("Sig Start Time", "10:00:00"); //no fresh position before signal start time
sigendtime = ParamTime("Sig End Time", "15:00:00"); //no fresh position after signal end time
sqofftime = ParamTime("Squareoff Time", "15:15:00");  //broker square off time




//////////////////////////////////////////////////////////////////////
//            Configure your trading condition here					//

longtradingcondition = Cross(MACD(), Signal());


//////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////
//            Trading Logic One Intraday Trade Per Day              //


Buy = longtradingcondition AND TimeNum() >= sigstarttime AND TimeNum() < sigendtime;
Buy = Buy AND Sum( Buy, BarsSince( newDay) +1 ) <= 1; //consider only the first signal for the day

entryprice = ValueWhen(Buy AND Sum( Buy, BarsSince( newDay) +1 )==1,Ref(Open,1));  //entry price at the next bar open and at the first signal
buystops1 = (100-stops)/100 * entryprice;
buytarget1 = (100+target)/100 * entryprice;


buystops = TickSz * round( buystops1 / TickSz );
buytarget = TickSz * round( buytarget1 / TickSz );


iSell = TimeNum() >= sqofftime OR Cross(High,buytarget) OR Cross(buystops,Low);

//Remove Excessive Signals
Buy = ExRem(Buy,iSell);
iSell = ExRem(iSell,Buy);


//Non Repainting  - Signals happens only after the close of the current
Buy = Ref(Buy,-1);
BuyPrice = Open;




iSellPrice = IIf(Cross(High,buytarget), buytarget, IIf( Cross(buystops,Low), buystops, Open));


buycontinue = Flip(Buy,iSell) OR isell; //look for continuation of trades

targethit = iSell AND Cross(High,buytarget);
stophit = iSell AND Cross(buystops,Low);
sqofftime = iSell AND TimeNum() >= sqofftime;


//This code place order only on Long Entry
Sell = Short = Cover = 0;


//////////////////////////////////////////////////////////////////////


Plot(IIf(buycontinue,buystops,Null),"Stops",colorRed);
Plot(IIf(buycontinue,buytarget,Null),"Target",colorgreen);


/* Plot Buy and Sell Signal Arrows */
PlotShapes(IIf(Buy, shapeSquare, shapeNone),colorGreen, 0, L, Offset=-40);
PlotShapes(IIf(Buy, shapeSquare, shapeNone),colorLime, 0,L, Offset=-50);
PlotShapes(IIf(Buy, shapeUpArrow, shapeNone),colorWhite, 0,L, Offset=-45);
PlotShapes(IIf(iSell, shapeSquare, shapeNone),colorRed, 0, H, Offset=40);
PlotShapes(IIf(iSell, shapeSquare, shapeNone),colorOrange, 0,H, Offset=50);
PlotShapes(IIf(iSell, shapeDownArrow, shapeNone),colorWhite, 0,H, Offset=-45);


SetPositionSize(1*RoundLotSize,spsShares);


fntsize = 8;// font size
dist = 65;// y-offset

bi = Barindex();
fvb = FirstVisiblevalue( bi );
lvb = LastVisiblevalue( bi );

bkcolor = -1;// text background color, -1 means default color (transparent)

PlotTextSetFont( "", "ARIAL", fntsize, BarCount-1, 0, -1 );

pnl = ValueWhen(iSell,iSellPrice - entryprice);

for ( i = fvb; i <= lvb; i++ ) {
    if( Buy[i] || iSell[i] )	{
		buyvar = "\n@" + BuyPrice[i];
		sellvar = "\n@" + iSellPrice[i]+"\nPnl= "+pnl[i];
		if( Buy[i] )  PlotText( "Long Entry" + buyvar, i, L[i], colorGreen, bkcolor, -dist-2*fntsize );
		if( targethit[i] ) PlotText( "Target Hit" + sellvar, i, H[i], colorRed, bkcolor, dist+4.5*fntsize );
		if( stophit[i] ) PlotText( "Stop Hit" + sellvar, i, H[i], colorRed, bkcolor, dist+4.5*fntsize );
		if( sqofftime[i] ) PlotText( "SQoff.Time Hit" + sellvar, i, H[i], colorRed, bkcolor, dist+4.5*fntsize );
    }
}



_SECTION_END();


_SECTION_BEGIN("Algomojo Bracket Order Module");

uid = ParamStr("uid ID","TS2499"); //Enter your Trading Account Login ID
user_apikey = ParamStr("user_apikey","xxxxxxxxxxxxx"); //Enter your API key here
api_secret = ParamStr("api_secret","xxxxxxxxxxxxx"); //Enter your API secret key here
broker = ParamStr("Broker Code1","tj"); //Enter your Broker Short Code here
ver = ParamStr("version","1.0"); //Enter your API version here
s_prdt_ali = ParamList("s_prdt_ali","BO:BO|CNC:CNC|CO:CO|MIS:MIS|NRML:NRML",0); //Type of order
Tsym = ParamStr("Tsym","RELIANCE-EQ "); //Enter the symbol name here
exch = ParamList("Exchange","NFO|NSE|BSE|CDS|MCX|NCDEX|BFO|MCXSXFO|MCXSX",1); 
Ret = ParamList("Ret","DAY|IOC",0);
//Ttranstype = ParamList("Ttranstype","B|S",0);
prctyp = ParamList("prctyp","MKT|L|SL|SL-M",0);
Price = 0; //ParamList("Price","0");
qty = Param("Quatity",1,0,10000,1); 
discqty = "0"; //ParamList("discqty","0");
AMO = "NO"; //ParamList("AMO","NO|YES",0); //After market order
TokenNo = ParamStr("TokenNo","11184"); //Enter the token number of the symbol here. Check the Algomojo Watchlist symbol info to get the relevant symbol token no.
ltpOratp = "LTP"; //ParamList("ltpOratp","LTP|ATP",0);


 
SqrOffAbsOrticks = "Absolute";  //ParamList("SqrOffAbsOrticks","Absolute|Ticks",0); //If you select absolute then you can enter a decimal quantity. If you selected ticks you need to enter in multiples of ticks
SqrOffvalue = buytarget-entryprice; //ParamStr("SqrOffvalue","1"); 
SLAbsOrticks = "Absolute";   //ParamList("SLAbsOrticks","Absolute|Ticks",0);
SLvalue = entryprice-buystops ; //ParamStr("SLvalue","30");
trailingSL = "N"; //ParamList("trailingSL","Y|N",0); 
tSLticks = 1000; //ParamStr("tSLticks","100"); //Trailing SL value in ticks if user has opted to use trailingSL
placeordertype = "Realtime"; //ParamList("Place Order On","Realtime|CandleCompletion",0); // Place Order Type
EnableAlgo = ParamList("Algo Mode","Disable|Enable",0); // Algo Mode
stgy_name = ParamStr("Strategy Name","Test Strategy Chart"); // Strategy Name

static_name_ = Name()+GetChartID()+interval(2)+stgy_name;
static_name_algo = Name()+GetChartID()+interval(2)+stgy_name+"algostatus";
//StaticVarSet(static_name_algo, -1); 
GfxSelectFont( "BOOK ANTIQUA", 14, 100 );
GfxSetBkMode( 1 );
if(EnableAlgo == "Enable")
{
AlgoStatus = "Algo Enabled";
GfxSetTextColor( colorGreen ); 
GfxTextOut( "Algostatus : "+AlgoStatus , 20, 40); 
if(Nz(StaticVarGet(static_name_algo),0)!=1)
{
_TRACE("Algo Status : Enabled");
StaticVarSet(static_name_algo, 1);
}
}
if(EnableAlgo == "Disable")
{
AlgoStatus = "Algo Disabled";
GfxSetTextColor( colorRed ); 
GfxTextOut( "Algostatus : "+AlgoStatus , 20, 40); 
if(Nz(StaticVarGet(static_name_algo),0)!=0)
{
_TRACE("Algo Status : Disabled");
StaticVarSet(static_name_algo, 0);
}
}

if(placeordertype == "Realtime")
{
AlgoBuy = lastvalue(Ref(Buy,0));
AlgoSell = lastvalue(Ref(Sell,0));
AlgoShort = lastvalue(Ref(Short,0));
AlgoCover = lastvalue(Ref(Cover,0));
}

if(placeordertype == "CandleCompletion")
{
AlgoBuy = lastvalue(Ref(Buy,-1));
AlgoSell = lastvalue(Ref(Sell,-1));
AlgoShort = lastvalue(Ref(Short,-1));
AlgoCover = lastvalue(Ref(Cover,-1));
}


resp = "";

function bracketorder_buy(orderqty)
{
	algomojo=CreateObject("AMAMIBRIDGE.Main");
	api_data ="{\"stgy_name\":\""+stgy_name+"\",\"s_prdt_ali\":\""+s_prdt_ali+"\",\"TokenNo\":\""+TokenNo+"\",\"exch\":\""+exch+"\",\"Ttranstype\":\""+"B"+"\",\"Ret\":\""+Ret+"\",\"prctyp\":\""+prctyp+"\",\"qty\":\""+qty+"\",\"discqty\":\""+discqty+"\",\"Price\":\""+Price+"\",\"ltpOratp\":\""+ltpOratp+"\",\"SqrOffAbsOrticks\":\""+SqrOffAbsOrticks+"\",\"SqrOffvalue\":\""+SqrOffvalue+"\",\"SLAbsOrticks\":\""+SLAbsOrticks+"\",\"SLvalue\":\""+SLvalue+"\",\"trailingSL\":\""+trailingSL+"\",\"tSLticks\":\""+tSLticks+"\"}";
	resp=algomojo.AMDispatcher(user_apikey, api_secret,"PlaceBOOrder",api_data,broker,ver);
	_TRACE(resp);
}

function bracketorder_sell(orderqty)
{
	algomojo=CreateObject("AMAMIBRIDGE.Main");
	api_data ="{\"stgy_name\":\""+stgy_name+"\",\"s_prdt_ali\":\""+s_prdt_ali+"\",\"TokenNo\":\""+TokenNo+"\",\"exch\":\""+exch+"\",\"Ttranstype\":\""+"S"+"\",\"Ret\":\""+Ret+"\",\"prctyp\":\""+prctyp+"\",\"qty\":\""+qty+"\",\"discqty\":\""+discqty+"\",\"Price\":\""+Price+"\",\"ltpOratp\":\""+ltpOratp+"\",\"SqrOffAbsOrticks\":\""+SqrOffAbsOrticks+"\",\"SqrOffvalue\":\""+SqrOffvalue+"\",\"SLAbsOrticks\":\""+SLAbsOrticks+"\",\"SLvalue\":\""+SLvalue+"\",\"trailingSL\":\""+trailingSL+"\",\"tSLticks\":\""+tSLticks+"\"}";
	resp=algomojo.AMDispatcher(user_apikey, api_secret,"PlaceBOOrder",api_data,broker,ver);
	_TRACE(resp);
}


if(EnableAlgo != "Disable")
{
        lasttime = StrFormat("%0.f",LastValue(BarIndex()));
        
        SetChartBkColor(colorDarkGrey);
        if(EnableAlgo == "Enable")
        {   
            if (AlgoBuy==True AND AlgoCover == True AND StaticVarGet(static_name_+"buyCoverAlgo")==0 )
            {
            // reverse Long Entry 
                bracketorder_buy(qty*2);
                StaticVarSet(static_name_+"buyCoverAlgo",1); //Algo Order was triggered, no more order on this bar
                _TRACE("Strategy : "+ stgy_name +"AlgoStatus : "+ EnableAlgo +"Chart Symbol : "+ Name() +"  Trading Symbol : "+  Tsym +"  Quantity : "+ qty*2 +"  Signal : Buy and Cover Signal  TimeFrame : "+ Interval(2)+"  Response : "+ resp +"  ChardId : "+ GetChartID() + " Latest Price : "+LastValue(C));
        
            }
            else if ((AlgoBuy != True OR AlgoCover != True))
            {   
                StaticVarSet(static_name_+"buyCoverAlgo",0);
            }
            
            if (AlgoBuy==True AND AlgoCover != True AND StaticVarGet(static_name_+"buyAlgo")==0 )
            {
            // Long Entry 
                bracketorder_buy(qty);
                StaticVarSet(static_name_+"buyAlgo",1); //Algo Order was triggered, no more order on this bar
                _TRACE("Strategy : "+ stgy_name +"AlgoStatus : "+ EnableAlgo +"Chart Symbol : "+ Name() +"  Trading Symbol : "+  Tsym +"  Quantity : "+ qty +"  Signal : Buy Signal  TimeFrame : "+ Interval(2)+"  Response : "+ resp +"  ChardId : "+ GetChartID() + " Latest Price : "+LastValue(C));
            }
            else if (AlgoBuy != True)
            {   
                StaticVarSet(static_name_+"buyAlgo",0);
                
            }
            if (AlgoSell==true AND AlgoShort != True AND StaticVarGet(static_name_+"sellAlgo")==0 )
            {     
            // Long Exit 
                bracketorder_sell(qty);
                StaticVarSet(static_name_+"sellAlgo",1); //Algo Order was triggered, no more order on this bar
                _TRACE("Strategy : "+ stgy_name +"AlgoStatus : "+ EnableAlgo +"Chart Symbol : "+ Name() +"  Trading Symbol : "+  Tsym +"  Quantity : "+ qty +"  Signal : Sell Signal  TimeFrame : "+ Interval(2)+"  Response : "+ resp +"  ChardId : "+ GetChartID() + " Latest Price : "+LastValue(C));
            }
            else if (AlgoSell != True )
            {   
                StaticVarSet(static_name_+"sellAlgo",0);
            }
            if (AlgoShort==True AND AlgoSell==True AND  StaticVarGet(static_name_+"ShortSellAlgo")==0 )
            {
            // reverse Short Entry 
                bracketorder_sell(2*qty);
                StaticVarSet(static_name_+"ShortSellAlgo",1); //Algo Order was triggered, no more order on this bar
                _TRACE("Strategy : "+ stgy_name +"AlgoStatus : "+ EnableAlgo +"Chart Symbol : "+ Name() +"  Trading Symbol : "+  Tsym +"  Quantity : "+ qty*2 +"  Signal : Short and Sell Signal  TimeFrame : "+ Interval(2)+"  Response : "+ resp +"  ChardId : "+ GetChartID() + " Latest Price : "+LastValue(C));
            }
            else if ((AlgoShort != True OR AlgoSell != True))
            {   
                StaticVarSet(static_name_+"ShortSellAlgo",0);
            }
                
            if (AlgoShort==True  AND  AlgoSell != True AND StaticVarGet(static_name_+"ShortAlgo")==0  )
            {
            // Short Entry
                bracketorder_sell(qty);
                StaticVarSet(static_name_+"ShortAlgo",1); //Algo Order was triggered, no more order on this bar
                _TRACE("Strategy : "+ stgy_name +"AlgoStatus : "+ EnableAlgo +"Chart Symbol : "+ Name() +"  Trading Symbol : "+  Tsym +"  Quantity : "+ qty +"  Signal : Short Signal  TimeFrame : "+ Interval(2)+"  Response : "+ resp +"  ChardId : "+ GetChartID() + " Latest Price : "+LastValue(C));
            }
            else if (AlgoShort != True )
            {   
                StaticVarSet(static_name_+"ShortAlgo",0);
            }
            if (AlgoCover==true AND AlgoBuy != True AND StaticVarGet(static_name_+"CoverAlgo")==0 )
            {
            // Short Exit
                bracketorder_buy(qty);
                StaticVarSet(static_name_+"CoverAlgo",1); //Algo Order was triggered, no more order on this bar
                _TRACE("Strategy : "+ stgy_name +"AlgoStatus : "+ EnableAlgo +"Chart Symbol : "+ Name() +"  Trading Symbol : "+  Tsym +"  Quantity : "+ qty +"  Signal : Cover Signal  TimeFrame : "+ Interval(2)+"  Response : "+ resp +"  ChardId : "+ GetChartID() + " Latest Price : "+LastValue(C));
            }
            else if (AlgoCover != True )
            {   
                StaticVarSet(static_name_+"CoverAlgo",0);
            }
        }
        
}
     


Rajandran R Telecom Engineer turned Full-time Derivative Trader. Mostly Trading Nifty, Banknifty, USDINR and High Liquid Stock Derivatives. Trading the Markets Since 2006 onwards. Using Market Profile and Orderflow for more than a decade. Designed and published 100+ open source trading systems on various trading tools. Strongly believe that market understanding and robust trading frameworks are the key to the trading success. Writing about Markets, Trading System Design, Market Sentiment, Trading Softwares & Trading Nuances since 2007 onwards. Author of Marketcalls.in)

[Live Coding Webinar] Build Your First Trading Bridge for…

In this course, you will be learning to build your own trading bridge using Python. This 60-minute session is perfect for traders, Python enthusiasts,...
Rajandran R
1 min read

[Webinar] Understanding and Mitigating Curve Fitting in System Trading

"Understanding and Mitigating Curve Fitting in System Trading"! This dynamic session aims to equip novice to intermediate traders, quantitative analysts, and financial engineers with...
Rajandran R
1 min read

P-Signal Strategy Long Only Strategy – Amibroker AFL Code

This tutorial provides an overview of the P-Signal reversal strategy, a quantitative trading strategy that utilizes statistical parameters and error functions to generate probabilistic...
Rajandran R
2 min read

3 Replies to “Things to Consider While Building a Bracket Order Execution…”

    1. This code if you want to backtest you have to configure the exit instructions properly. In the above code sell = 0 and cover = 0 to avoid any execution at the exit point coz bracket order takes care of that.

      Instead isell and icover variables are used. If you assign sell = isell and cover = icover then strategy is backtesable but this will create issues while execution as additional exit orders will be placed. To avoid that
      I kept sell = cover = 0

Leave a Reply

Get Notifications, Alerts on Market Updates, Trading Tools, Automation & More