The IR curve producer
Table of Contents
1. Summary
ores::marketdata::synthetic::ir_curve_generator is the generator that turns an
ir_curve_generation_config into vendor ticks, one for each pillar of the curve.
It is declared in ores.marketdata.synthetic.api/generators/ir_curve_generator.hpp.
It implements i_generator, and its kind() returns the string constant
ir_curve_generator_kind, spelled "ir_curve".
2. Detail
2.1. How the generator is built
make_ir_curve_feed is the builder the start paths share, so the auto-start
pass and an on-demand start cannot drift.
- It resolves the config's template entries into
ir_curve_resolved_entryrecords throughresolve(). - It builds the process through
map_parameters_to_yield_curve_process, passing the joined definitions and value rows. The starting short rate is the storedinitial_ratevalue row. - It names each pillar's vendor instrument from the template entry: the provider, the id scheme, the external id and the field. See the mapping.
2.2. One process step, many ticks
start() runs the same fixed-mode clock the FX feed uses. The period is one
hour divided by ticks_per_hour, slept in slices of one hundred milliseconds
so stop() is observed promptly, and stop_flag_ is left alone at the top
of the loop for the same reason recorded in the FX feed.
Each pass does this.
- It advances the process once with
next(). The new state is read from the process by the pricing step and its return value is discarded. - It takes one timestamp for the whole batch.
- For every resolved entry it builds one adapter tick, each with that same vendor time, and the adapter publishes it on its ingress subject.
2.3. How a pillar tick is named and priced
A curve is a series, as oresmd: ORE Studio Market Data URI explains. Each entry names its own pillar. The
loop builds a quote key through ores::marketdata::core::make_pillar_quote_key
from the config's currency, the config's index tenor and the entry's own start
tenor code, start date and end date, then turns that key into a URI through
pillar_datum_uri. The key is an IR_SWAP/RATE quote. Its fwd_start is the
start of the pillar, its tenor is the tenor of the index the curve stands for,
and its term is the end of the pillar. An overnight index such as SOFR has the
tenor 1D. A term index such as EURIBOR 6M has the tenor 6M. The series a
point lands in therefore carries the index of the curve, and a EURIBOR 6M curve
and a EURIBOR 3M curve are two series, as Funding and Projection Curves requires of a projection
curve per index tenor.
The value comes from price_ir_curve_entry in
ir_curve_template_resolver.cpp. That function reads the process's
discount_factor() values and dispatches on the entry's curve_role to the
matching curve_instrument_pricer formula, which is a simple rate for a
deposit, an implied forward for a forward rate agreement, and a par-rate
solve for a swap. The same function serves the curve shape preview handler,
so a preview and a run cannot disagree about what a state implies.
2.4. Identity and conflict
The generator reports the vendor instruments its pillars serve through
vendor_instruments(): one for each resolved entry. Two generators conflict when
their lists share a vendor instrument, because both would publish values for one
id. The role comes from the config, but it plays no part in what the generator
owns: two curves of one currency and index tenor serve the same instruments,
whatever their index family or role, and so cannot run together. See
The synthetic runner for the owner that
enforces it.
2.5. The facts the code shape does not show
The process's own time axis is fixed and does not follow the publish cadence.
The constant ir_curve_feed_dt is one over three hundred and sixty five, so
one model step is one calendar day whatever ticks_per_hour says. The
cadence decides how often a human sees a curve and the daily step decides how
far the curve's short rate has moved. The two are independent, and the same
short-rate parameters therefore describe a much slower-looking curve at a low
cadence than at a high one.
The seed is the literal 42, passed directly to the process builder. The
curve path has no entropy draw and no seed column, unlike the FX path, which
draws from std::random_device and logs the result. Two curve feeds started
with the same config and the same parameter rows therefore produce the same
sequence of states.
publish_count() counts batches, not ticks. One unit of the counter is one
pass of the loop and therefore one tick per resolved entry. The info-level
log line says so, spelling the counter as "batch" and printing the number of
points alongside it.
3. See also
- The market data path: a public fixing, a curve, a report — the structure note that orders this cluster, and where to read this page in it.
- Market Data Architecture — the structure note that orders this cluster, and where to read this page in it.
- The IR curve generation config, which this feed reads.
- The IR curve template and its parameters, the ladder this feed resolves.
- The yield curve process type catalogue, the engines the config may name.
- The generator library, which builds the short-rate process.
- Vendor adapters, the contract this generator's adapter shares with a live adapter.
- The generator factory and the kind seam, where
ir_curve_generator_kindselects this builder. - The market tick, the tick the party receives for each pillar.
- oresmd: ORE Studio Market Data URI — how a curve is a series, and what the grammar leaves to the consumer.
- Term Structure — what a curve is.
- Funding and Projection Curves — the family of curves, one series for each index tenor.
- The synthetic runner — the rule that two generators serving one vendor instrument cannot run together.