Task: Unified tenor resolution: tenor_schedules, SCHEDULE_STEP resolver, RATES_SPOT_FOMC, 1F..nF
Table of Contents
This page documents a task in the FOMC-dated OIS short end: calendar-event model and flat-forward pillars story. It captures the goal, current status, acceptance, and any notes or results.
Goal
Implement the unified tenor resolution model from the FOMC analysis (story * Decisions D2): a tenor resolves as anchor + a calendar offset + n steps along a named schedule axis. Calendar arithmetic (ANCHOR_OFFSET) stays as-is; a new SCHEDULE_STEP algorithm walks a named schedule from the tenor_schedules vocabulary – ROLL_QUARTER (closed-form IMM rule, code-side) and FOMC_MEETING (event-lookup into US.FOMC / central_bank_meeting events). IMM and FOMC become the same mechanism; the old IMM_ROLL algorithm row is superseded.
Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | FOMC-dated OIS short end: calendar-event model and flat-forward pillars |
| Now | tenor_schedules modelled and codegen'd; SCHEDULE_STEP walk implemented in tenor_resolution.cpp; RATES_SPOT_FOMC + 1F..8F and CREDIT_CDS_IMM migration seeded; all three suites green. |
| Waiting on | Nothing. |
| Next | D4 (calendar seeding): the 2025-2027 meeting dates land on the calendar_event store. |
| Last touched | 2026-08-10 |
Acceptance
- tenor_schedules entity (ores.refdata, codegen'd): code, name, description, display_order, schedule_source, calendar_code, diary_entry_type; seeded ROLL_QUARTER (CLOSED_FORM) and FOMC_MEETING (EVENT_LOOKUP on US.FOMC / central_bank_meeting).
- tenor_resolution_algorithms gains SCHEDULE_STEP; tenor_resolution.cpp implements walk(anchor + calendar offset, schedule, steps) for both schedule sources; the old IMM_ROLL / ROLL_QUARTER logic_error paths are gone.
- tenor_convention_resolutions gains nullable schedule_code and schedule_step_count; offset columns remain the calendar-axis offset.
- RATES_SPOT_FOMC convention (measured_from SPOT, algorithm SCHEDULE_STEP, schedule FOMC_MEETING) with tenors 1F..nF (kind SPECIAL, unit NONE, multiplier n) and resolution rows schedule_step_count = n, resolving to the n-th meeting on-or-after spot.
- CREDIT_CDS_IMM migrates to (SCHEDULE_STEP, ROLL_QUARTER) with offset YEAR x 1 and 1 schedule step ('1Y 1RQ'); the IMM_ROLL algorithm row is removed from populate once nothing references it; the IMM_ROLL anchor (measured_from) stays.
- Unit tests cover both schedules (closed-form roll stepping and event lookup) plus the migrated CDS convention.
Plan
(Implementation strategy. Written when work starts; key decisions
are distilled into the parent story's * Decisions at close, but the
plan itself stays — it is the historical record of what we did.)
Notes
- Junction codegen clobbering (2026-08-10): re-running
codegen entity generateon a junction model overwrites the hand-authored messaging layer (protocol request structs, handlerlist, read-only service) with template stubs and drops the tenant profile when:profile:is a top-level keyword instead of a* Flagsdrawer property. Recovery procedure used here: move the profile into the* Flagsdrawer, regenerate, restore the four hand-authored files from HEAD, delete the generated junction sub-registrar (unreferenced; the aggregate registrar wires the junction inline per its own comment), and re-runregenerate_cmake_component_files.pyso the directory scan drops the dead entries. - The exhaustion test (9F > 8 meetings) initially passed vacuously:
std::invalid_argumentderives fromstd::logic_error, soCHECK_THROWS_ASmatched the wrong throw. The fixture fix (SPECIAL offset columns on the FOMC rows) makes the walk genuinely exercise the exhaustion path. - CREDIT_CDS_IMM '1Y 1RQ' semantics: this catalog's one-year label is
12M(MONTH x 12), not1Y; the migration rows use 12M, 2Y, 3Y, 5Y, 7Y, 10Y withschedule_step_count = 1.
Test Scenarios
Manual QA scenarios (scaffolded via compass add test_scenario, run
through the QA Validation Runner panel) 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 |
|---|---|---|
PRs
| PR | Title |
|---|---|
| #1933 | [refdata] D2: unified tenor resolution — tenor_schedules, SCHEDULE_STEP walk, RATES_SPOT_FOMC, CDS migration |
Review
| Comment summary | File | Decision | Notes |
|---|---|---|---|
Result
Done. The unified resolution model is implemented end to end and all three suites are green:
tenor_schedulesentity (code, name, description, display_order, schedule_source, calendar_code, diary_entry_type) modelled viacompass add entity_org, codegen'd across api/core/service/qt/sql; seededROLL_QUARTER(CLOSED_FORM) andFOMC_MEETING(EVENT_LOOKUP on US.FOMC / central_bank_meeting).tenor_resolution_algorithmsgainsSCHEDULE_STEP; the oldIMM_ROLLrow is removed and theROLL_QUARTERlogic_error path inadd_offsetis gone.tenor_resolution.cppimplements the walk: anchor + calendar offset- n steps.
ROLL_QUARTERsteps are closed-form IMM dates (first
business day on-or-after the 20th of Mar/Jun/Sep/Dec, code-side);
FOMC_MEETINGsteps walk caller-supplied event dates. Missing schedule fields or exhaustion report asstd::logic_error; unrecognised algorithms asstd::invalid_argument.- n steps.
resolve_end_dategains a defaulted optional schedule-dates parameter; all existing callers compile unchanged.tenor_convention_resolutionsgains nullableschedule_code/schedule_step_count;RATES_SPOT_FOMC(SPOT, SCHEDULE_STEP, FOMC_MEETING) seeds 1F..8F (SPECIAL, NONE x n, DAY x 0 offset, n steps);CREDIT_CDS_IMMmigrates to (SCHEDULE_STEP, ROLL_QUARTER) with anchor_override SPOT and one roll-quarter step ('1Y 1RQ').- Test updates: the two red SCHEDULE_STEP dispatch tests and the exhaustion test are green; a ROLL_QUARTER closed-form walk test and the migrated-CDS pinned-date test are added (74/74 refdata, 369 assertions); marketdata 24/24 (164) and quant 372/372 (2.1M) unaffected and green.
tenor_convention_resolution.orgprofile moved into the* Flagsdrawer, restoring the tenant_id column to entity, SQL and repository.