Feature Request: Contract-Level Expiry Info in Expired Options API (for Realistic Backtesting)

Hi Dhan team,

I’m actively using the Expired Options Data API (and /v2/charts/rollingoption) to build an options backtesting engine, and I’ve run into a structural limitation that makes realistic backtests very hard – especially around expiry and rollovers.

Problem

Right now the expired options API / rolling options charts:

• Only expose the option relative to the underlying via strike macros like ATM, ATM+1, ATM-1, etc.

• Use expiry_flag (MONTH / WEEK) and expiry_code (1/2/3) to represent “current / next / far” relative to the trading date.

This design is great for live trading (you always get the current ATM series without worrying about exact contract symbols).

But for backtesting, it creates a big issue:

• “Current expiry, ATM+1” on day D is not the same contract as “current expiry, ATM+1” on day D+1 if an expiry has just passed.

• When I compute things like price % change vs previous close or OI % change, I need to compare today’s series to the same contract’s previous session, not to yesterday’s expired contract at that strike.

• With the current API, I can’t distinguish between:

• NIFTY 25-Oct 25250 CE (yesterday’s expiry)

• NIFTY 1-Nov 25250 CE (today’s new contract)

So on the day after expiry, if I use yesterday’s last ATM+1 candle as a baseline, I end up comparing today’s new contract (say 30 → 50) against yesterday’s expired contract that closed at ₹0.50 — which leads to nonsensical % changes like +4000% or −99% for what is actually a fresh contract.

This makes it very difficult to:

• Reconstruct realistic daily baselines for price change / OI% calculations.

• Backtest strategies that rely on contract-level continuity (e.g., “enter NIFTY 25200 CE on 24-Oct, exit on 25-Oct at close”) because we can’t be sure we’re looking at the same contract across sessions.

What would solve this

It would be extremely helpful if the expired options / rolling option charts API could expose contract-level information in addition to the current rolling identifiers, for example:

• A stable contract identifier (e.g. NIFTY25NOV245250CE or similar), or at least:

• expiry_date (e.g. 2025-11-27)

• strike_price (double / int)

• option_type (CE / PE)

With that, I can define a unique key like:

ContractKey = {

underlying_symbol,

exchange_segment,

instrument, // OPTIDX / OPTSTK

expiry_date, // actual expiry date

strike_price,

option_type // CALL / PUT

}

…and then:

• Compute baselines per contract, not just per underlying.

• Avoid mixing yesterday’s expired contract with today’s new one.

• Run proper, realistic backtests over 5+ years without hand-maintaining separate contract files.

Questions / Suggestions

1. Is there already an API or data file that exposes contract-level information (expiry date, strike, option type) for historical option series that I can join with the rolling option OHLC?

• e.g. GET /v1/options/contracts returning all contracts with their expiry dates and Dhan security_ids for the past X years.

2. If not available today, could you consider:

• Adding expiry_date (and possibly option_type) as extra fields in the rollingoption / expired options responses, and/or

• Providing a separate “contract master” API for historical option contracts, keyed by security_id, expiry_date, option_type, strike_price.

With that information, anyone building backtests or analytics on expired options can:

• Correctly separate contracts by expiry.

• Compute price/OI changes relative to the correct baseline.

• Avoid distortions around weekly/monthly expiry rollovers.

This would make the Expired Options API much more powerful for serious quants/strategy developers, without breaking the existing ATM / ATM±1 UX that live traders like.

Thanks a lot for considering this — happy to provide more examples or collaborate on requirements if that helps.

Hello @Parthiban_Sub

I understand this point and this is why we already have Strike Price and Option Type added on the rolling options data:

  • Strike Price - added with each row of values, to denote which strike is selected
  • Call/Put - which is passed by you when fetching the data

We will check on the expiry date as well. Let me know if this solves for your calculation of baselines and backtest your own strategies.

@Hardik – thanks for the quick reply and for confirming the presence of strikePrice + option type in the rolling options data. Those fields are definitely useful, but they don’t fully solve the baseline / backtest problem I’m trying to address.

The core issue isn’t within a single day – it’s across sessions and especially across expiries.

Right now, for rolling options:

  • I select contracts using macros like ATM, ATM+1, ATM-1, etc.

  • Over the course of the day, and especially around expiry, the macro continues to refer to “current ATM”, not to a specific contract.

  • After expiry, the same macro (ATM, ATM+1, etc.) will point to the next series, even though the prior series has already expired.

So even though each row in the rolling options API has:

  • strikePrice

  • optionType (CALL / PUT)

those are not enough for contract-level continuity, because:

  • On day D I might enter a trade in NIFTY 25 OCT 25250 CE via ATM+1.

  • On day D+1, if I fetch ATM+1 again for the same underlying, I might get NIFTY 01 NOV 25300 CE (new series).

  • Both rows will have a strikePrice and CALL, but there’s no field that tells me “these are different contracts (different expiry)”.

For realistic backtests and baselines I need to:

  • Join “today’s” OHLC to “yesterday’s” same contract (same expiry), and

  • Compute price / OI changes across sessions per contract, not just per underlying or macro.

For that, I need at least one contract-level identifier in the rolling options data, for example:

  • expiryDate (e.g. 2025-11-27) or

  • a stable contract id per series, or

  • a combination of fields like:

    • underlying symbol

    • instrument (OPTIDX/OPTSTK)

    • exchange segment

    • expiry date

    • strike price

    • option type (CE/PE)

With something like expiryDate included in each rolling-option row I can construct a clear key:{ underlyingSymbol, instrument, exchangeSegment, expiryDate, strikePrice, optionType }and use that to:

  • group candles per contract,

  • compute previous-day close per contract,

  • calculate accurate price-change / OI-change baselines across sessions, and

  • backtest “enter NIFTY 25 OCT 25250 CE on 24-Oct, exit at EOD on 25-Oct” in a way that’s consistent with how brokers compute P&L.

So to answer your question: strikePrice + optionType are helpful, but they don’t fully solve the baseline/backtesting problem without expiry information (or another contract-level identifier) in the response.

If you could:

  1. Add expiryDate to the /v2/charts/rollingoption / expired options response or

  2. Provide a separate “contract master” API keyed by securityId that returns expiryDate, strikePrice, optionType, etc.

that would be enough for me (and others) to build realistic options backtests on top of Dhan’s data.