Task: Generate the blotter's common-date view
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
The blotter reads one set of date columns across the rates family, from a view generated from the models rather than hand-written.
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-09 |
3. Acceptance
- A common-date view exists, generated from the family's models, mapping each product's dates to the common names.
- A query over the view reads one date column across the rates family, including a FRA whose date is stated as an end date and a swaption whose dates describe its underlying swap.
- A later family adds its mapping by declaring it on its models, with no hand-written edit to the view.
- A generated test proves the mapping names the columns the models declare.
4. Plan
- The mapping is a property of the models. Declare, on each product model, which of its columns states which common date; do not write the mapping in the view by hand.
- Generate the view from those declarations, as the rest of the schema is generated, so a later family adds its mapping by declaring it.
- The common names. Trade date, start, expiry and maturity. The rates family is the first to map: a FRA states its maturity as an end date, and a swaption states its underlying swap's dates, so both are cases the mapping must get right rather than the easy rows.
- The test. A generated test asserts the view's columns are the ones the models declare, and a query reads one date column across the whole family.
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 |
|---|---|---|---|
| Rows the rates view returns for a FRA and a swaption | 2: the FRA reads trade, start and maturity dates, the swaption reads its expiry | ./compass.sh sql -- -f the probe evidence/common_dates_probe.sql (rolled back) |
dea34a04e8 |
| Tests that hold the mapping to the models | 8 passed, with the 6 catalogue tests | projects/ores.codegen/venv/bin/python -m pytest projects/ores.codegen/tests/test_common_dates.py projects/ores.codegen/tests/test_trade_type_catalogue.py |
dea34a04e8 |
| Codegen drift, component trade | none | check_component_drift.py --component trade |
dea34a04e8 |
6. Notes
- Unblocked by unit 3: the header is the one row per rates trade the view reads its common dates from, which is why the view could not exist before it.
- It depends on no later unit and can run at any point after unit 3.
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 |
|---|---|
| #3076 | [trading,codegen] Generate the blotter's common-date view |
9. Review
| # | Comment summary | File | Decision | Notes |
|---|---|---|---|---|
| 1 | PR text says 8 new tests, the file has 6 | test_common_dates.py | Accept | The text was wrong: 14 passed was 6 new and 8 existing. The PR body is corrected. |
| 2 | Loader refusals have no tests | test_common_dates.py | Accept | Added tests on a temporary tree for each refusal and for a generated view. |
| 3 | Duplicate-name check ran after the shared lookups | org_loader.py | Accept | Moved before the lookups. |
| 4 | Bare next() raises StopIteration | org_loader.py | Accept | Replaced by a lookup the catalogue already validated. |
| 5 | Cascade tables skip silently | org_loader.py | Accept | Added a comment. |
| 6 | Trailing blank line in the generated SQL | template | Decline | Cosmetic, and the drift check holds it. |
| 7 | Tests pin the current vocabulary | test_common_dates.py | Decline | The pin makes a new family edit the test on purpose. |
| 8 | A missing booking reads as null | trade_type_catalogue.org | Accept | The Common dates text says so. |
10. Result
The rates family now has a generated view, ores_trading_rate_instruments_common_dates_vw.
It gives the deal grid four date columns, trade_date, start_date,
expiry_date and maturity_date, whatever name a product states a date under.
- The vocabulary is in the catalogue. A new
* Common datestable inores.trading.trade_type_cataloguelists the four names.trade_datehas an owner outside every family, so the table names the entity and column that hold it:trade_booking.trade_date. - The mapping is on the models. A column declares
:common_date: <name>. The rates header declaresstart_dateandmaturity_date. The swaption fact declaresexpiry_date. A FRA states its end date as the header'smaturity_date, as unit 3 decided. A swaption's header dates are the underlying swap's, and they read as null when the document does not carry them. - The view is generated. The loader reads the declarations from each
routed header and the tables its
* Delete cascadenames. Two new archetypes in theores.sql.trade_typefacet write the create and the drop script. A later family declares:common_date:on its columns and gets its own view, with no edit to a view. - The loader refuses a bad mapping. It fails on a name outside the vocabulary, a date stated twice in one family, a name the catalogue holds elsewhere, and a column in a table that is not keyed by the trade alone.
- Test.
test_common_dates.pyholds the view's columns to the columns the models declare, and holds the committed SQL to the loader's output.
Not done: the view has no C++ reader yet, and no ER diagram shows it.