LIVE
connecting to the live quote stream…
--:--:--UTC
Learn/Bots/IV Solver (NN)
AI QuantsAI
ν

IV Solver (NN)

Implied volatility straight from an option's price — no iteration needed.

⟢In plain English

When you see an option's price, you can run the math backwards to figure out what volatility the market is implying. The classic way (Newton-Raphson) is finicky and breaks near zero. Our AI does it in a single forward pass — fast and stable.

Reverse the BS pricer. You have an option's market price and need to back out the implied volatility — what σ makes the formula spit out that price? Classically done with Newton-Raphson, which is fragile near zero vega and can take 20+ iterations. The NN does it in a single forward pass with ~0.9% relative error.

⟢The math
formula
inverse BS surrogate · ≈0.9% relative error
parameters
typeTypechoices: C, Pdefault · C
spotSpot $range — → —default · 100
strikeStrike $range — → —default · 100
daysDays to expiryrange — → —default · 30
rateRate %range — → —default · 4.5
priceObserved $range 0.01 → —default · 4.5
⟢Live demo

Real IV Solver (NN) bot, running on real Yahoo data when the symbol is available. Drag the params — the bot re-runs instantly.

symbolloading…
loading AMZN bars…
⟢Source code · public

This is the actual code the bot runs — not a re-explanation, not a simplified version. Whatever ships here is what executes when you press Run All in the workbench. Read it, copy it, fork it, build a better one.

●lib/quant/ai-bots.ts·lines 263–350
TypeScript · MIT-licensed
const ivSolver: BotDef = aiBot<IVReq, IVRes>(
  {
    id: "ai-iv-solver",
    name: "IV Solver (NN)",
    category: "ai",
    glyph: "ν",
    tagline: "Implied volatility straight from an option's price — no iteration needed.",
    formula: "inverse BS surrogate · ≈0.9% relative error",
    endpoint: "/api/iv",
    module: "ai quants/models/implied_vol/train.py",
    params: [
      { key: "type", label: "Type", kind: "select", default: "C", options: [{ value: "C", label: "Call" }, { value: "P", label: "Put" }] },
      { key: "spot", label: "Spot $", kind: "number", default: 100, step: 0.5 },
      { key: "strike", label: "Strike $", kind: "number", default: 100, step: 0.5 },
      { key: "days", label: "Days to expiry", kind: "number", default: 30, step: 1 },
      { key: "rate", label: "Rate %", kind: "number", default: 4.5, step: 0.1 },
      { key: "price", label: "Observed $", kind: "number", default: 4.5, min: 0.01, step: 0.01, hint: "the option's actual mid price" },
    ],
  },
  {
    request: (ctx, p) => {
      const lastPx = ctx.candles[ctx.candles.length - 1]?.c ?? 100;
      const type = (str(p, "type", "C") === "P" ? "p" : "c") as "c" | "p";
      return {
        price: num(p, "price", 4.5),
        S: num(p, "spot", lastPx),
        K: num(p, "strike", Math.round(lastPx)),
        T: Math.max(0.0005, num(p, "days", 30) / 365),
        r: num(p, "rate", 4.5) / 100,
        flag: type,
      };
    },
    build: (data, ctx, p) => {
      const lastPx = ctx.candles[ctx.candles.length - 1]?.c ?? 100;
      const type = (str(p, "type", "C") === "P" ? "P" : "C") as "C" | "P";
      const spot = num(p, "spot", lastPx);
      const strike = num(p, "strike", Math.round(lastPx));
      const t = Math.max(0.0005, num(p, "days", 30) / 365);
      const rate = num(p, "rate", 4.5) / 100;
      const greeks = priceOption(spot, strike, t, rate, data.sigma, type).greeks;
      return {
        signals: [],
        metrics: [
          { key: "iv", label: "IV", value: `${(data.sigma * 100).toFixed(2)}%`, tone: "info" },
          { key: "vega", label: "ν Vega", value: fmtNum(greeks.vega, 3) },
          { key: "iters", label: "Iterations", value: "1 (NN)", tone: "neutral", hint: "vs ~25 for Newton-Raphson" },
          { key: "err", label: "Surrogate err", value: "≈0.9%", tone: "info" },
        ],
        summary: `Solved IV = ${(data.sigma * 100).toFixed(2)}% in a single forward pass. The python NN replaces Newton-Raphson, which usually takes 20+ iterations and explodes near zero vega.`,
        beginner:
          "Reverse the option pricer — given the price the market is showing, what volatility makes the formula match? The neural net does it in one inference.",
        verdict: { side: "hold", text: `Implied vol ${(data.sigma * 100).toFixed(2)}%.`, confidence: 1 },
      };
    },
    mock: (ctx, p) => {
      const lastPx = ctx.candles[ctx.candles.length - 1]?.c ?? 100;
      const type = (str(p, "type", "C") === "P" ? "P" : "C") as "C" | "P";
      const spot = num(p, "spot", lastPx);
      const strike = num(p, "strike", Math.round(lastPx));
      const days = num(p, "days", 30);
      const rate = num(p, "rate", 4.5) / 100;
      const obs = num(p, "price", 4.5);
      const t = Math.max(0.0005, days / 365);
      let lo = 0.01, hi = 3.0, mid = 0;
      for (let i = 0; i < 50; i++) {
        mid = (lo + hi) / 2;
        const guess = priceOption(spot, strike, t, rate, mid, type).price;
        if (guess > obs) hi = mid;
        else lo = mid;
      }
      const sigma = mid;
      const greeks = priceOption(spot, strike, t, rate, sigma, type).greeks;
      return {
        signals: [],
        metrics: [
          { key: "iv", label: "IV", value: `${(sigma * 100).toFixed(2)}%`, tone: "info" },
          { key: "vega", label: "ν Vega", value: fmtNum(greeks.vega, 3) },
          { key: "iters", label: "Iterations", value: "50 (bisection)", tone: "neutral", hint: "TS fallback" },
          { key: "err", label: "Surrogate err", value: "≈0.9%", tone: "info" },
        ],
        summary: `Solved IV = ${(sigma * 100).toFixed(2)}% via TS bisection (NN unavailable).`,
        beginner:
          "Reverse the option pricer — given the price the market is showing, what volatility makes the formula match?",
        verdict: { side: "hold", text: `Implied vol ${(sigma * 100).toFixed(2)}%.`, confidence: 1 },
      };
    },
  },
);
what each piece means
  • id — unique key the workbench uses to find the bot.
  • params — the sliders + inputs you see on the cell.
  • run(ctx, p) — the function that gets called with candles + your params and returns the verdict.
  • verdict — the BUY / SELL / HOLD pill at the top of the cell.
  • metrics — the small stat boxes shown in the cell body.
use this code yourself
  1. Copy the whole block above.
  2. On /quant, click + Import your bot in the bot library.
  3. Paste, hit save. It hot-loads into your workspace.
  4. Edit any param defaults or logic to your taste — it's now yours.
⟢Specialty · when it shines, when it fails
✓ Shines when
  • ·Real-time IV updates as the chain ticks. Newton's method has variable latency depending on starting point; the NN is constant-time.
  • ·Building IV surfaces. Need to solve for σ across hundreds of strikes/expiries simultaneously — batch inference shines here.
  • ·Robustness near low vega. Newton blows up when ∂Price/∂σ is small; the NN gracefully degrades instead.
✗ Fails when
  • ·Out-of-distribution. The training set covered 5-200% vol; if the option price implies σ outside that, predictions degrade.
  • ·Pricing arbitrage edge cases. When the market price violates put-call parity, no σ exists — the NN just returns its best guess instead of erroring.
  • ·Deep ITM/OTM at near-zero time-to-expiry. Both Newton and the NN struggle; you need a different algorithm entirely.
⟢How to read its verdict

HOLD always — solver, not a trade signal. The IV it returns is the trade input. Use it as the σ input to the Wheel bot, the BS Solver, or your own pricing logic.

⟢Python service

This bot tries to call the FastAPI service first. When it's up, you get real model output. When it's down, the bot transparently falls back to a deterministic TS surrogate.

srcai quants/models/implied_vol/train.pyapi/api/iv
FastAPI··/api/ivCHECKING…
How the request flows+
01
BotCell.run()
User clicks Run on this bot in /quant
02
callApi()
POST to localhost:8000/api/iv
03
load_surrogate()
ai quants/models/implied_vol/train.py
04
predict()
Forward pass on the inputs you provided
05
BotResult
JSON returned, card flips green Source: Python NN
spin it upcd "ai quants" && uvicorn serve:app --reload --port 8000
⟢FAQ
Why is the answer slightly different from a Newton-Raphson run?+
Newton finds the exact σ to floating-point precision. The NN is an approximation with ~0.9% mean relative error. For most use cases this is well inside bid-ask noise; for arbitrage strategies you'd still want the exact solver.
Can I trust this when the option is far OTM?+
Below an option price of ~0.05 the function gets flat and any solver becomes unstable. The NN is no exception — its predictions become noisy at deep OTM.