Story: Record trade activities and trade links
Table of Contents
This page documents a story in Sprint 27. It captures the goal, current status, acceptance criteria, and the tasks that compose it.
1. Goal
Add trade_activity with its type, and trade_link with its type, so every component version names its cause and every relation between trades is typed and directed.
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent sprint | Sprint 27 |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-10-08 |
3. Acceptance
- Every component version carries a foreign key to the trade_activity that caused it; the activity type states the economic, confirmable and real axes and the priority.
- trade_link joins two trades with a type from trade_link_type, which names both roles and the economic effect.
4. Tasks
| Task | State | Start | End | Description |
|---|---|---|---|---|
| Give the activity type its axes and priority | DONE | 2026-10-05 | 2026-10-05 | Extend the trade activity type reference data with the economic, confirmable and real axes and the priority order the design states, so an activity says what kind of event it is. |
| Record each business event as a trade activity | DONE | 2026-10-05 | 2026-10-05 | Add trade_activity, an append-only record of each business event with its type, actor, time, comment and operational-error flag, and make booking a trade write one. |
| Point every component version at its activity | DONE | 2026-10-06 | Give the booking, state, identifier, party role, additional field, portfolio and instrument tables a foreign key to the trade_activity that wrote each version, replacing the bare activity type code. | |
| Join trades with typed links | DONE | 2026-10-08 | 2026-10-08 | Add trade_link (from trade, to trade, type) and trade_link_type, which names both roles and whether the link has an economic effect, seeded from the link catalogue including exercise and roll. |
| Book a trade through the repositories | DONE | 2026-10-06 | 2026-10-07 | Booking a trade writes the trade, its activity, its booking and its state with SQL inserts in ores_trading_book_trade_fn, bypassing the generated repositories. Give ores.database a unit of work so several repository writes share one transaction, move booking onto the repositories, and add an architectural rule, enforced by a check, that application code writes entity tables only through repositories. |
5. Decisions
5.1. The trade activity is a stamp, and a process run is not
Taken 2026-10-07 with the owner. Two records that had been read as one are separate. A trade activity is stamped on a trade amendment to say what the amendment was about, so risk buckets by amendment type; it stands alone and names no other trade. A process run records one execution of a process over a set of trades, with its inputs, its outputs and the time point it read them at, so the process can be undone or repeated. Where a process generates an amendment it stamps its own activity, and that match is incidental: nothing requires a stamp to point at a run, and most stamps have no run behind them.
The process run is its own subject and its own story: Trace a process run and the trade groups it creates. The three tasks that hung process structure off the activity moved there, and the story waits on one process with a real client.
- Trace a process run and the trade groups it creates — the run, its state machine and the trade groups, waiting on a pilot process.
- Trace a process run over a set of trades — the capture the run model is written down in.
- Implement the processes that act on sets of trades — the capture for building the processes themselves, one pilot at a time.
- Trade sets and trade groups — the primitive, the trade group a run creates, and the roles the process fixes.
- Trade set — the set a run reads and writes, and how its membership is resolved.
5.2. The create aggregators stay hand-written, and a check guards them
Taken 2026-10-08 with the owner. A component's `*_create.sql` names its table files in the order psql must run them, and a new entity means a new line in it. Nothing generates that file: all 22 aggregators are hand-written, no template emits one, and neither `compass add` nor `codegen regenerate` writes an include.
It is hand-written because the order is the content, and the order is not something a model states. An alphabetical include set cannot build the schema at all: in `create/trading/`, `trading_trade_identifiers_create.sql` and `trading_trade_links_create.sql` both sort before `trading_trades_create.sql` and both carry a foreign key to it. Nor is the order purely foreign keys: the product type discriminator enum must precede the tables whose columns use the type, and no key records that edge.
The cost showed itself in this story. Two link tables had create files that matched their models and that no aggregator named, so no database ever created them, and every other check passed. A check now walks the include directives from the schema entry points and fails on any create file nothing reaches. Generating the order topologically was considered and rejected: it would mean touching all 22 files and modelling the ordering edges that today live in comments, to save one line per entity.
6. Out of scope
7. Promoted from capture
Captured 2026-10-02 in the product backlog; promoted preserving the UUID.
7.1. Goal
Implement sections 4, 8 and 12 of the trade shape investigation: one activity per business event, acts as activities with participants, and pairwise typed links.
7.2. Status
| Field | Value |
|---|---|
| State | BACKLOG |
| Parent sprint | Sprint 26 |
| Now | Not yet started. |
| Waiting on | Nothing. |
| Next | Break the story into tasks. |
| Last touched | 2026-10-02 |
7.3. Acceptance
- Every component version carries a foreign key to the trade_activity that caused it; the activity type states the economic, confirmable and real axes and the priority.
- A process run names its inputs and outputs, and compression, merge, allocation, a roll or a sweep and a bulk book move record their own facts against the run. The trade activity is the stamp on an amendment, not the parent of either.
- trade_link joins two trades with a type from trade_link_type, which names both roles and the economic effect; successor_trade_id is gone.
7.4. Tasks
| Task | State | Start | End | Description |
|---|---|---|---|---|