All projects Project / Derivatives Ops

Legwork

A structured-product decomposer. It strips a termsheet into its elementary legs, prices each leg with Black-Scholes or seeded Monte Carlo, and then does the part almost nobody shows: the operational calendar, corporate-action adjustments, and SPAN-style margin.

Status Shipped Year 2026 Stack Python 3.12 · NumPy · pydantic · pytest
Products priced3
Monte Carlo paths100,000
Autocallable valueEUR 103,346.76
Artifacts written14
REAL RUN DATA · data/run_meta.json · SEED 42 · VALUED 2026-08-12
AUTOCALLABLE EUR 103,346.76 STD ERROR ± EUR 30.42 SEEDED MONTE CARLO · 100,000 PATHS SEED 42 · VALUED 2026-08-12 = + LONG ZERO BOND QTY 100,000 NOTIONAL AT MATURITY, CONDITIONAL ON NO AUTOCALL MATURITY 2029-06-30 60 SHORT VANILLA PUT QTY 1,000 KNOCK-IN PUT, VANILLA COMPONENT STRIKE 60 · MATURITY 2029-06-30 60 SHORT DIGITAL PUT QTY 40,000 KNOCK-IN PUT, DIGITAL COMPONENT STRIKE 60 · MATURITY 2029-06-30 LEGS VERBATIM FROM data/payoff_autocall.json · QUANTITIES EXACT SUM OF LEG PAYOFFS = PRODUCT PAYOFF · PROVEN AT 797 SPOTS

The invariant

Legwork never asks you to trust its decomposition. For every product, the sum of the legs' payoffs must equal the product's own payoff formula, terminal spot by terminal spot. That equality runs as a pytest invariant across 797 spots from 1 to 200, for all three products: 2,391 equalities checked to nine decimal places on every run. If the split were wrong, the suite would fail, not just this page.

The invariant has already earned its keep once. A review pass caught a Reverse Convertible whose matured coupon legs were still being discounted at a negative time to maturity, letting a paid coupon keep contributing value and overpricing the product by up to 3.88% at several grid points. The fix was a one-line guard, landed with two regression tests that now pin a matured leg's contribution to exactly 0.0. Decomposition is proven, not claimed.

Three products

One synthetic underlying, three termsheets pinned in code. Two of the three price fully in closed form; the Autocallable is path-dependent, so it goes to seeded Monte Carlo. The values below are the run's own numbers from data/run_meta.json.

Term Capital-Protected Note Reverse Convertible Autocallable
Tenor 5y · matures 2031-06-30 1y · matures 2027-06-30 3y · matures 2029-06-30
Structure Zero-coupon bond plus a long call at 70% participation Deposit plus coupons, minus a short knock-in put Notional plus memory coupons, minus a short down-and-in put
Coupon None 8% in 2 installments 2% per quarter with memory, barrier 70
Barriers None · strike 100 Put barrier 70 at expiry only · strike 100 Trigger 100 · coupon 70 · put 60, 12 quarterly checks
Pricing Black-Scholes, closed form Closed form: vanilla put plus digital put Monte Carlo, 100,000 paths
Value EUR 105,903.77 EUR 105,167.22 EUR 103,346.76 ± 30.42
NOTIONAL EUR 100,000 EACH · FIXING 2026-06-30 · SPOT 100 · VOL 20% · RATE 2% · ALL SYNTHETIC

Payoff & value

Each product's terminal payoff across a 41-point spot axis from 50 to 150, against its current value re-read from the pricing grid. Drag spot, vol and date: the value curve is interpolated bilinearly in spot and vol, and the marker prices the product at your exact spot. Terminal curves from data/payoff_cpn.json, data/payoff_rc.json and data/payoff_autocall.json.

Greeks

Value, delta, gamma, vega and theta on a 41 × 7 × 13 grid: spot 50 to 150, vol 10% to 40%, thirteen dates from valuation to maturity. Closed form where the product allows it, 20,000 seeded paths per node where it does not. The four profiles below re-read the grid as the sliders above move. From data/grid_cpn.json, data/grid_rc.json and data/grid_autocall.json.

Operational calendar

Every date a desk has to act on: fixings, coupon observations and payments, autocall checks, settlement. 46 events across the three products, each with its dependency chain, plus a 3:1 share split walked through with a full audit trail. From data/events_cpn.json, data/events_rc.json and data/events_autocall.json.

Margin & collateral

SPAN-style initial margin from 16 spot and vol shock scenarios, then 60 days of variation margin against one simulated path. The Capital-Protected Note is the only product that breaches its threshold: one margin call of EUR 5,049.61 on 2026-09-21. From data/margin_cpn.json, data/margin_rc.json and data/margin_autocall.json.

Proof

51 tests pin the engine down: payoff parity, Black-Scholes against known values, Monte Carlo convergence, Greeks against the analytic answers, the calendar, the margin arithmetic and the CLI. The suite is fully offline and seeded end to end; the artifacts this page reads come from one run of the real thing.

$ pytest -q
...................................................                      [100%]
51 passed in 18.59s