Task: Construct every rate product by name
Table of Contents
This page documents a task in the Let the plan state domain rows, not a bag story. It captures the goal, current status, acceptance, and any notes or results.
1. Goal
Every routed rate product the planner draws is constructed by a function that names it, and the writer no longer translates a rate trade.
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Let the plan state domain rows, not a bag |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-10-29 |
3. Acceptance
- One constructor per rate product the planner draws, with the trade type fixed by it.
- The terms hold only the facts each product states, and the closed vocabularies are refused at construction.
- The writer appends the constructed rows and assembles no rate product.
- A provisioning run books the same eight rate products with the same row counts, and the suites are green.
4. Plan
A rates product is a header, two legs and one fact row, and the header states
no trade type: every code routes to one table, so the fact row is the
product's own statement. rate_product therefore carries a std::variant of
the eight fact rows, and each constructor produces exactly one alternative, so
the legs and the fact cannot disagree about what the trade is.
The writer keeps the choice of constructor, because something has to read the recorded trade type, and loses the leg building, the per-product branches and the field-by-field copy.
5. Measurements
Every number this task claims about a tree, with the command that produced it
and the commit it was measured at. A number without both is not a measurement,
because a clean-up record describes a tree and trunk moves under a branch: a
consumer count, a gate's component count and a suite's size all change with no
code changing, and the reader of a bare number cannot tell which tree it came
from. Where the raw output matters, put it in an evidence/ file beside the
task and name that file in the Command column.
| What | Value | Command | Commit |
|---|---|---|---|
| Rate headers, legs, amounts, rates | 24, 48, 48, 48 | compass db sql on the rate and leg tables |
4d23ae5159 |
| Strikes, swap facts, FRAs, caps, swaptions | 3, 6, 3, 3, 3 | the same | 4d23ae5159 |
| Products booked | 8, three trades each | the same, grouped by trade type | 4d23ae5159 |
ores.trading.api.tests |
518 assertions in 138 test cases | the suite binary | 4d23ae5159 |
ores.synthetic.core.tests |
1741 assertions in 79 test cases | the suite binary | 4d23ae5159 |
6. Notes
7. Test Scenarios
Manual QA scenarios (scaffolded via compass add test_scenario)
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 |
|---|---|---|
8. PRs
| PR | Title |
|---|---|
| #4044 | [trading] Construct every rate product by name |
9. Review
| Comment summary | File | Decision | Notes |
|---|---|---|---|
10. Result
Every rate product the planner draws is constructed by a function that names it. The writer no longer builds legs or branches per product: it fills the terms, calls the constructor, stamps the audit columns and appends what it is given.
Proved by a provisioning run on a recreated database, against a baseline taken from the previous build: the population is identical on every count – 24 headers, 48 legs, 48 amounts, 48 rates, 3 strikes, 6 vanilla swap facts, 3 FRAs, 3 caps and 3 swaptions, over the same eight products at three trades each.
The suites are green: ores.trading.api.tests at 518 assertions in 138 test
cases with eight new rate cases, and ores.synthetic.core.tests at 1741
assertions in 79.
11. What the constructors now refuse that nothing did before
- a leg without a currency, a day count, a business day convention or a payment frequency;
- a floating leg without an index;
- a rate product whose legs state no positive notional;
- a cross currency swap whose legs state the same currency;
- a cap or floor with no strike, which previously booked and paid nothing;
- a knock out swap whose barrier type is outside ORE's closed set;
- a swaption without an expiry, or with an exercise or settlement type the table refuses.