Story: Synthetic generation configuration and config-driven feeds

Table of Contents

This page documents a story in Sprint 21. It captures the goal, current status, acceptance criteria, and the tasks that compose it.

The producer half of the Market Data Architecture: ores.synthetic owns how synthetic data is generated, as a persisted, party-scoped, named configuration, and generates from it autonomously.

Goal

Replace the PoC's transient, boot-time, system-tenant generation with a proper producer: a persisted synthetic generation config in ores.synthetic that a user authors, and a service that generates from it autonomously and publishes on its own namespaced channel — stamping the config's tenant and source name so the data is correctly owned and traceable.

Status

Field Value
State DONE
Parent sprint Sprint 21
Now Complete. Library data task deferred to sprint 22.
Waiting on Nothing.
Next Nothing.
Last touched 2026-07-02

Acceptance

  • A persisted synthetic config exists in ores.synthetic: a container (synthetic_config: tenant, party, name/source, enabled) and a typed FX spot sub-config (GMM params, ore_key, tick mode/rate) linked by a real foreign key, party/tenant-scoped. (P1)
  • CRUD + NATS protocol (list/get/save/delete) for the config, authenticated. (P1)
  • A Qt UI creates/edits/lists configs scoped to the logged-in tenant/party; a config cannot be created without it. (P2)
  • The synthetic service loads enabled configs (replacing the boot-time system-tenant bootstrap) and generates autonomously, stamping every observation with the config's tenant and source name. (P3)
  • Generation publishes ticks to a producer-namespaced channel (synthetic.v1.tick.<key>); the per-tick observations.save is removed (persistence moves to marketdata — see the feed-binding story). (P4)
  • A business-tenant/party login sees only its own configs and its own data.

Tasks

Task State Start End Description
Synthetic config entities across all layers (currency pattern) DONE 2026-06-28 2026-06-28 Hand-write the synthetic generation config domain model — synthetic_config (container), synthetic_fx_spot_config (sub-config, FK to container), synthetic_gmm_component (FK to sub-config) — across every layer, mirroring the currency reference entity (and book for FKs) so they convert to codegen types later: domain type + json_io + table_io + table, generator, repository (entity/mapper/repository), NATS protocol, SQL (create/triggers/notify), service, handler, eventing, CMake + registrar wiring.
Qt config UI for synthetic market data generation configs DONE 2026-06-28 2026-06-29 Qt client UI to create/edit/list/delete the synthetic market data generation config entities (container + fx_spot sub-config + gmm components), mirroring the currency Qt setup exactly: table model, list window with pagination, create/edit dialogs, history view, controller, and plugin menu/toolbar wiring.
Synthetic FX spot library: 30 pairs with historically-consistent starting spots BACKLOG Pre-canned library data bundle covering the 30 benchmark FX spot pairs (G10 + key EM vs USD) that seeds the CRM. Each config carries a GMM starting spot consistent with a single reference date t (2024-01-02). Apply is idempotent.

Decisions

  • Modelled per Polymorphic types over NATS: a discriminated container with one typed sub-config struct + subject per concrete type; never a JSON blob.
  • Provenance is via the source name; market data stays tenant-scoped (no party column) — see cross-rates matrix for the wider model.

Out of scope

  • Marketdata feed binding, ingestion and the official stream (separate story).
  • The source-agnostic control panel (separate story).
  • CRM derivation and correlations (backlog).

Result

Config entities (synthetic_config container + synthetic_fx_spot_config sub-config + synthetic_gmm_component) delivered across all layers. Qt CRUD UI delivered. Config-driven autonomous generation running per-config. Library data task (30 benchmark pairs) deferred to sprint 22.

Emacs 29.3 (Org mode 9.6.15)