The generator library
Table of Contents
1. Summary
ores.analytics.quant is the library that holds the price and short-rate
processes the synthetic producers step, and the arrival laws that decide when a
producer ticks. Its two process interfaces are i_stochastic_process in
ores.analytics.quant/domain/i_stochastic_process.hpp and
i_yield_curve_process beside it, and the arrival laws are values in
ores.analytics.quant/domain/arrival_law.hpp. Its entry point for the processes
is process_factory in ores.analytics.quant/service/process_factory.hpp,
which has one method for each family: make_process and
make_yield_curve_process. make_arrival_law builds an arrival law.
2. Detail
2.1. The interface
i_stochastic_process has two methods. next() advances the process by one
step and returns the new price, and current() reads the price without
advancing. The process owns its own state, which is the current price, the
engine and the parameters, and it is not thread-safe.
i_yield_curve_process extends that interface with one method.
discount_factor(ticks_ahead) answers, from the current state, what
zero-coupon bond price the model implies at that distance in ticks. Every
instrument a caller derives from one state is evaluated through that one
call, which is what makes a published curve a slice of a single curve rather
than a set of separately noised quotes. Mapping a calendar tenor to a tick
count is the caller's job, not the process's.
The library sits outside ores.marketdata.synthetic on purpose, and the header records
why. A calibration service, ores.marketdata or ores.marketdata.synthetic can all
instantiate a process without linking the synthetic service binary. The
library also carries no logging dependency, so a caller that wants to diagnose
an unknown process name has to log around the call rather than inside it.
2.2. The factory
process_factory::make_process takes the process type string, the component
means, standard deviations and weights, an initial price, a seed and a tick
length in years. It has three branches.
"arithmetic"buildsarithmetic_gaussian_mixture_model_process."ornstein_uhlenbeck"buildsornstein_uhlenbeck_process."geometric"and every unrecognised string buildgaussian_mixture_model_process.
There is no error for an unknown name. The geometric engine is the silent
fallback, which is why the FX generation config's process_type column is a
plain checked string rather than a foreign key.
Before any branch it calls
ores::analytics::quant::domain::validate_process_parameters. That function
is the single rule set, shared with the Qt client, so a parameter set the
dialog rejects is rejected again in the service.
2.3. The Ornstein-Uhlenbeck branch repurposes the mixture columns
The FX config stores a mixture, and an Ornstein-Uhlenbeck process is a single
regime rather than a mixture. The factory therefore reads the component rows
as scalars. weights.front() is kappa, the reversion speed.
stdevs.front() is sigma, the volatility. initial_price doubles as theta,
the long-run mean, so a fresh process reverts toward its own starting level.
means is unused.
A reader who edits an FX config's components while its process_type is
"ornstein_uhlenbeck" is therefore editing a reversion speed in a field
labelled as a weight.
2.4. The arrival law is a third kind
Everything above answers what the next price is. When the price arrives is a
different question with a different answer, and it does not fit
i_stochastic_process, because next() there returns a level. An arrival law
is a value that gives the gap to the next tick in the market's operational
time. The scheduler, which lives in this library, draws each series' gaps from
its law, and a periodic law gives a fixed period. The value process in turn has next(elapsed), so a step can be longer
or shorter than one nominal tick. The design, its parameters and its limits are in
Tick arrival. The
mathematics is in Hawkes Process
and Poisson Process.
2.5. The RNG design
Every process owns a std::mt19937 engine built from the seed passed to its
constructor, and the constructor's default is 42. There is no global engine
and no shared mutable state, so concurrent feeds do not contend.
The mixture weight normalisation is delegated to the standard library. The
component weights are handed to a std::discrete_distribution<int>, which
normalises them itself, so no code rewrites the stored gmm_component rows.
2.6. The seeding rule
The two producers seed differently, and the difference is deliberate in one case and not recorded in the other.
- The FX path draws one
std::uint32_tfrom a function-localstatic std::random_deviceand writes it to the log at info level as "SYNTHETIC SEED" with the source name. See The FX spot producer. - The curve path passes the literal
42. See The IR curve producer. - The simulate and preview handlers take a caller seed and add the path index to it, so several paths in one request are different streams and a repeated request reproduces the same paths.
2.7. The facts the code shape does not show
A zero standard deviation is a legal input and both mixture processes handle
it directly by drawing the component's mean, because
std::normal_distribution asserts on a zero standard deviation in a debug
build and would abort the process. validate_process_parameters rejects a
negative standard deviation but permits a zero one.
make_yield_curve_process is a second factory entry point on the same class.
It is not on any producer's path, it constructs only three of the five
catalogued short-rate engines, and it has no caller in the tree. See
The yield curve process type catalogue.
3. See also
- Market Data Architecture — the structure note that orders this cluster, and where to read this page in it.
- Stochastic Processes, the hub that carries the mathematics of each process.
- Probability measures: P (real-world) and Q (risk-neutral), which explains why generation runs under P.
- Markov Property, which is what makes a one-step-at-a-time loop sufficient.
- Geometric Brownian Motion, the engine the factory falls back to.
- Arithmetic Brownian Motion, the engine the
"arithmetic"name selects. - Ornstein-Uhlenbeck Process, the engine whose parameters arrive through the mixture columns.
- The FX spot producer and The IR curve producer, the two callers.
- Tick arrival, the third kind of process: when a tick comes, not what it says.