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

  1. 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.
  2. Generate the view from those declarations, as the rest of the schema is generated, so a later family adds its mapping by declaring it.
  3. 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.
  4. 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 dates table in ores.trading.trade_type_catalogue lists the four names. trade_date has 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 declares start_date and maturity_date. The swaption fact declares expiry_date. A FRA states its end date as the header's maturity_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 cascade names. Two new archetypes in the ores.sql.trade_type facet 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.py holds 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.

Emacs 29.3 (Org mode 9.6.15)