Skip to content

Realtime Option Chain Streaming

Option-chain streaming lets you monitor full strike ladders per underlying and expiry, continuously.

Use this for:

  • live ATM shift monitoring
  • strike-level CE/PE scans
  • volatility-aware signal generation

Stream Input Shape

For option chain subscriptions, pass:

  • ASSET:EXPIRY keys
  • data_type="option"
  • exchange value (NSE / BSE as applicable)

Example key:

  • NIFTY:20250626

WebSocket Option Chain Example

from nubra_python_sdk.ticker import websocketdata
from nubra_python_sdk.start_sdk import InitNubraSdk, NubraEnv

nubra = InitNubraSdk(NubraEnv.UAT, env_creds=True)

def pick(obj, *names):
    for name in names:
        value = getattr(obj, name, None)
        if value is not None:
            return value
    return None

def clean(d):
    return {k: v for k, v in d.items() if v is not None}

def on_option_data(msg):
    chain = clean(
        {
            "asset": pick(msg, "asset"),
            "expiry": pick(msg, "expiry"),
            "atm": pick(msg, "at_the_money_strike", "atm"),
            "spot": pick(msg, "current_price", "currentprice"),
            "exchange": pick(msg, "exchange"),
        }
    )
    print("[OptionChain]", chain)

    ce = getattr(msg, "ce", []) or []
    pe = getattr(msg, "pe", []) or []

    if ce:
        first_ce = ce[0]
        print(
            "[CE sample]",
            clean(
                {
                    "ref_id": pick(first_ce, "ref_id"),
                    "strike": pick(first_ce, "strike_price", "sp"),
                    "ltp": pick(first_ce, "last_traded_price", "ltp"),
                    "iv": pick(first_ce, "iv"),
                    "delta": pick(first_ce, "delta"),
                    "gamma": pick(first_ce, "gamma"),
                    "theta": pick(first_ce, "theta"),
                    "vega": pick(first_ce, "vega"),
                    "oi": pick(first_ce, "open_interest", "oi"),
                    "volume": pick(first_ce, "volume"),
                }
            ),
        )
    if pe:
        first_pe = pe[0]
        print(
            "[PE sample]",
            clean(
                {
                    "ref_id": pick(first_pe, "ref_id"),
                    "strike": pick(first_pe, "strike_price", "sp"),
                    "ltp": pick(first_pe, "last_traded_price", "ltp"),
                    "iv": pick(first_pe, "iv"),
                    "delta": pick(first_pe, "delta"),
                    "gamma": pick(first_pe, "gamma"),
                    "theta": pick(first_pe, "theta"),
                    "vega": pick(first_pe, "vega"),
                    "oi": pick(first_pe, "open_interest", "oi"),
                    "volume": pick(first_pe, "volume"),
                }
            ),
        )

socket = websocketdata.NubraDataSocket(
    client=nubra,
    on_option_data=on_option_data,
)

socket.connect()
socket.subscribe(["NIFTY:20260505"], data_type="option", exchange="NSE")
socket.keep_running()

Practical Notes

  • always fetch the latest valid expiry before subscribing
  • treat this as a stream of chain snapshots/updates, not one-time data
  • for heavy chains, keep processing async and avoid expensive work inside callback
NEO Assistant