Tier 2 · Internal Risk Management

Futures Pricing — CTD / Convexity / Fair-Value Family

M-135 · lifecycle: monitoring · RAT-135-v1.0.1

Intended Use

Futures Pricing — CTD / Convexity / Fair-Value Family Price exchange-traded futures (Treasury, SOFR, equity index, Eris SOFR swap futures) with cheapest-to-deliver, convexity adjustment, and fair-value methodologies.

Family-level model covering futures pricing methodologies: cheapest- to-deliver (CTD) selection and conversion-factor adjustments for Treasury futures; convexity-adjustment for SOFR futures; fair-value basis with dividend yield for equity index futures; Eris standardized SOFR swap futures. Used in ALM portfolio and hedge program execution. Implementations: 4 FinView L1 + 1 Gold Copy L1 challenger.


Components

Inputs, processing, outputs

data sources
DS-001 · DS-002 · DS-005 · DS-006 · DS-009 · DS-031 · DS-033
assumptions
A-050, A-051, A-052, A-053
engines
finview.L1.treasury_futures_pricer
finview.L1.sofr_futures_pricer
finview.L1.equity_index_futures_pricer
finview.L1.eris_sofr_futures_pricer
goldcopy.L1.futures_pricer
contracts
futures_pricing_v1
upstream
M-137
dimensions
D2

Methodology & Mechanics

Methodology

M-135 is the Futures Pricing family: FinView-resident engines that price exchange-traded futures by cost-of-carry / convexity-adjusted forward construction and report fair value against a quoted market price. All members live in [redacted] (engine ids finview.L1.*); none of the source is in InsModel — InsModel consumes them cross-repo by adding the FinView path to sys.path (the same pattern M-040/CECL uses).

The family has four production engines plus a frozen "gold copy" challenger fixture:

Member Engine id Method DV01?
SOFR futures (SR1/SR3) finview.L1.sofr_futures_pricer forward rate from SOFR curve + Hull-White convexity adjustment; price = 100 − futures_rate×100 yes (tick value, $/bp)
Treasury futures (ZT/ZF/ZN/ZB/UB) finview.L1.treasury_futures_pricer cash-and-carry on the cheapest-to-deliver (CTD) bond; fair = (CTD cash + financing − coupon income) / conversion_factor yes (CTD-implied, /CF)
Equity-index futures (ES/NQ/RTY/YM + micros) finview.L1.equity_index_futures_pricer classic cost-of-carry F* = S·exp((r−d)·T) approx (S·T·1bp×mult)
Eris SOFR swap futures (2Y–30Y) finview.L1.eris_sofr_futures_pricer wraps IRSPricer; price = 100 + swap-NPV per $100 notional yes (from IRS)
Gold-copy challenger goldcopy.L1.futures_pricer frozen CME settlement prices + deliverable baskets (ZN=F, ZB=F, ES=F, SR3) for cross-check reference only

Note — credit_index_futures_pricer is not an M-135 member. Although it shares the *_futures_pricer naming and lives alongside the family in finlib/derivatives/, finview.L1.credit_index_futures_pricer is assigned model_membership: [M-133] (Credit Derivatives) in engine_registry.yaml (line 348), and the M-135 registry processing-engines list does not include it. It is documented under M-133, not here.

Two pricing modes coexist in the family. Rate futures (SOFR, Treasury) are priced off a discount curve with an explicit financing/convexity term; the equity engine is the textbook cost-of-carry forward; the Eris engine is a swap-future that reuses the existing IRSPricer rather than re-deriving swap math. The canonical exemplar documented here is the 3-Month SOFR future (SR3) — it is the cleanest, most self-contained rate-future pricer (depends only on bootstrap_sofr_curve and interpolate_curve) and it surfaces every output a rate future needs in one compute_fair_value call: forward rate, convexity adjustment, futures price, and DV01.

SR3 pricing chain. From the bootstrapped SOFR discount curve, zero rates are recovered (z = −ln(DF)/t), the forward rate over the contract reference period [t1, t2] is (DF(t1)/DF(t2) − 1)/(t2−t1), a convexity adjustment CA ≈ ½·σ²·t1·t2 (simplified Ho-Lee / Hull-White) lifts the forward to the futures rate (futures rate > forward rate because daily margining is positively correlated with rates), and the theoretical price is 100 − futures_rate×100. Fair value in dollars is the price gap times the contract tick value scale; DV01 is the contract tick value ($25.00/bp for SR3).


Key Assumptions

Key Assumptions and Their Justification

Assumption Value (SR3 canonical) Source / derivation Justification
Carry / financing implicit in curve DFs (no separate repo for SOFR) SOFR discount curve SOFR futures settle to compounded SOFR; the curve is the financing leg, so no external repo rate is needed (unlike Treasury futures, which take an explicit repo_rate, default 4.3%).
Curve flat 4.50% par yields, 10 tenors → bootstrapped DF curve bootstrap_sofr_curve test fixture Deterministic canonical input matching tests/test_sofr_futures_pricer.py; flat curve makes the forward ≈ the par rate, so outputs are inspectable by hand.
Convexity vol (σ) 0.005 (50 bp) short-rate vol engine default Convexity for short-dated SOFR is tiny (≈1.6e-6 here); the adjustment is O(σ²·t1·t2) so it is materially below a tick at the front end and only grows for deferred contracts.
Reference period 91 days (SR3); accrual start 0.25y CME SR3 spec Hard-coded to CME 3-Month SOFR contract definition; accrual_start_years selects which forward window the contract references.
Convexity bias sign futures rate ≥ forward rate Hull-White structure Daily variation margin on a short-rate future is paid/received when rates move, biasing the futures-implied rate above the forward — the model encodes this as an additive positive CA.

Prose. The single most important modelling choice is that SOFR futures require no exogenous carry input: the SOFR discount curve simultaneously supplies the forward rate and the financing, so the only "carry" the model adds is the convexity correction. This is the cleanest member of the family precisely because the curve collapses spot, carry, and forward into one object. Treasury futures, by contrast, need an explicit repo_rate and a deliverable basket to find the CTD — more inputs, more failure modes (see Limitations). The convexity-vol assumption is the only "soft" parameter in SR3 pricing and its impact is sub-tick at the front of the curve, which is why the test suite asserts convexity_adjustment < 0.001.


Output Snapshot

Output Snapshot

Deterministic single-contract run of SOFRFuturesPricer (SR3) — reproducible, requires no live market data (python scripts/model_snapshots.py M-135 in InsModel; the engine is asserted by tests/test_sofr_futures_pricer.py in FinView, 27 tests). BV-032 immune: the curve is a flat 4.50% synthetic par curve (the exact test fixture), so no FRED/CME live quote is touched.

Input: SR3 (3-Month SOFR) · notional $2,500,000 · futures_price 95.50 (implied rate 4.50%) · accrual start 0.25y · σ 0.005 · flat 4.50% SOFR curve

output value meaning
market_price (quoted) 95.5000 the contract quote being checked
implied_rate (100 − price) 0.045000 rate the market quote implies (4.500%)
forward_rate (from curve) 0.044499 curve forward over the 91-day window
convexity_adjustment 1.571e-06 ½·σ²·t1·t2 — sub-tick at the front end
futures_rate (fwd + CA) 0.044501 convexity-lifted rate the future references
theoretical_price 95.5499 100 − futures_rate×100
price_difference (theo − mkt) 0.0499 fair price sits ~5 ticks above the quote
dv01 ($/bp) 25.00 SR3 tick value, dollar value of 1 bp
fair_value ($ vs market) 124.74 dollar mispricing of the quoted contract

The theoretical price (95.5499) is about 5 bp / 5 ticks above the quoted 95.50, so the model flags the quote as cheap and reports a +$124.74 fair value on one contract. The convexity term is 1.6e-6 in rate space — economically negligible at the 3-month point, exactly as expected for a front-month SOFR future — so almost all of the price gap is the forward-vs-quote difference, not convexity. DV01 is the fixed CME tick value ($25.00/bp for SR3; $41.67/bp for SR1).

Captured 2026-06-04 · deterministic, no live data.


Limitations

Limitations and Known Gaps

  1. Convexity is a simplified Ho-Lee / Hull-White closed form, not a calibrated term-structure model. CA = ½·σ²·t1·t2 with a single flat σ. This is accurate for front-month contracts (the documented SR3 case) but understates convexity for deferred contracts where mean-reversion and a term structure of vol matter. No SABR/HJM calibration is wired in.

  2. Single flat convexity vol. σ is one scalar (default 0.005); there is no vol surface or per-tenor σ. A deferred SR3 strip priced off one σ will carry correlated convexity error across the curve.

  3. SOFR financing is curve-implicit; Treasury financing is a single repo scalar. The Treasury member takes one repo_rate (default 4.3%) and one days_to_delivery (default 90) for the whole basket — it does not model a term repo curve or special-collateral (squeeze) effects, which can move the real CTD and the net basis.

  4. CTD selection is static (lowest net basis at valuation). The Treasury engine picks the cheapest-to-deliver by current net basis and does not model the delivery-option / switch optionality (the right to deliver a different bond if rates move through the 6% notional yield). For SR3 this limitation is moot (cash-settled), but it caps accuracy of the Treasury sibling.

  5. Equity DV01 is a crude approximation. S·T·1bp×multiplier — a first-order rate sensitivity that ignores the dividend-yield term and is not a true Greeks computation. Fine for exposure bucketing, not for hedging.

  6. FinView-resident, cross-repo dependency. The entire family lives in [redacted]; InsModel reaches it only by sys.path.insert(0, "[redacted]"). There is no packaged interface — a FinView refactor of finlib.derivatives would silently break the InsModel snapshot. This is the same cross-repo fragility flagged for M-040 (CECL).

  7. No live-data path exercised here (by design). The gold-copy challenger (registered engine goldcopy.L1.futures_pricer; frozen-fixture data in finlib/gold_test_derivatives.py) carries frozen CME settlement prices and deliverable baskets for cross-check, but the documented snapshot uses the flat synthetic curve. The live fetchers (CME/yfinance/Eris FTP) exist but are out of scope for the deterministic card and untested for staleness here.

Tracked for ratification (not applied in this documentation pass). The following are output-changing / modeling-code or validation items left for ratification, noted here for transparency: convexity is a single-sigma Ho-Lee / Hull-White closed form under-built for deferred strips, equity-future DV01 is a crude S·T·1bp approximation, and Treasury CTD selection is static with no delivery-option modelling (INV-022); independent effective-challenge validation evidence does not yet exist (registry last_validated_on: null, peer-review pending — INV-029); and the family is FinView-resident, consumed by InsModel via sys.path with no packaged interface or drift gate (INV-032).


Validation Evidence

Validation Packet

Check Where What it asserts
Implied-rate identity tests/test_sofr_futures_pricer.py::TestImpliedRate rate = (100 − price)/100 exactly (95.75 → 4.25%).
Forward ≈ flat rate TestForwardRate::test_forward_rate_near_flat_rate on a flat 4% curve the recovered forward is within 50 bp of 4%.
Convexity sign + monotonicity TestConvexityAdjustment CA > 0 and increases with σ; CA < 0.001 (sub-tick) for short-dated.
Theoretical price band TestTheoreticalPrice 80 < theo < 105; theo ≈ 100 − rate×100 on a flat curve (±0.5).
Fair-value contract keys TestComputeFairValue::test_required_keys result exposes fair_value, forward_rate, convexity_adjustment, futures_rate, dv01, contract.
DV01 = tick value test_dv01_equals_tick_value / test_sr1_prices SR3 DV01 = $25.00, SR1 DV01 = $41.67.
Edge cases TestEdgeCases unknown contract raises; default/custom notional; accrual-end arithmetic.
Family regression tests/test_treasury_futures_pricer.py, test_equity_index_futures_pricer.py, test_eris_sofr_futures_pricer.py CTD/basis, cost-of-carry forward, and Eris-as-IRS pricing.
Suite result (2026-06-04) 4 family test files, FinView venv 91 passed (SR1/SR3 27, treasury 23, equity 21, eris 20).
Cross-venv reproducibility FinView .venv and InsModel Models/.venv identical SR3 outputs (theo 95.5499, fair_value 124.74, DV01 25.00) under both interpreters.

References

References

Futures-pricing / convexity literature: - Hull, Options, Futures, and Other Derivatives — cost-of-carry forward (F = S·e^((r−q)T)) and the futures-vs-forward convexity bias under daily margining. - Ho & Lee (1986) / Hull-White (1990) — short-rate term-structure models underlying the ½·σ²·t1·t2 convexity adjustment for rate futures. - CME Group SOFR Futures contract specifications (SR1 1-Month, SR3 3-Month); CME Treasury Futures conversion-factor and cheapest-to-deliver methodology. - Burghardt, The Treasury Bond Basis — gross/net basis, carry, implied repo, and CTD analytics (the Treasury sibling's framework).

Engine source (FinView-resident): - finlib/derivatives/sofr_futures_pricer.py (finview.L1.sofr_futures_pricer) — documented SR3 exemplar. - finlib/derivatives/treasury_futures_pricer.py, equity_index_futures_pricer.py, eris_sofr_futures_pricer.py, credit_index_futures_pricer.py — family members. - finlib/curve_builder.pybootstrap_sofr_curve, interpolate_curve.

Gold-copy challenger (registered engine): - goldcopy.L1.futures_pricer — registered challenger engine (codebase gold_copy, path instruments/futures_pricer.py, model_membership: [M-135] in engine_registry.yaml). This is the registry id the Components list (above) carries. The frozen CME-settlement fixture data is held in the FinView test file finlib/gold_test_derivatives.py, which the family test suites read for cross-check; that file is the test fixture, not the registered engine id.

Tests: - tests/test_sofr_futures_pricer.py (27), tests/test_treasury_futures_pricer.py (23), tests/test_equity_index_futures_pricer.py (21), tests/test_eris_sofr_futures_pricer.py (20).

Internal: - BV-032 (live-data immunity) — snapshot uses a synthetic flat curve; no live CME/FRED/yfinance fetch. - Cross-repo snapshot pattern — ecosystem/InsModel/Models/scripts/model_snapshots.py (snap_M_040 precedent for a FinView-resident engine on sys.path).


Change Log

Change Log

Card change history. Code-side change history lives in git log of the component files. This in-card Change Log is the change-log of record for M-135 (adopted per RAT-135-v1.0.0 COND-003, 2026-06-06); the registry documentation_pack.change_log flag points here.

  • 2026-05-08 — stub created from registry data per Decision 023 Phase 5 / B-07.
  • 2026-06-04 — Tier-2 hand-authoring of Methodology, Key Assumptions and Their Justification, Limitations and Known Gaps, Validation Packet, and References from the FinView sofr_futures_pricer.py engine (SR3 canonical exemplar) + the four family test suites (test_sofr_futures_pricer.py, test_treasury_futures_pricer.py, test_equity_index_futures_pricer.py, test_eris_sofr_futures_pricer.py). Stub marker advanced from to.
  • 2026-06-04 — captured the deterministic Output Snapshot (SR3 single contract, flat 4.50% synthetic curve, no live data) and recorded the 2026-06-04 family validation-suite run (91 passed across the four test files). No fabricated numbers — all figures are deterministic engine output.
  • 2026-06-06 — code-grounded documentation-accuracy pass against engine_registry.yaml. Removed finview.L1.credit_index_futures_pricer from the Methodology member table (it is model_membership: [M-133], registry line 348; the Components/processing list already correctly omitted it) and added a footnote. Reconciled the gold-copy challenger naming to the registered engine id goldcopy.L1.futures_pricer (codebase gold_copy, instruments/futures_pricer.py) in the Methodology table, References, and Limitation 7, noting finlib/gold_test_derivatives.py as the test fixture file. Added a downstream-consumers aggregate-risk view (M-100 ALM, M-110 Hedge Effectiveness, sourced from the Materiality justification) to Dependencies per §10.5 item 8. Added a ratification-tracking note under Limitations for the gated INV-022 / INV-029 / INV-032 items. No model outputs, back-test numbers, or validation results were fabricated or changed.
  • 2026-06-06 — RAT-135-v1.0.0 remediation (1L, Decision 053 charter §2.2). Assembled the Tier-2 validation-evidence pack at modelling/validation_evidence/M-135/v1.0.0/ (conceptual-soundness review, sensitivity_suite.py on convexity sigma / repo rate / days-to-delivery / dividend yield, and reconcile_finview_vs_goldcopy.py effective-challenge cross-check vs the registered goldcopy.L1.futures_pricer — equity cost-of-carry overlap, max rel diff 0.00e+00 within 0.5%) — discharges COND-002 / INV-029 on the buildable evidence (live-CME-settlement back-test honestly pending). Reconciled the registry documentation_pack to disk (model_card / validation_evidence / change_log -> present) and stamped last_validated_on: 2026-06-06 (COND-001); adopted this in-card Change Log as the change-log of record (COND-003). No model outputs, back-test numbers, or validation results were fabricated.

2L Inventory Review

Open findings (3)

Independent 2nd-line review (INV-2026-06) — implemented capability vs registered scope. Each carries a recommended fix and is tracked in insightalm-mrm until closed.

HIGH INV-029 · P5 · validation-gap

Validation evidence + change logs missing across most of the inventory

Only M-001/M-020/M-050 carried full documentation packs before this pass. Most models record validation_evidence: missing and change_log: missing with peer_review: pending. Gold tests freeze behaviour but many assert only structural invariants (e.g. reserve>0), not correctness against external truth. The flagship T0-vs-10-K match is circular (BV-032).

Recommendation: For each Tier-1 model: produce a validation-evidence pack (back-test vs disclosed results once BV-032 re-calibration lands, sensitivity suite, challenger comparison), a change log, and a 2L ratification. Sequence behind BV-032 (firm-data) for anything needing 10-K reconciliation.

LOW INV-022 · P3 · proxy

Futures convexity is a single-sigma closed form; sibling pricers have crude greeks

The convexity adjustment is a single-sigma Ho-Lee/Hull-White closed form — accurate front- month, under-built for deferred strips (no vol surface). Equity-future DV01 is a crude S*T*1bp approximation; Treasury CTD is static (no delivery-option/switch modelling).

Recommendation: Calibrate convexity to a short-rate vol surface for deferred contracts; model the CTD delivery option and a proper equity-future sensitivity.

LOW INV-032 · cross-repo · cross-repo

FinView-resident pricing/CECL engines reached cross-repo with no drift gate

M-040 (CECL) and M-130-137 (asset pricing) are FinView-resident, consumed by InsModel only via sys.path insertion. No packaged interface or drift gate — a finlib signature change silently breaks the InsModel snapshot harness / consumers.

Recommendation: Define a packaged interface (or a versioned contract) for the FinView pricing library and a CI drift gate, so cross-repo consumers fail loudly on signature change. Tie to D041 ownership.


Validation Coverage

Per-tier expectations

Per MRM Framework §10.2 + §10.3, this model's regulatory_frameworks tag list activates the following overlays:

asop_56 sr_26_2 internal
component tier-2 expectation status
Registry entry required present
Model card (§10.5 doc pack) required present
Validation evidence required present
Change log required present
Independent effective challenge (2L) required attested

Ratification

Ratified — RAT-135-v1.0.1

Latest ratification on file: RAT-135-v1.0.1. Authored by 2L (mrm-peer-reviewer) per Decision 028 charter §5 Pattern A.