CLI · commit 299a9c6

optionsdesk

Options strategy analyzer: pricing, Greeks, payoff & risk

Download optionsdesk.zip
Quickstart
unzip optionsdesk.zip && cd optionsdesk
uv venv .venv && uv pip install -p .venv/bin/python -e '.[dev]'
.venv/bin/python -m pytest -q

optionsdesk

Options strategy analyzer for the terminal. Price options with BSM, Black-76, a CRR binomial tree and Monte Carlo, solve implied volatility, fit an SVI volatility surface to an option chain, build multi-leg strategies (YAML, one-line shorthand or templates) and get breakevens, max profit/loss, net Greeks, probability of profit, a SPAN-like margin estimate and a P&L risk matrix, with a Unicode payoff chart in the terminal and SVG/HTML/JSON export. Fully offline, built for NSE (NIFTY, BANKNIFTY) and US equity traders.

Features

Install

Requires Python 3.12.

cd optionsdesk
uv venv .venv
uv pip install -p .venv/bin/python -e '.[dev]'
source .venv/bin/activate      # or call .venv/bin/optionsdesk directly

Quickstart

optionsdesk price -t call -S 42 -K 40 --days 182.5 -r 0.10 --vol 0.20 --greeks
optionsdesk smile examples/nifty_chain.csv -S 24650 -r 0.065 -q 0.013 --asof 2026-10-16
optionsdesk analyze examples/iron_condor.yaml --days 7,21

All numeric rates and volatilities are decimals (0.065 is 6.5%). Time to expiry is calendar days over 365. Valuation date defaults to today; pass --asof YYYY-MM-DD for reproducible runs. The examples below use --asof 2026-10-16.

Usage

Price an option

Hull's textbook example (S=42, K=40, r=10%, sigma=20%, six months): call 4.76.

$ optionsdesk price -t call -S 42 -K 40 --days 182.5 -r 0.10 --vol 0.20 --greeks
 Model  bsm
 Price  4.7594
Greeks

  Greek       Value   Unit
 ─────────────────────────────────────────
  delta      0.7791   per 1 unit move
  gamma    0.049963   per 1 unit move
  vega       0.0881   per vol point
  theta     -0.0125   per calendar day
  rho        0.1398   per 1% rate
  vanna   -0.009316   delta per vol point
  charm   -0.000064   delta per day
  vomma    0.002128   vega per vol point

Other models: --model american (CRR tree, --steps, default 500), --model black76 (pass the futures price as -S), --model mc (--paths, --seed). Add --json for machine-readable output.

$ optionsdesk price -t put -S 50 -K 50 --days 152 -r 0.10 --vol 0.40 --model american
 Model  american
 Price  4.2838

The European put on the same inputs is 4.0760; the early exercise premium is about 0.21.

$ optionsdesk price -t call -S 42 -K 40 --days 182.5 -r 0.10 --vol 0.20 --model mc --seed 1
 Model      mc
 Price      4.7504
 Std error  0.0055
 95% CI     [4.7397, 4.7611]

Implied volatility

$ optionsdesk iv --price 4.76 -t call -S 42 -K 40 --days 182.5 -r 0.10
Implied volatility (bsm): 20.0066%

An option price that no volatility can produce (below intrinsic or above the upper bound) exits with status 1 and a message such as price 1 is below the no-arbitrage lower bound 50.

$ optionsdesk iv --price 520 -t call -S 24650 -K 24700 --expiry 2026-11-24 --asof 2026-10-16 -r 0.065 -q 0.013
Implied volatility (bsm): 14.8366%

Fit a smile and surface

examples/nifty_chain.csv is synthetic: quotes priced from a known raw SVI surface with 0.3% IV noise, tick-rounded bid/ask spreads, stale last prices in the wings. Regenerate with python examples/generate_chain.py > examples/nifty_chain.csv. The generating ATM vols are 13.8%, 14.5%, 15.2% and 16.0%, which the fit recovers.

$ optionsdesk smile examples/nifty_chain.csv -S 24650 -r 0.065 -q 0.013 --asof 2026-10-16
Raw SVI fit per expiry, total variance w(k)

  Expiry       T (yr)   Pts         a         b       rho          m     sigma   ATM IV   RMSE (pts)
 ────────────────────────────────────────────────────────────────────────────────────────────────────
  2026-10-27   0.0301    86   0.00009   0.01497   -0.5482   +0.00417   0.02989   13.81%        0.059
  2026-11-24   0.1068   143   0.00096   0.02773   -0.5020   +0.00312   0.04454   14.50%        0.049
  2026-12-29   0.2027   190   0.00236   0.03803   -0.4490   +0.00219   0.06010   15.20%        0.052
  2027-03-30   0.4521   201   0.00660   0.05660   -0.4108   -0.00138   0.08814   15.99%        0.050

--quotes lists every quote's market IV against the fit. --json emits the parameters.

$ optionsdesk arb examples/nifty_chain.csv -S 24650 -r 0.065 -q 0.013 --asof 2026-10-16
PASS  Butterfly (SVI density g(k) >= 0)
PASS  Calendar (total variance non-decreasing)
FAIL  Quote convexity (call prices from market IVs): 18 violation(s)

  Expiry       Where         Magnitude   Detail
 ───────────────────────────────────────────────────────────────────────────
  2026-10-27   22,900.0000   -1.625      call price is not convex in strike
  2026-11-24   21,700.0000   -2.5        call price is not convex in strike
  2026-11-24   22,150.0000   -2.875      call price is not convex in strike
  2026-11-24   27,000.0000   -1.75       call price is not convex in strike
  2026-11-24   27,100.0000   -1.575      call price is not convex in strike
  2026-11-24   27,600.0000   -0.75       call price is not convex in strike
  2026-11-24   27,800.0000   -0.575      call price is not convex in strike
  2026-11-24   28,000.0000   -0.35       call price is not convex in strike
  ...                                    10 more

The SVI slices are free of butterfly and calendar arbitrage. The quote-level check flags wing quotes whose implied call prices are not convex beyond what their bid/ask spreads explain; the command exits 1 when anything fails so it can gate a pipeline.

Analyze a strategy

YAML (examples/iron_condor.yaml):

name: NIFTY iron condor (24 Nov)
underlying: NIFTY          # lot size 75 from the contract specs
spot: 24650
rate: 0.065
dividend_yield: 0.013
asof: 2026-10-16
chain: nifty_chain.csv     # volatility from the fitted SVI surface (or `vol: 0.145` for flat)
legs:
  - {qty: 1,  type: P, strike: 24100, expiry: 2026-11-24}
  - {qty: -1, type: P, strike: 24300, expiry: 2026-11-24}
  - {qty: -1, type: C, strike: 25000, expiry: 2026-11-24}
  - {qty: 1,  type: C, strike: 25200, expiry: 2026-11-24}
$ optionsdesk analyze examples/iron_condor.yaml --days 7,21
╭────────────────────────────╮
│ NIFTY iron condor (24 Nov) │
╰────────────────────────────╯
Legs

  Leg                      Entry   Size
 ───────────────────────────────────────
  +1 P 24100 2026-11-24   250.30     75
  -1 P 24300 2026-11-24   297.43    -75
  -1 C 25000 2026-11-24   357.68    -75
  +1 C 25200 2026-11-24   274.72     75


P&L at expiry

    9756 │                          ███████████████████
         │                         █████████████████████
         │                         █████████████████████
         │                         █████████████████████
         │                        ███████████████████████
         │                        ███████████████████████
         │                        ███████████████████████
         │                       █████████████████████████
         │                   ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦██████████
         │             ◦◦◦◦◦◦    ███████████████◦◦◦◦◦◦◦███
     0.0 │────────◦◦◦◦◦••••••••••••••••••••••••••••••──◦◦◦◦◦──────────────────────
         │•••◦◦◦◦◦██████████████             ┊       •••••••◦◦◦◦██████████████████
         │◦◦◦███████████████████             ┊             ███••◦◦◦◦◦•████████████
         │██████████████████████             ┊             ██████████◦◦◦◦◦◦•••████
         │█████████████████████              ┊              ███████████████◦◦◦◦◦◦◦
         │█████████████████████              ┊              ██████████████████████
   -5244 │█████████████████████              ┊               █████████████████████
         └────────────────────────────────────────────────────────────────────────
                                ▲                         ▲                         breakeven
          23.4k                            24.6k                             26.0k
          █ expiry P&L   • T+7   ◦ T+21   ┊ spot

Summary (spot 24,650.00, to 2026-11-24)

  Metric                                                                              Value
 ───────────────────────────────────────────────────────────────────────────────────────────
  Net credit                                                                          9,756
  Max profit                                                             9,756  (at 24,650)
  Max loss                                                                           -5,244
  Breakevens                                                           24,169.92, 25,130.08
  Probability of profit (drift 5.20%, vol 14.81%)                                     31.1%
  Expected P&L                                                                         -858
  Margin estimate (SPAN-like scan)                  4,874  (worst: price +8.0%, vol -4 pts)

Net Greeks (position)

  Greek       Value   Unit
 ─────────────────────────────────────────
  delta     -1.4711   per 1 unit move
  gamma   -0.002959   per 1 unit move
  vega    -246.3476   per vol point
  theta     39.5115   per calendar day
  rho      -28.3228   per 1% rate
  vanna    0.199122   delta per vol point
  charm   -0.013633   delta per day
  vomma   29.294011   vega per vol point

Risk matrix: P&L by spot and date

    Spot      T+7     T+21   expiry
 ───────────────────────────────────
  23,171   -1,595   -2,493   -5,244
  23,418     -791   -1,284   -5,244
  23,664      -77       23   -5,244
  23,910      459    1,222   -5,244
  24,157      746    2,077     -969
  24,404      746    2,389    9,756
  24,650      463    2,079    9,756
  24,896      -61    1,215    9,756
  25,143     -752      -10     -969
  25,390   -1,526   -1,347   -5,244
  25,636   -2,299   -2,574   -5,244
  25,882   -3,008   -3,556   -5,244
  26,129   -3,612   -4,254   -5,244

Legs without premium are priced by the model at the valuation date (using the surface vol for each strike), so T+0 P&L at today's spot is zero. Pass premium: 120.5 (or @120.5 in the shorthand) to use your actual fill. Quantities are signed lots; P&L and Greeks are scaled by the lot size.

Shorthand and templates need no file:

optionsdesk analyze --legs "+1 C 24500 2026-11-24, -1 C 24800 2026-11-24" \
    --underlying NIFTY --vol 0.145 -S 24650 -r 0.065 -q 0.013 --asof 2026-10-16

optionsdesk analyze --template iron-condor --strikes 24100,24300,25000,25200 \
    --expiry 2026-11-24 --underlying NIFTY --chain examples/nifty_chain.csv \
    -S 24650 -r 0.065 -q 0.013 --asof 2026-10-16
$ optionsdesk analyze --legs "+1 C 24500 2026-11-24, -1 C 24800 2026-11-24" --underlying NIFTY --vol 0.145 -S 24650 -r 0.065 -q 0.013 --asof 2026-10-16 --no-chart --days 14
╭─────────────────╮
│ Custom strategy │
╰─────────────────╯
Legs

  Leg                      Entry   Size
 ───────────────────────────────────────
  +1 C 24500 2026-11-24   619.32     75
  -1 C 24800 2026-11-24   459.27    -75

Summary (spot 24,650.00, to 2026-11-24)

  Metric                                                                               Value
 ────────────────────────────────────────────────────────────────────────────────────────────
  Net debit                                                                           12,004
  Max profit                                                                          10,496
  Max loss                                                              -12,004  (at 24,500)
  Breakevens                                                                       24,660.05
  Probability of profit (drift 5.20%, vol 14.50%)                                      53.4%
  Expected P&L                                                                         83.60
  Margin estimate (SPAN-like scan)                  11,767  (worst: price -8.0%, vol -4 pts)

Net Greeks (position)

  Greek       Value   Unit
 ─────────────────────────────────────────
  delta      7.5756   per 1 unit move
  gamma   -0.000911   per 1 unit move
  vega     -85.7870   per vol point
  theta     -8.5188   per calendar day
  rho      186.7043   per 1% rate
  vanna   -0.512755   delta per vol point
  charm    0.098790   delta per day
  vomma    9.673371   vega per vol point

Risk matrix: P&L by spot and
date

    Spot      T+14    expiry
 ────────────────────────────
  23,171   -10,644   -12,004
  23,418    -9,722   -12,004
  23,664    -8,430   -12,004
  23,910    -6,753   -12,004
  24,157    -4,737   -12,004
  24,404    -2,482   -12,004
  24,650      -136      -754
  24,896     2,142    10,496
  25,143     4,211    10,496
  25,390     5,971    10,496
  25,636     7,376    10,496
  25,882     8,432    10,496
  26,129     9,178    10,496

A calendar spread prices the surviving far leg with surface vol at the near expiry:

$ optionsdesk analyze examples/calendar.yaml --no-chart --days 14
╭──────────────────────────────╮
│ NIFTY call calendar at 24700 │
╰──────────────────────────────╯
Legs

  Leg                      Entry   Size
 ───────────────────────────────────────
  -1 C 24700 2026-11-24   515.36    -75
  +1 C 24700 2026-12-29   790.18     75

Summary (spot 24,650.00, to 2026-11-24)

  Metric                                                                               Value
 ────────────────────────────────────────────────────────────────────────────────────────────
  Net debit                                                                           20,612
  Max profit                                                             17,564  (at 24,700)
  Max loss                                                                           -20,641
  Breakevens                                                            24,192.85, 25,406.46
  Probability of profit (drift 5.20%, vol 14.81%)                                      38.7%
  Expected P&L                                                                        -2,637
  Margin estimate (SPAN-like scan)                  17,934  (worst: price -8.0%, vol -4 pts)

Net Greeks (position)

  Greek       Value   Unit
 ─────────────────────────────────────────
  delta      1.7102   per 1 unit move
  gamma   -0.007972   per 1 unit move
  vega     875.4994   per vol point
  theta    106.6384   per calendar day
  rho      960.5321   per 1% rate
  vanna   -0.065920   delta per vol point
  charm    0.026569   delta per day
  vomma    2.107162   vega per vol point

Risk matrix: P&L by spot and
date

    Spot      T+14    expiry
 ────────────────────────────
  23,171   -10,995   -16,921
  23,418    -8,366   -14,640
  23,664    -5,643   -11,367
  23,910    -3,047    -6,880
  24,157      -820      -984
  24,404       829     6,461
  24,650     1,760    15,526
  24,896     1,933    11,467
  25,143     1,408     5,186
  25,390       326       291
  25,636    -1,128    -3,407
  25,882    -2,761    -6,112
  26,129    -4,406    -8,030

Export: --svg out.svg, --html report.html (self-contained page with chart, summary and matrix), --json. Other examples: examples/bull_call_spread.yaml (explicit premiums, side: sell), calendar.yaml and ratio_spread.yaml (template keys), covered_call.yaml.

Templates and contract specs

$ optionsdesk templates
 Template           Strikes  Description
 bull-call-spread         2  Buy low call, sell high call (strikes: low, high)
 bear-put-spread          2  Buy high put, sell low put (strikes: low, high)
 bull-put-spread          2  Sell high put, buy low put for a credit (strikes: low, high)
 bear-call-spread         2  Sell low call, buy high call for a credit (strikes: low, high)
 long-straddle            1  Buy call and put at one strike (strike)
 short-straddle           1  Sell call and put at one strike (strike)
 long-strangle            2  Buy OTM put and OTM call (strikes: put, call)
 short-strangle           2  Sell OTM put and OTM call (strikes: put, call)
 iron-condor              4  Short strangle with long wings (strikes: put wing, short put, short
                             call, call wing)
 butterfly                3  Long call butterfly: +1 low, -2 mid, +1 high (strikes: low, mid, high)
 calendar                 1  Sell near call, buy far call at one strike (strike, needs far expiry)
 call-ratio-spread        2  Buy 1 low call, sell N high calls (strikes: low, high)
 put-ratio-spread         2  Sell N low puts, buy 1 high put (strikes: low, high)
 covered-call             1  Long underlying plus short call (strike)
 collar                   2  Long underlying, long put, short call (strikes: put, call)
$ optionsdesk specs
 Symbol      Lot size  Tick  Exchange   Currency  Style
 AAPL        100       0.01  NASDAQ     USD       american
 BANKNIFTY   35        0.05  NSE        INR       european
 FINNIFTY    65        0.05  NSE        INR       european
 MIDCPNIFTY  140       0.05  NSE        INR       european
 NIFTY       75        0.05  NSE        INR       european
 RELIANCE    500       0.05  NSE        INR       european
 SENSEX      20        0.05  BSE        INR       european
 SPX         100       0.05  CBOE       USD       european
 SPY         100       0.01  NYSE Arca  USD       american

Lot sizes change. Override with --contracts my.toml or OPTIONSDESK_CONTRACTS=my.toml; entries replace the bundled ones with the same symbol, and --lot-size overrides a single run. Contracts with style = "american" (US equities) are priced with the binomial tree under the default --model auto.

Configuration

Option Meaning
-r/--rate, -q/--div Risk-free rate (default 0.065) and dividend yield (default 0), continuous, decimal
--asof Valuation date; defaults to today
--vol / --chain Flat vol, or a chain CSV for surface vol (strike-based lookup)
--model auto (BSM for european contracts, tree for american), bsm, black76, american
--days 7,14 Extra T+n curves and risk-matrix columns
--drift Real-world annual drift for probability of profit and expected value (default risk-neutral r - q)
--margin-range, --margin-vol Margin scan: price move (default 8%) and vol shift (default 4 vol points)
OPTIONSDESK_CONTRACTS Path to a contracts TOML

Chain CSV columns: strike, expiry (YYYY-MM-DD), bid, ask, last, oi, type (C/P). The mid price is used when a two-sided quote exists, otherwise last.

Greeks units: vega per vol point, rho per 1% rate, theta and charm per calendar day, vanna per vol point, vomma per vol point squared (all per unit of underlying; strategy Greeks are multiplied by lots and lot size).

Architecture

optionsdesk/
  models/bsm.py        BSM price and Greeks (vectorised over spot)
  models/black76.py    Black-76 as BSM with q = r, own rho
  models/binomial.py   CRR tree vectorised over spots, bump Greeks
  models/montecarlo.py antithetic MC with CI
  models/iv.py         Newton/bisection IV (BSM, Black-76, American)
  market.py            spot, rate, yield, as-of date
  surface.py           chain loader, smile points, SVI fit, VolSurface, arbitrage checks
  strategy.py          Leg, shorthand parser, YAML loader, templates
  contracts.py         lot sizes from TOML (data/contracts.toml bundled)
  analytics.py         Position valuation, breakevens, max P&L, PoP, EV, margin, risk matrix
  charts.py            Unicode chart, SVG, HTML
  report.py            rich tables
  cli.py               click commands: price iv smile arb analyze templates specs
tests/                 pytest suite
examples/              synthetic NIFTY chain, generator, strategy YAMLs
docs/                  models.md, analytics.md

Algorithms, formulas and design decisions: docs/models.md and docs/analytics.md.

Tests

.venv/bin/pytest -q

Covers Hull textbook values, put-call parity, Greeks against finite differences, binomial convergence and the known American put, Monte Carlo inside its CI, IV recovery across moneyness and expiry, SVI parameter recovery, arbitrage detection, hand-calculated breakevens and max P&L for the templates, probability of profit against Monte Carlo, and CLI end-to-end runs on the examples.

Limitations