Futures to Options Module
Last updated
Last updated
The "Futures to Options Execution Module" is a highly modular and extensible Pine Script™ template designed for advanced TradingView users, particularly those interested in automating options trading based on futures signals. Here’s a concise overview of the template and how traders can build on it:
This module is structured into 8 distinct blocks, each with a specific function:
OpenAlgo API Controls: Connects to OpenAlgo for live execution, allowing integration with real trading APIs.
Backtesting & Risk Controls: Defines trading timeframes, and configurable risk parameters including Stoploss/Target (fixed, percentage, or ATR-based).
Trading Strategy Block: Users can plug in any logic here. The default implementation includes a HalfTrend + ATR channel-based strategy.
Signal Mapping & Intraday Filtering: Converts strategy conditions into buy/sell signals and handles intraday session logic.
Option Symbol Generation & API Messaging: Frames CE/PE option symbols dynamically based on spot price, expiry, and strike intervals.
Trade Execution Logic: Executes trades based on signal, handles square-off and mode control (Enable, Long-only, Short-only).
SL/TP Visualization: Plots stoploss and target markers based on the selected risk model.
Trading Dashboard: Displays real-time trade info (entry/exit signals) on the chart using tables.
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © openalgo
//Trading Block Description
//Block1 : OpenAlgo API controls
//Block2 : Backtesting Controls & Target and Stoploss Controls
//Block3: Trading Strategy and Controls (Write your strategy Block)
//Block4: Intraday Function and Buy and Sell Signal Mapping (Signal Mapping is Required)
//Block5: Framing Option Symbols and API Message Structure
//Block6: Trade Execution Controls
//Block7: Plotting Stoploss and Target
//Block8: Plotting Trading Dashboard
//@version=6
strategy("Futures to Options Execution Module", overlay=true, fill_orders_on_standard_ohlc = true)
//Block1 : OpenAlgo API controls
// Input controls
apikey = input.string("xxxxxxxxxxxx", title="OpenAlgo API Key", group="OpenAlgo")
strategyType = input.string("Tradingview", title="Strategy", group="OpenAlgo")
Underlying = input.symbol(title = "Underlying Symbol", defval = "NSE:NIFTY", group = "OpenAlgo")
Expiry = input.string(title="Expiry Date",defval="30JAN25",group = "OpenAlgo")
iInterval = input.int(title='Strike Interval',defval = 50, group = "OpenAlgo")
lotsize = input.int(title = "LotSize", defval = 75,group="OpenAlgo")
quantity = input.int(title = "Quantity(Lots)", defval = 1,group="OpenAlgo")
offsetCE = input.int(title = "OffsetCE", defval = 0,minval=-40,maxval=40, step=1, group="OpenAlgo")
offsetPE = input.int(title = "OffsetPE", defval = 0,minval=-40,maxval=40, step=1, group="OpenAlgo")
exchange = input.string("NFO", title="Exchange", options=["NFO", "BFO", "MCX"], group="OpenAlgo")
product = input.string("MIS", title="Product Type", options=["MIS", "NRML"], group="OpenAlgo")
algomode = input.string(title="Algo Mode",defval = "ENABLE",options=['ENABLE',"LONGONLY","SHORTONLY"])
// Hardcoded Price Type
pricetype = "MARKET"
//Get the Strike Interval
SpotC1 = request.security(Underlying,timeframe.period,close)
SpotC = SpotC1[1]
//calculate the ATM/OTM/ITM Options
strike = SpotC % iInterval > iInterval/2 ? SpotC - (SpotC%iInterval) + iInterval : SpotC - (SpotC%iInterval)
strikeCE = strike + (offsetCE * iInterval)
strikePE = strike - (offsetPE * iInterval)
////////////////////////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')
itype = 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))
longCondition = not na(arrowUp) and trend == 0 and trend[1] == 1
shortCondition = not na(arrowDown) and trend == 1 and trend[1] == 0
////////////////////////Block 3 Module Ends ///////////////////////////////////////////////////////////////////////
//Block 4 : Intraday Function and Buy and Sell Signal Mapping (Signal Mapping is Required)
//Remove the comments to do the long/short signal mapping
buySignal = longCondition
sellSignal = shortCondition
barInSession(sess) =>
time(timeframe.period, sess) != 0
bool intradaySession = barInSession(marketSession)
buy = buySignal
sell = sellSignal
buy1 = buy[1]
sell1 = sell[1]
////////////////////////Block 4 Module Ends ///////////////////////////////////////////////////////////////////////
//Block 5 : Framing Option Symbols and API Message 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
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
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
symPE := symbolinfo + Expiry + str.tostring(TSYMpe)+ 'PE'
tpslPE := symPE
exitsymCE := symCE //storing the CE symbol value for exit
symCE := ''
LongCall = '{ "apikey":"' + apikey + '", "strategy":"' + strategyType + '", "symbol":"' + symCE + '", "action":"BUY", "exchange":"' + exchange + '", "pricetype":"MARKET", "product":"' + product + '", "quantity":"' + str.tostring(quantity * lotsize) + '" }'
ExitCall = '{ "apikey":"' + apikey + '", "strategy":"' + strategyType + '", "symbol":"' + exitsymCE + '", "action":"SELL", "exchange":"' + exchange + '", "pricetype":"MARKET", "product":"' + product + '", "quantity":"' + str.tostring(quantity * lotsize) + '" }'
SqCall = '{ "apikey":"' + apikey + '", "strategy":"' + strategyType + '", "symbol":"' + tpslCE + '", "action":"SELL", "exchange":"' + exchange + '", "pricetype":"MARKET", "product":"' + product + '", "quantity":"' + str.tostring(quantity * lotsize) + '" }'
LongPut = '{ "apikey":"' + apikey + '", "strategy":"' + strategyType + '", "symbol":"' + symPE + '", "action":"BUY", "exchange":"' + exchange + '", "pricetype":"MARKET", "product":"' + product + '", "quantity":"' + str.tostring(quantity * lotsize) + '" }'
ExitPut = '{ "apikey":"' + apikey + '", "strategy":"' + strategyType + '", "symbol":"' + exitsymPE + '", "action":"SELL", "exchange":"' + exchange + '", "pricetype":"MARKET", "product":"' + product + '", "quantity":"' + str.tostring(quantity * lotsize) + '" }'
SqPut = '{ "apikey":"' + apikey + '", "strategy":"' + strategyType + '", "symbol":"' + tpslPE + '", "action":"SELL", "exchange":"' + exchange + '", "pricetype":"MARKET", "product":"' + product + '", "quantity":"' + str.tostring(quantity * lotsize) + '" }'
//assign trading signals
if(not intraday)
buy := buy
sell := sell
if(intraday)
buy := buy and intradaySession
sell := sell and intradaySession
////////////////////////Block 5 Module Ends ///////////////////////////////////////////////////////////////////////
//Block 6 : Trade Execution Controls
if(algomode=="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 Enter Fresh Call Option (Buy)
if buy and strategy.position_size < 0 and window()
strategy.close('LONGPUT', 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' ,alert_message=ExitCall)
strategy.entry('LONGPUT', strategy.short, alert_message=LongPut)
if(algomode=="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(algomode=="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
if(longsquareOff)
strategy.close(id='LONGCALL', comment='Square-off',alert_message=SqCall)
shortsquareOff = not intradaySession and strategy.position_size < 0
if(shortsquareOff)
strategy.close(id='LONGPUT', comment='Square-off',alert_message=SqPut)
////////////////////////Block 6 Module Ends ///////////////////////////////////////////////////////////////////////
//Block 7 : Plot Stoploss and 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(itype=="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(itype=="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 7 Module Ends ///////////////////////////////////////////////////////////////////////
//Block8: 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 )
////////////////////////Block 8 Module Ends ///////////////////////////////////////////////////////////////////////
Plug-and-Play Strategy Development: Insert your own logic into Block 3 to test strategies like Moving Average Crossovers, RSI signals, or ML-driven logic.
Backtest Ready: Instantly simulate performance with adjustable historical timeframes.
Options Execution: Automatically converts directional futures signals into options trades with customizable offsets.
Risk Management: Activate dynamic SL/TP configurations for robust risk control.
API Alerts: Sends alert messages structured for API consumption—ideal for auto-execution platforms.