Skip to content

Repository files navigation

Explain My Option

A lightweight Quant AI Agent that diagnoses why a specific option's price changed — not by predicting prices, but by combining deterministic quant metrics (Delta/Vega/Theta PnL attribution) with recent news, synthesized by an LLM into a human-readable Markdown report.

How it works

A unified LangGraph product graph (book-first parent + leg subgraph). Live compiled diagrams: notebooks/langgraph_architecture.ipynb.

flowchart LR
    A[require_openai] --> B[Send leg_branch]
    B --> C[aggregate_book]
    subgraph D[leg_branch subgraph]
      D1[fetch_market] --> D2[quant] --> D3[blotter] --> D4[diagnostic_pass]
      D4 --> D5[residual_gate loop]
      D5 --> D6[plan_search] --> D7[search] --> D8[synthesize]
      D8 --> D9[verify loop] --> D10[finalize_leg_report]
    end
Loading

The PnL of a 1-day move is decomposed as:

$$\Delta P \approx \underbrace{\Delta \cdot \Delta S}_{\text{Delta PnL}} + \underbrace{\mathcal{V} \cdot \Delta \sigma}_{\text{Vega PnL}} + \underbrace{\Theta \cdot \Delta t}_{\text{Theta PnL}} + \text{residual (gamma/convexity)}$$

Project layout

.
├── src/                   # Diagnoses option moves
│   ├── data_loader.py     # yfinance: stock, option IV, news, vol surface
│   ├── data/synthetic.py  # Fixture loader (primary eval path)
│   ├── pricing/           # QuantLib FDM official PnL + LSM/Merton analysis API
│   ├── agent_graph.py     # fetch_market → quant → blotter → plan_search → search → diagnose
│   ├── graph/             # GraphDeps ports (market / PnL)
│   ├── intel/             # SearchPlan + IntelSource registry
│   └── report_generator.py
├── tests/ci/              # Parts check (engine/graph/report + fixtures/golden)
├── tests/live_book/       # Recent live-book evaluation
├── tests/historical/      # Historical-event evaluation
├── tests/README.md         # Test layout
├── notebooks/            # LangGraph topology notebook (PNG / x-ray)
├── app.py                 # Streamlit + CLI entrypoint
├── requirements.txt
├── README.md
├── ACKNOWLEDGMENTS.md     # Third-party licenses
├── docs/                  # Notes + curated official links
│   ├── references/
│   └── knowledge/
└── scripts/               # run-tests.sh, smoke-offline.sh

Doc map: docs/README.md.
Case study (historical anomaly): docs/case-studies/vow_float_squeeze_2008.md.

Setup

python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

# All offline tests
./scripts/run-tests.sh

Set an OpenAI API key (required by default in the unified runtime):

export OPENAI_API_KEY="sk-..."
# default (cheapest common OpenAI chat model): gpt-4o-mini
# export EMO_LLM_MODEL="gpt-4o-mini"

You can also put these in a .env file (loaded automatically). Optional Tavily Search for vega / event queries: paste TAVILY_API_KEY= there (see .env.example). Never commit the key. Without it, Yahoo titles still run and Tavily is skipped.

Usage

CLI:

python app.py --ticker AAPL --type call
python app.py --ticker TSLA --type put --strike 250 --expiry 2026-01-16
python app.py --fixture vol_crush

Book input on the same product entrypoint:

python app.py --book tests/ci/fixtures/books/showcase_book.json

Eval reports belong under tests/live_book/output/ and tests/historical/output/<case>/ (gitignored), not the repo root. See tests/README.md.

Streamlit UI:

streamlit run app.py

Notes & MVP simplifications

  • Default US equity official pricing is American FDM (QuantLib FdBlackScholesVanillaEngine). Local vol is used when today's implied-vol grid passes a Dupire probe; otherwise the contract IV is treated as flat. CRR remains selectable via EMO_PRICING_ENGINE=crr.
  • Heston, when a vol grid is available, is diagnostic only.
  • LSM-BS and LSM-Merton are an analysis API (src/pricing/analysis_api.py) for later LLM tools — they are not the quant node.
  • yfinance has no historical option chain. Live iv_prev uses a local SQLite t-1 snapshot when present, otherwise a 20-day realized-vol (HV20) proxy.
  • Risk-free rate comes from ^IRX when available (else 4.5%).

Post-MVP roadmap

  • Wire compare_to_official as bounded diagnose-time tools
  • LangSmith golden dataset + numeric evaluators
  • Extra search sources on the existing search node — not a dedicated filings graph. Tavily (TAVILY_API_KEY) and SEC 8-K (EMO_SEC_USER_AGENT, free) are optional env toggles.

About

Diagnose why an equity option price moved — QuantLib PnL attribution + LangGraph LLM narrative (explain, not predict).

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages