Task: Dual-curve (discount + projection) short-rate model
Table of Contents
This page documents a task in the IR Rates synthetic data: dataset seeding, index cleanup, dual-curve, quoting conventions story. It captures the goal, current status, acceptance, and any notes or results.
1. Goal
Today ir_curve_generation_config drives exactly one short-rate
process, whose discount_factor() feeds every instrument (deposits,
FRAs, swaps) via curve_instrument_pricer – a single self-discounting
curve, deliberately simplified for Phase 1 (confirmed intentional for
the current PoC, not a gap). Real post-2008 market practice separates
OIS discounting from index/IBOR projection, with a basis spread
between them. This task adds that: a second process/curve per
currency+index representing the discounting leg, distinct from the
projection/index leg the existing process already models, with a
basis spread parameter between them.
2. Scope
curve_instrument_pricerneeds to accept two discount-factor sources (discounting + projection) instead of one.- New config fields for the discounting curve's own process parameters (mirroring the existing projection process' kappa/theta/ sigma/initial_rate).
- Separate charts/UI in the IR curve editor to show both curves distinctly (not one merged "curve shape" chart).
- Raised while reviewing the IR curve editor's charts in Tick-batch publishing and persistence for curve instruments; deliberately deferred out of that task's scope.
3. Note: not a mismatch today
The seeded indices (SOFR/US, ESTR/EUR, SONIA/GBP) are all overnight
RFRs – the same logic applies uniformly to all three, none is a
special case. An OIS swap referencing an overnight index genuinely is
a single-curve, self-discounting instrument in real markets: its
floating leg settles at the overnight rate itself, and that same
overnight rate is also the standard discounting rate for cleared/
collateralized derivatives in that currency (this is exactly what the
post-2008 multi-curve framework's "OIS-discounting" leg is – the
OIS curve itself, built from OIS instruments, is single-curve by
construction; it is only the IBOR-projection leg layered on top of
it that needs a second curve). So single-curve modeling is the
correct choice for what is currently seeded, not a simplification
that happens to work. The mismatch this task actually resolves would
arise from adding an IBOR-style term index (EURIBOR, legacy LIBOR,
term SOFR) – those carry a credit/liquidity/term premium distinct
from the risk-free overnight rate, so a swap referencing one genuinely
needs OIS discounting plus a separate IBOR projection curve. IBOR-style
indices should not be added to the seeded universe until this task
lands.
4. Status
| Field | Value |
|---|---|
| State | ABANDONED |
| Parent story | IR Rates synthetic data: dataset seeding, index cleanup, dual-curve, quoting conventions |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-09-23 |
5. Acceptance
- A decision is made and documented on the config-model shape (second
process embedded in
ir_curve_generation_config, vs. a separate linked discounting-curve entity). curve_instrument_pricerderives each instrument's rate from the correct pair of discount factors (discounting curve for the numeraire, projection curve for the index leg) rather than one shared source.- The IR curve editor shows both curves distinctly (separate charts or a clearly-labelled combined view, not a silent merge).
- Existing single-curve configs continue to work (either migrated to a degenerate discounting==projection case, or an explicit toggle).
6. Plan
(Implementation strategy. Written when work starts; key decisions
are distilled into the parent story's * Decisions at close, but the
plan itself stays — it is the historical record of what we did.)
7. Notes
8. Test Scenarios
Manual QA scenarios (scaffolded via compass add test_scenario, run
through the QA Validation Runner panel) that verify this task. Link
new ones here as they're created; the scenario doc itself links back
via its "Verifies task" field.
| Scenario | State | Notes |
|---|---|---|
9. PRs
| PR | Title |
|---|---|
10. Review
| Comment summary | File | Decision | Notes |
|---|---|---|---|
11. Result
Abandoned at sprint 25 close. The IR work needs a refactor at the implementation level before more features land, and sprint 26 does not reach it. The capture Refactor the IR rates implementation before more IR features land holds the remaining work.