d8c6938027e8e6857fd88d1e53860cf0a8f58a97
8 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d8c6938027 |
feat(engine, market, strategy, backtest): NodeSchema.doc threading across the domain crates
C29 compile/unit seam, tasks 4+5 of the self-description plan. aura-engine (task 4): derive_signature stamps doc: "" with the stance recorded in-code -- a derived composite signature is graph wiring, not a vocabulary entry; no seam walks its doc, the described surface is the composite's own doc at the register seam. All in-crate test literals thread doc: "test-only schema". Domain crates (task 5): the 12 production builder sites in aura-market / aura-strategy / aura-backtest carry authored meaning lines; test sites in aura-backtest / aura-composites / aura-ingest thread the test-only doc. Three texts were corrected against the actual node semantics after quality review rather than kept from the first authoring pass: SimBroker is the frictionless integrator of held exposure times price return into cumulative pip equity (no fills/stops/lifecycle -- that is PositionManagement's domain), the shared cost-node line names the PM-geometry inputs and both charge modes (AtClose / PerHeldCycle) instead of a "per-trade gross R" mapping, and LongOnly's line conditions on its enabled param and speaks port-term "exposure". Gates: cargo test green for all six touched crates (engine, market, strategy, backtest, composites, ingest); the workspace-wide gate follows task 6 (aura-runner is the one remaining unthreaded site, E0063 by design until then). refs #316 |
||
|
|
a56ab7859d |
refactor: cut the engine's backtest-metrics edge via RunReport<M>
C28 phase 2 (Stratification); realizes item 1 of the deferred #147. The engine's production surface no longer names a backtest-metric type: - RunReport becomes generic over its metric payload M; sweep/mc/walkforward/ blueprint thread the parameter (SweepPoint<M>, SweepFamily<M>, WindowRun<M>, WalkForwardResult<M>). RunManifest stays concrete and engine-owned (its selection: Option<FamilySelection> embeds the foundation-grade analysis type). - summarize and the MC assembly (McDraw/McFamily/McAggregate/RBootstrap/ r_bootstrap/monte_carlo) move to aura-backtest - McAggregate::from_draws reads RunMetrics fields by name, so generifying it is the phase-6 metric-vocabulary abstraction (#147 item 2), still deferred; wholesale relocation is the honest cut. The concrete instantiation lives in aura-backtest as `type RunReport = aura_engine::RunReport<RunMetrics>` + sibling aliases. - the statistics kernel (MetricStats/quantile/resample_block/SplitMix64) moves to the aura-analysis foundation; the engine re-imports it (inner->foundation, legal) and re-exports it so existing consumers stay source-compatible. Dependency inversion in one commit: aura-engine drops aura-backtest from [dependencies] (back to dev-deps for its SimBroker/RunMetrics test fixtures); aura-backtest gains aura-engine. Cycle-free for lib targets - the cycle closes only through the engine's dev-dep edge, the pattern aura-vocabulary already uses. aura-backtest reaches the kernel transitively through the engine re-export, so no aura-backtest -> aura-analysis edge exists (the C28 ladder permits backtest -> {core, engine} only). run_indexed / SplitMix64::next_f64 widened pub(crate) -> pub for cross-crate use. Consumers (registry/campaign/cli/composites/ingest/bench) rewired by import path only, no call-site logic changed. The c28_layering structural test extends to the full ladder: aura-analysis (no aura-* deps), aura-engine ⊆ {core, analysis}, aura-backtest ⊆ {core, engine}. Behaviour-preserving: 1448/0 tests, clippy -D warnings clean, serde shapes byte-identical (C18 - RunReport<M> keeps field order manifest,metrics; the CLI pre-serialized-splice contract unchanged), moved code traceable via git rename detection. Cycle-introduced broken intra-doc links fixed. closes #292 |
||
|
|
b39fd63396 |
refactor: split the aura-std roster into C28 layer crates
Phase 4 of the Stratification milestone. aura-std held four C28 ladder layers in one roster; this cuts them into layer-aligned, aura-core-only node crates so the import direction is enforced by the crate graph: - aura-std — engine nodes only (arithmetic/logic/rolling + sinks) - aura-market — session, resample - aura-strategy — bias, stops, sizer, cost-model machinery - aura-backtest — sim_broker, position_management - aura-vocabulary — the relocated closed std_vocabulary roster Node modules move verbatim (byte-identical renames); consumers are rewired by import path only. A new structural test (aura-vocabulary/tests/c28_layering.rs) asserts each node crate's [dependencies] stay within its C28-permitted inner set, catching the acyclic-but-outward violation the compiler misses. Behaviour byte-identical: full workspace suite green (1448 tests), no golden edited, clippy -D warnings clean. C28 Status block updated. closes #288 |
||
|
|
d1b3a3dd31 |
feat(research,composites,cli,docs): vol_tf — the timescale-matched stop regime
The second risk-regime variant vol_tf{period_minutes, length, k}
computes the vol estimator over completed time buckets: an H1 signal
gets an H1-matched stop in the research matrix instead of a hand-scaled
minute stop (the issue's k-inflation workaround retires). Additive
externally-tagged serde (stored Vol documents keep their content ids);
the executor arm wires the VolTfStop primitive via the builder+bind
chain; validate checks period_minutes/length/k positivity per regime.
The member-manifest round-trip holds for both variants (C1): vol_tf
members stamp stop_period_minutes/stop_length/stop_k and the reproduce
path re-derives the VolTf stop whenever stop_period_minutes is present
— never a silent default-Vol fallback. The Regimes slot label and the
unit notes name the new variant (period_minutes IS the stop's
timescale); glossary, authoring guide, and design ledger record the
second variant. Default regime and sugar paths byte-untouched.
Coverage: node units (rollover-only emission, bucket-delta math, the
constant-|delta| correspondence with the per-cycle regime), executor
fold, serde/validate units, the manifest round-trip unit, and a
hostless two-regime e2e (distinct ordinals; vol_tf members stamp their
timescale, vol members do not).
closes #262
|
||
|
|
4de6d5cbad |
rename: retire the stage1-* family for the r-family (r-sma / r-breakout / r-meanrev)
The stage1 ordinal has been dead vocabulary since the C10 reframe dropped the two-stage research model: a 1 structurally implies a 2 that no longer exists. The family is renamed by its live discriminator - the R yardstick - with members named by their signal, uniform with their signal-named siblings (sma, macd, momentum): - selectors: stage1-r -> r-sma, stage1-breakout -> r-breakout, stage1-meanrev -> r-meanrev (old tokens are usage errors, exit 2 - no silent alias) - identifiers: Strategy::RSma/RBreakout/RMeanRev, HarnessKind::RSma, r_sma_*/r_breakout_*/r_meanrev_*, wrap_r, run_signal_r, RGrid, R_SMA_* - persisted identity: the sma_signal composite (param prefix sma_signal.fast.length / .slow.length; fixtures regenerated; content-ids shift - no test pins a literal hash, the registry parses no record names) - e2e test files git-mv'd to r_sma_e2e / r_breakout_e2e / r_meanrev_e2e - dead Stage-1/Stage-2 prose reworded to post-C10 vocabulary across rustdoc, Cargo.tomls, ledger live lines, and the glossary (historical entries stay; fieldtests corpus untouched) - CLAUDE.md invariant 7 rewritten to record the ratified C10 reframe faithfully (the token-swap alone would have laundered the retired gated-currency/realistic-broker design into unmarked live prose); the unbacked account-mode clause dropped Verification: cargo build/test --workspace green (51 targets), clippy -D warnings clean, doc build clean, acceptance grep gate leaves exactly the one resampling-stage false positive (harness.rs), smoke: --harness r-sma runs, --harness stage1-r exits 2 with the new usage line. Decision log: forks and rationale recorded on the issue (reconciliation + implementation-phase comments). closes #174 |
||
|
|
3fe4684190 |
feat(0081): cost-model graph cycle 1 — ConstantCost node + net-R seam
Lands the first cycle of the "Cost-model graph (in R)" milestone: cost is
now a composable in-graph node, not a post-run scalar (C10).
- ConstantCost (aura-std): a flat round-trip cost per trade, emitted in R
as a 3-field record {cost_in_r, cum_cost_in_r, open_cost_in_r} isomorphic
to PositionManagement's R-triple. R-pure: cost_in_r = cost_per_trade /
|entry-stop|; notional cancels, no equity held.
- summarize_r folds the cost stream into net_expectancy_r, replacing its
scalar round_trip_cost (one home for cost, no double-count). Positional
co-temporal join; an empty stream is the gross-R baseline.
- net_r_equity tap (stage1_r_graph): LinComb(4) over [cum_realized_r,
unrealized_r, -cum_cost_in_r, -open_cost_in_r] -> Recorder, a sibling of
r_equity; --cost-per-trade on the run path wires the node + tap + fold.
- A no-cost run is byte-identical: no net_r_equity tap, net == gross, the
C18 golden unchanged.
Tests: exact-subsumption (the node-stream net == mean(r_i - cost_i) over
ALL trades incl. the window-end open one), the in-graph net_r_equity tap +
net < gross E2E, the no-cost golden held. Full suite green; clippy clean.
Implement-time decisions ratified (recorded on #148): the cost stream is
recorded 3-wide (the node's full output; summarize_r reads col 0/2, col 1
feeds the in-graph net curve) — resolving a 2-wide/3-wide inconsistency in
the plan's Step 3; Trade drops its `latched` field (cost now arrives in R),
so r_col ENTRY_PRICE/STOP_PRICE become #[allow(dead_code)] layout contract.
Scoped to the run path (non-reduce); sweep/walkforward/mc pass None — cost
on the reduce-mode sweep path and OOS-pooling cost are a deferred follow-up.
Known pre-existing concern (not this cycle): aura-std lib.rs module doc
still names "realistic broker profiles", retired by the C10 rework.
refs #148
|
||
|
|
54a5d68f51 |
feat(stage1-r-sweep): grid signal+stop timescales via CSV flags
Enabling change for the strategy-research run: `aura sweep --strategy
stage1-r` gains four optional comma-separated grid flags `--fast`,
`--slow`, `--stop-length`, `--stop-k` that become the sweep's grid axes
over the four stage1_r_graph knobs (sma fast/slow length, vol-stop
length, vol-stop k). The family is their cartesian product. This lets a
slow time-series-momentum edge be screened across timeframes — Phase 0
showed fast (2/4-bar) signals are chop-dominated noise on M1, so any
momentum edge lives at slower timescales, and the stop timescale must be
tunable alongside the signal.
Mechanism:
- aura-composites: factor vol_stop and risk_executor into a single
shared topology body each (vol_stop_inner / risk_executor_inner), with
the vol-stop knobs either BOUND (the original constant-bind form,
byte-identical) or left OPEN and named `stop_length` / `stop_k` so
their slots surface in param_space as sweepable axes. New
risk_executor_vol_open(risk_budget) is the gridding sibling of
risk_executor(StopRule::Vol{..}, ..). One body, two arms → topology
cannot drift; a member at any (length, k) matches the bound form
byte-for-byte.
- aura-cli: parse_csv_list (generic FromStr, rejects non-numeric/empty),
pure unit-testable parse_sweep_args, all four knobs gridded via
.axis(); absent flags fall back to today's exact defaults (fast {2,3},
slow {6,12}, stop_length {3}, stop_k {2.0}).
Default behaviour byte-identical: all existing goldens/sweep tests stay
green (541 passed, 0 failed; clippy -D warnings clean). Frictionless
Stage-1 R unchanged.
refs #137
|
||
|
|
1a6eafa056 |
refactor(composites): extract Stage-1 composite-builders into their own crate
Dissolve the aura-engine -> aura-std dependency by moving the vol_stop /
risk_executor composite-builders out of aura-engine into a new aura-composites
crate. This restores the engine's domain-free layering, which the
composites-in-engine placement (cycle 0065) had inverted.
Why: the engine routes type-erased Scalar records and never names a concrete
node -- summarize_r reads the PositionManagement record positionally, by column
index, without linking aura-std (which is exactly why aura-std was a dev-only
dependency before 0065). Parking the node-naming composite-builders inside
aura-engine forced the engine's production code to reference the node library
for the first time (aura-engine -> aura-std), an upside-down layering: the
engine is the foundation the node library builds upon, not the reverse.
The clean home is a dedicated crate that depends on BOTH the engine's
GraphBuilder and the std nodes, leaving each lower crate untouched:
aura-composites -> { aura-engine, aura-std } -> aura-core (acyclic)
aura-engine -> aura-core only (domain-free again)
aura-std -> aura-core only (lean node library)
aura-std reverts to a [dev-dependency] of aura-engine (the engine's own E2E
tests -- stage1_r_e2e, random_sweep_e2e, ger40_breakout -- still drive real
std nodes through a bootstrapped Harness; that test-only edge creates no cycle).
Moved with history (git mv):
- crates/aura-engine/src/composites.rs -> crates/aura-composites/src/lib.rs
- crates/aura-engine/tests/risk_executor.rs -> crates/aura-composites/tests/
- crates/aura-engine/tests/vol_stop_composite.rs -> crates/aura-composites/tests/
Consumers rewired: aura-cli imports risk_executor / StopRule from aura_composites;
the moved tests import the builders from the crate under test. The intra-doc link
to RollMode and the module rationale doc are updated for the new home.
Behaviour-preserving: workspace build clean; clippy --all-targets -D warnings
clean; full suite 513 passed / 0 failed, identical to baseline (the two moved
test files run unchanged under aura-composites); cargo doc --no-deps clean (no
broken intra-doc links).
|