ores.marketdata.market_observation
Table of Contents
A single market data observation: the value of a series at a given
observation_datetime and point_id (tenor/surface coordinate).
observation_datetime is the financial valid-time (UTC); valid_from=/=valid_to
is the transaction time. Corrections replace the previous value via the
soft-update trigger.
TimescaleDB hypertable partitioned by observation_datetime with 30-day chunks;
GIST exclusion and DELETE RULEs are incompatible with hypertables — uniqueness
is enforced via partial unique index and the soft-update/soft-delete trigger pair.
No audit trail columns (version, modified_by, performed_by, change_reason_code, change_commentary) — tick-level data volumes make these impractical.
1. Flags
2. Columns
2.1. id
Surrogate UUID uniquely identifying this observation row.
2.2. party_id
Party that owns this observation.
Set server-side from the authenticated session. Enforced by RLS.
ctx.generate_uuid()
2.3. series_id
Reference to ores_marketdata_market_series_tbl(id) — identifies what was observed.
2.4. observation_datetime
Financial valid-time: when the market value was observed (UTC). Also the hypertable partition column.
ctx.past_timepoint()
2.5. point_id
Tenor or compound surface identifier (e.g. 1Y, 5Y/2Y/ATM, 0.03/10Y/2Y).
Every observation carries one. A series whose keys have no coordinate of
their own has a single point and names it explicitly – SPOT for an FX
rate, an equity or a commodity price, the empty string for a series with
no coordinate at all, such as a recovery rate. The value comes from
series_key_registry::default_point_for(), so it is a property of the
series type rather than something each producer decides.
2.6. value
Serialised market value (numeric string; format is series-type-specific).
std::to_string(faker::number::decimal<double>(0.0, 100.0))
2.7. source
Source tag identifying the producer channel that published this observation
(e.g. synthetic.v1.tick.fx_spot.eur-usd).
3. SQL
3.1. Flags
3.2. Checks
| expression |
|---|
| "value" <> '' |
3.3. Bitemporal natural keys
| column | nullable |
|---|---|
| series_id | false |
| observation_datetime | false |
| point_id | false |
3.4. Indexes
| name | columns | unique | current_only | where_extra |
|---|---|---|---|---|
| observations_current_uniq | tenant_id, party_id, series_id, observation_datetime, point_id | true | true | |
| observations_series_datetime | tenant_id, party_id, series_id, observation_datetime desc | false | false | |
| observations_tenant_datetime | tenant_id, party_id, observation_datetime desc | false | false | |
| observations_source | tenant_id, party_id, source, observation_datetime desc | false | false | source is not null |
| observations_series_point_datetime | tenant_id, series_id, point_id, observation_datetime desc | false | false |
4. Foreign keys
4.1. series_id
Every real caller lists observations scoped to one series (tick-level
volumes make an unfiltered list impractical) — generates a dedicated,
paginated list_by_series_id endpoint (protocol/repository/service/
registrar) instead of an optional filter bolted onto the generic
.list endpoint. Default page size is 1000 (vs the usual 100):
market data is high-volume tick data, not user-managed reference rows.
Ordered by observation_datetime desc (not the facet's usual primary-key
order): a fully random UUID id has no correlation to time, so the
default order would silently return an arbitrary subset rather than
the most recent observations whenever a series exceeds the page limit
— exactly the "most recent N" behaviour the hand-written override this
facet replaces used to provide, and the observations_series_datetime
index below exists specifically to serve this ordering.
5. C++
5.1. Flags
5.2. Repository
5.3. Domain includes
#include <boost/uuid/uuid.hpp> #include <chrono> #include <optional> #include <string>
5.4. Entity includes
#include <optional> #include <string>