feat(cli): SugarInvocation + generalize goes blueprint-generic (#220 slice 1)
Tasks 1-2 of the verb-axis-generalization plan (spec auto-signed on a grounding-check PASS, decision log on #220): - verb_sugar gains the shared SugarInvocation<'_> carrier (#214) with VolStop and the factored doc_axes_from/risk_from/probe_params_from helpers; translate_sweep/run_sweep_sugar adopt it (no behaviour change — sweep argv and family output byte-identical), and translate_generalize/run_generalize_sugar follow, dropping their too_many_arguments allows (4 remain for wf/mc). - generalize is de-welded: GeneralizeCmd takes a blueprint positional plus repeatable --axis <wrapped-name>=<value> (one value per axis); --strategy/--fast/--slow are deleted; dispatch_generalize runs the sweep sequence (read, wrapped-namespace validation, canonicalize + topology_hash registration, wrapped_to_raw_axis strip) with a new usage closure. RGrid is deleted workspace-wide. - cli_run generalize tests migrate argv-only; the exact-grade anchor keeps all pinned floats verbatim; generalize_refuses_a_non_r_sma_ strategy is deleted (its premise — a strategy gate — dissolves by design); the multi-value refusal now fires per --axis. Verification: full workspace suite green in the loop's independent verify; build + clippy clean. Held quality finding (kept as a plan-hold): dispatch_generalize duplicates dispatch_sweep's validation/strip block verbatim — dedup follows once wf/mc land the same block (rule-of-three, end of this cycle). refs #220, refs #214
This commit is contained in:
@@ -1306,6 +1306,33 @@ fn sweep_channel_flag_is_removed_from_the_grammar() {
|
||||
let _ = std::fs::remove_dir_all(&cwd);
|
||||
}
|
||||
|
||||
/// Property (#220 generalize vertical): `--strategy`/`--fast`/`--slow` are
|
||||
/// genuinely removed from the generalize grammar, not merely unused — clap
|
||||
/// rejects `--strategy` as a structurally unknown argument (exit 2) rather
|
||||
/// than silently accepting and ignoring it now that the candidate is an
|
||||
/// arbitrary blueprint positional + generic `--axis`. A regression that left
|
||||
/// the old flags on `GeneralizeCmd` while deleting only their plumbing would
|
||||
/// parse successfully here and this test would fail on the exit code.
|
||||
#[test]
|
||||
fn generalize_strategy_flag_is_removed_from_the_grammar() {
|
||||
let cwd = temp_cwd("generalize-strategy-flag-retired");
|
||||
let out = Command::new(BIN)
|
||||
.args([
|
||||
"generalize", "--strategy", "r-sma", "--real", "GER40,USDJPY",
|
||||
"--fast", "3", "--slow", "12", "--stop-length", "14", "--stop-k", "2.0",
|
||||
])
|
||||
.current_dir(&cwd)
|
||||
.output()
|
||||
.expect("spawn aura generalize --strategy");
|
||||
assert_eq!(out.status.code(), Some(2), "--strategy must be an unrecognized clap argument: {:?}", out.status);
|
||||
let stderr = String::from_utf8_lossy(&out.stderr);
|
||||
assert!(
|
||||
stderr.contains("--strategy") || stderr.to_lowercase().contains("unexpected argument"),
|
||||
"clap must name the unknown flag: {stderr:?}"
|
||||
);
|
||||
let _ = std::fs::remove_dir_all(&cwd);
|
||||
}
|
||||
|
||||
/// Property: `aura generalize` grades a single r-sma candidate across two
|
||||
/// instruments — its stdout carries the per-instrument breakdown + the worst-case
|
||||
/// floor + the sign-agreement, then the persisted CrossInstrument family handle.
|
||||
@@ -1316,10 +1343,12 @@ fn generalize_grades_a_candidate_across_two_instruments() {
|
||||
const FROM_MS: &str = "1725148800000";
|
||||
const TO_MS: &str = "1727740799999";
|
||||
let cwd = temp_cwd("generalize-two");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", "--strategy", "r-sma", "--real", "GER40,USDJPY",
|
||||
"--fast", "3", "--slow", "12", "--stop-length", "14", "--stop-k", "2.0",
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
"--axis", "sma_signal.fast.length=3", "--axis", "sma_signal.slow.length=12",
|
||||
"--stop-length", "14", "--stop-k", "2.0",
|
||||
"--from", FROM_MS, "--to", TO_MS,
|
||||
])
|
||||
.current_dir(&cwd)
|
||||
@@ -1360,10 +1389,12 @@ fn generalize_real_e2e_pins_the_exact_current_grade() {
|
||||
const FROM_MS: &str = "1725148800000";
|
||||
const TO_MS: &str = "1727740799999";
|
||||
let cwd = temp_cwd("generalize-exact-grade");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", "--strategy", "r-sma", "--real", "GER40,USDJPY",
|
||||
"--fast", "3", "--slow", "12", "--stop-length", "14", "--stop-k", "2.0",
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
"--axis", "sma_signal.fast.length=3", "--axis", "sma_signal.slow.length=12",
|
||||
"--stop-length", "14", "--stop-k", "2.0",
|
||||
"--from", FROM_MS, "--to", TO_MS,
|
||||
])
|
||||
.current_dir(&cwd)
|
||||
@@ -1399,6 +1430,53 @@ fn generalize_real_e2e_pins_the_exact_current_grade() {
|
||||
assert_eq!(per[1][1].as_f64(), Some(0.005795903617609842), "USDJPY expectancy R: {grade_line}");
|
||||
}
|
||||
|
||||
/// Property (#220 generalize vertical): `aura generalize` grades ANY sweepable
|
||||
/// blueprint, not just the historical r-sma candidate — the whole point of
|
||||
/// dropping `--strategy r-sma`/`--fast`/`--slow` for a positional blueprint +
|
||||
/// generic `--axis`. Every other generalize E2E test here still exercises
|
||||
/// `r_sma_open.json`, so a regression that silently special-cased r-sma paths
|
||||
/// back in (e.g. resolving axes against a hardcoded `sma_signal.*` namespace)
|
||||
/// would ship green there while breaking every other blueprint. This runs the
|
||||
/// unrelated r-breakout candidate (`channel_hi`/`channel_lo` axes, no
|
||||
/// `sma_signal` node in sight) end-to-end and asserts a well-formed two-
|
||||
/// instrument grade. Gated on the shared GER40/USDJPY Sept-2024 archive; skips
|
||||
/// cleanly on a data refusal.
|
||||
#[test]
|
||||
fn generalize_grades_a_non_r_sma_blueprint() {
|
||||
const FROM_MS: &str = "1725148800000";
|
||||
const TO_MS: &str = "1727740799999";
|
||||
let cwd = temp_cwd("generalize-non-r-sma");
|
||||
let fixture = format!("{}/examples/r_breakout_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
"--axis", "r_breakout_signal.channel_hi.length=20",
|
||||
"--axis", "r_breakout_signal.channel_lo.length=20",
|
||||
"--stop-length", "14", "--stop-k", "2.0",
|
||||
"--from", FROM_MS, "--to", TO_MS,
|
||||
])
|
||||
.current_dir(&cwd)
|
||||
.output()
|
||||
.expect("spawn aura");
|
||||
if out.status.code() == Some(1) {
|
||||
let stderr = String::from_utf8_lossy(&out.stderr);
|
||||
assert!(
|
||||
stderr.contains("no local data") || stderr.contains("no recorded geometry"),
|
||||
"exit 1 must be a data refusal, got: {stderr}"
|
||||
);
|
||||
eprintln!("skip: no local GER40/USDJPY data");
|
||||
return;
|
||||
}
|
||||
assert_eq!(out.status.code(), Some(0), "exit: {:?}", out.status);
|
||||
let stdout = String::from_utf8(out.stdout).expect("utf-8 stdout");
|
||||
assert!(stdout.contains("\"generalize\":"), "aggregate object: {stdout}");
|
||||
assert!(stdout.contains("\"n_instruments\":2"), "two instruments: {stdout}");
|
||||
assert!(stdout.contains("\"worst_case\":"), "worst_case present: {stdout}");
|
||||
assert!(stdout.contains("\"sign_agreement\":"), "sign_agreement present: {stdout}");
|
||||
assert!(stdout.contains("GER40") && stdout.contains("USDJPY"), "per-instrument breakdown: {stdout}");
|
||||
assert!(stdout.contains("\"family_id\":"), "family handle: {stdout}");
|
||||
}
|
||||
|
||||
/// Characterization pin (byte-identity anchor for the walkforward dissolution,
|
||||
/// #210). The current `aura walkforward` runs its per-window IS-refit inline
|
||||
/// (`walkforward_family` -> `select_winner` -> OOS run -> stitch/pool); the
|
||||
@@ -1494,9 +1572,8 @@ fn walkforward_dissolved_refuses_select_plateau() {
|
||||
assert!(stderr.contains("#215"), "forward pointer to the plateau follow-up: {stderr}");
|
||||
}
|
||||
|
||||
/// `walkforward_args_from` requires all four grid knobs on the dissolved r-sma-real
|
||||
/// path (unlike the inline path, which defaults an absent flag via `RGrid::default()`)
|
||||
/// — a missing knob is a usage refusal (exit 2), not a silent default.
|
||||
/// `walkforward_args_from` requires both stop knobs on the campaign path — a
|
||||
/// missing knob is a usage refusal (exit 2), not a silent default.
|
||||
#[test]
|
||||
fn walkforward_dissolved_refuses_missing_knobs() {
|
||||
let cwd = temp_cwd("walkforward-missing-knobs");
|
||||
@@ -1665,10 +1742,12 @@ fn generalize_dissolves_through_the_campaign_path() {
|
||||
const FROM_MS: &str = "1725148800000";
|
||||
const TO_MS: &str = "1727740799999";
|
||||
let cwd = temp_cwd("generalize-dissolves");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", "--strategy", "r-sma", "--real", "GER40,USDJPY",
|
||||
"--fast", "3", "--slow", "12", "--stop-length", "14", "--stop-k", "2.0",
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
"--axis", "sma_signal.fast.length=3", "--axis", "sma_signal.slow.length=12",
|
||||
"--stop-length", "14", "--stop-k", "2.0",
|
||||
"--from", FROM_MS, "--to", TO_MS,
|
||||
])
|
||||
.current_dir(&cwd)
|
||||
@@ -1754,11 +1833,13 @@ fn generalize_repeated_identical_invocation_does_not_litter_the_store() {
|
||||
const FROM_MS: &str = "1725148800000";
|
||||
const TO_MS: &str = "1727740799999";
|
||||
let cwd = temp_cwd("generalize-repeat-idempotent");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let invoke = || {
|
||||
std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", "--strategy", "r-sma", "--real", "GER40,USDJPY",
|
||||
"--fast", "3", "--slow", "12", "--stop-length", "14", "--stop-k", "2.0",
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
"--axis", "sma_signal.fast.length=3", "--axis", "sma_signal.slow.length=12",
|
||||
"--stop-length", "14", "--stop-k", "2.0",
|
||||
"--from", FROM_MS, "--to", TO_MS,
|
||||
])
|
||||
.current_dir(&cwd)
|
||||
@@ -1807,11 +1888,14 @@ fn generalize_distinct_invocations_persist_distinct_campaign_documents() {
|
||||
const FROM_MS: &str = "1725148800000";
|
||||
const TO_MS: &str = "1727740799999";
|
||||
let cwd = temp_cwd("generalize-distinct-content");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let invoke = |fast: &str| {
|
||||
let fast_axis = format!("sma_signal.fast.length={fast}");
|
||||
std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", "--strategy", "r-sma", "--real", "GER40,USDJPY",
|
||||
"--fast", fast, "--slow", "12", "--stop-length", "14", "--stop-k", "2.0",
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
"--axis", &fast_axis, "--axis", "sma_signal.slow.length=12",
|
||||
"--stop-length", "14", "--stop-k", "2.0",
|
||||
"--from", FROM_MS, "--to", TO_MS,
|
||||
])
|
||||
.current_dir(&cwd)
|
||||
@@ -1853,10 +1937,12 @@ fn generalize_distinct_invocations_persist_distinct_campaign_documents() {
|
||||
#[test]
|
||||
fn generalize_without_explicit_window_falls_back_to_the_first_symbols_full_window() {
|
||||
let cwd = temp_cwd("generalize-default-window");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", "--strategy", "r-sma", "--real", "GER40,USDJPY",
|
||||
"--fast", "3", "--slow", "12", "--stop-length", "14", "--stop-k", "2.0",
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
"--axis", "sma_signal.fast.length=3", "--axis", "sma_signal.slow.length=12",
|
||||
"--stop-length", "14", "--stop-k", "2.0",
|
||||
])
|
||||
.current_dir(&cwd)
|
||||
.output()
|
||||
@@ -1883,10 +1969,12 @@ fn generalize_without_explicit_window_falls_back_to_the_first_symbols_full_windo
|
||||
/// before any data access — so it asserts the arity refusal on any machine.
|
||||
#[test]
|
||||
fn generalize_refuses_a_single_instrument() {
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", "--strategy", "r-sma", "--real", "GER40",
|
||||
"--fast", "3", "--slow", "12", "--stop-length", "14", "--stop-k", "2.0",
|
||||
"generalize", &fixture, "--real", "GER40",
|
||||
"--axis", "sma_signal.fast.length=3", "--axis", "sma_signal.slow.length=12",
|
||||
"--stop-length", "14", "--stop-k", "2.0",
|
||||
])
|
||||
.output()
|
||||
.expect("spawn aura");
|
||||
@@ -1897,10 +1985,12 @@ fn generalize_refuses_a_single_instrument() {
|
||||
/// `check_r_metric` pre-check), so this asserts the R-only refusal on any machine.
|
||||
#[test]
|
||||
fn generalize_refuses_a_non_r_metric() {
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", "--strategy", "r-sma", "--real", "GER40,USDJPY",
|
||||
"--fast", "3", "--slow", "12", "--stop-length", "14", "--stop-k", "2.0",
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
"--axis", "sma_signal.fast.length=3", "--axis", "sma_signal.slow.length=12",
|
||||
"--stop-length", "14", "--stop-k", "2.0",
|
||||
"--metric", "total_pips",
|
||||
])
|
||||
.output()
|
||||
@@ -1920,10 +2010,12 @@ fn generalize_refuses_a_non_r_metric() {
|
||||
/// check precedes any geometry/archive lookup, so it asserts on any machine.
|
||||
#[test]
|
||||
fn generalize_refuses_a_duplicate_instrument() {
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", "--strategy", "r-sma", "--real", "GER40,GER40",
|
||||
"--fast", "3", "--slow", "12", "--stop-length", "14", "--stop-k", "2.0",
|
||||
"generalize", &fixture, "--real", "GER40,GER40",
|
||||
"--axis", "sma_signal.fast.length=3", "--axis", "sma_signal.slow.length=12",
|
||||
"--stop-length", "14", "--stop-k", "2.0",
|
||||
])
|
||||
.output()
|
||||
.expect("spawn aura");
|
||||
@@ -1937,22 +2029,24 @@ fn generalize_refuses_a_duplicate_instrument() {
|
||||
assert!(stderr.contains("generalize"), "must surface the generalize usage, got: {stderr}");
|
||||
}
|
||||
|
||||
/// Property: a non-`r-sma` strategy is refused at the binary boundary (exit 2,
|
||||
/// no run, data-free). The candidate must produce R (C10) — the cross-instrument
|
||||
/// reduction is R-only — so only the r-sma grid is an admissible candidate. The
|
||||
/// parser unit test pins the grammar refusal; this pins that `--strategy sma`
|
||||
/// reaches `exit(2)` through the dispatch arm rather than silently defaulting to a
|
||||
/// running candidate. Asserts on any machine (the strategy check precedes any run).
|
||||
/// Property: a multi-value axis is refused at the binary boundary (exit 2, no
|
||||
/// run, data-free). A *candidate* is a single grid cell, not a sweep — so any
|
||||
/// `--axis` carrying more than one value is refused, never silently widened
|
||||
/// into a multi-cell run whose generalization grade would be ill-defined.
|
||||
#[test]
|
||||
fn generalize_refuses_a_non_r_sma_strategy() {
|
||||
fn generalize_refuses_a_multi_value_axis() {
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", "--strategy", "sma", "--real", "GER40,USDJPY",
|
||||
"--fast", "3", "--slow", "12", "--stop-length", "14", "--stop-k", "2.0",
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
"--axis", "sma_signal.fast.length=2,3", "--axis", "sma_signal.slow.length=12",
|
||||
"--stop-length", "14", "--stop-k", "2.0",
|
||||
])
|
||||
.output()
|
||||
.expect("spawn aura");
|
||||
assert_eq!(out.status.code(), Some(2), "a non-r-sma strategy must exit 2");
|
||||
assert_eq!(out.status.code(), Some(2), "a multi-value axis must exit 2");
|
||||
let stderr = String::from_utf8_lossy(&out.stderr);
|
||||
assert!(stderr.contains("each --axis takes exactly one value"), "arity refusal: {stderr}");
|
||||
assert!(
|
||||
out.stdout.is_empty(),
|
||||
"the refusal must not leak an aggregate to stdout, got: {:?}",
|
||||
@@ -1960,22 +2054,50 @@ fn generalize_refuses_a_non_r_sma_strategy() {
|
||||
);
|
||||
}
|
||||
|
||||
/// Property: a multi-value candidate flag is refused at the binary boundary (exit 2,
|
||||
/// no run, data-free). A *candidate* is a single grid cell, not a sweep — so any of
|
||||
/// `--fast/--slow/--stop-length/--stop-k` carrying more than one value (`--fast 2,3`)
|
||||
/// is refused, never silently widened into a multi-cell run whose generalization
|
||||
/// grade would be ill-defined (the reduction grades one candidate, not a family).
|
||||
/// The parser unit test pins the grammar; this pins the wiring to `exit(2)`.
|
||||
/// Property: a `--axis` with no `--axis` flags at all is a usage error (exit 2,
|
||||
/// no run) — generalize needs >= 1 axis to name a candidate, mirroring the sibling
|
||||
/// sweep/walkforward "no axis" refusals. Data-free (fires before any archive access).
|
||||
#[test]
|
||||
fn generalize_refuses_a_multi_value_candidate_flag() {
|
||||
fn generalize_refuses_no_axis() {
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", "--strategy", "r-sma", "--real", "GER40,USDJPY",
|
||||
"--fast", "2,3", "--slow", "12", "--stop-length", "14", "--stop-k", "2.0",
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
"--stop-length", "14", "--stop-k", "2.0",
|
||||
])
|
||||
.output()
|
||||
.expect("spawn aura");
|
||||
assert_eq!(out.status.code(), Some(2), "a multi-value candidate flag must exit 2");
|
||||
assert_eq!(out.status.code(), Some(2), "zero axes must exit 2");
|
||||
let stderr = String::from_utf8_lossy(&out.stderr);
|
||||
assert!(stderr.contains("Usage: aura generalize"), "must print the generalize usage: {stderr}");
|
||||
assert!(
|
||||
out.stdout.is_empty(),
|
||||
"the refusal must not leak an aggregate to stdout, got: {:?}",
|
||||
String::from_utf8_lossy(&out.stdout)
|
||||
);
|
||||
}
|
||||
|
||||
/// Property: an `--axis` name that is not among the loaded blueprint's sweepable
|
||||
/// axes is refused before the raw-namespace strip or any archive access (exit 2),
|
||||
/// echoing exactly the name the user typed — the same WRAPPED-probe preflight
|
||||
/// `aura sweep` enforces (`aura_sweep_real_blueprint_refuses_a_raw_form_axis_name_before_data_access`).
|
||||
#[test]
|
||||
fn generalize_refuses_an_unknown_axis_name() {
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
"--axis", "sma_signal.nope=3", "--axis", "sma_signal.slow.length=12",
|
||||
"--stop-length", "14", "--stop-k", "2.0",
|
||||
])
|
||||
.output()
|
||||
.expect("spawn aura");
|
||||
assert_eq!(out.status.code(), Some(2), "an unknown axis name must exit 2");
|
||||
let stderr = String::from_utf8_lossy(&out.stderr);
|
||||
assert!(
|
||||
stderr.contains("axis \"sma_signal.nope\"") && stderr.contains("sweepable axes"),
|
||||
"must name the unresolved axis exactly as typed: {stderr}"
|
||||
);
|
||||
assert!(
|
||||
out.stdout.is_empty(),
|
||||
"the refusal must not leak an aggregate to stdout, got: {:?}",
|
||||
@@ -1998,10 +2120,12 @@ fn generalize_persists_a_discoverable_cross_instrument_family() {
|
||||
const FROM_MS: &str = "1725148800000";
|
||||
const TO_MS: &str = "1727740799999";
|
||||
let cwd = temp_cwd("generalize-family");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", "--strategy", "r-sma", "--real", "GER40,USDJPY",
|
||||
"--fast", "3", "--slow", "12", "--stop-length", "14", "--stop-k", "2.0",
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
"--axis", "sma_signal.fast.length=3", "--axis", "sma_signal.slow.length=12",
|
||||
"--stop-length", "14", "--stop-k", "2.0",
|
||||
"--from", FROM_MS, "--to", TO_MS,
|
||||
])
|
||||
.current_dir(&cwd)
|
||||
@@ -2061,10 +2185,12 @@ fn generalize_family_members_are_attributed_to_the_right_instrument() {
|
||||
const FROM_MS: &str = "1725148800000";
|
||||
const TO_MS: &str = "1727740799999";
|
||||
let cwd = temp_cwd("generalize-member-attribution");
|
||||
let fixture = format!("{}/examples/r_sma_open.json", env!("CARGO_MANIFEST_DIR"));
|
||||
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
|
||||
.args([
|
||||
"generalize", "--strategy", "r-sma", "--real", "GER40,USDJPY",
|
||||
"--fast", "3", "--slow", "12", "--stop-length", "14", "--stop-k", "2.0",
|
||||
"generalize", &fixture, "--real", "GER40,USDJPY",
|
||||
"--axis", "sma_signal.fast.length=3", "--axis", "sma_signal.slow.length=12",
|
||||
"--stop-length", "14", "--stop-k", "2.0",
|
||||
"--from", FROM_MS, "--to", TO_MS,
|
||||
])
|
||||
.current_dir(&cwd)
|
||||
|
||||
Reference in New Issue
Block a user