Task: Carry the FX money digits across the ORE boundary
Table of Contents
This page documents a task in the Rework the FX instruments to the instrument table rule story. It captures the goal, current status, acceptance, and any notes or results.
1. Goal
Make every FX money value keep the digits the ORE document wrote. Today each
FX money leaf is a plain float in the binding, so the XML parse discards the
text and the mapper's exact_decimal call takes the from_double overload.
The stored decimal is therefore the binary float's spelling, not the document's
number.
This unit comes first because it moves the goldens.
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Rework the FX instruments to the instrument table rule |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-10-16 |
3. Acceptance
- Every FX money leaf in the binding is a lexical leaf, and each one is patched by
scripts/reapply_ore_lexical_form.py, never by hand. - The script handles a required plain
floatmember, or it refuses the shape with a stated reason. Today it handlesxsd::optional<float>only, and most FX money members are required. - Every FX money field that has a continuous sibling stays a binary float. A variance strike, a ratio and a quantity are not money.
- The forward mapping reads each money leaf with the
xsd::base<T>overload ofexact_decimal, and the reverse mapping writes each one withset_exact. - A mapper test holds the digits of each money member: a value with more significant digits than a float carries survives the round trip.
- No golden that changes has a non-numeric change.
4. Plan
- Classify every FX binding member as money or continuous, with the exact-money rule of the data-oriented design page.
- Extend
scripts/reapply_ore_lexical_form.pyto a required member, with a self-test for the new shape. - Add the FX money members to the script's table and run it. Check the diff by hand: the struct, the getter, the element info and the serializer of each member.
- Replace the reverse casts with
set_exact. - Add the digit tests, then regenerate the goldens and read every changed line.
- Run the ORE core and trading core suites, and the codegen tests.
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 | |
|---|---|---|---|---|
| FX money members made lexical leaves | 23 | grep -c 'domain::moneyFloat' projects/ores.ore/core/include/ores.ore.core/domain/domain.hpp is 29: the FRA pair, the four credit members and these 23 |
the PR head | |
| Money members the script patches | 27 | =grep -cE '^ \("[a-zA-Z0-9_]+", "[a-zA-Z0-9_]+", "(required\ | optional)"\),$' scripts/reapply_ore_lexical_form.py= | the PR head |
| Goldens changed | 3, one numeric line each | git diff --stat -- assets |
the PR head | |
| ORE core suite | 668 cases, 483,175 assertions, all pass | ores.ore.core.tests with the .env loaded |
the PR head | |
| FX suite | 33 cases, 182 assertions, all pass | ores.ore.core.tests "[fx]" |
the PR head | |
| Reapply script self-tests | both pass | scripts/reapply_ore_lexical_form.py --self-test and --self-test-missing-anchor |
the PR head | |
| Local checks | 51 of 52, format and both drift checks pass | compass check --exclude-heavy |
the PR head |
6. Notes
- The evidence for this task is Investigation: FX family data model review, finding 1. Measured there: 35
exact_decimalcall sites infx_instrument_mapper.cpp, 0set_exactsites, and 6 money leaves carrying the lexical form in the whole tree. - The credit task Carry the credit instruments' digits is the template for the shape of this unit.
- The lever was broken before this unit started. The nightly clang-format run reflowed
_moneyFloat_Infoindomain.cpp, and the script's byte-exact "already applied" test then reported a half-applied patch and refused to run. Its own--self-testfailed onmain. The script now recognises a patch modulo whitespace, writes the declaration where the earliest user needs it rather than inside the FRA edit, and runs clang-format over what it writes. Both self-tests pass again. - The reach is wider than the family. The leaf types are shared, so the commodity and equity variance-swap mappers and the equity accumulator and TaRF mappers now write their money with
set_exact. Their goldens do not change; the three that do are the FX digital option, the FX digital barrier option and the exotic FX TaRF, one numeric line each. - Two money members are deliberately left for other units:
barrierData_Levels_t.Levelis a vector, so the script does not yet patch it, andrangeBoundis the accumulator's encoded child, which the range-bounds unit removes.
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 |
|---|---|
| #3392 | [ore] Carry the FX money digits across the ORE boundary |
9. Review
| Comment summary | File | Decision | Notes |
|---|---|---|---|
10. Result
The FX family now carries the digits its documents state. 23 money members
across the seven products are lexical leaves, the reverse mapping writes them
with set_exact, and a mapper test holds a 16-digit amount through both
directions. The ORE core suite passes: 668 cases, 483,175 assertions.
The unit also repaired the lever it depends on. reapply_ore_lexical_form.py
could not run on main at all, because the nightly format run had reflowed one
of its anchors and its own self-test failed. It now recognises a patch modulo
whitespace, places the leaf declaration before the earliest user rather than
inside the FRA edit, and formats what it writes.
Three goldens changed, one numeric line each, and the whole diff was read. The
reach of the shared leaf types was checked: the commodity and equity variance
swaps and the equity accumulator and TaRF map their money with set_exact now,
and their goldens do not move.
Left for other units: the barrier level vectors, which the script does not yet patch, and the accumulator's encoded range bounds, which its own unit removes.