Metadata-Version: 2.4
Name: nubra-iv-monitor
Version: 0.1.0
Summary: Real-time intraday ATM Implied Volatility monitor for the Nubra SDK
License: MIT
Project-URL: Bug Tracker, https://github.com/your-username/nubra-iv-monitor/issues
Keywords: options,implied-volatility,iv-crush,nubra,NSE,trading
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business :: Financial :: Investment
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: nubra-sdk>=0.3.8
Requires-Dist: matplotlib>=3.7
Requires-Dist: pandas>=2.0

# nubra-iv-monitor

Real-time intraday **ATM Implied Volatility monitor** for NSE options, built on the [Nubra SDK](https://pypi.org/project/nubra-sdk/).

Tracks the IV of the at-the-money strike for any number of underlyings simultaneously, plots them on a single normalised chart, and fires a callback with a structured DataFrame on every candle close.

---

## Install

```bash
pip install nubra-iv-monitor
```

Requires Python 3.12 and an active Nubra account with API access.

---

## Quick start

```python
from nubra_python_sdk.start_sdk import InitNubraSdk, NubraEnv
from nubra_python_sdk.refdata.instruments import InstrumentData
from nubra_python_sdk.marketdata.market_data import MarketData
from nubra_iv_monitor import monitor_iv

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

monitor_iv(
    stocks          = ["NIFTY", "BANKNIFTY", "RELIANCE"],
    market_data_obj = MarketData(nubra),
    instruments_obj = InstrumentData(nubra),
    interval        = "5m",
)
```

This opens a live chart and prints an IV table to the terminal every 5 minutes, aligned to the NSE candle grid (09:15 open).

---

## Authentication

The library does not handle authentication — you initialise the Nubra SDK yourself and pass the objects in.

```python
from nubra_python_sdk.start_sdk import InitNubraSdk, NubraEnv

# Reads PHONE_NO and MPIN from a .env file
nubra = InitNubraSdk(NubraEnv.PROD, env_creds=True)
```

`.env` file format:
```
PHONE_NO="9999999999"
MPIN="1234"
```

---

## Parameters

```python
monitor_iv(
    stocks,           # list[str]   — underlying symbols
    market_data_obj,  # MarketData  — authenticated Nubra instance
    instruments_obj,  # InstrumentData — authenticated Nubra instance
    interval   = "1m",    # str   — candle interval (see below)
    intraday   = True,    # bool  — fetch today's session only
    continuous = True,    # bool  — keep refreshing on candle closes
    plot       = True,    # bool  — show live matplotlib chart
    on_update  = None,    # callable(df) — callback fired every pass
)
```

### `interval` options

| Value | Candle size | Grid ticks from 09:15 |
|-------|-------------|------------------------|
| `"1m"` | 1 minute | 09:16, 09:17, 09:18 … |
| `"3m"` | 3 minutes | 09:18, 09:21, 09:24 … |
| `"5m"` | 5 minutes | 09:20, 09:25, 09:30 … |
| `"15m"` | 15 minutes | 09:30, 09:45, 10:00 … |
| `"30m"` | 30 minutes | 09:45, 10:15, 10:45 … |
| `"1h"` | 1 hour | 10:15, 11:15, 12:15 … |


---

## Live chart

When `plot=True` (default), a matplotlib window opens showing all stocks on the same graph.

- Y-axis: **IV change from open (%)** — all lines start at 0 so stocks with very different absolute IV levels can be compared directly.
- X-axis: Time in IST.
- Each line is labelled at its endpoint with the stock name.
- The chart redraws on every candle close and saves a snapshot to `iv_monitor.png`.

Set `plot=False` for headless / server environments.

---

## DataFrame output via `on_update`

Pass a callback to receive a **long-format DataFrame** on every candle close:

```python
def on_update(df):
    print(df)

monitor_iv(["NIFTY", "HDFCBANK"], market_data, instruments,
           interval="5m", on_update=on_update)
```

### DataFrame schema

| Column | Type | Description |
|--------|------|-------------|
| `time` | `datetime` (IST, tz-aware) | Candle timestamp |
| `stock` | `str` | Underlying symbol, e.g. `"NIFTY"` |
| `avg_iv_pct` | `float` | Average of CE + PE ATM IV in % (e.g. `18.42`) |
| `delta_from_open` | `float` | IV change since market open in % points (e.g. `-1.30`) |
| `ce_symbol` | `str` | ATM call option symbol, e.g. `"NIFTY2611324500CE"` |
| `pe_symbol` | `str` | ATM put option symbol, e.g. `"NIFTY2611324500PE"` |
| `current_price` | `float` | Underlying spot price in ₹ at time of fetch |
| `atm_strike` | `float` | ATM strike in ₹ |

### Sample output

```
                       time   stock  avg_iv_pct  delta_from_open         ce_symbol         pe_symbol  current_price  atm_strike
2026-05-12 09:20:00+05:30   NIFTY       18.42             0.00  NIFTY2611324500CE  NIFTY2611324500PE       24487.30     24500.0
2026-05-12 09:25:00+05:30   NIFTY       18.10            -0.32  NIFTY2611324500CE  NIFTY2611324500PE       24487.30     24500.0
2026-05-12 09:30:00+05:30   NIFTY       17.85            -0.57  NIFTY2611324500CE  NIFTY2611324500PE       24487.30     24500.0
2026-05-12 09:20:00+05:30  HDFCBANK     22.10             0.00  HDFCBANK26MAY1800CE HDFCBANK26MAY1800PE     1812.50      1800.0
```

The DataFrame contains all historical candles from 09:15 to now for every stock in a single flat table — suitable for filtering, alerting, database writes, or further analysis.

### Accessing the latest value per stock

```python
def on_update(df):
    latest = df.sort_values("time").groupby("stock").last().reset_index()
    print(latest[["stock", "avg_iv_pct", "delta_from_open"]])
```

---

## Continuous vs one-shot

```python
# Run once and exit
monitor_iv([...], market_data, instruments, continuous=False)

# Run continuously until you stop the script (Ctrl+C)
monitor_iv([...], market_data, instruments, continuous=True)
```

When `continuous=True` and the market is closed, the monitor waits 60 seconds and rechecks. It runs automatically when the market opens.

---


## Requirements

-  Python = 3.12
- `nubra-sdk >= 0.3.8`
- `pandas >= 2.0`
- `matplotlib >= 3.7`

---

