This tutorial focus on how to automate your index straddle/strangle strategy with intraday stop-loss levels with time-based entry and exits using Algomojo Platform and Amibroker.

Trading Activity | Orders to be Placed |
Time Based Entry | Enter Straddle/Strangle at 9.30a.m (Two legged Order) |
Calculate the Short Call Average Price | Calculate the Short call Stoploss |
Calculate the Short Put Average Price | Calculate the Short Put Stoploss |
Place Stoploss Orders | Place the Stoploss for both Short call and Short Put if the entry order status is completed |
Check Open Positions | Check the Open Positions for the Qty traded |
Time Based Exit | Square of Short Call and Short Put legs for the qty present in the open positions around 3.15p.m. |
upported Brokers : Aliceblue, Tradejini, Zebu
Supported Trading Instruments : Index Options
To Build this module we need 2 components
1)Header Option Execution Module that needs to be placed inside the Amibroker\Formulas\Include folder
2)Main Option Execution Module that needs to be drag and dropped over the Blank Chart
1)Header Include Option Execution Module
Copy the Header Execution Module to Amibroker\Formulas\include folder. Save the AFL under the name algomojostraddle.afl
//////////////////////////////////////////////
//Multi Broker Amibroker Option Straddle Execution Module
//Coded by Rajandran - Algomojo Co-Founder
//Date : 18/01/2021
//////////////////////////////////////////////
//Use this code only for Single Legged Long Only Options and Exiting Long Only Options
_SECTION_BEGIN("Algomojo Multi legged Options");
uid = ParamStr("Client ID","TS2499");
user_apikey = ParamStr("user_apikey","86cbef19e7e61ccee91e497690d5814e"); //Enter your API key here
api_secret = ParamStr("api_secret","4a94db82ea4fa140afaa2f039efffd18"); //Enter your API secret key here
s_prdt_ali = "BO:BO||CNC:CNC||CO:CO||MIS:MIS||NRML:NRML";
prctyp = ParamList("prctyp","MKT|L|SL|SL-M",0);
Pcode = ParamList("Pcode","NRML|CO|MIS",2);
Price = ParamList("Price","0");
TrigPrice = ParamList("TrigPrice","0");
exch = "NFO"; //Exchange
Ret = "DAY"; //Retention
AMO = "NO"; //AMO Order
stgy_name = ParamStr("Strategy Name", "Options");
broker = ParamStr("Broker","ab"); //Broker Short Code - ab - aliceblue, tj - tradejini, zb - zebu, en - enrich
ver = ParamStr("API Version","1.0");
fpath = ParamStr("Symbol Filepath", "C:\\Program Files (x86)\\AmiBroker\\Formulas\\Algomojo\\");
timer = 1; //3 seconds for providing delay after placing order
RequestTimedRefresh(1,False);
function placestoplossorder(SLTsym,orderaction,averageprice,stoppercent,orderqty)
{
//rounded of to nearest tick
TickSize = 0.05;
slprice = int(StrToNum(averageprice) + (StrToNum(averageprice) * stoppercent/100));
slprice = Prec(slprice,2);
rem = slprice % TickSize;
slprice = slprice - rem; //rounded of to nearest tick size
algomojo=CreateObject("AMAMIBRIDGE.Main");
api_data ="{\"stgy_name\":\""+stgy_name+"\",\"s_prdt_ali\":\""+s_prdt_ali+"\",\"Tsym\":\""+SLTsym+"\",\"exch\":\""+exch+"\",\"Ttranstype\":\""+orderaction+"\",\"Ret\":\""+Ret+"\",\"prctyp\":\""+"SL-M"+"\",\"qty\":\""+orderqty+"\",\"discqty\":\""+"0"+"\",\"MktPro\":\""+"NA"+"\",\"Price\":\""+"0"+"\",\"TrigPrice\":\""+slprice+"\",\"Pcode\":\""+Pcode+"\",\"AMO\":\""+AMO+"\"}";
_TRACE("");
_TRACE("API Request"+api_data);
resp=algomojo.AMDispatcher(user_apikey, api_secret,"PlaceOrder",api_data,broker,ver);
Say( "Stoploss Order is Placed" );
return resp;
}
function getnestorderno(response)
{
NOrdNo = "";
if(StrFind(response,"NOrdNo")) //Matches the orderstatus
{
NOrdNo = StrTrim( response, "{\"NOrdNo\":" );
NOrdNo = StrTrim( NOrdNo, "\",\"stat\":\"Ok\"}" );
}
return NOrdNo;
}
function getorderhistory(orderno)
{
algomojo=CreateObject("AMAMIBRIDGE.Main");
api_data = "{\"uid\":\""+uid+"\",\"NOrdNo\":\""+orderno+"\",\"s_prdt_ali\":\""+s_prdt_ali+"\"}";
resp=algomojo.AMDispatcher(user_apikey, api_secret,"OrderHistory",api_data,broker,ver);
return resp;
}
function getsymbol(orderno)
{
ordresp = getorderhistory(orderno);
data = "";
Trsym="";
for( item = 0; ( sym = StrExtract( ordresp, item,'{' )) != ""; item++ )
{
sym = StrTrim(sym," "); //Trim Whitespaces
if(StrFind(sym,"complete") OR StrFind(sym,"rejected")) //Matches the orderstatus
{
flag = 1; //turn on the flag
data = sym;
for( jitem = 0; ( ohistory = StrExtract( data, jitem,',' )) != ""; jitem++ )
{
if(Strfind(ohistory,"Trsym"))
{
Trsym = StrExtract(ohistory,1,':');
Trsym = StrTrim(Trsym,"\"");
}
}
}
}
return Trsym;
}
function getaverageprice(orderno)
{
ordresp = getorderhistory(orderno);
data = "";
averageprice="";
for( item = 0; ( sym = StrExtract( ordresp, item,'{' )) != ""; item++ )
{
sym = StrTrim(sym," "); //Trim Whitespaces
if(StrFind(sym,"complete") OR StrFind(sym,"rejected")) //Matches the orderstatus
{
flag = 1; //turn on the flag
data = sym;
for( jitem = 0; ( ohistory = StrExtract( data, jitem,',' )) != ""; jitem++ )
{
if(Strfind(ohistory,"averageprice"))
{
averageprice = StrExtract(ohistory,1,':');
averageprice = StrTrim(averageprice,"\"");
}
}
}
}
if(averageprice=="0.0")
{
averageprice = "100";
}
return averageprice;
}
function getorderstatus(orderno)
{
orderstatus="";
ordresp = getorderhistory(orderno);
data = "";
for( item = 0; ( sym = StrExtract( ordresp, item,'{' )) != ""; item++ )
{
sym = StrTrim(sym," "); //Trim Whitespaces
if(StrFind(sym,"complete") OR StrFind(sym,"rejected")) //Matches the orderstatus
{
flag = 1; //turn on the flag
data = sym;
for( jitem = 0; ( ohistory = StrExtract( data, jitem,',' )) != ""; jitem++ )
{
if(Strfind(ohistory,"Status"))
{
orderstatus = StrExtract(ohistory,1,':');
orderstatus = StrTrim(orderstatus,"\"");
}
}
}
}
return orderstatus;
}//end function
function gettoken(symbol)
{
stoken="";
algomojo=CreateObject("AMAMIBRIDGE.Main");
api_data = "{\"s\":\""+symbol+"\"}";
resp=algomojo.AMDispatcher(user_apikey, api_secret,"fetchsymbol",api_data,broker,ver);
for( item = 0; ( sym = StrExtract( resp, item,'{' )) != ""; item++ )
{
sym = StrTrim(sym," "); //Trim Whitespaces
data = sym;
for( jitem = 0; ( ofetch = StrExtract( data, jitem,',' )) != ""; jitem++ )
{
if(Strfind(ofetch,"symbol_token"))
{
stoken = StrExtract(ofetch,1,':');
stoken = StrTrim(stoken,"\"");
}
}
}
return stoken;
}
function writetofile(filepath,ordno,symbol,ostatus,averageprice)
{
result =0;
if(ostatus=="complete" OR ostatus=="rejected")
{
fh = fopen( filepath, "w"); //Filepath of csv file with symbols
if(fh)
{
fputs(ordno + ",", fh);
fputs(symbol + ",", fh);
fputs(ostatus+",", fh);
fputs(averageprice+",", fh);
fclose(fh);
result =1;
}
}
return result;
}
function placeoptionorder(spot_sym,expiry_dt,strike_int,qty,Ttranstype,opt,off,leg,stoppercent)
{
algomojo=CreateObject("AMAMIBRIDGE.Main");
api_data = "{\"strg_name\":\""+stgy_name+"\",\"spot_sym\":\""+spot_sym+"\",\"expiry_dt\":\""+expiry_dt+"\",\"opt_type\":\""+opt+"\",\"Ttranstype\":\""+Ttranstype+"\",\"prctyp\":\""+prctyp+"\",\"qty\":\""+qty+"\",\"Price\":\""+Price+"\",\"TrigPrice\":\""+TrigPrice+"\",\"Pcode\":\""+Pcode+"\",\"strike_int\":\""+strike_int+"\",\"offset\":\""+off+"\"}";
resp=algomojo.AMDispatcher(user_apikey, api_secret,"PlaceFOOptionsOrder",api_data,broker,ver);
_TRACE("\n"+api_data);
//Get Nest Order Number
nestorderno = getnestorderno(resp);
_TRACE("\nNest Order No : "+nestorderno);
tradetime=GetPerformanceCounter()/1000;
while ((GetPerformanceCounter()/1000 - tradetime) < timer)
{
//Get Trading Symbol
Tsym = getsymbol(nestorderno);
}
_TRACE("\nTrading Symbol : "+Tsym);
//Get Order Status
orderstatus = getorderstatus(nestorderno);
_TRACE("\nOrder Status : "+orderstatus);
if(orderstatus=="complete" OR orderstatus=="rejected")
{
averageprice = getaverageprice(nestorderno);
_TRACE("Average Price: "+averageprice);
}
if(orderstatus=="complete") //changed to complete in a live environment and rejected for testing purpose
{
//Stoploss order x% from the average price
slresponse = placestoplossorder(Tsym,"B",averageprice,stoppercent,qty);
_TRACE("Leg "+leg+" Stoploss Response: "+slresponse);
}
//Get Token Number
//token = gettoken(Tsym);
//_TRACE("\nSymbol Token : "+token);
if(opt=="CE")
{
path = fpath+leg+"AlgomojoCE.csv";
}
if(opt=="PE")
{
path = fpath+leg+"AlgomojoPE.csv";
}
writestatus = writetofile(path,nestorderno,Tsym,orderstatus,averageprice);
_TRACEF(WriteIf(writestatus,"\nWriting to File - Success","\nWriting to File - Failure"));
//resp = resp+"\nNest Order No : "+nestorderno+"\nTrading Symbol : "+Tsym+"\nOrder Status : "+orderstatus+"\nSymbol Token : "+token;
return Tsym;
}
function getquantity(Tsym)
{
algomojo=CreateObject("AMAMIBRIDGE.Main");
api_data ="{\"uid\":\""+uid+"\",\"actid\":\""+uid+"\",\"type\":\""+"NET"+"\",\"s_prdt_ali\":\""+s_prdt_ali+"\"}";
resp=algomojo.AMDispatcher(user_apikey, api_secret,"PositionBook",api_data,broker,ver);
//Initialization
flag = 0;
possym = "";
posNetqty =0;
for( item = 0; ( sym = StrExtract( resp, item,'{' )) != ""; item++ )
{
sym = StrTrim(sym," ");
Tsym = StrTrim(Tsym," ");
if(Strfind(sym,Tsym) AND StrFind(sym,Pcode)) //Matches the symbol and //Matches the Order Type
{
flag = 1; //turn on the flag
data = sym;
_TRACE(" Position Book : " +data);
for( jitem = 0; ( posdetails = StrExtract( data, jitem,',' )) != ""; jitem++ )
{
if(Strfind(posdetails,"Netqty"))
{
posdetails = StrExtract(posdetails,1,':');
posNetqty = StrToNum(StrTrim(posdetails,"\""));
_TRACE("\nNetQty : "+posNetqty);
}
} //end of for loop
}
}//end of for loop
if(flag==0)
{
_TRACE("\nTrading Symbol Not Found");
}
return posNetqty;
}
function squareoffoptions(opt,Ttranstype,leg)
{
ttype="";
if(Ttranstype=="B")
{
ttype = "S";
}
if(Ttranstype=="S")
{
ttype = "B";
}
ordno = "";
Symbol = "";
ostatus ="";
if(opt=="CE")
{
fpath = fpath+leg+"AlgomojoCE.csv";
}
if(opt=="PE")
{
fpath = fpath+leg+"AlgomojoPE.csv";
}
fh = fopen(fpath, "r");
if(fh)
{
read = fgets(fh);
ordno = StrTrim(StrExtract(read,0)," ");
Symbol = StrTrim(StrExtract(read,1)," ");
ostatus = StrTrim(StrExtract(read,2)," ");
averageprice = StrTrim(StrExtract(read,3)," ");
fclose(fh);
}
exitqty = getquantity(Symbol);
_TRACE("Net Quantity in the OrderBook for the Symbol : "+Symbol+" is : "+exitqty);
if(ostatus=="complete" AND exitqty!=0)
{
algomojo=CreateObject("AMAMIBRIDGE.Main");
api_data = "{\"strg_name\":\""+stgy_name+"\",\"s_prdt_ali\":\""+s_prdt_ali+"\",\"Tsym\":\""+Symbol+"\",\"exch\":\""+"NFO"+"\",\"Ttranstype\":\""+ttype+"\",\"Ret\":\""+"DAY"+"\",\"prctyp\":\""+prctyp+"\",\"qty\":\""+exitqty+"\",\"discqty\":\""+"0"+"\",\"MktPro\":\""+"NA"+"\",\"Price\":\""+"0"+"\",\"TrigPrice\":\""+"0"+"\",\"Pcode\":\""+Pcode+"\",\"AMO\":\""+"NO"+"\"}";
resp=algomojo.AMDispatcher(user_apikey, api_secret,"PlaceOrder",api_data,broker,ver);
//Get Nest Order Number
nestorderno = getnestorderno(resp);
_TRACE("\nNest Order No : "+nestorderno);
tradetime=GetPerformanceCounter()/1000;
while ((GetPerformanceCounter()/1000 - tradetime) < timer)
{
//Get Trading Symbol
Tsym = getsymbol(nestorderno);
}
_TRACE("\nTrading Symbol : "+Tsym);
//Get Order Status
orderstatus = getorderstatus(nestorderno);
_TRACE("\nOrder Status : "+orderstatus);
}
else
{
resp = "Not Squared Off. Either No Open Position Exist or Prev Signal Status Not in Completed State";
}
return resp;
}
_SECTION_END();
3)Main Option Execution Module
Copy the Main Execution Module to Amibroker\Formulas\Algomojo Platform. Save the AFL under the name Short Straddle – Strangle Execution.afl
Now drag and Drop the Module on top of your Charting with Buy/Sell Trading System
_SECTION_BEGIN("Algomojo - Time Based Short Straddle/Strangle Execution Module with Stoploss");
#include < algomojostraddle.afl >
RequestTimedRefresh(1, False);
function GetSecondNum()
{
Time = Now( 4 );
return Time;
}
EntryTime = ParamTime("Execution Time", "09:30:00", 0);
SqOffTime = ParamTime("SquareoffTime", "15:15:00", 0);
spot_sym = ParamStr("spot_sym","NIFTY"); //Enter the symbol name here
strike_int = ParamStr("strike_int","50");
lotsize = Param("Symbol Lot Size",75,1,50000);
leg1expiry_dt = ParamStr("Leg 1 expiry_dt", "28JAN21");
leg1qty = Param("Leg 1 Lot Size",1)*lotsize;
leg1Ttranstype = ParamList("Leg 1 Transaction Type","S");
leg1opt_type = ParamList("Leg 1 Option Type","PE",0);
leg1offset = ParamStr("Leg 1 Offset","0");
leg2expiry_dt = ParamStr("Leg 2 expiry_dt", "28JAN21");
leg2qty = Param("Leg 2 Lot Size",1)*lotsize;
leg2Ttranstype = ParamList("Leg 2 Transaction Type","S");
leg2opt_type = ParamList("Leg 2 Option Type","CE",0);
leg2offset = ParamStr("Leg 2 Offset","0");
SL = Param("Stop Percentage", 20,1,100,1);
stgy_name = ParamStr("Strategy Name","Test Strategy Chart");
static_name = Name()+GetChartID()+interval(2)+stgy_name;
static_name_algo = Name()+GetChartID()+interval(2)+stgy_name+"algostatus";
tradedelay = Param("Trade Delay",0);
EnableAlgo = ParamList("Algo Mode","Disable|Enable",0); // Algo Mode
static_name_ = Name()+GetChartID()+interval(2)+stgy_name;
//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(EnableAlgo == "LongOnly")
{
AlgoStatus = "Long Only";
GfxSetTextColor( colorYellow );
GfxTextOut( "Algostatus : "+AlgoStatus , 20, 40);
if(Nz(StaticVarGet(static_name_algo),0)!=2)
{
_TRACE("Algo Status : Long Only");
StaticVarSet(static_name_algo, 2);
}
}
if(EnableAlgo == "ShortOnly")
{
AlgoStatus = "Short Only";
GfxSetTextColor( colorYellow );
GfxTextOut( "Algostatus : "+AlgoStatus , 20, 40);
if(Nz(StaticVarGet(static_name_algo),0)!=3)
{
_TRACE("Algo Status : Short Only");
StaticVarSet(static_name_algo, 3);
}
}
resp = "";
if(EnableAlgo == "Enable")
{
SetChartBkColor(colorDarkGrey);
if(GetsecondNum() == EntryTime AND StaticVarGet(static_name + EntryTime) == 0)
{
//Entry Short Straddle/Strangle at the Entry Time
StaticVarSet(static_name + EntryTime, 1);
leg1response = placeoptionorder(spot_sym,leg1expiry_dt,strike_int,leg1qty,leg1Ttranstype,leg1opt_type,leg1offset,1,SL);
_TRACE("Leg 1 Short Order Placed Successfully");
leg2response = placeoptionorder(spot_sym,leg2expiry_dt,strike_int,leg2qty,leg2Ttranstype,leg2opt_type,leg2offset,2,SL);
_TRACE("Leg 2 Short Order Placed Successfully");
}
else if(GetsecondNum() != EntryTime)
{
StaticVarSet(static_name + EntryTime, 0);
}
if(GetsecondNum() == SqOffTime AND StaticVarGet(static_name + SqOffTime) == 0)
{
//Exit Short Straddle / Short Strangle
StaticVarSet(static_name + SqOffTime, 1);
sqoff1status = squareoffoptions(leg1opt_type,leg1Ttranstype,1);
_TRACE("Leg 1 Exit Response :"+sqoff1status);
sqoff2status = squareoffoptions(leg2opt_type,leg2Ttranstype,2);
_TRACE("Leg 2 Exit Response :"+sqoff2status);
}
else if(GetsecondNum() != SqOffTime)
{
StaticVarSet(static_name + SqOffTime, 0);
}
}
_SECTION_BEGIN("Price");
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();
4)Now right-click over the charts and set the Client ID, user_apikey, api_secretkey,broker and set the required quantity
5)Ensure the Symbol File Path Exists. This is the path where the executed symbols CE and PE Options will get saved in a CSV file for later squareoff.
Ensure while entering the Option Expiry Format. Login to Algomojo Terminal and check out the weekly and monthly option format and enter the expiry date accordingly.
For Aliceblue account holders Monthly Option Symbol Format: NIFTY21JAN14500CE
Hence the Expiry Date needs to be entered as 21JAN
For Aliceblue Account holders weekly Option Symbol Format: NIFTY2111414500CE
Hence the Expiry Date needs to be entered as 21114
For Tradejini and Zebu Account Holders Monthly Option Symbol Format: NIFTY28JAN2114500CE
Hence the Expiry Date needs to be entered as 28JAN21
For Tradejini and Zebu Account Holders Monthly Option Symbol Format: NIFTY14JAN2114500CE
Hence the Expiry Date needs to be entered as 14JAN21
1AlgomojoCE.csv and 1AlgomojoPE.csv and 2AlgomojoCE.csv and 2AlgomojoPE.csv will be saved whenever the straddle or strangle are executed and files will be saved only if the execution status is in complete or in rejected mode

7)Ensure Log Window is open to capture the Trace Logs
8)Bingo Now you have setup the complete end to end automated straddle/strangle execution. Straddle/Strangle Control can be controlled via offset parameters.
9)Code is designed such a way that stoploss is placed for individual price legs and not for the combined premium of Straddle/Strangle Spreads
10)Make the Algo Enable and send time based straddle execution (Supports both entry and exit conditions).
How to keep a stop loss for say 10% SL of combined premium, and it should trial SL for every 10% fall in premium
This can be done only by monitoring the historical spreads. In the case what I discussed combined spreads are not monitored.