Files
Aura/CLAUDE.md
T
Brummel f040b66f30 design(c10): reframe to a bias stream + R-unit signal quality
Adopt the R-reframe ratified in #117: the strategy's native unit is risk
(R), not pips/dollars, and its primary output is a directional bias.

- exposure -> bias: the primary output is an UNSIZED direction + conviction
  `f64 in [-1,+1]`; sizing and the protective stop leave the strategy.
- Signal quality is measured in R (Stage 1): an R-evaluator integrates the
  per-trade R-outcomes of a flat-1R RiskExecutor into R-expectancy. R is
  defined by the stop, account-/instrument-agnostic; pips retired as the unit.
  Flat-1R needs no equity, so Stage 1 is feed-forward (no cycle).
- Risk-based execution is a decoupled layer: a RiskExecutor composite
  (stop-rule -> Sizer -> Veto -> position-management) per symbol, nested in a
  Broker/Account composite; account mode (netting/hedging) = composition
  constraint. "Sizer" is not "risk-manager" (that names the Veto layer).
- Currency P&L is Stage 2 (fixed-fractional, compounding). The only feedback
  (equity -> Sizer) is cut by a z^-1 register on the fill edge (mark-to-market
  stays a same-cycle price read), encapsulated in the executor; flat-1R vs
  compounding is a structural axis (the explicit register is mandatory because
  C23 reorders the flat graph).
- Position-event table stays the decoupled Stage-2 audit layer = first
  difference of the book (deal = target - book - in_flight); the flawed 0064
  exposure-integral derive is abandoned.

Touches: ledger C10 + CLAUDE.md domain invariant #7 + glossary (adds bias, R,
R-evaluator, RiskExecutor, Sizer, veto, Stage 1/2; revises broker, exposure
stream, position table, sim-optimal broker, strategy, ...). Also fixes
cross-file drift surfaced by adversarial review (C20 guarantee + front-matter
provenance still claimed "exposure stream"; cross-refs corrected to
C9/C19/C20/C23). Industry-grounded against LEAN / nautilus_trader / backtrader
/ QSTrader / vectorbt / zipline.

refs #117
2026-06-23 13:14:31 +02:00

11 KiB
Raw Blame History

aura — project rules

aura is a "game engine for traders": a Rust framework and a playground to author trading nodes, backtest them deterministically and massively in parallel, compose them fractally, validate them (sweep / Monte-Carlo / walk-forward), and freeze a validated strategy into a standalone bot with a broker connection.

This file is the project sittenkodex. It imports the universal discipline from ~/dev/skills/templates/CLAUDE.md.fragment and adds aura's domain invariants. The full architecture lives in the design ledger (docs/design/), not here. Per-cycle specs (docs/specs/) and plans (docs/plans/) are ephemeral working artifacts, kept git-tracked — committed while their cycle is live and removed (git rm) at cycle close, valid only for the cycle that produces them. Durable rationale is lifted to the ledger; a spec/plan is never treated as a live API reference (its code snippets drift the moment the code moves). The canonical record of past cycles is the ledger plus the git history.

Roles

I am the orchestrator, not the implementer. The skills-plugin agents are my workers: I plan, design, decide, and integrate; they implement, refactor, test, and diagnose. Trivial mechanical edits I may do directly; anything needing broad reading or judgement goes to an agent. Agent reports describe intent, not outcome — I verify the diff and the test output myself before committing.

Commit discipline and main-branch sanctity

  • Only the orchestrator commits. No skill agent runs git commit; agents leave their output as unstaged working-tree changes for me to inspect and shape into commits.
  • main HEAD is sacrosanct — with one narrow /boss exception. As a rule, no git reset/git revert on main: it moves forward only via my commits, and pushed or user-ratified history is never rewound (a bad landing there is fixed forward with git revert, never reset). Wrong agent output is discarded with git checkout -- <paths>/git stash. The exception: under /boss, the orchestrator MAY git reset --hard to wind back its own autonomous, unpushed commits made this run — those above the session anchor (main HEAD at the run's start) — when it has run a line of work into a genuine dead end. Never below the anchor; never a pushed commit; the discarded attempt is hard-dropped (its trace survives in the run's reference issue). This is the /boss rollback sandbox, not a licence to rewrite history.
  • When a commit closes a Gitea issue, reference it in the body: closes #N (or refs #N for non-final work).

Design rationale ≠ implementation effort

Design choices are justified by substance — semantics, structural fit, what the design permits vs forbids, compositional clarity, future-proofing. Implementation effort ("approach A touches 250 sites, B touches 1") is an observation about the current code, not a rationale. Effort is at most a named tiebreaker after substantive reasons tie.

Bug fixes — TDD, always

Bug fixes are RED-first and autonomous: the failing test exists in the working tree before any fix. The debug skill is mandatory for any observable misbehaviour (failing test, panic, wrong output).

Domain invariants (load-bearing — never silently violate)

These are the contracts the whole design rests on. A change that breaks one is a design decision, not a refactor, and belongs in the ledger.

  1. Determinism. A backtest is a deterministic, synchronous, non-concurrent event loop that reaches a unique state after each input tick. Same input → same run, reproducibly. Two backtests are fully disjoint → concurrently executable without locking. Parallelism is across sims, never within one.
  2. Causality / no look-ahead. A node sees only the past. Look-ahead is made structurally impossible (read-only input windows that end at the cursor; resamplers emit a bar only once it is complete), not merely discouraged.
  3. One merge, at ingestion only. Heterogeneous timestamped sources are k-way-merged into a single chronological cycle stream at the ingestion boundary. There is no merge / as-of join inside the graph.
  4. The four scalar base types, streamed as SoA. Only i64, f64, bool, timestamp are streamed, as columnar Structure-of-Arrays. Composite streams (e.g. OHLCV) are bundles of base columns. Non-scalars (String, Records, tables, calendars) exist as metadata beside the hot path, never in it.
  5. Acyclic dataflow. The graph is a DAG; the only feedback path is an explicit delay/state node (the RTL "register"). The "cycle" of the research workflow is not a dataflow cycle.
  6. Record-then-replay determinism boundary. Anything non-deterministic, external, or slow (LLM news agents, web sources) is materialized into a recorded, timestamped stream before it enters the engine. The sim never makes a live external call mid-replay. (See ~/.claude/CLAUDE.md for the IONOS consent rule: external LLM calls happen at the recording/live-source edge, with explicit per-session consent, never inside a backtest.)
  7. Strategy output is a directional bias stream; risk-based execution and realistic brokers are decoupled downstream layers; signal quality is measured in R. The DAG expresses one state at t (C8: ≤1 record per eval), so a strategy's primary, backtestable output is a signed, bounded bias f64 ∈ [-1,+1] per cycle — direction (sign) + conviction (magnitude, optional), unsized (not an equity curve, not a position, not a size). Sizing leaves the strategy: a decoupled risk-based execution layer bias → stop-rule → Sizer → Veto → position-management (the RiskExecutor composite, per symbol, nested in a Broker/Account composite) turns bias + a protective stop into a sized intent. The stop defines the risk unit R (1R = the loss if stopped). Signal quality is measured in R (R-multiples / expectancy), the account- and instrument-agnostic yardstick — Stage 1: flat-1R sizing, feed-forward, no equity feedback, the primary research loop. Currency P&L is Stage 2 (deploy viability): fixed-fractional sizing reads equity (compounding) → realistic brokers apply real frictions → currency equity, entered only after E[R] > 0. The single feedback (equity → Sizer) is cut by a z⁻¹ register on the fill edge (mark-to-market stays a same-cycle price read), encapsulated in the executor composite; flat-1R vs compounding is a structural axis (C11). The broker-independent position-event table (event_ts, action[buy/sell/close], position_id, instrument_id, volume) remains the decoupled, derived Stage-2 audit layer — the first difference of the book (deal = target book in_flight), a computed table (not a per-eval output, since one decision instant may yield >1 event) — feeding realistic brokers. Brokers/executors are ordinary downstream nodes, never part of the strategy; account mode (netting/hedging) is a composition constraint.
  8. Deploy artifacts are frozen. Hot-reload (cdylib) is an authoring-loop tool only. The live bot is a statically-linked, versioned, frozen artifact — never hot-swapped (audit trail: this bot = this commit).
  9. Engine / project separation. This repo is the reusable engine. Research projects are separate external repos that depend on it. Project-specific signals live in a project's nodes/; cross-project-reusable nodes in shared crates; universal blocks in aura-std (shipped here). Reuse is cargo-native; the hot-reload unit is always the project-side cdylib. No user/project signals in this repo (only examples/ fixtures for the engine's own tests); no multi-project manager or node registry inside aura. A project is always a Rust crate (a cdylib library of node / strategy / experiment blueprints + a static Aura.toml), hosted by aura during research and frozen to a standalone binary for deploy.
  10. Authoring surface — all logic is Rust. Nodes, strategies, and experiments/harnesses are authored in native Rust via Claude Code + the skills pipeline, using builder APIs. Declarative config (Aura.toml) carries only static project context, never logic — no experiment/strategy DSL (the RustAst trap). aura ships no embedded coding-LLM; IONOS LLMs are used only as a runtime data source (news bias), with per-session consent, never in the code path.
  11. Construction is a bootstrap phase. Blueprints (param-generic graph-as- data from a Rust builder) are bootstrapped into frozen instances (buffers sized, topology fixed) by binding params + data + seed. Params configure and size nodes but never change topology (a topology change is a different blueprint). The harness — sources + strategy + broker node(s) + sinks — is the root sim graph, itself bootstrapped, and is C1's disjoint unit; its structural axes form the experiment matrix, its tuning params the sweep. The bootstrap is a compilation to a flat, type-erased FlatGraph, wired by raw index (composites inline — a composite is an authoring-level node, not a runtime object; names survive only as non-load-bearing debug symbols, as today). The flat graph is the target of behaviour-preserving optimisation, C1 the correctness invariant — intra-graph (CSE/DCE) and across a sweep family (sweep-invariant sub-graph computed once, shared via C11/C12). See C9/C19/C23.
  12. The World is the product; the playground is a trace explorer. Three ontological tiers: a node is an open, composable fragment (at most one output, C8); a harness is the closed root graph that runs (sources + strategy + brokers + sinks + clock — C1's disjoint unit / root scope), not a node; the World is the program that dynamically constructs and orchestrates families of harnesses (walk-forward / sweep / MC / comparison) — aura's differentiator, not the single backtest. The World is a program: nothing is displayable until it runs, and what is displayable is exactly what a sink (C8) records into the registry (C18). The playground plays any harness and is an execution viewer / trace explorer (structure before, live streams during, recorded traces after) — never a scene editor; topology is grown in Rust + hot-reload, runtime params are UI-tunable.

Skills plugin: project facts

The few facts the skills plugin needs that genuinely vary per project. Everything else is a fixed convention (see ~/dev/skills/docs/conventions.md).

  • Code rootscrates
  • Buildcargo build --workspace
  • Testcargo test --workspace
  • Lintcargo clippy --workspace --all-targets -- -D warnings
  • Doc buildcargo doc --workspace --no-deps 2>&1
  • Design ledgerdocs/design/INDEX.md
  • Glossarydocs/glossary.md
  • Issue tracker — Gitea, repo Brummel/Aura:
    • browsable URL: http://192.168.178.103:3000/Brummel/Aura/issues
    • list open issues: tea issues ls --repo Brummel/Aura --state open