From option-volatility
Fit and visualize the implied volatility surface for a ticker — IV across strike (skew) and time (term structure). Use this skill when the user asks for an IV surface, vol surface, mispriced options across the chain, butterfly arbitrage check, or vol-of-vol context. Triggers: "IV surface", "vol surface", "show me the smile", "find dislocated options", "is the surface arb-free", "fit SVI / SABR", "surface for AAPL/SPY/QQQ", "scan the chain for cheap vol". Use even with partial input — defaults: nearest 6 expiries, ±20% strike range from spot.
How this skill is triggered — by the user, by Claude, or both
Slash command
/option-volatility:iv-surfaceThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Build the full IV surface (strike × time → IV) for a ticker, fit a smooth parameterization (SVI or SABR), and flag arbitrage violations.
Build the full IV surface (strike × time → IV) for a ticker, fit a smooth parameterization (SVI or SABR), and flag arbitrage violations.
Use the yfinance-options skill to pull ALL expiries (or top 6 by liquidity) and BOTH puts and calls.
For each contract: store strike K, expiry T (years), bid, ask, last, mid, IV (from chain), open interest, volume.
Filters before fitting:
If after filtering you have < 6 contracts per expiry, stop and report the chain is too thin to fit.
If the chain IV is missing or stale, back out IV from mid price using Newton-Raphson on Black-Scholes:
def implied_vol(price, S, K, T, r, opt_type='call', q=0.0, tol=1e-6, max_iter=50):
sigma = 0.3 # initial guess
for _ in range(max_iter):
from math import log, sqrt, exp, pi
from scipy.stats import norm
d1 = (log(S/K) + (r - q + 0.5*sigma**2)*T) / (sigma*sqrt(T))
d2 = d1 - sigma*sqrt(T)
if opt_type == 'call':
price_model = S*exp(-q*T)*norm.cdf(d1) - K*exp(-r*T)*norm.cdf(d2)
else:
price_model = K*exp(-r*T)*norm.cdf(-d2) - S*exp(-q*T)*norm.cdf(-d1)
vega = S*exp(-q*T)*(1/sqrt(2*pi))*exp(-0.5*d1*d1)*sqrt(T)
if vega < 1e-10:
return None
diff = price_model - price
if abs(diff) < tol:
return sigma
sigma -= diff / vega
if sigma <= 0:
sigma = 0.01
return None
If Newton-Raphson fails (returns None or oscillates) on > 20% of contracts, fall back to bisection. If still failing, report which strikes failed — do not silently drop them.
For each expiry T, fit one of:
Five parameters (a, b, ρ, m, σ) describe total variance w(k) where k = log(K/F):
w(k) = a + b · [ρ·(k − m) + √((k − m)² + σ²)]
references/iv_reference.md for full formulas)Four parameters (α, β, ρ, ν). Hagan 2002 approximation gives IV(K, F, T).
Fit with scipy.optimize.least_squares on (IV_market − IV_model). Constrain: b > 0, σ > 0, |ρ| < 1 (SVI); α, ν > 0, |ρ| < 1, β ∈ [0, 1] (SABR).
If any check fails, list the violating (K, T) pairs in the response. Do not silently smooth them away.
Two charts:
For Claude.ai widgets, use show_widget with ["chart"] modules and plot via Chart.js scatter.
After the fit, compute the residual IV_market − IV_fitted for each contract. Report:
Caveat: residuals can be wide near zero-bid contracts or right after a jump — report the liquidity (OI, volume, spread) alongside each, so the user can judge whether the dislocation is tradeable.
For trading off the dislocation, recommend options-payoff to size and visualize the structure. For pure skew interpretation, recommend vol-skew.
references/iv_reference.md — Full SVI and SABR derivations, Newton-Raphson edge cases, arbitrage-test codeCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub dongzhuoyao/finance-option-skills --plugin option-volatility