Task: Collapse the instrument identity into the trade and split the bond security
Table of Contents
This page documents a task in the Clean ores.trading to the component clean standard story. It captures the goal, current status, acceptance, and any notes or results.
1. Goal
Give the component two identities where it carries three, and give the database the relationships the schema can hold. This is item M05 and the identity half of M07, and it implements decision D2: the trade id identifies the trade and its instrument, and the security issue is a separate reference datum.
The rule is already written down.
doc/knowledge/architecture/trade_modeling.org says that the economic
terms belong to one agreement, that the trade and instrument
relationship is one to one, and that "the trade id identifies both".
doc/knowledge/domain/trade.org names the four entities: the product
type, the security issue where one exists, the trade, and the
instrument carrying the economic terms.
The code disagrees. instrument_identity_field_group.org declares
instrument_id as a key and trade_id as an optional soft
back-reference, and 26 models inherit the group. trade adds a second
nullable pointer back at the instrument. The declaration carries 91
instrument_id columns and no foreign key targets an instrument table,
so the two directions of a one-to-one relationship are two nullable
pointers that nothing can make agree.
This re-opens two tasks the sprint 25 story abandoned:
trading_model_cleanup task 7B23DB0F, collapse the instrument
identity into the trade, and task 0C525D24, split the bond security
from the trade. The order is the order the abandoned split task gave:
collapse first, because the reverse reshapes the same tables twice.
2. Status
| Field | Value |
|---|---|
| State | BACKLOG |
| Parent story | Clean ores.trading to the component clean standard |
| Now | Not yet started. |
| Waiting on | PR 3 merged, so every family has a model to reshape. |
| Next | Model the collapse, regenerate, then split the security. |
| Last touched | 2026-09-26 |
3. Acceptance
instrument_idis gone frominstrument_identity_field_groupand from every entity that inherits or references it.trade.instrument_idis gone, so the two directions of a one-to-one relationship cannot disagree.- Instrument tables are keyed by
trade_id, not null, with a real foreign key to the trade rather than a soft link. - An instrument with no real trade is a trade of a reserved type, so there is one shape rather than two.
- The bond security split follows: the shared entities are keyed by the
ORE reference datum id, which is SecurityId for a bond and
ContractName for a bond future;
bond_futurekeeps only what ORE keeps on the trade;bond_legand its rate, amount and amortization children hang off the security;bond_issuegains the fields ORE has and we lack, and losesbond_notional, which ORE holds on the trade; and the fields duplicated against the leg tables are held once. - Defect 7 of the trade model investigation closes: the schema declares the relationships it enforces, instead of 866 check constraints and no foreign keys.
- Defect 9 closes or is recorded: five equity tables hold two products
each behind a
trade_type_codediscriminator. - Defect 10 closes or is recorded:
product_typestops being a database enum on the trades table and becomes the modelled entity. - Defect 13 closes: one key name for an instrument's identity.
- A trade that states its bond inline rather than by reference still round-trips, so the ORE round trip stays at zero loss across the bond products and the trade envelope.
check_component_drift.py --component trading-cpp --dry-runreports nothing, and the four suites pass.
4. Plan
4.1. 1. Model the collapse
instrument_identity_field_group is the leverage point. It declares
instrument_id, trade_type_code, party_id and trade_id, and 26
models inherit it. Removing instrument_id there and making trade_id
the non-nullable key carries most of the change. The remaining entities
keyed on instrument_id are the per-product and child tables. The
sprint 25 analysis counted 47 of them; re-count at this head, because
PR 3 adds more.
trade.instrument_id goes with it. The link becomes the child's
trade_id, and a real foreign key replaces the soft one.
4.2. 2. Sequence so nothing breaks in the middle
Model first, then regenerate, then the hand-written callers, then the SQL. No commit removes a column before its replacement exists. The component audit runs before the task closes.
4.3. 3. Split the security, after the collapse
Apply the split plan from the abandoned task, which is written against ORE's schema rather than invented:
bondReferenceDatumis exactlybondDataminusSecurityId,BondNotional,PayerandCreditRisk. Everything else on a bond is static data about the security, and the four exceptions are the trade's own: which security, how much, which side, and whether credit risk applies.- The key is the datum id, so a bond's is its
SecurityIdand a bond future's is itsContractName. No entity needs the words "reference data" in its name;bond_issueis already the shape to follow. bond_issuegains the six fields ORE has and we lack, and losesbond_notional.- A trade may state its bond inline or by reference. Normalising on the security is right, and the inline case then populates the security rather than bypassing it.
4.4. 4. Regenerate and repair the callers
Regenerate the component and the SQL, then repair every hand-written caller: the mappers, the readers, the import path and the shell commands. The ORE mapper and its container are hand-written and will need a pass.
4.5. 5. Prove
Run the ORE round trip through the shell over the bond documents and require zero loss. Then the whole-tree build, the four suites and the drift dry run.
4.6. 6. Record
Update the story's checklist rows for M05 and M07, and record the closure of defects 7, 9, 10 and 13.
5. Notes
- Two documents already describe this change and both are stale in
detail only. Read
trade_modeling.orgfor the rule and the abandoned task bodies7B23DB0Fand0C525D24for the plan; both are underdoc/agile/versions/v0/sprint_25/data-oriented-trading-model/. - The design's ER page names
ores_trading_schedules_tblwhile the code shipsinstrument_schedules. Reconcile the names in the same pass, or record the difference. - The design's
instrument_underlyingstable was never built. PR 5 owns that. trade_classification.hppcitesores_refdata_instruments_tblandtrade_identity_field_group.json, and neither exists. Correct the comments here.- The bond family's facts and legs are still per trade, so the security split is the largest part of the diff. If it cannot land in one PR with the collapse, stop after the collapse with the tree green and open a follow-up rather than leaving the component mid-reshape.
6. Test Scenarios
| Scenario | State | Notes |
|---|---|---|
7. PRs
| PR | Title |
|---|---|
| Collapse the instrument identity into the trade and split the bond security |
8. Review
| Comment summary | File | Decision | Notes |
|---|---|---|---|