ores.synthetic.fx_spot_generation_config

Table of Contents

A typed sub-configuration owned by a market_data_generation_config. Describes how to synthesise the tick stream for a single FX spot rate: which ORE market key it produces, the starting price, the tick cadence, and the price process. The price process is a Gaussian Mixture Model whose components are held separately as gmm_component rows. Scoped to a tenant and a party.

1. Flags

2. Columns

2.1. id

Surrogate UUID uniquely identifying this configuration.

2.2. party_id

Owning party (legal entity) this configuration belongs to.

uuid_gen()

2.3. config_id

Parent market_data_generation_config this sub-config belongs to.

uuid_gen()

2.4. base_currency_code

Base currency ISO code of the FX spot pair (soft FK to currencies).

std::string("EUR")

2.5. quote_currency_code

Quote currency ISO code of the FX spot pair (soft FK to currencies).

std::string("USD")

2.6. source_name

Stable source name carried as provenance of generated observations (e.g. "synthetic.eurusd"). Derived from the currency pair; unique per tenant and party.

std::string("synthetic.") + std::string(faker::finance::currencyCode())

2.7. oresmd_uri

The oresmd quote URI of the FX spot rate this feed produces (e.g. "oresmd://fx/EUR?type=quote&instrument=fx_spot&quote=rate&ccy=USD"). Derived from the currency pair; not entered directly. A feed built from the config reads it with the strict oresmd codec, and refuses a URI that is not an fx_spot quote or whose currencies differ from the base and the quote currency.

std::string("oresmd://fx/EUR?type=quote&instrument=fx_spot&quote=rate&ccy=USD")

2.8. price_source

Where this feed's initial spot price comes from: "fixed" (use gmm_initial_price as entered) or "fixing" (start from the first of the config's fx_spot_fixing_item rows that has a fixing, and size the mixture to the spread of its fixings, keeping gmm_initial_price when none has one). A fixing item is a pointer to observed data: a feed pinned to a past day names that day in the item's policy.

std::string("fixed")

2.9. calibration_window_days

Optional per-feed override of the class calibration window, in days. Empty means the feed follows its asset class's policy, or the 90-day default when there is no policy. It is the one per-feed exception that has nowhere else to live: a pinned item or an explicit item list is an fx_spot_fixing_item.

faker::number::integer(30, 180)

2.10. gmm_initial_price

Initial spot price the generated process starts from, > 0: the price a "fixed" feed starts from, and the level a "fixing" feed keeps when no item has a fixing.

faker::number::decimal(0.5, 2.0)

2.11. ticks_per_hour

Number of synthetic ticks produced per hour.

faker::number::integer(1, 3600)

2.12. process_type

Price-process engine: "geometric" (multiplicative), "arithmetic" (additive), or "ornstein_uhlenbeck" (Ornstein-Uhlenbeck, mean-reverting).

std::string("geometric")

2.13. enabled

Whether the configuration is active and eligible for generation.

faker::datatype::boolean()

2.14. auto_start

Whether this config starts automatically when the service comes up, as opposed to manual-start-only. Orthogonal to enabled: a config can be enabled=true, auto_start=false (valid, manually startable, but never auto-started – e.g. a legacy/alternate-index variant living alongside a currency's primary config so the two never silently fight over the same published qualifier at boot). Starting a feed – whether auto-start-at-boot or a manual Start – is rejected outright if another feed is already running for the same oresmd_uri; nothing auto-disables the running one, so switching requires an explicit Stop then Start.

faker::datatype::boolean()

2.15. folder_id

The folder this feed lives under (the instrument-type folder, e.g. "FX Rates", nested under an asset-class folder under this feed's owning collection). Real, queryable hierarchy position – not parsed out of source_name, which stays a display/NATS-subject string. Nullable for now: only the publish-from-dq path populates it; manual creation (the New FX Rate action) doesn't yet resolve/create folders – follow-up work.

std::nullopt

2.16. asset_class_code

The asset class the feed belongs to (soft FK to asset_class_code.code): Every FX spot feed is fx. A screen filters the feeds by it. The catalogue ores.refdata.asset_class_catalogue declares the codes.

std::string("fx")

2.17. arrival_mode

How the feed's ticks arrive. "periodic" gives equal gaps, "poisson" gives exponential gaps and "hawkes" gives gaps that cluster. The long-run mean rate is ticks_per_hour in every mode, so switching mode changes only how the same load is spread in time.

std::string("periodic")

2.18. branching_ratio

For "hawkes": how much one tick raises the rate of the next, as the expected number of further ticks. At least zero and strictly below one; one or more has no stationary rate and is refused. Ignored by the other modes.

0.0

2.19. decay

For "hawkes": how fast a burst fades, in units of one over a second, so a value means the same thing at any tick rate. Finite and strictly positive. Ignored by the other modes.

1.0

2.20. sensitivity

How strongly the market-wide arrival factor moves this row, where one is the average series and a value below one makes it calmer than the market. Finite and strictly positive. It does nothing until the market factor lands; a value of one leaves today's behaviour unchanged.

1.0

2.21. variance_model

How the feed's daily variance moves: "constant", the mixture's own variance on every day, or "gjr_garch", a GJR-GARCH(1,1) variance carried from one market day to the next that scales the mixture's shocks, with the shape of the approved calibration the config names. "gjr_garch" needs an engine that can scale its law, geometric or arithmetic.

std::string("constant")

2.22. variance_calibration_id

For "gjr_garch": the approved variance_calibration the feed runs. Naming it here makes each change of calibration a new version of the config, so the feed's history shows when every calibration came into use; approving a later calibration of the pair re-points the feeds that named the earlier one. A feed whose calibration is no longer approved does not start, and says why.

std::nullopt

3. Artefact columns

The synthetic feed import carries one denormalised row per FX spot feed: the parent generation config's own fields beside the FX spot sub-config's. The parent's uuid is made when the row publishes, so the import carries the row's own id instead.

3.1. id

3.2. version

3.3. name

3.4. description

3.5. enabled

3.6. auto_start

3.7. base_currency_code

3.8. quote_currency_code

3.9. gmm_initial_price

3.10. ticks_per_hour

3.11. process_type

3.12. price_source

3.13. provider_code

3.14. arrival_mode

How the feed's ticks arrive: periodic, poisson or hawkes.

3.15. branching_ratio

For hawkes: the expected number of further ticks per tick, below one.

3.16. decay

For hawkes: how fast a burst fades, per second.

3.17. sensitivity

How strongly a market-wide regime moves this row, where one is the average.

3.18. variance_model

How the daily variance moves: constant or gjr_garch.

3.19. garch_alpha

For gjr_garch: the reaction to a day's move. The four GARCH columns are the authored shape the publish installs as the pair's approved calibration, when the pair has none; the live config names that calibration instead of holding them.

3.20. garch_gamma

For gjr_garch: the extra reaction to a fall.

3.21. garch_beta

For gjr_garch: the carry-over of a day's variance.

3.22. garch_window_days

For gjr_garch: the days of fixings the fit reads.

4. Artefact indexes

4.1. base_currency_code

4.2. quote_currency_code

5. SQL

5.1. Flags

5.2. Checks

expression
"base_currency_code" <> ''
"quote_currency_code" <> ''
"base_currency_code" <> "quote_currency_code"
"source_name" <> ''
"source_name" like 'synthetic.%'
"oresmd_uri" like 'oresmd://fx/%?type=quote&instrument=fx_spot&quote=rate&ccy=%'
"ticks_per_hour" > 0
"process_type" in ('geometric', 'arithmetic', 'ornstein_uhlenbeck')
"price_source" in ('fixed', 'fixing')
"gmm_initial_price" > 0
"calibration_window_days" is null or "calibration_window_days" between 2 and 180
"variance_model" in ('constant', 'gjr_garch')
"variance_model" <> 'gjr_garch' or "process_type" in ('geometric', 'arithmetic')
"variance_model" <> 'gjr_garch' or "variance_calibration_id" is not null

6. Foreign keys

6.1. config_id

6.2. folder_id

6.3. variance_calibration_id

7. Insert trigger

7.1. Validations

column validation_function
asset_class_code ores_refdata_validate_asset_class_code_fn

8. Validation function

9. C++

9.1. Flags

9.2. Repository

The installation's system collections, their feeds and the provider catalogue ship under the system tenant, and every tenant reads them, which :system_tenant_visible: true states on the repository. The row-level security policy still decides which system rows a tenant sees and who may write them.

9.3. Domain includes

#include <boost/uuid/uuid.hpp>
#include <string>

9.4. Entity includes

#include <string>

9.5. Conventions

9.6. Table display

column header
base_currency_code Base
quote_currency_code Quote
source_name Source
oresmd_uri oresmd URI
price_source Price Source
ticks_per_hour Ticks/Hour
enabled Enabled
modified_by Modified By
version Version

9.7. Presentation

9.7.1. Detail fields

field label widget type is_key is_required placeholder
base_currency_code Base Currency baseCurrencyEdit line_edit   true Enter base currency code
quote_currency_code Quote Currency quoteCurrencyEdit line_edit   true Enter quote currency code
price_source Price Source priceSourceEdit line_edit   true fixed, or fixing
gmm_initial_price Initial Price gmmInitialPriceEdit line_edit     Required if Price Source is fixed
ticks_per_hour Ticks per Hour ticksPerHourEdit spin_box   true  
process_type Process Type processTypeEdit line_edit   true geometric, arithmetic, or ornstein_uhlenbeck
enabled Enabled enabledCheck check_box      
auto_start Auto-Start autoStartCheck check_box      

9.7.2. Columns

formatter is optional: a free function formatter(field) returning the rendered string, called instead of the type's built-in renderer — for a column whose raw value needs a friendly label (e.g. ProcessType's "geometric""ornstein_uhlenbeck" code becoming "Geometric Brownian Motion""Ornstein-Uhlenbeck"). Leave blank to use the plain type renderer. formatter_include names the header the formatter function needs, if any.

enum_name field header type width formatter formatter_include
BaseCurrencyCode base_currency_code Base Currency string 100    
QuoteCurrencyCode quote_currency_code Quote Currency string 100    
SourceName source_name Source Name string 180    
OresmdUri oresmd_uri oresmd URI string 180    
PriceSource price_source Price Source string 100    
GmmInitialPrice gmm_initial_price Initial Price double 100    
TicksPerHour ticks_per_hour Ticks/Hr int 80    
ProcessType process_type Process Type string 100 processTypeLabel  
Enabled enabled Enabled bool 70    
AutoStart auto_start Auto-Start bool 80    
Version version Version int 70    
ModifiedBy modified_by Modified By string 120    
RecordedAt recorded_at Recorded At timestamp 150    

9.7.3. Icon columns

Base and quote currency each get their own flag icon, same as any other single-currency cell (e.g. Currency's own code column) — no compositing needed since they're separate columns.

column accessor field1 field2
BaseCurrencyCode currency_flag_icon base_currency_code  
QuoteCurrencyCode currency_flag_icon quote_currency_code  
if (index.column() == ProcessType)
    return processTypeLabel(fx_spot_generation_config.process_type);

Emacs 29.3 (Org mode 9.6.15)