Skip to content

Repository files navigation

Exotic & Path-Dependent Option Engine

A structured-product desk in a single HTML file: build an autocallable note with sliders, watch the fair coupon solve itself, and see the two modelling shortcuts that cost more than the entire bid-offer.

Python NumPy SciPy Plotly tests no build step licence

the interface

Live demo: https://codeebytee.github.io/05-exotic-options-engine/ (enable Pages: Settings → Pages → main /docs)

Run the interface locally: clone the repo and double-click docs/index.html. No install, no server, no internet connection. requirements.txt is only needed to re-run the research.

What this does

  • Prices the autocallable notes banks actually sell — memory coupons, an autocall trigger with a lockout, and European or American soft protection — by randomised quasi-Monte Carlo, and reports a 95% confidence interval on every number rather than a bare price.
  • Solves the fair coupon in closed form from a single simulation, because a note's present value is exactly affine in its coupon rate. That is what lets the browser resolve the term sheet live on every slider drag.
  • Quantifies what the standard shortcuts cost. A naive daily-stepped barrier simulation overprices a continuously monitored contract by 285 bp; flat lognormal vol understates the fair coupon by 76 bp; an American rather than European knock-in is worth another 105 bp. All three exceed the bid-offer on the contract.

Headline result

At SPY's own at-the-money implied vol (18.9%, snapshot 2026-08-07, spot 773.26), a three-year quarterly memory-coupon autocallable — autocall at 100% after a two-quarter lockout, coupon barrier 75%, European protection at 70% —

Fair coupon 7.19% against a printed 9%
Value at the printed coupon 101.85 per 100 (95% CI ±0.02)
Expected life 1.20 years against a 3-year stated maturity
P(autocall at the first eligible date, 6 months in) 51.9%
P(loss) 7.4%, and 40.8 points of notional when it happens

The gap between 7.19% and 9% is not free money: it pays the issuer's credit spread, hedging cost and margin, and the skew correction above eats into it from the other side. The point of the decomposition is that the term sheet describes none of that in words.

Validation, not assertion: nine exotic contracts priced against nine closed forms, all inside their 95% interval, worst discrepancy 1.59 standard errors; the affine coupon identity agrees with a Brent repricing search to $10^{-17}$; and the browser's own engine is cross-checked against the Python library on load, live, in the page's validation tab.

Install and run

pip install -r requirements.txt
python scripts/make_results.py          # the full study: ~2.5 min, writes results/
python scripts/build_frontend.py        # regenerates docs/data.js from src/

Then pytest for the test suite, and double-click docs/index.html for the interface. The interface needs none of the above — it is committed ready to run.

The interface

Four tabs, all recomputing live in the browser:

  • Structured product builder — assemble a note from its term sheet (maturity, observation frequency, lockout, all three barriers, memory on/off, knock-in style, participation) and get the price, the fair coupon, the redemption-date distribution, the payoff histogram, and the price-vs-coupon line whose slope is the coupon annuity.
  • Exotics desk — Asian, lookback, barrier, digital and cliquet contracts priced live against their closed forms where one exists, plus a whole price-vs-strike curve from a single simulation.
  • Barrier monitoring — the discrete-vs-continuous problem, live: move the observation frequency and watch the price of a down-and-out call converge from 1371 bp above the continuous value down toward it.
  • Validation — the page checks itself against the Python library on every load and shows you the numbers, including where it disagrees.

Plus a stress panel with degenerate inputs (zero vol, zero maturity, inverted or crossed barriers, a barrier at spot) that produce a readable warning banner rather than a blank chart.

Repo map

05-exotic-options-engine/
├── docs/                      # the interface — index.html + generated data.js + vendored plotly
├── src/
│   ├── models/
│   │   ├── paths.py           # Sobol, Brownian-bridge construction, Owen scrambling, GBM + CEV
│   │   ├── exotics.py         # Asian, barrier, lookback, digital, cliquet + the survival weight
│   │   ├── autocallable.py    # the note: payoff decomposition, affine coupon solve
│   │   ├── analytic.py        # Reiner-Rubinstein, Kemna-Vorst, Goldman-Sosin-Gatto, BGK
│   │   └── black.py           # Black-Scholes and digitals
│   ├── data/market.py         # market snapshot: live → cached → labelled synthetic
│   └── utils/                 # config loading, RQMC confidence intervals
├── scripts/
│   ├── make_results.py        # the whole study → results/
│   ├── build_frontend.py      # results → docs/data.js
│   ├── check_page.py          # drives the page headless from file:// and cross-checks it
│   ├── make_gif.py            # records results/interface.gif
│   └── refresh_market.py      # refetches data/market_snapshot.json
├── notebooks/                 # the argument end to end (source .py + generated .ipynb)
├── tests/                     # 90 tests
├── results/                   # every number and figure the documents cite
└── config.yaml                # every tunable in the project; src/ hardcodes nothing

Start here: PREREQUISITES.md if you do not have a finance background — it is written for an engineer and defines every symbol. DEEP_DIVE.md if you do — the equations, the validation evidence, and an honest limitations section.

Design decisions

  • The fair coupon is a division, not a search. The autocall time and the coupon indicators depend on the path only, never on the coupon rate, so $PV(c) = PV_0 + cA$ exactly. One Monte Carlo run yields both terms, so $c^\star = (N - PV_0)/A$ costs nothing. This is why a browser can resolve the term sheet on a slider drag — and because it is a claim, it is tested against a Brent repricing search rather than asserted.
  • Barrier crossings are weighted, not sampled. Each path carries the conditional probability that it never touched the barrier, from the Brownian bridge, instead of a 0/1 flag. By Rao–Blackwell this cuts variance and removes the discretisation bias — there is no tradeoff. The alternative costs 285 bp on the contract in results/, an error that does not shrink with more paths.
  • Sobol's benefit is measured, not assumed. The famous $O(N^{-1})$ rate appears only on the one-dimensional digital payoff (fitted slope $-1.31$), and it appears there despite that payoff being discontinuous. On the twelve-dimensional note the slope is $-0.59$: a large constant-factor win, not a better rate. Effective dimension, not smoothness, is what governs it — which is exactly why the paths are built by Brownian bridge.
  • The flat-vol error is reported rather than buried. The note is short a deep out-of-the-money put, so a single lognormal vol is wrong in a direction that flatters the issuer. A CEV arm measures that at ~76 bp of coupon and the page says so on the same screen as the price.

Honesty notes

  • Every number is as of the 2026-08-07 snapshot in data/, stated on the page and reproducible from the committed file with no network.
  • The notebook is committed without outputs by design — its code lives in notebooks/autocallable_story.py, which runs end to end and is what generated every table it shows. Run it top to bottom and it fills itself in.
  • This engine prices one underlying. Real retail autocallables are usually worst-of on three or four, where correlation skew dominates everything measured here. It also carries no issuer credit spread. DEEP_DIVE.md §7 is the full list.
  • Nothing here forecasts a market. Every output is a price, a probability or a risk measure under the risk-neutral measure.

Licence

MIT — see LICENSE.

About

Autocallable notes priced by randomised quasi-Monte Carlo, with the fair coupon solved in closed form from one simulation. Live in-browser structuring desk.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages