The shell operation surface
Table of Contents
1. Summary
The shell gives the synthetic commands one menu, built by
synthetic_commands::register_commands in
projects/ores.shell/application/src/app/commands/synthetic_commands.cpp.
The verbs mirror the Market Simulator window, so an operator who cannot run
the Qt client still starts, stops and inspects feeds. Nothing in the group
names an asset class, and the folder verbs cross asset classes because the
marketdata service owns the fan-out.
2. Detail
2.1. The verbs
synthetic list folders lists the folder hierarchy visible to the logged in
party. It takes the flags --config-id to scope the listing to one
collection and --name to filter by name.
synthetic list feeds lists every configured feed of every asset class,
whether or not the service is running it. It takes no arguments and no asset
class flag. Each line states the feed's class, its source name, whether it is
enabled, whether it is set to auto-start, whether it is running now, and the
child rows it holds; a feed missing a child row is marked [partial], so an
incomplete feed is visible rather than absent. The one fact no config row
carries is what is running, so the command joins the config families against
the runner's running set by generator id.
synthetic setup authors a whole feed in one pass, of the class --kind
names: for FX the collection, the folder chain, the generation config, the FX
spot config and its GMM components; for IR the same container and chain, the
IR curve config, its Curve Template entries and its process parameter values.
Every reference the run depends on is checked before the first row is written,
so a missing process type, parameter or required flag is named and nothing is
half authored. The flow, its order and its reporting are shared; the class
supplies only which rows a feed needs.
synthetic preview fx-spot, synthetic preview ir-shape and synthetic
preview ir-paths take one feed token and reach the three dry-run operations
the service already offers: synthetic.v1.ops.simulate_fx_spot_paths,
synthetic.v1.ops.preview_ir_curve_shape and
synthetic.v1.ops.simulate_ir_curve_paths. Each states the feed's own process
type and its stored rows, so the preview is of the configured feed and not of
a request the caller assembles. fx-spot and ir-paths take --ticks,
--paths and --seed; ir-shape takes --seed and --frequency.
synthetic start and synthetic stop take one target, written as
folder <token> or feed <token>.
2.2. marketdata stream
marketdata stream <oresmd-uri> watches one datum on the republished tick
stream. It resolves the URI with the oresmd codec, writes the datum's
canonical ORE key, and subscribes on the caller's own tenant and party
subject, so the command takes no tenant or party argument. Each tick prints
its observation time, the point's oresmd URI, the value and the source;
--csv <path> writes the same four fields as a header and one row per tick
instead. Ctrl-C stops the stream, prints the count, and leaves the file
flushed.
An unparseable or unknown URI is refused with the codec's own message, naming what the grammar did not admit rather than a subject error. A series URI states two subjects, because the series key and the point keys under it are different subjects and no NATS wildcard covers both: the series subject and the point subject one token down.
2.3. The target rule
A folder token is a UUID, an exact folder name, or a standard codename path
such as synthetic/2026realistic/fx. The matching applies slugify to both
sides, which lowercases the value and removes spaces, so 2026 Realistic
and 2026realistic are the same component. A leading slash is ignored, and
absolute and relative paths resolve to the same folder.
A bare codename matches a folder at any depth. Two folders named fx under
different collections therefore produce an ambiguous match, and the command
prints the candidates instead of choosing one.
A feed token is a UUID, an oresmd URI, or a source_name. resolve_feed
probes the FX spot config family first and the IR curve family second. A
UUID is matched against the config ids in that same order. A name is matched
against an FX config's oresmd URI or source name, and then against an IR curve
config's source name only, because an IR curve config names several series and not one URI. A
token shared by several visible feeds is reported as ambiguous, with each
feed's source_name listed.
The probe order follows the server. The service resolves a kind by probing the repositories in the same order, so a token that could name either family resolves to the feed the server would start.
2.4. What a target becomes on the wire
synthetic start folder sends
marketdata::messaging::start_feeds_under_folder_request with the resolved
folder id. The marketdata service fans the request out over the folder and
replies with a started count, an already running count and a skipped count.
synthetic start feed sends synthetic::messaging::start_feed_request with
the config id. Stop mirrors both with the stop requests.
The client never derives a source_name. The per-feed request is keyed by
config_id and the server resolves it to the config's own source_name.
2.5. Facts the code shape does not show
- The group is kind agnostic by construction. No verb takes an asset class, and the folder verbs work for a mix of kinds because the marketdata service, not the shell, walks the folder.
- The shell talks to two services for one subject. The folder verbs are marketdata requests and the per-feed verbs are synthetic requests. That split follows the folder tree, which the marketdata side owns.
synthetic list feedsreads the config families and asks the service what is running, then joins the two bysource_name. A stopped feed and a config that was never started therefore still appear, marked[stopped], which is what makes a partial feed visible rather than absent.synthetic setupis the one verb that writes more than one row. It builds the whole plan before it sends the first row, and every row it sends is the request the matching generatedaddverb sends, on the same subject, so the porcelain flow is not a second writer for a row the generated menus already write. It is not transactional: a failure part way leaves the rows already written, and the command says how many were not.- The command group is the surface a script uses, so its verb names and
target grammar are a contract. The proposal keeps this note in step with
synthetic_commands.cppin the same change as any new verb.
3. See also
- Market Data Architecture — the structure note that orders this cluster, and where to read this page in it.
- Synthetic data generation screens, the window these verbs mirror.
- The generation config collection and folders, the tree a folder token addresses.
- The command group is
projects/ores.shell/application/src/app/commands/synthetic_commands.cpp, built bysynthetic_commands::register_commands. - oresmd: ORE Studio Market Data URI — the series URI that a feed owns and that two feeds must not share.