# Futures to Options Module

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:

<figure><img src="/files/xIn8VeZlLIKlIOyahAIx" alt=""><figcaption></figcaption></figure>

#### Sample Template Overview

This module is structured into 8 distinct blocks, each with a specific function:

1. **OpenAlgo API Controls**: Connects to OpenAlgo for live execution, allowing integration with real trading APIs.
2. **Backtesting & Risk Controls**: Defines trading timeframes, and configurable risk parameters including Stoploss/Target (fixed, percentage, or ATR-based).
3. **Trading Strategy Block**: Users can plug in any logic here. The default implementation includes a HalfTrend + ATR channel-based strategy.
4. **Signal Mapping & Intraday Filtering**: Converts strategy conditions into buy/sell signals and handles intraday session logic.
5. **Option Symbol Generation & API Messaging**: Frames CE/PE option symbols dynamically based on spot price, expiry, and strike intervals.
6. **Trade Execution Logic**: Executes trades based on signal, handles square-off and mode control (Enable, Long-only, Short-only).
7. **SL/TP Visualization**: Plots stoploss and target markers based on the selected risk model.
8. **Trading Dashboard**: Displays real-time trade info (entry/exit signals) on the chart using tables.

```coffeescript
// 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 ///////////////////////////////////////////////////////////////////////

```

### Ensure Position Size is handled in the Properties Section

<figure><img src="/files/3tL5Mn29AFK7K0VT0nLh" alt=""><figcaption></figcaption></figure>

### Ensure Alert Message is Set

<figure><img src="/files/Ul5gTUusUV8KHZgoLaSX" alt=""><figcaption></figcaption></figure>

#### 💡 How Traders Can Use It

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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.openalgo.in/trading-platform/tradingview/futures-to-options-module.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
