Task: Model the unmodelled trading families and bind the unbound
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
Close the gap between what the component persists and what its models describe. This is item group M. Three things are missing: entities with a table and no model, entities with a model and no profile binding, and types the model declares in a shape the database should not hold.
The last of these is the sixteen-defect investigation
doc/agile/versions/v0/sprint_25/ore_trade_generator_trade_populations/trade_model_defects.org,
whose model-shape defects belong here. Defect 11 and defect 12 belong
to the reference-data work and are out of scope, per decision D5.
2. Status
| Field | Value |
|---|---|
| State | BACKLOG |
| Parent story | Clean ores.trading to the component clean standard |
| Now | Not yet started. |
| Waiting on | PR 2 merged, so the model work starts from a drift-clean tree. |
| Next | Bind the 26 unbound entities, then author the seven missing models. |
| Last touched | 2026-09-26 |
3. Acceptance
- Every entity model binds a profile, or records a no-match with its feature values and the reason. Twenty-six of fifty-seven bind none today: the fourteen bond family entities, the seven instrument child entities and the five trade envelope and party entities.
- The tables that have no model have one:
commodity_instruments,composite_instruments,composite_legs,credit_instruments,scripted_instruments,swap_legsandproduct_type. Each regenerates, and the drift dry run stays empty with it included. - Every hand-written domain type with no model is classified as a model to author, a message that is not an entity, or infrastructure, and the classification is recorded. Twenty-four are in that state today.
- M04 is checked per model: each feature sits in the namespace the loader reads, and regeneration shows the change it should.
- M09 passes: no presentation drawer, no property naming a retired
message type, no dead history property, and the twenty-five singular
generator_facet_namevalues are corrected. The scheduler pass recorded that all twenty-five remaining instances are in ores.trading. - The type defects close at the model level: defect 1 JSON-text collections, defect 2 dates held as text, defect 3 amounts held as double, defect 4 free-text enumerations, defect 5 code fields with no reference table, defect 6 one concept under two names, defect 8 enumerations enforced in PL/pgSQL, and defects 14, 15 and 16, which are shapes the model cannot express today.
- Every generator defect found is fixed at its source with a regression test in the codegen suite.
check_component_drift.py --component trading-cpp --dry-runreports nothing after the work, andcheck_model_drift.py --summaryreports no drift.
4. Plan
4.1. 1. Bind the unbound entities
Choose a profile or record a no-match for each of the 26. The bond
family is the large group: bond_issue and its children are shared
static data rather than per-trade records, so a profile built for a
per-trade instrument is the wrong bind, and a forced nearest bind is not
allowed. Where no profile fits, record the entity's actual feature
values and the reason, as item M02 requires.
4.2. 2. Author the seven missing models
Five families have a table, a repository, a service, a handler and SQL,
and no model at all: commodity, composite with its legs child table,
credit, scripted, and the shared swap legs table. product_type is the
seventh, and its current shape is a database enum on the trades table
rather than an entity, which is defect 10.
Use the established entity org format. The bond family from the sprint
25 pilot is the worked example. swap_legs needs a decision the sprint
25 analysis left open: a shared table with one model, or one per
family. Record the decision on the story before authoring it.
4.3. 3. Classify the unmodelled hand-written domain types
Twenty-four hand-written domain types have no model:
activity_type, fpml_event_type, commodity_instrument,
composite_instrument, composite_leg, credit_instrument,
scripted_instrument, swap_leg, product_type,
rates_instrument_variant, equity_instrument_variant,
fx_instrument_variant, instrument, instrument_identity,
instrument_payload, trade_instrument, trade_audit,
trade_classification, trade_envelope_data, trade_identity,
trade_lifecycle, trade_parties, bond_instrument_data and
bond_schedule_data.
Some become models in step 2. Some are messages, and item M05 says a joined or denormalised shape is a message rather than an entity: the instrument variants, the payload and the container are the candidates. The rest are infrastructure with a recorded reason. No type is left unclassified, and none is deleted from this PR.
4.4. 4. Clear the legacy fragments
grep -rn "Presentation" projects/ores.trading/modeling/ grep -rn "generator_facet_name" projects/ores.trading/modeling/
Five models carry a presentation drawer: trade, lifecycle_event,
party_role_type, trade_id_type and trade_type. Twenty-five models
name the generator facet in the singular. Fix both in the models and
regenerate; do not edit the generated output.
4.5. 5. Close the type defects
Work them in the order the investigation gives, because each makes the
next smaller. Defects 2, 3, 4 and 6 are item M08: SQL type spellings
must be canonical, flags must be booleans, and one concept must have one
name. Defect 5 is a _code suffix with no reference table behind it,
so either the table is created or the suffix is dropped. Defect 1 is a
collection held as JSON text; where the collection is a keyed child row
under the relational rule, model it as one. Defect 8 moves twenty-seven
enumeration checks out of trigger functions and into the schema.
Defects 14, 15 and 16 need a shape the grammar may not express today:
declared coverage, a qualified underlying rather than a free-text name,
and an observation schedule rather than two scalar dates. If the
grammar cannot express one, record it as a generator defect with a
failing regression test rather than forcing the tree.
4.6. 6. Regenerate and prove
Regenerate the component and re-run the dry run twice. Every new entity must leave the tree byte-identical. Then run the codegen suite.
projects/ores.codegen/venv/bin/python -m pytest projects/ores.codegen/tests -q projects/ores.codegen/venv/bin/python projects/ores.codegen/scripts/check_component_drift.py --component trading-cpp --dry-run
4.7. 7. Record
Update the story's checklist rows for M02, M04, M05, M08 and M09.
5. Notes
- The sprint 25 design analysis is a September 8 snapshot of 38 orgs. This component has 65. Read the design for the shape of each family, not for its counts.
- The trade model investigation measured its defects by loading every table, so its figures are reproducible. Its per-family detail for equity shows how to do the same for bond.
- Two models under
core/modeling/are not entity models:ores.trading.protocol.orgnames four trade subjects in prose, andtrade_status_fsm_implementation.orgdescribes an FSM. Neither is a codegen model and neither belongs in the B02 census. ores.trading.module.orglistsleg_typeandfloating_index_typeas trading entities after the move to ores.refdata. Correct it here.- Missing reference tables (defect 5) may need reference data from another component. If so, record the dependency rather than inventing rows here.
6. Test Scenarios
| Scenario | State | Notes |
|---|---|---|
7. PRs
| PR | Title |
|---|---|
| Model the unmodelled trading families and bind the unbound |
8. Review
| Comment summary | File | Decision | Notes |
|---|---|---|---|