claude 98342246f6 docs(ledger, glossary): ratify the fold summary-row timestamp semantics
Fieldtest spec_gap (#335): the timestamp a fold's one summary row
carries was undocumented. Ratified as-is (derived decision, minuted on
the issue): the row is emitted at finalize and stamped with the instant
of the last contributing (warm) value (TapFold::last_ts) — first alone
pins the first contributing instant, and min/max deliberately do not
carry the extremum's instant (a whole-window row privileges no interior
instant, and the extremum ts would cost extra state for no consumer).

The issue's initial finalize-ts reading (and the first draft of this
ratification) was refuted in review against tap_fold.rs: a tap that
goes cold before run end stamps the last WARM eval's instant, not the
run-end instant — observationally identical only while the tap stays
warm to the end, which is what the fieldtest fixtures did. Correction
minuted on the issue.

Recorded in C27's Current state and the glossary tap-plan paragraph;
the fold-registry roster doc lines state it on the surface itself
(sibling commit).

closes #335
2026-07-24 16:29:50 +02:00

aura

aura is a "game engine for traders." It is a Rust framework — and a playground — for authoring trading strategies as composable dataflow nodes, backtesting them deterministically and massively in parallel, validating them (sweep / Monte-Carlo / walk-forward), and freezing a validated strategy into a standalone bot with a broker connection. Its differentiator is the World: a program that constructs and orchestrates whole families of backtests, not the single run.

This README is a discoverability map of the shipped aura CLI — what commands exist and what they do. It deliberately keeps per-flag detail light; the two authoritative sources for exact syntax are always:

  • aura <command> --help — the exhaustive flag grammar.
  • The design ledger (docs/design/INDEX.md) and glossary (docs/glossary.md) — the concepts and invariants behind the surface.

Build & run

aura is a Cargo workspace. Build everything and you get one binary named aura:

cargo build --workspace          # binary at target/debug/aura
cargo build --workspace --release  # optimized, at target/release/aura

Invoke it as aura <command> … (examples below use the plain name).

Concepts in one breath

  • Blueprint — a serialized signal graph as data: a param-generic price → bias node graph. A blueprint file (blueprint.json) is the unit a downstream consumer loads and drives verbs over.
  • Open vs. closed — a blueprint with unbound (free) numeric knobs is open; one with every knob bound is closed. Different verbs want different states (see each verb below).
  • Family — the set of runs one verb produces over a blueprint (a sweep grid, a Monte-Carlo seed set, a walk-forward window sequence). Families are persisted in a content-addressed store and can be listed, ranked, and reproduced.
  • Axis — one named, sweepable knob of a blueprint (e.g. graph.fast.length), bound with a comma-separated value list. A gang fuses several sibling knobs into one axis (one value drives all members).

Running & orchestrating a loaded blueprint

These verbs all take the blueprint file as their first positional argument. Most drive a family of runs over it; graph renders its structure so a mis-wire is visible before a run. walkforward, mc, and generalize share sweep's generic grammar — the blueprint positional plus --real and a repeatable --axis <name>=<csv> (generalize takes --real <SYM1,SYM2,…>, at least two instruments, with a single value per axis) — see --help.

Command Purpose
aura run <bp.json> Run one backtest of a closed blueprint and print its report. An open (free-knob) blueprint is refused with a clean error — bind it, or use sweep.
aura graph <bp.json> Render the blueprint's structure as an interactive HTML DAG so a mis-wire is visible before a run. Omit the file to render the built-in sample; a named-but-unreadable file is a usage error.
aura sweep <bp.json> --list-axes Discover the blueprint's open, sweepable knobs. Prints each as <name>:<kind>. Run this first to learn the axis names.
aura sweep <bp.json> --axis <name>=<csv> [--axis …] Run a grid family over the named axes and persist it.
aura mc <bp.json> --seeds <n> Run a synthetic Monte-Carlo family of n seeded realizations. Wants a closed blueprint (the inverse of sweep).
aura mc <bp.json> --real <sym> --axis <name>=<csv> [--axis …] Run a Monte-Carlo R-bootstrap campaign over recorded data — driven through the same generated-campaign pipeline as sweep; --block-len/--resamples/--seed tune the bootstrap.
aura walkforward <bp.json> --axis <name>=<csv> [--axis …] Run an in-sample-refit walk-forward family — rolling optimize + out-of-sample test across windows, stitched into one verdict + parameter stability. --select chooses the per-window objective.
aura runs families List every persisted family (id, kind, member count).
aura runs family <id> [rank <metric>] List one family's members, optionally ranked best-first by an R metric (e.g. sqn_normalized, expectancy_r).
aura reproduce <family-id> Re-derive every member of a persisted family from the content-addressed store and check it is bit-identical (the C18/C1 determinism guarantee).

Important contract — every open knob is mandatory. On sweep and walkforward, the knobs enumerated by --list-axes are all required: you must supply an --axis for each open knob. There is no default value — pin a knob you don't want to vary with a single-value axis (--axis name=4). Omitting one is a clean error naming the missing knob, not a silent default.

Use aura <cmd> --help for the full data-window (--real/--from/--to), naming (--name), and selection (--select) flags.

Authoring & introspecting topology

A blueprint is authored declaratively from a JSON op-list: an ordered list of by-identifier construction ops replayed against the standard node vocabulary. Adding a new node type to that vocabulary is Rust, not JSON — see docs/authoring-guide.md, §0, "Authoring a new node in Rust".

Command Purpose
aura graph build Read an op-list document on stdin, build the blueprint, and print its canonical JSON to stdout (no trailing newline — it is the content-addressed artifact).
aura graph introspect --vocabulary List every node type available to op-lists.
aura graph introspect --node <T> Show one type's input ports, output fields, and param paths (with the bind-value form).
aura graph introspect --unwired Read a partial op-list on stdin and list its still-open interior slots.
aura graph introspect --content-id Read an op-list on stdin and print the SHA-256 content id of the blueprint it would build.
aura graph introspect --identity-id Read an op-list on stdin and print the SHA-256 identity id — the topology's debug-name-blind id, so two documents (or an op-script and a Rust-built blueprint) expressing the same topology print the same id. Combinable with --content-id (both ids, one per line, content id first).

Op-list shape

Each element is one op, tagged by "op". Node params are bound with the typed Scalar form — a tagged, capitalized-kind object: {"I64": 5}, {"F64": 1.5}, {"Bool": true}. A worked example (an SMA-crossover → bias signal):

[
  {"op":"source","role":"price","kind":"F64"},
  {"op":"add","type":"SMA","name":"fast","bind":{"length":{"I64":2}}},
  {"op":"add","type":"SMA","name":"slow","bind":{"length":{"I64":4}}},
  {"op":"add","type":"Sub"},
  {"op":"add","type":"Bias"},
  {"op":"feed","role":"price","into":["fast.series","slow.series"]},
  {"op":"connect","from":"fast.value","to":"sub.lhs"},
  {"op":"connect","from":"slow.value","to":"sub.rhs"},
  {"op":"connect","from":"sub.value","to":"bias.signal"},
  {"op":"expose","from":"bias.bias","as":"bias"}
]

Piping this document into aura graph build emits a blueprint.json you can then feed to run / sweep / mc / walkforward above:

aura graph build < crossover.ops.json > crossover.bp.json
aura sweep crossover.bp.json --list-axes

The op kinds are source, input, add, feed, connect, expose, tap, gang, and doc (tap declares a recorded measurement point on an interior wire; doc declares the composite's one-line meaning, required at register — C29; see the authoring guide). See aura graph introspect --node <T> for a type's exact ports and the op-script grammar in the design ledger for the full semantics.

Where to go deeper

  • aura <command> --help — exhaustive, always-current flag grammar.
  • docs/design/INDEX.md — the design ledger: architecture, invariants, the World.
  • docs/glossary.md — canonical terminology (blueprint, family, axis, sweep / Monte-Carlo / walk-forward, R, content-id, …).
S
Description
No description provided
Readme 18 MiB
Languages
Rust 68.9%
JavaScript 24.4%
HTML 6%
Shell 0.6%
CSS 0.1%