# AHS Rates 338 — execution modes

Research demonstrator adapted from Fletcher & Gardner (2009), chapters 4–12, appendices C–D. New implementation, not a transcription of PPF.

- `python -m research.rates338.demo`: Python pricing.
- `python -m research.rates338.server`: JSON HTTP API bound to **127.0.0.1:8338**, not a hosted API. Start from repository root; requires NumPy. Registry is process-memory only; restart invalidates IDs. No internet exposure, authentication or persistence provided. Static site does not execute this Python server.
- `python -m research.rates338.com_server --register`: Windows / pywin32 COM registration. Same Python engine, no HTTP calls. A single COM instance owns the registry; Excel must retain that instance. Unregister with `--unregister`. Match Excel/Python bitness and test registration under the intended account. **COM registration and Excel execution not tested on Linux.**
- `g++ -std=c++17 -O2 -shared -fPIC research/rates338/ou.cpp -o research/rates338/ou.so`: optional C++ OU moments kernel, called explicitly via `native.moments`. Set `AHS_RATES338_NATIVE=1` to use this compiled moments kernel inside the Python pricer. Missing native library then raises an error; default is Python/NumPy. This is not a full native C++ pricer. Windows DLL build/export must be validated separately.

## Contracts
POST `/v1/{operation}` with JSON body. Success `{ok:true,data:{...}}`; invalid input HTTP 422 with `{ok:false,error:{code,field,message}}`; unknown object HTTP 404. COM takes a JSON string and returns the same data object as JSON (without HTTP envelope), or raises a COM exception.

All rates are decimal (0.025 = 2.5%, 0.0001 = 1 bp); prices and notionals EUR; times are year fractions from valuation, not adjusted calendar dates; continuous zero rates, single-curve projection/discounting. Date is an ISO metadata anchor. Unsupported calendars, day-count schedules, historical fixings, multi-curve basis, settlement lags, exercise notice, fees, XVA are not silently approximated. Exercise at a payment boundary enters the remaining co-terminal swap immediately after the boundary payment. No principal exchange.

|Operation|Required JSON payload|Output|
|---|---|---|
|CreateMarket|valuation_date ISO, currency EUR|immutable market id|
|AddCurve|market_id, curve:{times:[0,...],discount_factors:[1,...],interpolation:log_df/linear_df/linear_zero}|new market id|
|AddVolatilitySurface|market_id,surface:{expiries,tenors,values,quote_convention:normal_decimal_sqrt_year}|new market id; quotes stored, no calibration|
|SetModelParameters|market_id,a (0.001–3/year),sigma (0–0.1 rate/sqrt(year))|new market id|
|CreateSwap|notional,start,payment_times,fixed_rate,direction:1/-1|swap id|
|CreateExerciseSchedule|times|exercise id|
|CreateBermudanSwaption|swap_id,exercise_id|bermudan id|
|CreateTARN|notional,rates,target,coupon,gearing,floor,accrual|tarn id, deterministic coupon scenario|
|CreatePricer|market_id,trade_id,steps integer 4–600|pricer id|
|RunValuation|pricer_id|price,currency,method,diagnostics,result_id,snapshots|
|ComputeSensitivities|pricer_id,bump|up,down,central_change,derivative_per_decimal_rate|
|RunScenario|pricer_id,parallel_shift|scenario price and diagnostics|
|GetDiagnostics|pricer_id|curve fit, prices on three grids or explicit alignment errors|
|ExportResults|result_id|CSV string including snapshots, units and version|

Objects: create → immutable snapshot → referenced by pricer → result snapshot → export. Content-addressed IDs, no updates/deletion/persistence in this research service. API serializes requests with a lock. No production concurrency or SLA claim. Snapshot IDs are local to this process. Invalid types must yield explicit errors, never silently reset to defaults.

## Model and boundaries
Under Q, r(t)=x(t)+phi(t), dx=-a x dt+sigma dW; a,sigma constant, x(0)=0. At each tree step phi is fitted to reproduce P(0,t). OU transitions match conditional mean and variance with non-negative trinomial probabilities on recombining support. No hard state clipping. Continuous account numeraire for theoretical pricing; discrete one-step discount factors in tree. Inspect step refinement; exact curve fit does not imply exact option price.

Initial curve: log-linear DF, linear DF or linear continuous zero. At t=0, linear-zero uses first nonzero zero rate. Extrapolation rejected; knots may create forward jumps. Negative rates and DF>1 are permitted. Positive DFs required. No bootstrapping or automatic market volatility calibration. Single Gaussian factor cannot represent arbitrary smiles/term-correlation.

Monte Carlo exploration prices a zero coupon via exact joint OU state/integral; reference is the input discount factor. It does not claim Monte Carlo Bermudan pricing. Tree exercise policies are used for the exercise visualization: immediate versus continuation. Appendix D pickup-value regression is explained as a distinct methodology, not claimed as an implemented alternative algorithm. TARN is a deterministic path coupon-leg scenario, capped last coupon, no final target top-up, no funding leg. Not a stochastic full TARN pricer.

## Excel
The delivered .xlsx has no embedded macros. Save a copy as .xlsm, import AHSRates338.bas and run RunAHS338. VBA invokes the 14 operations directly on a retained COM object. `ExportAHS338` uses the COM convenience method `ExportCSV(result_id)`, returning ExportResults.csv as plain text. Numerical inputs use invariant decimal conversion; exceptions are shown in Results!B9. Initial Results, Sensitivities and Scenarios are labeled Python snapshots and require an explicit rerun after input edits. Trade sheet formulas are an independent node-aligned swap check. The spreadsheet, VBA parser, COM registration, DLL bitness and chart recalculation still require a real Windows/Excel test.

Download all Python files into research/rates338 beneath a repository root (retain __init__.py or use namespace package). Run from that root. NumPy required; pywin32 required only for Windows COM. `openapi.json` specifies requests, responses and units. The browser uses a separately tested JavaScript implementation, not a network call to Python.
