Pricing Methodology and Validation
Models, cross-implementation reference validation, and honest limitations behind the Logos Capital options tools.
Last updated: 14 September 2026 · Build: ad67360
This note documents the models behind the Logos Capital options tools, the reference values they are validated against, and — equally important — the things they do not do. It is published so that anyone relying on these tools can judge for themselves whether the numbers are fit for their purpose.
This page is the full technical record. The calculators are built to be useful without reading it: enter inputs, read prices and charts. Everything that matters for a professional judgment — which engine runs where, documented simplifications, chart scope, validation tolerances, and explicit omissions — is stated here plainly for readers who want the complete picture.
All outputs are theoretical. They are not live market quotes and not investment advice.
1. Scope
Three tools share one analytics architecture. The payoff diagram is model-free at a single shared expiry; when legs expire on different dates it uses a staged horizon (intrinsic for legs that expire on the horizon date, fill-implied marks for later legs). The pricing and scenario tools use the engines in section 2. What each tool actually shows in the interface is spelled out in sections 1.1–1.3 so the published note matches the product.
| Tool | What it computes |
|---|---|
| Payoff diagram | Expiration P&L when all legs share one expiry; staged horizon P&L when legs have different expiries (calendars, diagonals, PMCC). Strategy auto-naming from presets. Details in 1.1. |
| Options calculator | Single-option theoretical price and Greeks under a selectable engine; ET timestamp expiry including 0DTE; scenario sweeps and exploratory charts. Flat IV only (no SVI surface on this tool). Details in 1.2. |
| Position scenario analyzer | Saved-position mark-to-market, parallel stress rows, first-order P&L attribution, and six chart views (ladders, heatmaps, 3D). SVI surface and vol shocks. Per-leg ET expiry including 0DTE. Details in 1.3. |
1.1 Payoff diagram
- Single shared expiry — model-free expiration P&L for calls, puts, and stock legs. Premium is your fill per share; contracts or share count scale the outcome. No time value, no vol path.
- Multiple expiries — staged payoff horizon. When option legs have more than one expiry date (calendars, diagonals, poor man’s covered call, and similar), the chart title and summary use a payoff horizon date you choose from the leg expiry dates (near or far). Legs expiring on that date settle at intrinsic value. Legs expiring after that date stay open and are marked with the American CRR engine at each underlying price on the chart, using fill-implied IV from your entered premiums at entry spot (same IV inversion as the calculator’s market-σ solve). Stock legs are always mark-to-spot. This is not a full path simulation — vol and time are fixed to the horizon; only spot varies on the chart.
- Strategy naming (single source of truth). All strategy labels and descriptions live in
strategy-presets.ts(41 loadable presets plus a Custom strategy fallback).strategy-match.tsmaps your leg book to a preset id (exact shape, structural match, orcustom). Manual entry without loading a preset is auto-named when the structure is recognized (e.g. a bull call spread). Loading a preset storesstrategyPresetIdin the shared position draft so ambiguous shapes (e.g. call ratio vs call backspread after strike rounding) keep the name you loaded. Structural leg edits clear the pin. - Strategy presets load example leg structures from that same preset list; all inputs remain editable.
- Summary statistics: net premium, break-even price(s), and max profit and max loss where bounded. Break-evens are exact roots on the piecewise payoff curve (kinks at each strike and stock cost basis), not grid-sampled. Labels read Break-even at expiration or Break-even at horizon depending on mode.
- Contract multiplier (default 100) scales option leg dollar outcomes. Stock legs use share count directly (multiplier does not scale stock P&L).
- Shared position draft. Leg structure, premiums, spot, multiplier, commission, per-leg expiry settings, payoff horizon date, and pinned preset id persist in the browser and carry into the options calculator and position scenario analyzer.
- Underlying spot. Optional Tier-1 symbol search fills spot from Regime Intelligence ingested bars (15-minute bar while the session is open; prior session daily close after the close). Delayed-data labeling applies when applicable.
- Layout (desktop). Configure and chart columns are separated by a draggable splitter (30–75% of grid width; preference stored locally). A visible grip marks the handle.
- Not modelled (single-expiry mode): time decay, implied-volatility changes, early exercise, or any path before expiration.
- Not modelled (staged horizon): vol shocks, dividend/rate paths, or rolling the book between expiries — only the chosen horizon date and fill-implied marks for still-open legs.
1.2 Options calculator — outputs
Single-leg book. Call and put price from the selected engine at the contract strike; σ and r used at the valuation point; a comparison table prices the same contract under all three engines; Greeks table with per-share and per-contract columns (contract multiplier, default 100).
Multi-leg book (two or more legs, typically from the shared position draft). Workflow: Pricing engine (model · rates · dividends) → Results (market premiums · IV · Greeks) → Volatility (“What if IV changes”) → Position sensitivity (net Greeks table) → Plots (spot sweep and model charts).
- Market IV from fills. Each option leg’s IV Market σ is the implied volatility that makes the selected pricing engine reproduce that leg’s entered premium at the current spot and time inputs — Brent inversion on the production
priceOptionpath (0.1%–500% σ search). When inversion succeeds, the column shows that σ. When it fails, the column shows Your σ (the leg’s entered flat IV), repricing uses that σ, and the UI shows an explicit per-leg warning plus a banner when any leg failed. There is no silent reuse of a prior implied σ from an earlier solve. - Position mark at market. Combined entry cash flow (after commission), theoretical mark, mark vs entry, net Greeks, and per-leg / net Greeks & second-order tables — legs with a successful fill-implied solve use that σ; legs that failed inversion use Your σ with warnings as above. Per-leg expiry comes from the leg matrix. Single-contract sweeps and charts anchor on the first leg’s strike as the reference contract. Multi-leg spot sweeps in Plots hold fill-implied σ fixed at entry spot (solved once at the mark spot, not re-inverted at each sweep point).
- Implied vs. realized volatility (Tier-1 symbol required). Compares |vega|-weighted position market IV from fills to trailing realized vol (RV₁₄ or RV₃₀ — whichever is closer in calendar days to the position’s shared expiry). The headline spread is IV − RV in volatility points. This is an implied-vs-realized snapshot, not a forward-looking volatility-risk-premium estimate. See section 3.6.
- What if IV changes (optional, collapsed by default). Reprices the book at a user flat or per-leg IV and compares theoretical entry cash flow to the market fills (favourable / unfavourable verdict for buyers and sellers).
Scenario sweep. Vary one input while holding the rest fixed:
| Sweep variable | What moves |
|---|---|
| Spot (S), strike (X) | Direct price inputs |
| Log-moneyness ln(S/X) | Spot at fixed strike |
| Call delta / put delta (target Δ) | Strike at fixed spot — see limitation below |
| Implied vol (σ), time (T), rate (r), dividend yield (q) | Standard inputs |
User-controlled range and 1–100 steps (default 41). Prices and Greeks at each sweep point use the selected pricing engine.
Rate and dividend sweeps. Swept r is applied as a flat rate at each point (Treasury curve mode is overridden on the sweep axis so the x-axis matches the repriced r). Swept q applies only in continuous-yield dividend mode; discrete schedule mode ignores a dividend-yield sweep.
Delta-strike sweeps. Target Δ is inverted to a strike by European Merton bisection at fixed spot, using the same r as the base-case mark (flat or curve-interpolated). Repricing along the sweep still uses the selected engine, so American CRR or Black-76 prices at a “25Δ” point are not guaranteed to show exactly 0.25 delta under that engine.
Adaptive sweep density. When time to expiry is under 14 calendar days, the sweep variable is spot, and the Greek chart plots a second-order sensitivity (gamma, vanna, or volga), the engine uses at least 61 points even if fewer were requested.
Quick chart presets (results column): Gamma vs time; Theta vs time; Vanna vs spot; P(ITM) vs delta; Early exercise premium (loads K = 100, 1Y, r = 5%, σ = 30%, American CRR). Each preset sets the sweep and opens the matching chart panel.
Charts and tables (all in the results column unless noted):
| Output | Engine / data source | Notes |
|---|---|---|
| Early exercise premium | Selected American engine minus European Merton vs spot | American leg follows model selection |
| Price sweep | Selected model, or optional all-models overlay (European Merton, American CRR, Black-76) | Overlay always runs all three product engines |
| P(ITM) vs delta | European Merton only | N(d₂) call / N(−d₂) put vs Δ on the spot sweep; same r as base-case mark (flat or curve-interpolated); ignores selected pricing model |
| 2D risk views (spot × time, spot × IV) | Selected model | 25×25 heatmaps; z-axis: call/put price, gamma, call Δ, or vega. Default ranges from sweep helpers (spot ±20%; time 25%–200% of base T; IV floored at 0.1% up to max(5× base, 500%)). Plotly hover — no cursor readout bar |
| CRR convergence | American CRR only | Price vs steps 20–500; raw single-tree and adjacent-step average. Diagnostic; not the live pricing path |
| Exercise boundary S*(t) | American CRR only | Single tree at the user’s binomial step setting (not adjacent-step average) |
| Greek sweep chart | Selected model only | One Greek vs sweep variable — not the all-models overlay |
| Scenario data table | Selected model | Numeric sweep export |
Chart readout. Recharts line charts (including calculator and position line/Greek charts) show a cursor readout bar with formatted values. Plotly heatmaps and the position 3D surface use native Plotly hover.
Volatility on the calculator. Single flat IV input. SVI surface mode, skew/curvature shocks, and sticky-strike vs sticky-delta spot rules are available only in the position scenario analyzer (section 4), not here.
1.3 Position scenario analyzer — outputs
Entry requirement. Stress analysis runs on a saved position loaded from the toolbar. The position summary still reflects the shared payoff draft, but parallel stress rows, charts, and attribution unlock only after a named book is saved or loaded. Sign-in is required for server-backed saved positions; the scenario book (preset toggles, custom and grid rows, chart preferences, custom-row draft) persists in the browser and syncs to the server when authenticated (with retry on sync failure).
Three-step workflow (stacked workspace):
- Position summary — leg structure from the payoff draft (read-only matrix). Same leg model as payoff and calculator.
- Where am I now — mark-to-market at today’s clock: live spot (Regime Intelligence default, editable), DTE at save vs now, elapsed time, pricing engine panel, and a full reprice at current marks. This baseline drives every stress row and chart.
- What if scenarios — parallel stress rows (each fully repriced), exploratory charts, and Greek panels for the selected row.
Position construction. Calls, puts, stock. Strategy presets. Per-leg premium, contracts, flat IV, and ET expiry (equity 4:00 PM or index 9:30 AM, optional time override). Position-level option contract multiplier (default 100; scales option marks and net Greeks — stock legs use share count only, as in the payoff tool).
Where am I now controls. Current spot; IV level shock on the main control (±30 percentage points); pricing engine: model, rates, dividends, Treasury curve, SVI surface mode, parallel level / skew / curvature vol shocks (section 4), and sticky-strike vs sticky-delta when SVI is on. Days forward on stress rows are whole calendar days, capped so no leg is forwarded past its expiry.
Marks. Net P/L vs entry (gross — option premiums and marks exclude commission; aligned with the Step 2 owner “since entry” summary), position value, net Greeks (delta, gamma, vega, theta/day, vanna, volga, charm/day), per-leg marks, and vega by expiry buckets. Stress-row P/L uses the same gross convention (entryCommission is zero in the scenario engine).
Stress grid (scenario builder).
- Preset scenarios: 9 rows (Base + 8 togglable presets): gap ±10%, IV crush/spike ±30pp, +7 calendar days, at expiry, gap down combined with IV spike or crush. Enable/disable chips; reset to defaults.
- Custom row: spot %, days forward, parallel IV shift (pp), SVI ρ and b shocks; optional label. Spot % shocks that would leave shocked spot at or below zero are blocked in the builder (“Spot must stay above zero.”); if such a row exists in persisted data, the engine returns an unpriced row (value and P/L show “—”, not a misleading number). When the book has multiple option expiries, per-expiry IV shift inputs appear (keyed by expiry date, overriding parallel IV for that slice). The custom-row draft persists across refresh.
- Bulk grid generator: Cartesian product of user-entered spot % and IV shift lists (default 9 rows: −10/0/+10% × −30/0/+30pp). Individual grid and custom rows can be removed.
Each enabled row is fully repriced through the scenario engine (not a Taylor approximation). Click a row to drive chart crosshairs, headline tiles, and attribution.
Chart sweep ranges. Spot uses the payoff chart range from the shared position draft (same min/max as the payoff tool — break-even centred, not a fixed % of entry spot). IV level shock on charts −50 to +50 percentage points (wider than the main slider). SVI skew shock −20 to +20; curvature shock −30 to +30 (skew and curvature axes require SVI surface mode).
Chart views (tabbed):
| View | X / Y axes | Steps / mesh |
|---|---|---|
| Spot ladder | Spot | 41 points (default) |
| IV ladder | IV level, SVI ρ, or SVI b (vol shock axis setting) | 41 points |
| Time decay | Calendar days forward | 41 points |
| Spot × IV | Spot × vol shock axis | Fast 15×15 (default) or Audit 25×25 (8–50 per axis cap) |
| Spot × time | Spot × days forward | 15×10 (fast) or 25×10 (audit) |
| 3D surface | Same mesh as Spot × IV | Same Y metrics as heatmaps |
Y-axis metrics: P/L vs entry, position value, or net dollar delta (net Δ × spot). Spot ladder optionally shades a ±1σ expected-move band from model IV and DTE.
Chart settings. Vol shock axis (level / skew / curvature); grid mesh Fast (15×15) vs Audit (25×25) — applied to Spot×IV heatmaps, Spot×time heatmaps, and the 3D surface (same step count as Spot×IV for the selected density). Spot move rule inherit pricing, sticky strike, or sticky delta applies to chart sweeps and grids only; parallel stress rows use the sticky rule from the pricing panel (not this chart override). Ladders use Recharts with a cursor readout bar; heatmaps and 3D use Plotly hover. CSV export is available on Spot×IV, Spot×time, and 3D tabs (audit mesh when selected).
P&L attribution (selected stressed row). First-order Greek decomposition vs the base row: Δ, Γ, Θ, parallel vega, and residual (higher-order / skew), with reconciliation to total ΔP/L. Expanded Greeks table with per-share and position columns. Educational decomposition only — see section 6.
Not on this tool. Calculator-only outputs (IV inversion, P(ITM) vs delta, early exercise premium, CRR convergence, exercise boundary) are not replicated here.
2. Pricing engines
2.1 European — Black–Scholes–Merton
Closed-form Merton model with continuous dividend yield q. Used for European-exercise contracts (cash-settled index options such as SPX) and as the routing target for the American no-early-exercise case described in 2.4.
2.2 American — Cox–Ross–Rubinstein binomial
Recombining CRR tree with early-exercise testing at every node.
-
Steps: Production CRR applies adjacent-step averaging by default when the requested step count exceeds 20 (mean of the (n−1)- and n-step trees). The UI default is 300 steps when an American model is selected, adjustable 50–500 in the pricing panel. Section 5 validation asserts the 500-step capped configuration against reference values. CRR error alternates in sign as step count increases rather than decaying monotonically, so averaging adjacent step counts substantially reduces the observed oscillation. Measured informally against a 4,000-step tree, this takes the error from roughly 0.5 cents to under 0.1 cents at no meaningful latency cost when using 500 steps. That comparison is an engineering observation, not a build gate — the enforced tolerances are in section 5.0.
This is not Richardson extrapolation, which combines solutions at systematically related grid sizes weighted by a known convergence order. The improvement here is empirical, and we do not claim it as a general bound.
-
Why not more steps: At 500 steps the tree is already within ~0.5 cents of a 4,000-step tree before averaging. Raising the cap costs browser latency for accuracy below the resolution of any real quote.
-
Short tenor. When time to expiry is very small, the tree caps its step count so each interval is at least one minute, validates the risk-neutral probability
p ∈ [0, 1], and — below fifteen minutes with no discrete dividend schedule — routes to the European closed form rather than running a numerically unstable tree. Production output is benchmarked at six hours, one hour, and fifteen minutes to expiry (section 5.2).
2.3 Black-76 (European on forward / futures)
Closed-form Black (1976) model for European options on a forward or futures price F (not equity spot with dividends):
C = e^{-rT}[F N(d₁) − K N(d₂)], P = e^{-rT}[K N(−d₂) − F N(−d₁)], with d₁ = [ln(F/K) + ½σ²T] / (σ√T) and d₂ = d₁ − σ√T.
- UI input. The underlying quote field is labelled Forward (F) when this engine is selected. Tier-1 commodities and FX from Regime Intelligence, plus extension-catalog symbols (SPX, ES, FDAX, etc.), can auto-select the engine from asset class or catalog metadata.
- Dividends. Continuous yield and discrete schedules are not applied — carry is assumed embedded in F.
- Implied vol. Same Brent inversion on
priceOptionas the other engines: solve σ so the Black-76 price matches the entered premium.
2.4 Legacy audit engine — Bjerksund–Stensland (2002)
Not offered in the product UI. The BS2002 closed-form American approximation remains in the repository for audit grids and regression only (section 5). Production defaults to American CRR for listed equity-style American exercise.
The former §2.3 detail is retained for audit readers:
- Puts via put–call symmetry on the call routine (see prior revision history).
- Numerical range may route to the CRR tree in audit comparisons when the closed form is out of range.
- Discrete dividends in audit paths route to CRR, not BS2002.
2.5 Model routing (American CRR)
For an American call where the cost-of-carry condition holds with q ≤ 0 (equivalently b = r − q ≥ r when b is carry), early exercise is not optimal and the model routes to the European closed-form value rather than approximating it.
The familiar special case is a non-dividend-paying underlying, q = 0, where the American and European call values coincide. It is equivalent to the carry condition b ≥ r, and the carry form is what the code tests, because q here is a carry parameter, not solely a dividend yield: a negative q may represent a borrow cost, a convenience yield, or a financing convention, none of which are economically the same as an absence of dividends. The routing is valid across all of them.
This case is also used as a regression canary (section 5): a malformed binomial tree cannot reproduce the closed-form value.
3. Market inputs
3.1 Interest rates
Rates are sourced from the Federal Reserve Economic Data (FRED) service using eight constant-maturity Treasury (CMT) series:
DGS1MO, DGS3MO, DGS6MO, DGS1, DGS2, DGS5, DGS10, DGS30
Each leg is discounted at a rate linearly interpolated in tenor to its own time to expiry, rather than at a single flat rate across the position.
What this is, and is not
This is a simplified Treasury-rate curve, not a constructed discount curve. The distinction matters and is stated plainly here rather than implied.
A discount curve built to institutional standards would proceed from instruments to a bootstrapped zero curve to discount factors and forward rates, handling coupon structure, settlement conventions, and day counts along the way. This engine does none of that. It takes published CMT yields and interpolates between them.
Three specific consequences:
-
CMT yields are par yields on coupon-bearing instruments, not zero rates. Using them directly as discount rates conflates the two. The discrepancy is small when the curve is flat and grows with curve slope and tenor.
-
Interpolation is linear in yield against tenor, not in log-discount factor or forward space. Linear-in-yield interpolation is not arbitrage-free across the curve, though the effect is negligible at the tenors most options positions occupy.
-
Compounding convention. CMT yields are quoted on a bond-equivalent, semi-annual basis, while Black–Scholes–Merton and the binomial engine discount continuously. Yields are therefore converted at ingestion via
r_c = 2·ln(1 + y/2). Passing the quoted yield through unconverted would overstate the discount rate by approximatelyy²/4— about 4bp at a 4.00% yield and 6bp at 5.00% — making calls marginally rich and puts marginally cheap. The same conversion is applied to the static fallback curve so that live and fallback paths remain numerically consistent.This addresses the compounding mismatch only. It does not resolve the par-versus-zero issue above: CMT yields remain par yields on coupon-bearing instruments, and no bootstrapping is performed.
For option tenors under two years and ordinary curve shapes, the aggregate effect of the above is small relative to bid-ask spread. It is documented because the difference between "we interpolate published yields" and "we build a discount curve" is exactly the kind of thing a professional reader will assume in your favour unless told otherwise.
Data currency
When Treasury / OIS curve mode is enabled, the pricing panel shows whether the curve is live from FRED (with the observation date of the latest CMT print across the eight series) or a static fallback when FRED is unavailable or FRED_API_KEY is not set. Live and fallback paths use the same bond-equivalent-to-continuous yield conversion so they remain numerically consistent.
Default. The curve is opt-in; the default is a flat rate. This is a usability choice for the common case of a short-dated position, where the difference is immaterial. For LEAPS or calendar structures spanning very different tenors, enable the curve.
3.2 Dividends
Two modes:
- Continuous yield (default). A single annualised
q. Appropriate for broad index and ETF underlyings. - Discrete schedule (opt-in). Explicit ex-dates and amounts. The European engine uses an escrowed-spot adjustment; the binomial subtracts dividends at the corresponding node.
Limitation. Continuous yield is a smooth approximation that cannot represent the mechanism driving early exercise of American calls on single names: a single lumpy payment on a known date shortly before expiry. For single-stock analysis, use the discrete schedule. The schedule is currently per-session rather than stored per underlying.
3.3 Time to expiry
The options calculator and position scenario analyzer both measure T as elapsed calendar time from the user's current clock to an expiry timestamp in US Eastern time, divided by 365 calendar days (not trading days).
- Equity close (default): 4:00 PM ET on the selected expiration date — appropriate for most listed equity and ETF options.
- Index AM: 9:30 AM ET on the expiration date — the standard cash-settlement clock for index products such as SPX. The same calendar date can imply very different
Tunder the two conventions; always check the summary line under the inputs. - Time override: an optional ET clock overrides the settlement preset.
The calendar-days shortcut sets the expiration date only (0 = today, 1 = tomorrow). It does not encode hours. For 0DTE, pick today's date and the correct settlement clock; the interface shows remaining time (for example 8h 6m to expiry).
When the expiry timestamp is in the past, T = 0 and prices equal intrinsic value.
In the browser, the valuation “now” clock advances on a ~60 second refresh cadence so 0DTE and intraday marks do not freeze for the whole session (each tab still uses one frozen instant between refreshes).
The position scenario “days forward” slider advances the pricing clock by whole calendar days; each leg’s remaining T is then recomputed from the forwarded clock to that leg’s ET expiry instant (so 0DTE legs decay intraday the same way as in the calculator).
Not modelled: a business-time clock (weekends, holidays, or session hours). Elapsed time is wall-clock calendar time in ET to the stated expiry instant.
3.4 Greeks and sensitivities
Displayed Greeks use the definitions below unless noted. Values are per share unless a contract multiplier is applied in the interface (default 100 on the calculator and position tools for option legs; scales per-contract Greek columns and option-leg dollar P/L).
| Greek | Definition in this engine |
|---|---|
| Delta, gamma | Standard BSM/tree finite differences on price |
| Vega, vanna | Change per one vol point (1 percentage point absolute σ, i.e. 25% → 26%) |
| Volga | Change in vega (per vol point) per one vol point |
| Theta ("life decay") | Expected P&L over the next decay step — not instantaneous Θ = ∂V/∂t ÷ 365. Step: one calendar day when ≥ 1 DTE; one hour when < 1 DTE but ≥ 1 hour; remaining life when < 1 hour |
| Charm | ∂Δ/∂t expressed per calendar day, using the same decay step as theta |
| Rho | Change in value per one percentage point move in r (∂V/∂r × 0.01). European Merton: closed form. American CRR / BS2002: central difference on r with a 1 bp bump, same display units |
Risk-neutral ITM probability (P(ITM) vs delta chart, section 1.2): N(d₂) for calls and N(−d₂) for puts under European Merton. This is not delta; the chart plots both on the same spot sweep for comparison.
Model-specific notes:
- CRR volga uses the European closed form (vega·d₁·d₂/σ) because tree vol bumps are unreliable away from at-the-money. Other CRR Greeks use tree bumps; gamma's spot bump is scaled to tree node spacing rather than a fixed percentage.
- BS2002 routes call-side Greeks to European when
q = 0(no early exercise on calls), matching the price engine.
On a time sweep, reported theta changes step size below one DTE. That is a convention change, not a slowdown in instantaneous decay rate.
3.5 Implied volatility inversion
Fill-implied IV (market marks). For each option leg, Brent inversion on the selected pricing engine (priceOption production path) so model value matches the leg’s payoff premium at current spot and ET time inputs. Same 0.1%–500% search; discrete dividend schedules use the same solver (escrowed spot on European paths, CRR tree on American). Used on the options calculator (multi-leg market position), position scenario “Where am I now” premium mode, staged payoff horizon marks, and the vega weights in section 3.6. When inversion fails, marks and Greeks fall back to the leg’s Your σ with explicit warnings — there is no silent reuse of a prior implied σ. Broker platforms may still report different greeks at the same displayed IV because of internal clock, yield, or greek-engine conventions — an observed gap is not, by itself, evidence that this inversion is wrong.
3.6 Realized volatility and implied–realized spread
The calculator’s Implied vs. realized volatility panel (multi-leg, Tier-1 symbol) compares fill-implied market IV to trailing realized vol. It does not invoke Regime Intelligence feature engines; Logos reads daily closes via Regime’s existing /api/bars-ingested HTTP endpoint only.
Realized vol formula. On log returns from daily closes, annualized realized volatility is:
RV = √( ann × mean(r²) )
over a trailing window of 14 or 30 calendar days of daily returns (one close per session). Annualization uses 252 trading days per year for ordinary equities and 365 for crypto asset class.
Window choice. The panel uses RV₁₄ or RV₃₀ — whichever window length is closer in calendar days to the position’s shared expiry (from the payoff-owned leg matrix).
Position market IV. Vega-weighted mean of per-leg fill-implied IVs: each leg’s solved IV is weighted by |vega| at the market mark (same position scaling as the Greeks table). Legs without a successful IV solve or zero vega are omitted from the blend.
Spread and labels. IV − RV is shown in volatility points (same units as percent vol). Positive spread is labelled vol rich vs RV; negative vol cheap vs RV. Copy describes the arithmetic spread only — not investor sentiment or a formal forward-looking volatility risk premium.
Percentile. When at least 60 prior RV readings exist in a 252-reading lookback, the panel shows where today’s RV sits in that history (0–100 percentile). Insufficient history omits the percentile.
Availability. Requires a Tier-1 symbol on the payoff draft and enough ingested daily bars to compute the chosen window (and percentile when shown). API responses are cached privately for 24 hours per asset and window.
4. Volatility surface
The position scenario analyzer treats implied volatility as a per-leg flat input, through parallel level shocks on flat IV, or through a fitted SVI surface with optional skew and curvature shocks. The options calculator uses a single flat IV input only (section 1.2) — no SVI surface UI and no vol-shock controls on that tool.
4.1 Parameterization
Raw Gatheral SVI in total variance per expiry slice:
w(k) = a + b · ( ρ(k − m) + √((k − m)² + σ²) )
with k = ln(K/F), forward F = S·e^{(r−q)T}, and implied volatility recovered as σ(k) = √(w(k)/T).
Rates in SVI calibration. When fitting slices from leg quotes, each expiry slice uses r and q interpolated to that slice’s tenor (Treasury curve when enabled, otherwise flat r). This matches leg pricing; it is not a single flat r across all expiries when the curve is on.
4.2 What actually runs
The engine is honest about how much information it has:
| Quotes at a given expiry | Behaviour |
|---|---|
| One | Flat slice (a = w, b = 0). Reproduces the entered IV at every strike and tenor. No skew is invented. |
| Exactly two, fit valid | Exact solve for (a, b) with m = 0 and ρ, σ held fixed. Two equations, two unknowns — the quotes are reproduced exactly, and no residual is minimised. |
| Three or more, fit valid | Least-squares fit for (a, b), overdetermined. |
| Fit invalid | Falls back to linear interpolation of IV in log-moneyness between quotes. |
| Fit fails outright | Falls back to per-leg flat IV, with a visible warning in the panel. |
A fit is rejected when it would produce b < 0 (an inverted wing) or a negative variance vertex. Because ρ and m are currently fixed, a position consisting of two out-of-the-money calls with volatility declining in strike — an ordinary call spread — will be rejected and routed to interpolation. This is intentional: the fit refuses to represent a shape it cannot represent correctly.
4.3 Guards
- IV is floored at 0.5% on every surface and interpolation path. This is a numerical safeguard against downstream division and root-finding failure, not a market-data assumption. It does not represent a view that 0.5% is a plausible minimum implied volatility.
- Outside the outermost quoted strikes, IV is held flat. There is no linear extrapolation, which would otherwise drive volatility negative when two quoted strikes sit close together.
- ATM total variance is checked for monotonicity across expiry slices. A decrease in ATM
was tenor increases is a warning sign for potential calendar arbitrage and raises a flag — most commonly triggered by an elevated front month into earnings. This is a diagnostic, not a proof: passing the check does not establish absence of calendar arbitrage, for the reasons given in 4.4.
4.4 Known limitations
This is not yet a full SVI calibration.
-
ρandmare fixed constants, not fitted. The surface therefore has two free parameters, not five. -
No constrained least-squares fit across three or more strikes.
-
Gatheral–Jacquier static no-arbitrage conditions are not enforced on fitted parameters. Our current test set has not identified violations of the butterfly condition
g(k) ≥ 0, but the test set does not cover every generated slice, every supported parameter combination, or every interpolation and extrapolation transition. Absence of observed violations is not a guarantee of absence. -
Skew shocks adjust SVI ρ and are clamped to ±0.99 so |ρ| cannot reach 1, but the clamp is not a guarantee of static no-arbitrage across the shocked surface.
-
The calendar check compares ATM variance only. Calendar arbitrage at other strikes is possible in principle; it is largely unreachable with the current flat-and-interpolated slices but will become reachable once slices carry genuine curvature.
-
Volatility behaviour on spot moves — sticky strike (default). When spot is shocked, each strike retains its implied volatility. Spot and volatility are therefore shocked independently and the two effects can be read separately.
-
Sticky delta attaches volatility to moneyness rather than to the strike. It is arguably closer to how some markets behave, particularly when modelling skew, but embeds a considerably stronger assumption about surface dynamics. Sticky strike is the default because it is transparent and the user can see exactly what was shocked.
-
Spot move rule in the pricing panel (when SVI surface mode is on) switches between sticky strike and sticky delta. This choice materially affects scenario delta; the assumption is visible and adjustable rather than hidden in the engine.
5. Validation
The build does not ship unless the following pass.
5.0 Provenance and acceptance criteria
How reference values were produced. Reference values are generated by an internal Python script (scripts/reference/generate_reference.py, standard library only) and written to reference-values.json, which is committed with each release. The TypeScript build asserts production output against that file. The script is not published separately; the benchmark tables in sections 5.1–5.2 reproduce the committed reference values so readers can compare live tool output against documented cases.
European cases use the closed-form Merton formula. The American reference is a 4,000-step binomial tree written independently of the production tree code — from the published formulae rather than ported — so that a mistake in one implementation is unlikely to be reproduced in the other. BS2002 expected values follow the published Bjerksund–Stensland (2002) approximation.
This matters because regression tests against hand-entered constants prove only that behaviour has not changed, not that it was ever correct. A wrong value frozen into a fixture passes indefinitely. That is not hypothetical here: a malformed binomial stock tree previously shipped while its tests passed.
What this is not. Two implementations by the same organisation agreeing is weaker than validation against an established third-party library or a published benchmark table. Treat these as cross-implementation agreement, not external certification. Two further caveats: the SVI reference mirrors production's finite-difference step and sample points, so it checks the butterfly formula rather than the choice of discretization; and BS2002 puts run through the call routine via put–call symmetry, so the two are not independent checks of one another.
What the build asserts. Production output (500-step adjacent-step averaged CRR) is compared to americanCrrReference in the JSON. The JSON also carries americanCrrProductionEquivalent for diagnosis when a test fails — it is not an assertion target.
Acceptance tolerances. These are the tolerances the test suite actually asserts. The build fails if any is exceeded. All figures are absolute, per share, unless stated otherwise. Constants live in lib/tools/pricing/benchmark-tolerances.ts and are cross-checked against the published copy in lib/tools/pricing/methodology-claims.ts.
| Check | Tolerance |
|---|---|
| European (Merton) vs reference | ±0.0005 |
| CRR production (500-step, averaged) vs independent reference | ±0.003 default; ±0.02 on the high-volatility and 2-year LEAP cases |
| BS2002 vs reference | ±0.02 default; ±0.05 low-volatility; ±0.2 LEAP; ±0.6 high-volatility |
| Zero-carry American call vs European closed form | ±0.001 |
| Averaged vs single-tree CRR | must differ by more than 0.001 |
| American ≥ intrinsic | −1 × 10⁻¹⁰ |
| American ≥ European − slack | slack = 0.01 × (500 / steps); 0.01 at default settings |
| Very-deep-ITM put vs intrinsic | ±0.0005 |
| European put–call parity residual | ±0.00005 over 729 grid points |
| SVI implied volatility reproduction | ±0.0005 (decimal IV); ±1 × 10⁻⁶ on the failed-fit flat fallback |
| SVI implied volatility floor | ≥ 0.005 |
Low-vol American put (fixture low_vol_put) | CRR ÷ European > 1.8 |
Three of these deserve comment rather than being left to speak for themselves.
The BS2002 tolerances widen substantially — from ±0.02 in the ordinary cases to ±0.6 on the high-volatility case. That is a disclosure, not a convenience: it quantifies where the analytic approximation departs from the tree, and it is consistent with section 2.3's statement that observed gaps widen at long tenor and high volatility. A reader should not treat BS2002 output at 120% volatility as interchangeable with the binomial result.
The averaged-versus-single-tree check asserts a minimum difference, not a maximum. It exists because adjacent-step averaging was at one point applied in the test helper but not on the production path, so the tests measured an improvement that users never received. The assertion now fails if the two paths ever coincide, which would indicate averaging has been silently disabled again.
The CRR-versus-European slack scales with step count as 0.01 × (500 / steps), tightening automatically if the step cap is raised.
Differential audit grids (section 5.4). In addition to the nineteen fixed fixtures above, the build runs randomly generated single-option and multi-leg strategy cases from committed JSON grids (audit-grid.json, strategy-grid.json, plus seeds 2 and 3). Those suites use spot-scaled tolerances — max(10⁻⁶, spot × 0.01 × √(500 / referenceSteps)) per share, with referenceSteps = 800 on the audit grid — rather than the absolute dollar bands in the table. Each audit row carries its own binomialSteps (50, 150, 300, or 500); production is compared to americanCrrProductionEquivalent at that step count. Rows where the reference marks bs2002Ok: false assert that production routes BS2002 to the CRR tree at the same step count rather than returning an out-of-range analytic value.
5.4 Differential audit grids
Generated offline by scripts/reference/audit_grid.py and scripts/reference/strategy_grid.py (standard library only). Each seed is deterministic; seeds 1–3 are committed and exercised in CI so the suite cannot overfit a single draw.
| Grid | Cases per seed | What it checks |
|---|---|---|
audit-grid.json | 2000 | Random single options: European, 800-step CRR reference, production-equivalent CRR at row binomialSteps, BS2002 (when in range), structural bounds |
strategy-grid.json | 270 | Multi-leg strategies: per-leg netting, box-spread and synthetic-long exact European identities, bounded/positive structures |
Spot-scaled tolerance per audit row: max(10⁻⁶, spot × 0.01 × √(500 / 800)). Exact strategy invariants (box spread, synthetic long) are asserted to near floating-point precision on the European net — arbitrage identities that hold regardless of model choice.
All values per share.
| Case | S | K | T | r | q | σ | European | CRR American | BS2002 |
|---|---|---|---|---|---|---|---|---|---|
| Deep ITM put | 80 | 100 | 1.00 | 5% | 0 | 30% | 19.6762 | 21.3244 | 21.2319 |
| ATM put | 100 | 100 | 1.00 | 5% | 0 | 30% | 9.3542 | 9.8697 | 9.7458 |
| ATM put, r = 8% | 100 | 100 | 1.00 | 8% | 0 | 30% | 8.0229 | 8.9040 | 8.7724 |
| ATM call, q = 6% | 100 | 100 | 1.00 | 3% | 6% | 30% | 10.0226 | 10.4041 | 10.3173 |
| ATM call, q = 0 | 100 | 100 | 1.00 | 5% | 0 | 30% | 14.2313 | 14.2305 | 14.2313 |
| Base case call | 100 | 100 | 0.25 | 4% | 0 | 25% | 5.4721 | 5.4718 | 5.4721 |
| Base case put | 100 | 100 | 0.25 | 4% | 0 | 25% | 4.4771 | 4.5559 | 4.5161 |
CRR column: independent 4,000-step reference (americanCrrReference in reference-values.json). The build asserts production output — a 500-step adjacent-step-averaged tree — against these values within the tolerances in section 5.0.
5.2 Edge cases
Chosen because they sit where implementations typically fail.
| Case | S | K | T | r | q | σ | European | CRR American |
|---|---|---|---|---|---|---|---|---|
| 1 DTE ATM put | 100 | 100 | 1/365 | 5% | 0 | 30% | 0.6196 | 0.6202 |
| 1 DTE deep ITM put | 70 | 100 | 1/365 | 5% | 0 | 30% | 29.9863 | 30.0000 |
| 6h ATM call | 100 | 100 | 6/8760 | 5% | 0 | 30% | 0.3149 | 0.3149 |
| 1h ATM call | 100 | 100 | 1/8760 | 5% | 0 | 30% | 0.1282 | 0.1281 |
| 15min ATM put | 100 | 100 | 15/525600 | 5% | 0 | 30% | 0.0639 | 0.0639 |
| High vol put | 100 | 100 | 1.00 | 5% | 0 | 120% | 41.6437 | 42.3402 |
| Low vol put | 100 | 100 | 1.00 | 5% | 0 | 5% | 0.4062 | 0.8226 |
| Deep OTM call | 100 | 200 | 0.25 | 4% | 0 | 25% | 0.0000 | 0.0000 |
| LEAP put, 2y | 100 | 100 | 2.00 | 5% | 0 | 30% | 11.6775 | 12.8418 |
| Put, q = 6% | 100 | 100 | 1.00 | 3% | 6% | 30% | 12.8907 | 12.8909 |
| Very deep ITM put | 40 | 100 | 1.00 | 5% | 0 | 30% | 55.1333 | 60.0000 |
| Zero rate put | 100 | 100 | 1.00 | 0% | 0 | 30% | 11.9235 | 11.9228 |
CRR column: independent 4,000-step reference (americanCrrReference in reference-values.json). The build asserts production output — a 500-step adjacent-step-averaged tree — against these values within the tolerances in section 5.0.
Two of these carry more information than the rest.
The low volatility put is worth roughly twice its European counterpart. At low volatility, the American put's early-exercise feature becomes particularly valuable relative to its European counterpart under these rate and moneyness conditions. The size of the American–European difference depends jointly on rate, volatility, moneyness, time to expiry, and carry, and no general rule is implied by this single case. It is included because an engine that reproduces it is locating the exercise boundary rather than approximating around it.
In the tested very-deep-ITM cases, immediate exercise is optimal and the American value equals intrinsic value. This is a property of these specific parameter sets, not of deep-ITM American puts in general — depending on rate, volatility, and remaining time, a deep-ITM American put may retain time value.
5.3 Invariants
Property tests over a parameter grid rather than fixed points:
- American ≥ intrinsic, across the full property grid. This is a genuine universal invariant and the single cheapest detector of tree construction errors.
- American ≥ European − slack, where slack = 0.01 × (500 / steps), giving 0.01 at default settings. The true relationship
American ≥ Europeanholds exactly; the tolerance exists because the binomial value is a numerical approximation whose error alternates in sign, so a correct implementation can return a value marginally below the closed-form European price. The slack is set from observed discretization magnitude and scales with step count rather than being derived analytically. - Very-deep-ITM American puts equal intrinsic on the specific benchmark cases in 5.2. This is a fixture assertion on those parameter sets, not a general invariant.
- Put–call parity across a European parameter grid (729 points). Note that parity is a weak constraint: it catches sign and discounting errors but not volatility mishandling, since a systematically wrong σ satisfies parity perfectly.
- Zero-carry American call equals European closed form. The cheapest possible canary for tree construction errors — a malformed tree cannot pass it.
- Butterfly condition
g(k) > 0on a single fitted default slice, atk ∈ {-0.4, -0.2, 0, 0.2, 0.4}.w′andw″are computed by symmetric finite differences onw(k)withε = 10⁻⁴. The assertion is strict> 0with no tolerance band. This is a sampled diagnostic on one slice shape, not a proof across all surfaces: it detects violations, it does not establish their absence. - Flat extension beyond outer quoted strikes, asserted so it cannot regress.
6. What these tools are not
Stated plainly, because the omissions matter more than the features:
- Not live market data. All inputs are entered manually or derived from the published rate curve. There is no options chain feed. Realized-vol comparison reads Regime ingested daily bars for Tier-1 symbols only — not a live vol surface or broker marks feed.
- Not portfolio-level. Positions are analysed one at a time. There is no netting across underlyings, no beta-weighted delta, and no margin modelling under either Reg-T or portfolio margin.
- Not a replacement for a risk system. No managed stress library, no historical scenario replay, and no portfolio-level risk attribution. The position scenario tool does offer first-order Greek P&L attribution vs a selected base row for education — that is not the same as firm-wide P&L explain or historical replay.
- Not advice. Educational use only.
7. Reporting an error
If you find a number you believe is wrong, we want to know. To let us recreate the calculation exactly, please include:
Inputs — spot, strike, time to expiry (including expiration date, settlement clock, and ET time override in the calculator), rate (and whether the curve was enabled), dividend treatment (continuous yield or discrete schedule, with the schedule if used), volatility or per-leg volatilities, contract multiplier, and the full leg structure for multi-leg positions.
Configuration — model selected (European Merton / American CRR / Black-76), binomial steps if CRR, surface mode on or off (position tool only), sticky convention (sticky strike or sticky delta), sweep variable and range if using charts, and which chart panel showed the issue (e.g. P(ITM) vs delta, CRR convergence, exercise boundary). For the position scenario analyzer, include saved position name, stress row definition (preset, custom, or grid), chart tab (spot ladder, IV ladder, time decay, Spot×IV, Spot×time, 3D), Y metric, vol shock axis, and grid mesh (fast vs audit).
Environment — build or commit identifier if shown in the interface, the timestamp of the calculation, and browser and device if the issue concerns the interface rather than a number.
Output — what you received, and what you expected instead, with a source for the expected value if you have one.
Send via the contact form at logos-capital.com/contact — select Research or Support and include the details above.
Every correction described in this document originated in exactly that kind of check.
Educational content only. Not investment advice. Trading involves substantial risk of loss, including loss exceeding amounts invested. Trade at your own risk.
Educational content only. Not investment advice. Trading involves substantial risk of loss, including loss exceeding amounts invested. Trade at your own risk. Full educational disclaimer.
