This tutorial focus on how to automate your time-based index straddle/strangle management with intraday stop-loss levels with time-based entry and exits using Algomojo Platform and Amibroker. Modern Internal memory management is used to speed up the execution and management of Index Straddle.
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. |
Supported Brokers : Upstox
Supported Algo Platform: Algomojo Platform
Supported Amibroker Version: Amibroker 6.0 or Higher
Supported Trading Instruments: Index Options
Intraday Straddle Management – Amibroker AFL Code
_SECTION_BEGIN("Upstox - Broker Controls");
//Static Variables will be saved in Amibroker every 30 seconds once
SetOption("StaticVarAutoSave",60);
// Send orders even if Amibroker is minimized or Chart is not active
RequestTimedRefresh(1, False);
EnableTextOutput(False);
//Creating Input Controls for Setting Order Related Information
broker = ParamStr("Broker","up");
ver = ParamStr("API Version","1.0");
client_id = ParamStr("Client ID","xxxxxxx");
apikey = ParamStr("APIKey","xxxxxx");
apisecret = ParamStr("APIsecret","xxxxxxx");
_SECTION_END();
_SECTION_BEGIN("Upstox - Order Controls");
stgy_name = ParamStr("Strategy Name","Intraday Short Straddle");
entrytime = ParamTime("Entry Time","09:20:00");
exittime = ParamTime("Exit Time","15:15:00");
stopsenabled = ParamToggle("Stoploss Controls","Enable|Disable",0);
stoppercentage = Param("Stoploss Percentage",30,10,100,1);
stoplossslippagebuffer = Param("Stoploss Slippage Buffer",2,0.25,100,0.25);
spot_sym = ParamList("Spot Symbol","NIFTY|BANKNIFTY");
expiry_date = ParamStr("Expiry Date","22421");
transtype = Paramlist("Options Transaction Type","S",0);
exchange = "NSE_FO";
duration = "DAY";
MktPro = "NA";
price = "0";
disclosed_quantity = "0";
trigger_price = "0";
is_amo = "NO";
if(spot_sym == "NIFTY")
{
lotsize = 50;
strike_interval = 50;
}
if(spot_sym == "BANKNIFTY")
{
lotsize = 25;
strike_interval = 100;
}
quantity = Param("Quantity(Lots)",1,1,10000,1)*lotsize;
order_type = "MKT";
productType = ParamList("Product Type","MIS|NRML",0); //MIS - Intraday, NRML - Carryforward
price = "0";
trigger_price = "0";
if(productType=="MIS")
{
product = "I";
}
if(productType=="CNC" OR productType=="NRML")
{
product = "D";
}
// Offset = 0 -> ATM, Offset = +ve number -> OTM, Offset = -ve -> ITM
OffsetCE = Param("CE Offset",0,-20,20,1);
OffsetPE = Param("PE Offset",0,-20,20,1);
Entrydelay = Param("Entry Delay",0,0,1); // 0 - Execution with No Delay after a signal, 1- Execution at the end of the candle
Exitdelay = Param("Exit Delay",0,0,1);
EnableAlgo = ParamList("Algo Mode","Disable|Enable|LongOnly|ShortOnly",0); // Algo Mode
clear = ParamTrigger("Clear Static Variables","Clear");
static_var_options = "staticvar_options"+Name()+Interval(2)+GetChartID() + stgy_name;
if(clear)
{
StaticVarRemove("staticvar_options*");
_TRACE("Static Variables Cleared");
}
function removeinteralmemory(typeoforder,opt_type,legno)
{
StaticVarRemove(static_var_options+typeoforder+"Options_Trans"+opt_type+legno);
StaticVarRemove(static_var_options+typeoforder+"Options_OrderNo"+opt_type+legno);
StaticVarRemove(static_var_options+typeoforder+"Options_Symbol"+opt_type+legno);
StaticVarRemove(static_var_options+typeoforder+"Options_OrderStatus"+opt_type+legno);
StaticVarRemove(static_var_options+typeoforder+"Options_NetQty"+opt_type+legno);
StaticVarRemove(static_var_options+typeoforder+"Options_AveragePrice"+opt_type+legno);
StaticVarRemove(static_var_options+typeoforder+"Options_ExecutionTime"+opt_type+legno);
}
//Internal Memory
opt_type="CE";
legno = 1;
printf("\n---------------Leg 1 CE Orders (Main) Internal Memory----------");
printf("\nOrderType : "+StaticVarGetText(static_var_options+"Options_Trans"+opt_type+legno));
printf("\nOrderNo : "+StaticVarGetText(static_var_options+"Options_OrderNo"+opt_type+legno));
printf("\nSymbol : "+StaticVarGetText(static_var_options+"Options_Symbol"+opt_type+legno));
printf("\nStatus : "+StaticVarGetText(static_var_options+"Options_OrderStatus"+opt_type+legno));
printf("\nNetQty : "+StaticVarGetText(static_var_options+"Options_NetQty"+opt_type+legno));
printf("\nAveragePrice : "+StaticVarGetText(static_var_options+"Options_AveragePrice"+opt_type+legno));
printf("\nExecutionTime : "+StaticVarGetText(static_var_options+"Options_ExecutionTime"+opt_type+legno));
opt_type="CE";
legno = 1;
printf("\n---------------Leg 1 CE Orders (Stoploss) Internal Memory----------");
printf("\nOrderType : "+StaticVarGetText(static_var_options+"SLOptions_Trans"+opt_type+legno));
printf("\nOrderNo : "+StaticVarGetText(static_var_options+"SLOptions_OrderNo"+opt_type+legno));
printf("\nSymbol : "+StaticVarGetText(static_var_options+"SLOptions_Symbol"+opt_type+legno));
printf("\nStatus : "+StaticVarGetText(static_var_options+"SLOptions_OrderStatus"+opt_type+legno));
opt_type="PE";
legno = 2;
printf("\n---------------Leg 2 PE Orders Internal Memory----------");
printf("\nOrderType : "+StaticVarGetText(static_var_options+"Options_Trans"+opt_type+legno));
printf("\nOrderNo : "+StaticVarGetText(static_var_options+"Options_OrderNo"+opt_type+legno));
printf("\nSymbol : "+StaticVarGetText(static_var_options+"Options_Symbol"+opt_type+legno));
printf("\nStatus : "+StaticVarGetText(static_var_options+"Options_OrderStatus"+opt_type+legno));
printf("\nNetQty : "+StaticVarGetText(static_var_options+"Options_NetQty"+opt_type+legno));
printf("\nAveragePrice : "+StaticVarGetText(static_var_options+"Options_AveragePrice"+opt_type+legno));
printf("\nExecutionTime : "+StaticVarGetText(static_var_options+"Options_ExecutionTime"+opt_type+legno));
opt_type="PE";
legno = 2;
printf("\n---------------Leg 2 PE Orders (Stoploss) Internal Memory----------");
printf("\nOrderType : "+StaticVarGetText(static_var_options+"SLOptions_Trans"+opt_type+legno));
printf("\nOrderNo : "+StaticVarGetText(static_var_options+"SLOptions_OrderNo"+opt_type+legno));
printf("\nSymbol : "+StaticVarGetText(static_var_options+"SLOptions_Symbol"+opt_type+legno));
printf("\nStatus : "+StaticVarGetText(static_var_options+"SLOptions_OrderStatus"+opt_type+legno));
function GetSecondNum()
{
Time = Now(4);
return Time;
}
function PlaceOrder(EntrySymbol,TransType,order_type,LimitPrice,stoplevel)
{
//Creating the Trading Bridge
algomojo=CreateObject("AMAMIBRIDGE.Main");
//Preparing the API data
api_data = "{
\"stgy_name\": \""+stgy_name+"\",
\"symbol\":\""+EntrySymbol+"\",
\"exchange\":\""+exchange+"\",
\"transaction_type\":\""+TransType+"\",
\"duration\":\""+duration+"\",
\"order_type\":\""+order_type+"\",
\"quantity\":\""+quantity+"\",
\"disclosed_quantity\":\""+disclosed_quantity+"\",
\"MktPro\":\""+MktPro+"\",
\"price\":\""+LimitPrice+"\",
\"trigger_price\":\""+stoplevel+"\",
\"product\":\""+productType+"\",
\"is_amo\":\""+is_amo+"\"
}";
_TRACE("Broker API Request"+api_data);
resp=algomojo.AMDispatcher(apikey, apisecret,"PlaceOrder",api_data,broker,ver);
_TRACE("API Response : "+resp);
_TRACE("Strategy Name : "+stgy_name+" AlgoStatus : "+ EnableAlgo);
_TRACE("Chart Symbol : "+ Name() +" Trading Symbol : "+ EntrySymbol +"Trading Interval : "+Interval(2)+" Chard Id : "+ GetChartID());
Say( "Order Placed" );
return resp;
}
function GetOrderNo(resp)
{
OrderNo = "";
sym = StrExtract( resp, 2,'{' );
for( jitem = 0; ( posdetails = StrExtract( sym, jitem,',' )) != ""; jitem++ )
{
if(StrFind(posdetails,"order_id") AND !StrFind(posdetails,"exchange_order_id")
AND !StrFind(posdetails,"parent_order_id"))
{
OrderNo = StrExtract(posdetails,1,':');
OrderNo = StrTrim(OrderNo,"\""); //Trim if any extra white space
_TRACE("\nOrderNo : "+OrderNo);
}
} //end of for loop
return OrderNo;
}
function GetSymbol(resp)
{
Symbol = "";
OrderNo = "";
sym = StrExtract( resp, 2,'{' );
for( jitem = 0; ( posdetails = StrExtract( sym, jitem,',' )) != ""; jitem++ )
{
if(StrFind(posdetails,"symbol") AND !StrFind(posdetails,"trading_symbol"))
{
Symbol = StrExtract(posdetails,1,':');
Symbol = StrTrim(Symbol,"\""); //Trim if any extra white space
_TRACE("\nSymbol : "+Symbol);
}
}
return Symbol;
}
function GetOrderHistory(OrderNo)
{
//Creating the Trading Bridge
algomojo=CreateObject("AMAMIBRIDGE.Main");
api_data = "{
\"order_id\": \""+OrderNo+"\"
}";
_TRACE("OrderHistory API Request"+api_data);
//Sending The Broker Request for NetOpenPositions
resp=algomojo.AMDispatcher(apikey, apisecret,"OrderHistory",api_data,broker,ver);
_TRACE("OrderHistory API Response : "+resp);
return resp;
}
function GetOrderStatus(OrderNo) //OrderHistory for OrderStatus
{
OrderStatus = "";
resp = GetOrderHistory(OrderNo);
sym = StrExtract( resp, 2,'{' );
for( jitem = 0; ( posdetails = StrExtract( sym, jitem,',' )) != ""; jitem++ )
{
if(StrFind(posdetails,"status"))
{
OrderStatus = StrExtract(posdetails,1,':');
OrderStatus = StrTrim(OrderStatus,"\""); //Trim if any extra white space
_TRACE("\nOrderStatus : "+OrderStatus);
}
}
return OrderStatus;
}
function GetPositionsBook()
{
//Creating the Trading Bridge
algomojo=CreateObject("AMAMIBRIDGE.Main");
api_data = "{ }";
_TRACE("PositionBook API Request"+api_data);
//Sending The Broker Request for NetOpenPositions
resp=algomojo.AMDispatcher(apikey, apisecret,"Positions",api_data,broker,ver);
_TRACE("PositionBook API Response : "+resp);
return resp;
}
function NetOpenPos(Symbol)
{
flag = 0;
resp = GetPositionsBook();
posNetqty ="0";
productmsg="";
for( item = 1; ( sym = StrExtract( resp, item,'{' )) != ""; item++ )
{
if(Strfind(sym,Symbol) AND StrFind(sym,product)) //Matches the symbol and //Matches the Order Type
{
flag = 1; //turn on the flag
for( jitem = 0; ( posdetails = StrExtract( sym, jitem,',' )) != ""; jitem++ )
{
if(Strfind(posdetails,"product"))
{
productmsg = StrExtract(posdetails,1,':');
productmsg = StrTrim(productmsg,"\""); //Trim if any extra white space
}
if(productmsg == product AND Strfind(posdetails,"net_quantity"))
{
posNetqty = StrExtract(posdetails,1,':');
posNetqty = StrTrim(posNetqty,"\""); //Trim if any extra white space
_TRACE("\nNetqty : "+posNetqty);
}
} //end of for loop
}
}//end of for loop
if(flag==0)
{
_TRACE("\nTrading Symbol Not Found");
//posNetqty =0;
_TRACE("\nNetQty : "+posNetqty);
}
return posNetqty;
}
function GetExecTime(Symbol)
{
flag = 0;
resp = GetPositionsBook();
ExecTime = "Not Executed";
productmsg="";
for( item = 1; ( sym = StrExtract( resp, item,'{' )) != ""; item++ )
{
if(Strfind(sym,Symbol) AND StrFind(sym,product)) //Matches the symbol and //Matches the Order Type
{
flag = 1; //turn on the flag
for( jitem = 0; ( posdetails = StrExtract( sym, jitem,',' )) != ""; jitem++ )
{
if(Strfind(posdetails,"product"))
{
productmsg = StrExtract(posdetails,1,':');
productmsg = StrTrim(productmsg,"\""); //Trim if any extra white space
}
if(productmsg == product AND Strfind(posdetails,"exchange_time"))
{
exchange_time = StrExtract(posdetails,1,':');
exchange_time = StrTrim(exchange_time,"\""); //Trim if any extra white space
_TRACE("\nexchange_time : "+exchange_time);
}
} //end of for loop
}
}//end of for loop
if(flag==0)
{
_TRACE("\nTrading Execution Time Not Available and Trading Symbol Not Found");
}
return ExecTime;
}
function GetAveragePrice(OrderNo) //OrderHistory for OrderStatus
{
AveragePrice = "";
resp = GetOrderHistory(OrderNo);
sym = StrExtract( resp, 2,'{' );
for( jitem = 0; ( posdetails = StrExtract( sym, jitem,',' )) != ""; jitem++ )
{
if(StrFind(posdetails,"average_price"))
{
AveragePrice = StrExtract(posdetails,1,':');
AveragePrice = StrTrim(AveragePrice,"\""); //Trim if any extra white space
_TRACE("\nAverage Price : "+AveragePrice);
}
}
return AveragePrice;
}
function PlaceSLOptionsOrder(EntrySymbol, opt_type,legno,AveragePrice)
{
_TRACE("Place Stoploss Order");
if(stopsenabled)
{
//stoploss computation and stoploss order placement logic,
//stoploss computation
stoplevel = StrToNum(AveragePrice) * (1+ stoppercentage/100);
//round off to the nearest ticksize
TickSz = 0.05;
stoplevel = TickSz * round( stoplevel / TickSz );
LimitPrice = stoplevel + stoplossslippagebuffer; //slippage is restricted to 2 points (Slippage Buffer)
resp = PlaceOrder(EntrySymbol,"B","SL",LimitPrice,stoplevel);
Trans = "B";
StaticVarSetText(static_var_options+"SLOptions_Trans"+opt_type+legno,Trans,True);
OrderNo = GetOrderNo(resp);
StaticVarSetText(static_var_options+"SLOptions_OrderNo"+opt_type+legno,OrderNo,True);
Symbol = GetSymbol(resp);
StaticVarSetText(static_var_options+"SLOptions_Symbol"+opt_type+legno,Symbol,True);
Orderstatus = GetOrderStatus(OrderNo); //Get the Orderstatus from OrderHistory
StaticVarSetText(static_var_options+"SLOptions_OrderStatus"+opt_type+legno,Orderstatus,True);
}
return 0;
}
function PlaceOptionsOrder(spot_sym,expiry_date,strike_int,TransType, opt_type, offset,legno)
{
if(opt_type=="PE")
{
offset = -offset; //changing the polarity
}
//create the Trading Bridge
algomojo = CreateObject("AMAMIBRIDGE.Main"); //calling the bridge dll
//Prepart the API data
api_data = "{
\"stgy_name\":\""+stgy_name+"\",
\"spot_sym\":\""+spot_sym+"\",
\"expiry_dt\":\""+expiry_date+"\",
\"opt_type\":\""+opt_type+"\",
\"transaction_type\":\""+TransType+"\",
\"order_type\":\""+order_type+"\",
\"quantity\":\""+quantity+"\",
\"price\":\"0\",
\"trigger_price\":\"0\",
\"product\":\""+productType+"\",
\"strike_int\":\""+strike_int+"\",
\"offset\":\""+offset+"\"
}";
_TRACE("Broker API Request"+api_data);
resp = algomojo.AMDispatcher(apikey,apisecret,"PlaceFOOptionsOrder",api_data,broker,ver);
_TRACE("Broker API Respone"+resp);
//Store the Transaction Type, OrderNo,Trading Symbol,OrderStatus,Netqty
Trans = TransType;
StaticVarSetText(static_var_options+"Options_Trans"+opt_type+legno,Trans,True);
OrderNo = GetOrderNo(resp);
StaticVarSetText(static_var_options+"Options_OrderNo"+opt_type+legno,OrderNo,True);
Symbol = GetSymbol(resp);
StaticVarSetText(static_var_options+"Options_Symbol"+opt_type+legno,Symbol,True);
Orderstatus = GetOrderStatus(OrderNo); //Get the Orderstatus from OrderHistory
StaticVarSetText(static_var_options+"Options_OrderStatus"+opt_type+legno,Orderstatus,True);
NetQty = NetOpenPos(Symbol); //Get the Netqty from the Positions Book
StaticVarSetText(static_var_options+"Options_NetQty"+opt_type+legno,NetQty,True);
AveragePrice = GetAveragePrice(OrderNo);
StaticVarSetText(static_var_options+"Options_AveragePrice"+opt_type+legno,AveragePrice,True);
ExecutionTime = GetExecTime(Symbol); //Get the Execution Time from OrderHistory
StaticVarSetText(static_var_options+"Options_ExecutionTime"+opt_type+legno,ExecutionTime,True);
//follow thro stoploss order
//Testing Purpose
//PlaceSLOptionsOrder(Symbol, opt_type,legno,"100");
//Live Trading Purpose
PlaceSLOptionsOrder(Symbol, opt_type,legno,AveragePrice);
}
function cancelorder(OrderNo)
{
//Creating the Trading Bridge
algomojo=CreateObject("AMAMIBRIDGE.Main");
api_data = "{
\"order_id\": \""+OrderNo+"\"
}";
_TRACE("Cancel API Request"+api_data);
//Sending The Broker Request for NetOpenPositions
resp=algomojo.AMDispatcher(apikey, apisecret,"CancelOrder",api_data,broker,ver);
_TRACE("Cancel API Response : "+resp);
}
function cancelSLorders()
{
opt_type = "CE";
legno = 1;
CEorderid = StaticVarGetText(static_var_options+"SLOptions_OrderNo"+opt_type+legno);
cancelorder(CEorderid);
removeinteralmemory("SL",opt_type,legno);
opt_type = "PE";
legno = 2;
PEorderid = StaticVarGetText(static_var_options+"SLOptions_OrderNo"+opt_type+legno);
cancelorder(PEorderid);
removeinteralmemory("SL",opt_type,legno);
}
function SquareOffPosition(opt_type,legno)
{
resp ="";
TType = "";
ExitSymbol = StaticVarGetText(static_var_options+"Options_Symbol"+opt_type+legno);
Netqty = StrToNum(NetOpenPos(ExitSymbol));
if(StaticVarGetText(static_var_options+"Options_Trans"+opt_type+legno)=="B")
{
TType = "S";
}
if(StaticVarGetText(static_var_options+"Options_Trans"+opt_type+legno)=="S")
{
TType = "B";
}
//Creating the Trading Bridge
algomojo=CreateObject("AMAMIBRIDGE.Main");
//Preparing the API data
api_data = "{
\"stgy_name\": \""+stgy_name+"\",
\"symbol\":\""+ExitSymbol+"\",
\"exchange\":\""+exchange+"\",
\"transaction_type\":\""+TType+"\",
\"duration\":\""+duration+"\",
\"order_type\":\""+order_type+"\",
\"quantity\":\""+Netqty+"\",
\"disclosed_quantity\":\""+disclosed_quantity+"\",
\"MktPro\":\""+MktPro+"\",
\"price\":\""+price+"\",
\"trigger_price\":\""+trigger_price+"\",
\"product\":\""+productType+"\",
\"is_amo\":\""+is_amo+"\"
}";
_TRACE("Squareoff API Request"+api_data);
//Testing
//if(Netqty==0 AND ExitSymbol!="")
//Live Trading Purpose
if(Netqty!=0 AND ExitSymbol!="")
{
resp=algomojo.AMDispatcher(apikey, apisecret,"PlaceOrder",api_data,broker,ver);
removeinteralmemory("",opt_type,legno);
}
if(resp!="")
{
_TRACE("Squareoff API Response : "+resp);
}
else
{
_TRACE("Squareoff Order Not Triggered");
}
return resp;
}
//straddletrigger = ParamTrigger("Straddle Entry Trigger","Place Straddle Options");
//exittrigger = ParamTrigger("Straddle Exit Trigger","Exit Straddle");
//if(straddletrigger)
//{
//PlaceOptionsOrder(spot_sym,expiry_date,strike_interval,TransType, "CE", offsetCE,1);
//PlaceOptionsOrder(spot_sym,expiry_date,strike_interval,TransType, "PE", offsetPE,2);
//}
//if(exittrigger)
//{
//cancelSLorders();
//SquareOffPosition("CE",1);
//SquareOffPosition("PE",2);
//}
if(EnableAlgo != "Disable")
{
//if the time set as per the parameter control is reached
if(GetSecondNum() == entrytime AND StaticVarGet(static_var_options + entrytime) == 0)
{
//send the straddle orders
StaticVarSet(static_var_options + entrytime,1);
PlaceOptionsOrder(spot_sym,expiry_date,strike_interval,TransType, "CE", offsetCE,1);
PlaceOptionsOrder(spot_sym,expiry_date,strike_interval,TransType, "PE", offsetPE,2);
}
//reset the static variable if the otime is not matching
else if(GetSecondNum() != entrytime)
{
StaticVarSet(static_var_options + entrytime,0);
}
//if the time set as per the parameter control is reached
if(GetSecondNum() == exittime AND StaticVarGet(static_var_options + exittime) == 0)
{
//send the straddle orders
StaticVarSet(static_var_options + exittime,1);
cancelSLorders();
SquareOffPosition("CE",1);
SquareOffPosition("PE",2);
}
//reset the static variable if the otime is not matching
else if(GetSecondNum() != exittime)
{
StaticVarSet(static_var_options + exittime,0);
}
}//end of Main if loop
SetChartOptions(0, chartShowArrows | chartShowDates); //x-Axis will be plottted
//plot the candles
Plot(Close,"Close",colorDefault,GetPriceStyle() | styleNoTitle);
How to Setup Intraday Straddle Module?
1)Apply the AFL Code with proper Algomojo API Key and API secret key and Stoploss controls , Set the Entry and Exit time
2)Press Clear Static Variables to clear the temporary memory
3)Temporary Multi Legged Memory Management can be seen at Amibroker -> Window -> Interpretation Box as shown below
Expiry Symbol Format
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 Upstox account holders Monthly Option Symbol Format: NIFTY22APR17200CE
Hence the Expiry Date needs to be entered as 22APR
For Aliceblue Account holders weekly Option Symbol Format: NIFTY2242117200CE
Hence the Expiry Date needs to be entered as 22421Upstox – Symbol Format
4)Ensure Log Window is open to capture the Trace Logs
5)Bingo Now you have setup the complete end to end automated straddle/strangle execution. Straddle/Strangle Control can be controlled via offset parameters.
6)Code is designed such a way that stoploss is placed for individual price legs and not for the combined premium of Straddle/Strangle Spreads
7)Make the Algo Enable and send time based straddle execution (Supports both entry and exit conditions).
wil it retrace sl of profitable posion