Algomojo Index Straddle/Strangle Execution Module with Intraday Stoploss

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 ActivityOrders to be Placed
Time Based EntryEnter Straddle/Strangle at 9.30a.m (Two legged Order)
Calculate the Short Call Average PriceCalculate the Short call Stoploss
Calculate the Short Put Average PriceCalculate the Short Put Stoploss
Place Stoploss OrdersPlace the Stoploss for both Short call and Short Put if the entry order status is completed
Check Open PositionsCheck the Open Positions for the Qty traded
Time Based ExitSquare 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).

10 thoughts on “Algomojo Index Straddle/Strangle Execution Module with Intraday Stoploss”

  1. Does it take only one trade in short strangle or does this code adjust the short strangle as and when the market moves ?

    1. 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.

  2. Selvakumar Appadurai

    I HAVE ALICEBLUE ACCOUNT, BASED ON YOUR INSTRUCTION I DID , IT IS NOT WORKING.
    PLEASE SUGGEST

  3. Cecil Varghese

    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 !!!

Leave a Comment

Your email address will not be published. Required fields are marked *