anti-gambling-trader-tw
Free open-source investment anti-fraud, trading statistics and automated trading program tools: default PaperBroker, provides 14 broker/exchange options; trade record analysis runs locally.
AI translation
Interactive implied volatility terminal: free-spin 3D surface and skew, no-arbitrage checks, SVI sandbox and a surface query tool.
Translation pending
FinancePythonGitHub @jainamh029OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Implied volatility surface builder: Black-76 inversion, no-arbitrage SVI calibration, interactive dashboard
Translation pending
Taken from the repository README
Loading the full README.
Read the full README ↗Take a real options chain, work backwards from option prices to the volatility the market is pricing at every strike and expiry, fit an arbitrage-aware surface, and plot it in 3D. Black-Scholes assumes one flat volatility; the surface shows how wrong that is.
Smiles by expiry, with the SVI fit and the flat Black-Scholes vol:
On a live SPY chain (26 Oct 2026, after the close) the at-the-money vol is ~15%, while far out-of-the-money puts at the front of the curve price in ~60%. The red dashed line above is the flat vol Black-Scholes would use.
Live demo: https://jainamh029.github.io/iv-surface-builder/ | Interactive dashboard
The dashboard is a static page (no server, no build step) with a dark "Obsidian & Gold" theme and a light "Paper & Ink" theme.
All surface maths is re-implemented client-side in JavaScript from the exported SVI parameters; the query tool was checked against the Python library to the printed precision.
| Contracts | 3,701 downloaded, 1,528 survive cleaning (every drop is logged with a reason) |
| Expiries fitted | 10, from 9 to 339 days |
| Fit error on market quotes | 0.16 vol points mean RMSE, 1.2 worst case |
| Static arbitrage | 0 butterfly and 0 calendar violations on the observed strikes |
| Validation | recovers a known SSVI surface to 0.18 vol points max (test-enforced) |
| Cross-check | matches svi-py to ~0.1 vol points when it is tuned (see below) |
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
python -m ivsurface SPY # live chain from Yahoo Finance
python -m ivsurface --synthetic # offline, known ground truth
python -m ivsurface --from-csv data/SPY_*.csv # re-run a chain saved by an earlier live run
pytest # 13 tests
Results land in outputs/<name>/: surface.html (interactive, self-contained), smiles.png, summary.png,
quotes_clean.csv, quotes_audit.csv (every raw row with its keep/drop reason), svi_params.csv, and
surface.json (reload with IVSurface.from_json). If the market is closed Yahoo often returns zero
bids/asks; add --use-last to fall back on last trades. For European-style options use ^SPX.
| Stage | Module | What it does |
|---|---|---|
| Fetch | data.py | yfinance chain; expiries picked log-spaced in time so the long end isn't empty |
| Clean | prep.py | Filter cascade with a reason per dropped row: crossed, no quote, wide spread, tiny price, short-dated, far OTM, IV failure, Hampel IV outlier, thin slice |
| Forward | prep.py | F = K + (C-P)/DF from near-the-money put-call parity, median over 10 strikes; reports the implied dividend yield as a sanity check |
| Invert | black.py | Black-76 on the forward, vectorised bisection. NaN where a price breaks static no-arbitrage bounds. Only OTM options are used (puts below F, calls above): most time value, least early-exercise contamination |
| Fit | svi.py | Raw SVI per expiry via the Zeliade quasi-explicit reduction: for fixed (m, sigma) the rest is a small linear constrained least-squares problem. Inverse-variance weights from bid/ask width in vol units |
| Surface | surface.py | Linear interpolation of total variance in T at fixed ln(K/F) |
w >= 0 and Lee's wing bound b(1+|rho|) <= 2: linear constraints in the inner fit.w_T(k) >= w_{T-1}(k), imposed as linear constraints.g(k) >= 0; if violated a constrained 5-parameter refit is tried,
and accepted only if it does not materially worsen the fit.A fit that matches the market proves little when the market is noisy. So the pipeline is also run on a chain
generated from a known arbitrage-free SSVI surface, with bid/ask noise, tick rounding and ~4% injected bad
quotes (one-sided, crossed, stale outliers). Everywhere data exists the recovered vols are within 0.18 vol
points of the truth, and tests/test_pipeline.py enforces a 1-point bound.
svi-py (import name pysvi) is run on exactly the same cleaned quotes and
forwards. Fit quality, butterfly and calendar checks are computed by
scripts/crosscheck_svi_py.py, independent of either library.
| Calibrator | Mean RMSE (vol pts) | Worst error | Slices w/ butterfly arb | Calendar violations | Curve gap vs mine |
|---|---|---|---|---|---|
| this project | 0.16 | 1.21 | 0 | 0 | - |
| svi-py default | 1.15 | 9.80 | 6 | 45 | 1.04 |
| svi-py default + no-butterfly | 1.45 | 8.37 | 0 | 23 | 1.27 |
| svi-py tuned | 0.15 | 1.04 | 0 | 1 | 0.06 |
| svi-py tuned + no-butterfly | 0.17 | 1.02 | 0 | 0 | 0.11 |
Reading it fairly. svi-py's default minimises unweighted total-variance error, which neglects the
at-the-money region, so in vol terms it is ~7x worse. "Tuned" means its own objective="implied_vol" with
initialization="multi_start". Tuned, the two independent calibrators agree to about a tenth of a vol point,
which is the real result. Differences: this project enforces calendar spreads by construction, and is ~15-20x
faster than svi-py's tuned configuration (~0.09 s vs 1.5-2 s per slice; svi-py's untuned default is faster at
~0.01 s but is the inaccurate one). Timings are one machine, one run.
svi-py needs Python >= 3.13, so the script runs from its own environment:
uv venv --python 3.13 .venv-xcheck
uv pip install --python .venv-xcheck/bin/python svi-py pandas matplotlib
.venv-xcheck/bin/python scripts/crosscheck_svi_py.py outputs/SPY
python -m ivsurface SPY # fetch + fit (writes data/ and outputs/SPY)
# optional: the svi-py cross-check above
python scripts/build_site.py outputs/SPY # writes docs/: report, dashboard, JSON data, bundled Plotly.js
python -m http.server -d docs # preview at http://localhost:8000 (fetch() needs HTTP, not file://)
docs/ is fully static: no build step and no CDN (Plotly.js is bundled in docs/assets). To host it, set
Settings -> Pages -> Deploy from a branch -> main / /docs.
ivsurface/ black.py data.py synthetic.py prep.py svi.py surface.py plots.py cli.py
scripts/ crosscheck_svi_py.py build_site.py make_linkedin_image.py
social/ linkedin_post.png: shareable summary graphic (python scripts/make_linkedin_image.py outputs/SPY social/linkedin_post.png)
tests/ 13 tests: pricing, SVI recovery, constraints, end-to-end on a known surface
docs/ static site: index.html (report), dashboard.html (interactive), data/*.json, assets/
data/ raw chains saved by live runs (git-ignored: Yahoo data is not redistributed here)
^SPX) is the clean choice. I have only run SPY.--rate, default 4%), used only for discounting; the forward comes from parity.rho/m are weakly identified when one wing has no quotes (the fit is still good in-sample).ValueError).docs/assets)Three.js r160 (MIT), Plotly.js (MIT), Fira Sans and Fira Code (SIL OFL 1.1). Licenses are alongside the files. Three.js and the fonts were installed from npm at pinned versions and checked against the registry's SHA-512 integrity hashes.