feat(aura-std): add Mul + Sqrt primitives

The two genuinely-missing arithmetic primitives (Mul = two-stream f64 product,
Sqrt = one-input f64 root, negatives clamped to 0). They are the building blocks
for the volatility stop as a composition (rolling EWMA stddev), replacing the
fused VolStop node. Also corrects plan 0066 Task 3 (the VolStop removal must
migrate its stage1_r_e2e.rs caller — a false premise the implementer caught).

refs #117 #119
This commit is contained in:
2026-06-24 00:53:28 +02:00
parent 5de8576fd0
commit 831092841e
4 changed files with 198 additions and 12 deletions
+45 -12
View File
@@ -218,13 +218,46 @@ Add `mod sqrt;` (alphabetical, after `mod sma;` / before `mod stop_rule;`) and
---
## Task 3: Remove the fused `VolStop` node (keep `FixedStop`)
## Task 3: Remove the fused `VolStop` node (keep `FixedStop`) + migrate its one caller
`VolStop` IS referenced outside `stop_rule.rs`/`lib.rs`: `crates/aura-engine/tests/stage1_r_e2e.rs`
imports it (line 30) and constructs `VolStop::new(1, 1.0)` in
`r_is_stop_defined_two_stops_fold_to_different_expectancy`. That caller must be migrated
in this task or the workspace build breaks.
**Files:**
- Modify: `crates/aura-std/src/stop_rule.rs`
- Modify: `crates/aura-std/src/lib.rs`
- Modify: `crates/aura-engine/tests/stage1_r_e2e.rs`
- [ ] **Step 1: Delete `VolStop` from `stop_rule.rs`**
- [ ] **Step 1: Migrate the `stage1_r_e2e.rs` caller off `VolStop` (FIRST)**
`run_chain` drives a `&mut dyn Node` directly, so the vol stop (now a bootstrapped
composite, Task 4) cannot slot in there. The test's property — "different stop distances
fold to different R" — holds via two CONSTANT stops (R = (exitentry)/distance, so a
10×-tighter stop folds to a ~10× deeper R-loss). Replace the `VolStop` arm with a tight
`FixedStop`:
- line 30 import → `use aura_std::{FixedStop, PM_FIELD_NAMES, PM_RECORD_KINDS, PM_WIDTH, PositionManagement};` (drop `VolStop`).
- in `r_is_stop_defined_two_stops_fold_to_different_expectancy`, replace the lines from
`let mut vol = VolStop::new(1, 1.0);` through the final `assert!` with:
```rust
// A TIGHT FixedStop (distance 1.0) vs the wide one (10.0): R = (exit-entry)/distance,
// so the 10x-tighter stop folds to a ~10x deeper R-loss for a comparable drop.
let mut tight = FixedStop::new(1.0);
let tight_m = run_chain(&mut tight, &long_path(&[100.0, 100.0, 96.0]));
assert!(wide.n_trades >= 1 && tight_m.n_trades >= 1);
assert!(
tight_m.expectancy_r < wide.expectancy_r,
"stop choice must change folded R: tight={:?} wide={:?}",
tight_m.expectancy_r,
wide.expectancy_r,
);
```
Update the test's doc-comment "tight VolStop" → "tight FixedStop". (The vol stop's
varying-distance behaviour is covered by `vol_stop_composite.rs`, Task 4.)
- [ ] **Step 2: Delete `VolStop` from `stop_rule.rs`**
Remove the entire `pub struct VolStop`, its `impl VolStop`, its `impl Node for VolStop`,
and the two inline tests `vol_stop_is_none_until_warm` and
@@ -235,18 +268,17 @@ the module doc-comment: the volatility stop is now a composition (see
`crates/aura-engine/tests/vol_stop_composite.rs`), `FixedStop` the only stop-rule
primitive.
- [ ] **Step 2: Drop the `VolStop` re-export**
- [ ] **Step 3: Drop the `VolStop` re-export**
In `crates/aura-std/src/lib.rs`: change `pub use stop_rule::{FixedStop, VolStop};` to
`pub use stop_rule::FixedStop;`.
- [ ] **Step 3: Build the workspace green-unchanged**
- [ ] **Step 4: Build the workspace green**
Run: `cargo build --workspace 2>&1 | grep -E "error|cannot find VolStop" | head`
Expected: empty (no code outside `stop_rule.rs`/`lib.rs` references `VolStop` — the iter-1
E2E uses `FixedStop`). Then `cargo test -p aura-std stop_rule` Expected: PASS
(`fixed_stop_is_constant_after_first_price`). Then `cargo test --workspace 2>&1 | tail -5`
Expected: all green.
Run: `cargo build --workspace 2>&1 | grep -E "error" | head`
Expected: empty. Then `cargo test --workspace 2>&1 | tail -8`
Expected: all green (incl. the migrated
`r_is_stop_defined_two_stops_fold_to_different_expectancy`).
---
@@ -345,9 +377,10 @@ Run: `cargo clippy --workspace --all-targets -- -D warnings` Expected: clean.
Task 4 match the builders the implementer verifies.
- **Step granularity:** each step 2-5 min; Tasks 1-2 are patterned mirrors of `sub.rs`.
- **No commit steps:** none.
- **Compile-gate ordering:** Task 3's `VolStop` removal threads its only references
(`stop_rule.rs` + the `lib.rs` re-export) within Task 3; the workspace build gate is
satisfiable because no other code references `VolStop` (iter-1 E2E uses `FixedStop`).
- **Compile-gate ordering:** `VolStop` IS referenced by `stage1_r_e2e.rs`
(`VolStop::new(1, 1.0)`), so Task 3 threads all three references — `stop_rule.rs`, the
`lib.rs` re-export, AND the E2E caller (migrated to a tight `FixedStop` in Step 1, BEFORE
the deletion) — within Task 3; the workspace build gate at Step 4 is then satisfiable.
- **Verification filters resolve:** `cargo test -p aura-std mul` / `sqrt` /
`stop_rule` / `-p aura-engine --test vol_stop_composite` match the new/kept named
tests; the removal gate uses `cargo build --workspace` + the unfiltered suite.