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 Algomojo
//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 in such a way that stop loss is placed for individual price legs and not for the combined premium of Straddle/Strangle Spreads. And Stoploss orders will be placed only if the entry order goes to a completed state.
10)Make the Algo Enable and send time based straddle execution (Supports both entry and exit conditions).
Hi,
does this work for Upstox as well ?
NS
The above code is compatible only with Aliceblue, Tradejini & Zebu. However we are planning to launch
similar modules for upstox as well shortly.
Does it take only one trade in short strangle or does this code adjust the short strangle as and when the market moves ?
Code does time based straddle/strangle entry and exit with immediately fixed stoploss. However it will not do any adjustments at this point in time.
We are working on Adjustments module. Shortly it will be launched.
Does this code Compitable with angel broking ?
For Angel Broking, a new module related to options will be launched shortly.
I HAVE ALICEBLUE ACCOUNT, BASED ON YOUR INSTRUCTION I DID , IT IS NOT WORKING.
PLEASE SUGGEST
What error you are getting?
Hello Rajandran,
Due to the removal stop loss market order by NSE , now the SL orders are getting rejected. Hence the exiting of the orders are also not happening with the specified time. it would be of great help if your team can look into this issue .
Thank you !!!
I will look into the issue and reconfigure to SL-Limit orders instead of SL-Market Orders