Task: Prove the rates round trip over the corpus
Table of Contents
This page documents a task in the Rework the rates instruments to the instrument table rule story. It captures the goal, current status, acceptance, and any notes or results.
1. Goal
The family is proved at its new shape: the corpus round-trips with equal family rows, and the coverage the family lacked exists. No migration is written: the project recreates the database (see Decisions on the story).
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Rework the rates instruments to the instrument table rule |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-10-11 |
3. Acceptance
- The ORE round trip runs over the family's corpus at the new shape and every document comes back equivalent.
- No migration script exists, by the project rule that a schema change recreates the database.
- The eventing integration test for the rates instruments is generated, and the family's repository and service coverage exists where it had none.
- The round trip's documents and trades are recorded as measurements with their commands.
4. Plan
- The corpus round trip. Import every rates trade of the corpus, export it on its own, import it again and compare the family rows the two imports produce. Record the document and trade counts with the command.
- The eventing test. Generate the rates instruments' eventing integration test as the other entities' are generated.
- The coverage gap. Check the repository and service cases the family has. The generated eventing test of each table also writes a row, reads it through the service and updates it, so the ten tables have that coverage once the eventing tests exist. No further case was needed.
- Measurements. The corpus counts go in this page's Measurements table with their commands, as the header task's did.
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 |
|---|---|---|---|
| Rates documents in the corpus | 47 | ores.ore.core.tests "every rates trade in the corpus comes back as the same family rows" |
b50b0acba4 |
| Rates trades in those documents | 70 | same | b50b0acba4 |
| Documents whose family rows change on the round trip | 0 | same; the known-differences set is empty | b50b0acba4 |
| ORE core suite | 646 cases, 482,954 assertions, all pass | ores.ore.core.tests |
the PR head |
| Trading core suite | 152 cases, 1,080 assertions, all pass | ores.trading.core.tests |
c82f06be8a |
| Rates eventing tests | 10 added; 54 eventing cases pass in all | ores.trading.core.tests "[eventing]" |
c82f06be8a |
| Golden files regenerated for the digits change | 73 of 132 | ORES_BOOTSTRAP_GOLDENS=1 ores.ore.core.tests every_example_trade_round_trips_through_a_golden |
the PR head |
6. Notes
- The migration the plan first named is dropped. The project memory "no migrations, trash and recreate" says a schema change edits the create scripts and the database is recreated; the operator confirmed that for this unit.
- It is last because it proves a shape the other units settle; running it earlier would prove a tree that is about to change.
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 |
|---|---|
| #3117 | [ore,trading] Prove the rates round trip over the corpus |
9. Review
| # | Comment summary | File | Decision | Notes |
|---|---|---|---|---|
| 1 | The round trip dropped the leg day count and payment convention | swap_instrument_mapper.cpp | accept | Fixed in the reverse leg and the cap/floor reverse; found by the corpus test. |
| 2 | The nine fact-table eventing tests wrote with no session party | the nine fact models | accept | Each model declares party_scoped_writes; the tests are regenerated. |
| 3 | The rate instrument generator drew start and maturity independently | ores.trading.rate_instruments.org | accept | generator_expr makes the maturity the start plus 365 days. |
| 4 | The flexi header declared an unused <optional> |
ores.trading.flexi_swap_instrument.org | accept | Removed from the model; the header is regenerated. |
| 5 | A rates document that stops importing drops out of the walk unnoticed | xml_rates_corpus_roundtrip_tests.cpp | accept | The test pins 47 documents and 70 trades. |
| 6 | day_counter_count is a magic number |
swap_instrument_mapper.cpp | decline | It follows the neighbouring *_count constants, and the enum has no size sentinel. |
| 7 | parse_code falls back silently on an unknown code |
swap_instrument_mapper.cpp | decline | The pattern existed before this task; the corpus test catches a document that hits it. |
| 8 | REQUIRE in the loop leaves the scratch directory on failure |
xml_rates_corpus_roundtrip_tests.cpp | decline | The next run clears the directory first. |
| 9 | Confirm CI initialises external/ore |
xml_rates_corpus_roundtrip_tests.cpp | decline | The path is vendored in the repository, and CI does not run the tests. |
| 10 | After the rebase the swap leg rates differed on the round trip (0.0065 came back as 0.00650000013) | domain.cpp, swap_instrument_mapper.cpp | accept | Main made the rate an exact decimal. The writer printed a float with nine digits. The writer now prints a leaf's own digits, the reverse mapper and the stress mapper hand them over, and the goldens are regenerated. |
10. Result
The rates family round-trips over the whole ORE corpus. All 47 rates documents (70 trades) come back as the same family rows after an import, an export of the trade on its own and a second import. The comparison is of the rows the family stores, so a field the mapper drops shows as a difference. It found two losses, the leg day count and payment convention, and the mapper now carries both. The set of known differences is empty.
The ten rates tables have a generated eventing integration test. Each also writes, reads and updates a row through its service, which closes the repository and service gap. The generated tests exposed two defects, now fixed in the models: the fact tables lacked the session party, and the header generator could draw a maturity before the start.
No migration is written, by the project rule that a schema change recreates the database.
Acceptance met: the corpus round trip is equivalent, there is no migration, the eventing tests are generated, and the measurements carry their commands.
After the rebase onto main, which holds money as an exact decimal, the proof failed on 20 documents: the exporter wrote a rate as a nine-digit float, so 0.0065 came back as 0.00650000013. The exporter now writes the digits a leaf carries. The reapply script patches the generated writer, the rates and stress test reverse mappers set the digits on the leaves, and 73 golden files now hold the document's own digits. The FRA's notional and strike are bare floats in the ORE binding, so they carry no digits and are not covered. That is a separate defect, noted for a follow-up task. The new digits tests also found that a cap or floor strike was stored through a double, as 0.02500000037252903 for 0.025. It is now read from the document's digits.