Task: Hold the FRA notional and strike as the document's digits
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
A FRA's notional and strike are stored as the exact decimal the document wrote, and the exporter writes the same digits back. 0.0065 is stored as 0.0065, not as 0.006500000134110451.
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 binding keeps the digits of the FRA notional and strike, through the reapply script, not by hand.
- The forward mapper stores the document's digits for both, and the reverse mapper hands them back.
- A mapper test holds the digits of a FRA strike and notional through the round trip.
- The golden files that change are regenerated and every changed line is a numeric leaf.
- The corpus proof and the ORE suite pass.
4. Plan
- The binding. Make the FRA's
StrikeandNotionala lexical leaf,moneyFloat, instead of a bare float. The change is made byscripts/reapply_ore_lexical_form.pyondomain.hppanddomain.cpp, so a regenerated binding keeps it. The script refuses to patch when an anchor is missing or not unique. - The mapper. The forward mapper already reads a lexical leaf through
exact_decimal, so it now stores the document's digits. The reverse mapper hands the stored digits back withset_exact. - Tests. Correct the FRA forward test, which pinned the float artifact, and add a test that the digits survive the reverse mapping.
- Goldens. Regenerate the one golden that changes and check that the change is numeric text only.
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 |
|---|---|---|---|
| FRA strike of IR_FRA.xml, stored | 0.005 (was 0.005 widened from a float) | ores.ore.core.tests mapper_roundtrip_fra_forward |
the PR head |
| ORE core suite | 649 cases, 482,966 assertions, all pass | ores.ore.core.tests |
the PR head |
| Golden files changed | 1 (IR_FRA.xml, one numeric line) | git diff -U0 -- assets |
the PR head |
| Reapply script self-tests | both pass on three files | scripts/reapply_ore_lexical_form.py --self-test and --self-test-missing-anchor |
the PR head |
6. Notes
- The binding has 152 bare float members. Only the FRA's two are changed here, because the FRA is the case that stored a wrong value. The others are not audited by this task.
- The new leaf is a plain
xsd::base<float>with its own setter, element info and serializer, so the existing leaf types are not touched.
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 |
|---|---|
| #3129 | [ore] Hold the FRA notional and strike as the document's digits |
9. Review
| # | Comment summary | File | Decision | Notes |
|---|---|---|---|---|
| 1 | The FRA forward test pinned the float artifact as the expected strike | xml_ir_mapper_roundtrip_tests.cpp | accept | It now expects the document's 0.005. |
| 2 | The serializer anchor for the FRA body occurs in two structs | reapply_ore_lexical_form.py | accept | The anchor starts at the FRA's Index line, and the script refuses a non-unique anchor. |
| 3 | The idempotence guard returns early when moneyFloat appears anywhere |
reapply_ore_lexical_form.py | accept | Every edit must be present or none; a partial state is refused. |
| 4 | A comment names a where element the edit tuples do not have |
reapply_ore_lexical_form.py | accept | Comment corrected. |
| 5 | Pin the serializer's fallback for a FRA built in code | reapply_ore_lexical_form.py | decline | The fallback is the shared get_string(float, lexical), which the a leaf set in code test already holds. |
| 6 | Check the serialized XML after the reverse mapping | xml_ir_mapper_roundtrip_tests.cpp | accept | The FRA digits test now writes the trade and checks <Strike>0.005</Strike>. |
| 7 | List the other bare float members in a follow-up | none | decline | Left to the operator; the Result states the scope. |
10. Result
A FRA's strike and notional are stored as the digits the document wrote and exported as the same digits. IR_FRA.xml states a strike of 0.005; the mapper stored the float nearest to it and the exporter wrote 0.00499999989. The binding now holds both members as a lexical leaf, through the reapply script, the mapper reads and writes the digits, and the one golden that changed holds the document's text.
Acceptance met: the binding keeps the digits through the script, both mapper directions carry them, a test holds them through the reverse mapping, the golden change is one numeric line, and the ORE suite passes.
Other bare float members of the binding are not covered, and no task is open for them.