Brummel 81ac6fd654 docs(ledger): declare the canonical project shape — templates canon, fixture frozen twin
Resolves the #181 design pass (option c: ledger declaration, no lockstep
mechanism). The aura-new templates (scaffold.rs) are the canonical
authoring shape and evolve with the engine; the cycle-0102 demo-project
fixture is an intentionally frozen known-good twin for the load-boundary
tests. Deliberately NOT lockstep-guarded: no consumer requires the copies
to match (skeptic-verified — nothing treats the fixture as what aura new
emits), each is e2e-guarded on its fitness for purpose (build/load/
charter/deterministic run; blueprint wiring is pinned in neither, stated
honestly after an adversarial skeptic pass refuted the stronger claim),
and an equality guard would convert deliberate template improvements into
forced churn of the frozen fixture — the same cross-purpose coupling that
rules out regenerating the fixture from the scaffolder.

closes #181, refs #180
2026-07-02 22:07:40 +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.

Running & orchestrating a loaded blueprint

These verbs all take the blueprint file as their first positional argument and drive a family of runs over it. (Each verb also has a legacy built-in form selected by --strategy/--harness instead of a .json path, for the engine's own bundled example strategies — 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 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 Monte-Carlo family of n seeded realizations. Wants a closed blueprint (the inverse of sweep).
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/--trace), 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.

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, and expose. 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%