// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © algomojo // Module - Spot/Futures to Options Module // Description - Build your Trading Logic in Spot/Futures - Trade Execution in Options // Coded by Rajandran R - Co-Creator - Algomojo // Module V3.0 // Date 6th Dec 2022 //////////////////////////////////////////////////////////////////////////////////////////////////////////// //Trading Block Description //Block 1 : API Controls + Algomojo Input Controls //Block 2 : Backtesting Controls & Target and Stoploss Controls //Block 3 : Trading Strategy and Controls (write your trading strategy in the block //Block 4 : Intraday Function and Buy and Sell Signal Mapping (Signal Mapping is required) //Block 5 : Framing Option Symbols and API Messaging Structure //Block 6 : Trade Execution Controls //Block 7 : Plotting Stoploss Target //Block 8 : Plotting Trading Dashboard /////////////////////////////////////////////////////////////////////////////////////////////////////////// //@version=5 strategy('Halftrend Algomojo Trading Strategy with Target/Stoploss', overlay=true, calc_on_every_tick=false, process_orders_on_close = true) //Block 1 : API Controls + Algomojo Input Controls //Enter Your Algomojo API Key and API Secret Key api_key = input.string(title='API Key', defval='xxxxxxxxxxxx', group='AlgoControls') api_secret = input.string(title='API Secret Key', defval='xxxxxxxxxxxx', group='AlgoControls') br = input.string(title='Broker', defval='ALICEBLUE', options=['ALICEBLUE', 'ANGELONE', 'FIRSTOCK', 'FYERS','MASTERTRUST','SAMCO','TRADEJINI','UPSTOX','ZEBU','ZERODHA'], group='AlgoControls') strategy = input.string(title='Strategy Name', defval='halftrend Strategy', group='AlgoControls') Underlying = input.symbol(title='UnderlyingSymbol',defval='NSE:NIFTY', group='AlgoControls') Expiry = input.string(title='Expiry Date',defval='26MAY22' , group='AlgoControls') iInterval = input.int(title='Strike Interval', defval=50, group='AlgoControls') lotsize = input.int(title='Lot Size', defval=50, group='AlgoControls') offsetCE = input.int(title='offsetCE', defval=0,minval=-40,maxval=40, group='AlgoControls') offsetPE = input.int(title='offsetPE', defval=0,minval=-40,maxval=40, group='AlgoControls') exchange = input.string(title='Exchange', defval='NFO', group='AlgoControls') quantity = input.int(title='Quantity', defval=1, group='AlgoControls') pricetype = input.string(title='Price Type', defval='MARKET', options=['MARKET'], group='AlgoControls') product = input.string(title='Product Type', defval='NRML', options=['NRML','MIS'], group='AlgoControls') splitorder = input.string(title='Split Order?', defval='NO', options=['NO', 'YES'], group='AlgoControls') split_quantity = input.int(title='Split Quantity', defval=1, group='AlgoControls') price = '0' disclosed_quantity = '0' trigger_price = '0' amo = 'NO' broker = switch br "ALICEBLUE" => "ab" "ANGELONE" => "an" "FIRSTOCK" => "fs" "FYERS" => "fy" "GOODWILL" => "gw" "MASTERTRUST" => "mt" "PAYTM" => "pt" "SAMCO" => "sm" "TRADEJINI" => "tc" "UPSTOX" => "up" "ZEBU" => "zb" "ZERODHA" => "ze" => runtime.error("No matching broker found.") string(na) am_Mode = input.string(title='Algo Mode', defval='ENABLE', options=['ENABLE', 'LONGONLY', 'SHORTONLY'], group='AlgoControls') //Get the Strike Interval SpotC1 = request.security(Underlying, timeframe.period,close) SpotC = SpotC1[1] //Calculate the ATM,ITM,OTM Options based on the Offset Selected strike = SpotC % iInterval > iInterval/2 ? SpotC - (SpotC%iInterval) + iInterval : SpotC - (SpotC%iInterval) strikeCE = strike + (offsetCE * iInterval) strikePE = strike - (offsetPE * iInterval) //plot(strikeCE, "strikeCE",color.blue) //plot(strikePE, "strikePE",color.blue) ////////////////////////////////////////Block 1 Module Ends//////////////////////////////////////////////////////////////////////// //Block 2 : Backtesting Controls & Target and Stoploss Controls FromMonth = input.int(defval=9, title='From Month', minval=1, maxval=12, group='Backtesting') FromDay = input.int(defval=1, title='From Day', minval=1, maxval=31, group='Backtesting') FromYear = input.int(defval=2018, title='From Year', minval=999, group='Backtesting') ToMonth = input.int(defval=1, title='To Month', minval=1, maxval=12, group='Backtesting') ToDay = input.int(defval=1, title='To Day', minval=1, maxval=31, group='Backtesting') ToYear = input.int(defval=9999, title='To Year', minval=999, group='Backtesting') start = timestamp(FromYear, FromMonth, FromDay, 00, 00) finish = timestamp(ToYear, ToMonth, ToDay, 23, 59) window() => time >= start and time <= finish ? true : false highlighting = input.bool(title='Highlighter On/Off ?', defval=true, group='Intraday Controls') barcoloring = input.bool(title='Bar Coloring On/Off ?', defval=true, group='Intraday Controls') intraday = input.bool(title='Intraday On/Off ?', defval=false, group='Intraday Controls') marketSession = input.session(title='Market session', defval='0915-1500', confirm=false, group='Intraday Controls') risk = input.bool(title='Stoploss/Target On/Off', defval=false, group='Stoploss/Target Controls') type = input.string(title='Type', defval='FIXED', options=['FIXED', 'PERCENTAGE', 'VOLATILITY'], group='Stoploss/Target Controls') stop = input.float(defval=10.0, title='Stoploss', group='Stoploss/Target Controls') target = input.float(defval=20.0, title='Target', group='Stoploss/Target Controls') TickSz = input.float(defval=0.05, title='TickSize', group='Stoploss/Target Controls') ATRMultiplier = input.float(title='ATR Multiplier', step=0.1, defval=1.5, group='Stoploss/Target Controls') ATRLength = input.int(title='ATR Period', defval=20, group='Stoploss/Target Controls') iATR = ta.atr(ATRLength) ////////////////////////////////////////Block 2 Module Ends//////////////////////////////////////////////////////////////////////// //Block 3 : Trading Strategy and Controls amplitude = input(title='Amplitude', defval=2) channelDeviation = input(title='Channel Deviation', defval=2) showArrows = input(title='Show Arrows', defval=true) showChannels = input(title='Show Channels', defval=true) var int trend = 0 var int nextTrend = 0 var float maxLowPrice = nz(low[1], low) var float minHighPrice = nz(high[1], high) var float up = 0.0 var float down = 0.0 float atrHigh = 0.0 float atrLow = 0.0 float arrowUp = na float arrowDown = na atr2 = ta.atr(100) / 2 dev = channelDeviation * atr2 highPrice = high[math.abs(ta.highestbars(amplitude))] lowPrice = low[math.abs(ta.lowestbars(amplitude))] highma = ta.sma(high, amplitude) lowma = ta.sma(low, amplitude) if nextTrend == 1 maxLowPrice := math.max(lowPrice, maxLowPrice) if highma < maxLowPrice and close < nz(low[1], low) trend := 1 nextTrend := 0 minHighPrice := highPrice minHighPrice else minHighPrice := math.min(highPrice, minHighPrice) if lowma > minHighPrice and close > nz(high[1], high) trend := 0 nextTrend := 1 maxLowPrice := lowPrice maxLowPrice if trend == 0 if not na(trend[1]) and trend[1] != 0 up := na(down[1]) ? down : down[1] arrowUp := up - atr2 arrowUp else up := na(up[1]) ? maxLowPrice : math.max(maxLowPrice, up[1]) up atrHigh := up + dev atrLow := up - dev atrLow else if not na(trend[1]) and trend[1] != 1 down := na(up[1]) ? up : up[1] arrowDown := down + atr2 arrowDown else down := na(down[1]) ? minHighPrice : math.min(minHighPrice, down[1]) down atrHigh := down + dev atrLow := down - dev atrLow ht = trend == 0 ? up : down var color buyColor = color.blue var color sellColor = color.red htColor = trend == 0 ? buyColor : sellColor htPlot = plot(ht, title='HalfTrend', linewidth=2, color=htColor) atrHighPlot = plot(showChannels ? atrHigh : na, title='ATR High', style=plot.style_circles, color=color.new(sellColor, 0)) atrLowPlot = plot(showChannels ? atrLow : na, title='ATR Low', style=plot.style_circles, color=color.new(buyColor, 0)) fill(htPlot, atrHighPlot, title='ATR High Ribbon', color=color.new(sellColor, 90)) fill(htPlot, atrLowPlot, title='ATR Low Ribbon', color=color.new(buyColor, 90)) buySignal = not na(arrowUp) and trend == 0 and trend[1] == 1 sellSignal = not na(arrowDown) and trend == 1 and trend[1] == 0 plotshape(showArrows and buySignal ? atrLow : na, title='Arrow Up', style=shape.triangleup, location=location.absolute, size=size.tiny, color=color.new(buyColor, 0)) plotshape(showArrows and sellSignal ? atrHigh : na, title='Arrow Down', style=shape.triangledown, location=location.absolute, size=size.tiny, color=color.new(sellColor, 0)) alertcondition(buySignal, title='Alert: HalfTrend Buy', message='HalfTrend Buy') alertcondition(sellSignal, title='Alert: HalfTrend Sell', message='HalfTrend Sell') ////////////////////////////////////////Block 3 Module Ends//////////////////////////////////////////////////////////////////////// //Block 4 : Intraday Function and Buy and Sell Signal Mapping //Remove the comments to do the long/short signal mapping barInSession(sess) => time(timeframe.period, sess) != 0 bool intradaySession = barInSession(marketSession) buy = buySignal sell = sellSignal buy1 = buy[1] sell1 = sell[1] //Block 5 : Framing Option Symbols and API Messaging Structure TSYMce= ta.valuewhen(buy,strikeCE,0) TSYMpe= ta.valuewhen(sell,strikePE,0) symbolinfo = str.replace_all(Underlying,"NSE:","") symbolinfo := str.replace_all(symbolinfo,"1!","") symbolinfo := str.replace_all(symbolinfo,"2!","") //Framing a Option Symbols if(broker=='tc' or broker=='fs') tradSYMCE=symbolinfo + Expiry + 'C' + str.tostring(TSYMce) tradSYMPE=symbolinfo + Expiry + 'P' + str.tostring(TSYMpe) else tradSYMCE=symbolinfo + Expiry + str.tostring(TSYMce)+ 'CE' tradSYMPE=symbolinfo + Expiry + str.tostring(TSYMpe)+ 'PE' //initial declarations var islong = false var issell = false var symCE = '' var symPE = '' var exitsymCE = '' var exitsymPE = '' var tpslCE = '' var tpslPE = '' buy := not islong and buy sell := not issell and sell if buy islong := true //Buy signal is continuing issell := false //reset the sell continue if(broker=='tc' or broker=='fs') symCE := symbolinfo + Expiry + 'C' + str.tostring(TSYMce) else symCE := symbolinfo + Expiry + str.tostring(TSYMce)+ 'CE' tpslCE := symCE exitsymPE := symPE //storing the PE symbol value for exit symPE := '' if sell islong :=false //Buy Signal is no more continuing issell :=true //Sell Signal is continuing if(broker=='tc' or broker=='fs') symPE := symbolinfo + Expiry + 'P' + str.tostring(TSYMce) else symPE := symbolinfo + Expiry + str.tostring(TSYMpe)+ 'PE' tpslPE := symPE exitsymCE := symCE //storing the CE symbol value for exit symCE := '' //api data configuration LongCall = '{ "api_key":"' + api_key + '", "api_secret":"' + api_secret + '", "data": {"broker": "' + broker + '", "strategy":"' + strategy + '", "exchange":"' + exchange + '", "symbol":"' + symCE + '", "action":"BUY", "product":"' + product + '", "pricetype":"' + pricetype + '", "quantity":"' + str.tostring(quantity*lotsize) + '", "price":"' + price + '", "disclosed_quantity":"' + disclosed_quantity + '", "trigger_price": "' + trigger_price + '", "amo": "' + amo + '", "splitorder": "' + splitorder + '", "split_quantity":"' + str.tostring(split_quantity) + '" } }' ExitCall = '{ "api_key":"' + api_key + '", "api_secret":"' + api_secret + '", "data": {"broker": "' + broker + '", "strategy":"' + strategy + '", "exchange":"' + exchange + '", "symbol":"' + exitsymCE + '", "action":"SELL", "product":"' + product + '", "pricetype":"' + pricetype + '", "quantity":"' + str.tostring(quantity*lotsize) + '", "price":"' + price + '", "disclosed_quantity":"' + disclosed_quantity + '", "trigger_price": "' + trigger_price + '", "amo": "' + amo + '", "splitorder": "' + splitorder + '", "split_quantity":"' + str.tostring(split_quantity) + '" } }' sqCall = '{ "api_key":"' + api_key + '", "api_secret":"' + api_secret + '", "data": {"broker": "' + broker + '", "strategy":"' + strategy + '", "exchange":"' + exchange + '", "symbol":"' + tpslCE + '", "action":"SELL", "product":"' + product + '", "pricetype":"' + pricetype + '", "quantity":"' + str.tostring(quantity*lotsize) + '", "price":"' + price + '", "disclosed_quantity":"' + disclosed_quantity + '", "trigger_price": "' + trigger_price + '", "amo": "' + amo + '", "splitorder": "' + splitorder + '", "split_quantity":"' + str.tostring(split_quantity) + '" } }' LongPut = '{ "api_key":"' + api_key + '", "api_secret":"' + api_secret + '", "data": {"broker": "' + broker + '", "strategy":"' + strategy + '", "exchange":"' + exchange + '", "symbol":"' + symPE + '", "action":"BUY", "product":"' + product + '", "pricetype":"' + pricetype + '", "quantity":"' + str.tostring(quantity*lotsize) + '", "price":"' + price + '", "disclosed_quantity":"' + disclosed_quantity + '", "trigger_price": "' + trigger_price + '", "amo": "' + amo + '", "splitorder": "' + splitorder + '", "split_quantity":"' + str.tostring(split_quantity) + '" } }' ExitPut = '{ "api_key":"' + api_key + '", "api_secret":"' + api_secret + '", "data": {"broker": "' + broker + '", "strategy":"' + strategy + '", "exchange":"' + exchange + '", "symbol":"' + exitsymPE + '", "action":"SELL", "product":"' + product + '", "pricetype":"' + pricetype + '", "quantity":"' + str.tostring(quantity*lotsize) + '", "price":"' + price + '", "disclosed_quantity":"' + disclosed_quantity + '", "trigger_price": "' + trigger_price + '", "amo": "' + amo + '", "splitorder": "' + splitorder + '", "split_quantity":"' + str.tostring(split_quantity) + '" } }' sqPut = '{ "api_key":"' + api_key + '", "api_secret":"' + api_secret + '", "data": {"broker": "' + broker + '", "strategy":"' + strategy + '", "exchange":"' + exchange + '", "symbol":"' + tpslPE + '", "action":"SELL", "product":"' + product + '", "pricetype":"' + pricetype + '", "quantity":"' + str.tostring(quantity*lotsize) + '", "price":"' + price + '", "disclosed_quantity":"' + disclosed_quantity + '", "trigger_price": "' + trigger_price + '", "amo": "' + amo + '", "splitorder": "' + splitorder + '", "split_quantity":"' + str.tostring(split_quantity) + '" } }' //assign trading signals if(not intraday) buy := buy sell := sell if(intraday) buy := buy and intradaySession sell := sell and intradaySession //Block 6 : Trade Execution Controls if(am_Mode=="ENABLE") //Buy Fresh Call Option if buy and strategy.position_size == 0 and window() strategy.entry('LONGCALL', strategy.long, alert_message=LongCall) //Buy Fresh Put Option if sell and strategy.position_size == 0 and window() strategy.entry('LONGPUT', strategy.short, alert_message=LongPut) //Exit Old Put Option and Entery Fresh Call Option (Buy) if buy and strategy.position_size < 0 and window() strategy.close('LONGPUT', when=window(), alert_message=ExitPut) strategy.entry('LONGCALL', strategy.long, alert_message=LongCall) //Exit Old Call Option and Enter Fresh Put Option (Buy) if sell and strategy.position_size > 0 and window() strategy.close('LONGCALL', when=window() ,alert_message=ExitCall) strategy.entry('LONGPUT', strategy.short, alert_message=LongPut) if(am_Mode=="LONGONLY") //Buy Fresh Call Option if buy and strategy.position_size == 0 and window() strategy.entry('LONGCALL', strategy.long, alert_message=LongCall) if sell and strategy.position_size > 0 and window() strategy.close('LONGCALL' ,alert_message=ExitCall) if(am_Mode=="SHORTONLY") if buy and strategy.position_size < 0 and window() strategy.close('LONGPUT', alert_message=ExitPut) //Buy Fresh Put Option if sell and strategy.position_size == 0 and window() strategy.entry('LONGPUT', strategy.short, alert_message=LongPut) if(intraday) longsquareOff = not intradaySession and strategy.position_size > 0 strategy.close(id='LONGCALL', when=longsquareOff, comment='Square-off',alert_message=sqCall) shortsquareOff = not intradaySession and strategy.position_size < 0 strategy.close(id='LONGPUT', when=shortsquareOff, comment='Square-off',alert_message=sqPut) ////////////////////////////////////////Block 6 Module Ends//////////////////////////////////////////////////////////////////////// //Block 7 : Plotting Stoploss Target buycount = ta.barssince(buySignal) sellcount = ta.barssince(sellSignal) color1 = buycount[1] < sellcount[1] ? color.green : buycount[1] > sellcount[1] ? color.red : na barcolor(barcoloring ? color1 : na) long_stop_level = ta.valuewhen(buy1, open - stop, 0) long_profit_level = ta.valuewhen(buy1, open + target, 0) short_stop_level = ta.valuewhen(sell1, open + stop, 0) short_profit_level = ta.valuewhen(sell1, open - target, 0) if(type=="PERCENTAGE") long_stop_level := ta.valuewhen(buy1, open, 0) * (100-stop)/100 long_profit_level := ta.valuewhen(buy1, open, 0) * (100+target)/100 long_stop_level := TickSz * math.round(long_stop_level/TickSz) long_profit_level := TickSz * math.round(long_profit_level/TickSz) short_stop_level := ta.valuewhen(sell1, open, 0) * (100+stop)/100 short_profit_level := ta.valuewhen(sell1, open, 0) * (100-target)/100 short_stop_level := TickSz * math.round(short_stop_level/TickSz) short_profit_level := TickSz * math.round(short_profit_level/TickSz) if(type=="VOLATILITY") long_stop_level := ta.valuewhen(buy1, open - iATR*ATRMultiplier, 0) long_profit_level := ta.valuewhen(buy1, open + iATR*ATRMultiplier, 0) short_stop_level := ta.valuewhen(sell1, open + iATR*ATRMultiplier, 0) short_profit_level := ta.valuewhen(sell1, open - iATR*ATRMultiplier, 0) if(risk) if(strategy.position_size>0) strategy.exit('CALL TP/SL', 'LONGCALL', stop=long_stop_level, limit=long_profit_level,alert_message=sqCall) if(strategy.position_size<0) strategy.exit('PUT TP/SL', 'LONGPUT', stop=short_stop_level, limit=short_profit_level,alert_message=sqPut) plot(strategy.position_size <= 0 or not risk ? na : long_stop_level, color=color.new(color.red, 0), style=plot.style_circles, linewidth=2) plot(strategy.position_size <= 0 or not risk ? na : long_profit_level, color=color.new(color.green, 0), style=plot.style_circles, linewidth=2) plot(strategy.position_size >= 0 or not risk ? na : short_stop_level, color=color.new(color.red, 0), style=plot.style_circles, linewidth=2) plot(strategy.position_size >= 0 or not risk ? na : short_profit_level, color=color.new(color.green, 0), style=plot.style_circles, linewidth=2) //Block 8 : Plotting Trading Dashboard entrytext = '' exittext = '' if(islong) entrytext := 'Long Call : '+symCE exittext := 'Exit Put : '+exitsymPE if(issell) entrytext := 'Exit Call : '+exitsymCE exittext := 'Long Put : '+symPE //Trading Dashboard var tLog = table.new(position = position.bottom_left, rows = 2, columns = 2, bgcolor = color.black, border_width=1) table.cell(tLog, row = 0, column = 1, text = entrytext, text_color = color.green) table.cell_set_text(tLog, row = 0, column = 1, text = entrytext) table.cell(tLog, row = 1, column = 1, text = exittext, text_color = color.red) table.cell_set_text(tLog, row = 1, column = 1, text = exittext )