diff --git a/fieldtests/cycle-0107-campaign-executor/FINDINGS.md b/fieldtests/cycle-0107-campaign-executor/FINDINGS.md new file mode 100644 index 0000000..f55e702 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/FINDINGS.md @@ -0,0 +1,215 @@ +# Fieldtest — cycle 0107 — campaign executor + blueprint on-ramp — 2026-07-03 + +**Role:** downstream consumer (methodology / campaign designer), public interface +only (ledger C16/C18/C20/C24/C25, glossary, CLI `--help` + introspection verbs, +the 0106 fieldtest corpus as shape hints). No `crates/` source read. Binary +built from HEAD (`cargo build --workspace`, `target/debug/aura`, commit +`428f83c`). Real data: scaffolded `demo_project/` (`aura new`), `cargo build` +for the dylib, ran the executor over the local GER40 2024-09 Pepperstone +archive. + +## Fixtures (this directory) + +- `c0107_1_smacross.json` — SMA-cross op-script, lengths **bound** (content id `573262…`) +- `c0107_1_smacross_open.json` / `_open_built.json` — lengths **unbound** (sweepable), op-script + its `graph build` envelope (content id `597d71…`) +- `c0107_2_process.json` — sweep(sqn,argmax,deflate) → gate(expectancy_r>0) → walk_forward(rolling, ms lengths) (content id `5a88…`) +- `c0107_2_campaign.json` — campaign missing a `bias.scale` axis (validates, then fails run) +- `c0107_2_campaign_full.json` — the runnable campaign (all 3 open params covered), GER40, 2024-09 +- `c0107_2_realization_campaign_runs.jsonl` — the recorded realization (3 identical runs + 1 gate-all) +- `c0107_3_process_{mc,gateall,badmetric}.json` + `c0107_3_campaign_*.json` — refusal probes +- `c0107_4_process_{plateau_wf,deflate_plateau,wf_toobig}.json` + `c0107_4_campaign_*.json` + `c0107_4_campaign_prefixref.json` — trip-up probes +- `demo_project/` — `aura new` scaffold + all docs (its `runs/` store is project-gitignored; the realization is copied out to the corpus root as evidence) + +## Findings + +### F1 [working] The full loop closes — 0106 F7 is answered +`aura campaign run c0107_2_campaign_full.json` (file = register-then-run) and +`aura campaign run 533aed18…` (id) both execute the cell +`GER40 × [2024-09-01,10-01]` through `std::sweep → std::gate → +std::walk_forward` over real data (exit 0). The gate `expectancy_r > 0` kept +survivors `[0,1,2]` (dropped the losing `fast=4/slow=16` member, +`expectancy_r=-0.022`); the sweep argmax winner was ordinal 0 (`sqn=1.054`); +walk-forward rolled 2 OOS folds re-sweeping **only** the survivor points and +stamped `manifest.selection` on the OOS winners. Emit honored: `family_table` + +`selection_report` lines, always the `campaign_run` record. The stored +`CampaignRunRecord` (`runs/campaign_runs.jsonl`) links +`{campaign, process, run, seed, cells[{stages: family_id / survivor_ordinals / +selection}]}` over untouched `families.jsonl` records, run-counted per campaign +id (3 successful runs → run 0/1/2). Intent → execution → recorded realization +is one continuous, reproducible path. → carry-on. + +### F2 [working] Determinism is bit-identical across re-run and addressing mode +Two file runs and one id-addressed run of the same campaign are +**byte-identical** after normalizing only the per-campaign run counter in +family ids (`diff` clean on both pairs). Deflation nulls seed from the doc +`seed=42` (`overfit_probability`, `deflated_score` reproduce). Realization is a +pure function of doc + stores + data, as C1 promises. → carry-on. + +### F3 [working] 0106 F1 closed — the document envelope is now introspectable +`aura campaign introspect --unwired ` enumerates the whole envelope, +including the previously-invisible `seed`: +``` +open slot: format_version (required, must be 1) +open slot: kind (required, must be "campaign") +open slot: name / data / strategies / process.ref / seed / presentation … +``` +`process introspect --unwired {}` likewise names +`format_version/kind/name/pipeline`. The field names (`data`, `strategies`, +`process.ref`, `presentation`) that 0106 F1 could not map are now spelled out. +→ carry-on. + +### F4 [working] The honest-refusal surface is loud, precise, and correctly disposed +All probed refusals were clean, actionable prose with the right exit code: +- v1 boundary: `process stage 1 (std::monte_carlo) is not executable in v1; + executable pipeline shape: std::sweep [std::gate]* [std::walk_forward]` + (exit 1). `std::generalize` is symmetric. +- gate-everything-out (`expectancy_r > 100`): exit **0**, `family_table` + + sweep `selection_report` still emitted, walk-forward **truncated**, loud + stderr `cell …: gate at stage 1 left no survivors; cell realization + truncated`. +- `plateau:mean` inside walk_forward: `walk_forward cannot use a plateau select + (a gated survivor subset has no parameter lattice)` (exit 1). +- `deflate:true` + non-argmax: `sweep deflate: true composes only with select + "argmax"` (exit 1). +- old 0106 wf vocab (`folds`): `block std::walk_forward: unknown slot "folds"` + (exit 1) — the 0107 machinery-true vocabulary correction is enforced. +- bogus file / unknown 64-hex id / uppercase-hex / outside-project: each exit 1 + with a precise message (`neither a readable .json file nor a 64-hex content + id` / `no campaign in the project store` / `campaign run needs a + project: … no Aura.toml found up from `). +- `persist_taps` deferred **LOUDLY** on stderr before execution + (`persist_taps not yet honored (N tap(s) ignored)`), the 0106 F7 lesson + honored. +→ carry-on. + +### F5 [friction] The on-ramp rejects the op-script; the `graph build` bridge is undocumented +The corpus's canonical strategy form is an **op-script** (`c0106_2_strategy.json`, +`c0107_1_*`). `aura graph introspect --content-id FILE` accepts it +(shape-discriminated) — but `aura graph register FILE` and `aura graph +introspect --params FILE` **reject** it with a raw serde message: +``` +aura: blueprint document is not valid JSON: invalid type: map, expected u32 at line 2 column 2 +``` +Only the envelope emitted by `aura graph build < op-script > envelope.json` is +accepted. Nothing in `--help`, the glossary `blueprint` entry, or the error +names this `graph build` step, and the three on-ramp verbs disagree on which +shapes they accept. (Once bridged, the content id is shape-invariant — +op-script and envelope both hash to `573262…`, so `register` and a ref computed +from the op-script agree; this part is correct.) +Repro: `aura graph register c0107_1_smacross_open.json`. +→ plan: shape-discriminate the op-list in `register`/`--params` (as +`--content-id` already does), or make the error name the `graph build` bridge. + +### F6 [friction] The `content:` prefix trap persists and the on-ramp emits the wrong-to-paste form +`graph|process|campaign register` and `introspect --content-id` all print +`content:`, but every `ref` wants the **bare** hash. A campaign whose +`process.ref` carries the copied `content:5a88…` form **passes intrinsic +validation** and then fails referential: +``` +aura: campaign references do not resolve: + process content:5a88…6ea not found in the project store +``` +The error now echoes the offending prefixed ref (an improvement over 0106 F3) +but never says "strip the `content:` prefix", and `register` still prints +exactly the form that breaks. This directly taxes the on-ramp the cycle set out +to smooth. +Repro: `aura campaign validate c0107_4_campaign_prefixref.json`. +→ plan: one bare display form across verbs, or accept/strip the `content:` +prefix in refs (carried from 0106 F3, still open: #194). + +### F7 [friction] `campaign validate` passes but `campaign run` aborts when an open param is uncovered +Referential validation reports `all references resolve, axes are in the param +space` (exit 0), but it only checks that each axis **name** is in `param_space` +— not that **every** open param is covered by an axis. The open blueprint has +three open params (`fast.length`, `slow.length`, `bias.scale`); a campaign +sweeping only the two lengths **validates**, then aborts at member-bind: +``` +aura: a member failed to bind: open param "graph.bias.scale" of strategy 597d71… is bound by no campaign axis +``` +The executor's "every open knob required, no default" rule (documented for +`sweep`/`walkforward` in the glossary) is not mirrored in the validator, so +"valid" ≠ "runnable". (Secondary: the bind error uses the wrapped +`graph.bias.scale` path while `--params` and the axis use the raw `bias.scale` +— two namespaces for one knob.) +Repro: `aura campaign validate c0107_2_campaign.json` (passes) then +`aura campaign run c0107_2_campaign.json` (aborts). +→ plan: extend the referential tier to require full open-param coverage, +surfacing the missing knob at validate time; reconcile the raw-vs-wrapped param +path in the bind message. + +### F8 [friction] The walk-forward window-fit refusal leaks a raw Rust `Debug` struct +A walk_forward whose `in_sample_ms` exceeds the campaign window refuses +correctly, but in internal `{:?}` form, unlike its clean sibling refusals: +``` +aura: process stage 1: walk_forward windows do not fit the campaign window: + SpanTooShort { span: (Timestamp(1725148800000), Timestamp(1727740800000)), need: 315964799999 } +``` +The `SpanTooShort {…}` struct, the `Timestamp()` wrapper, and the +unit-unlabeled `need` (ms) break the "Debug-free house seam" the cycle +otherwise maintains, and a user cannot easily see that `need` is +`in_sample_ms + out_of_sample_ms` in ms against the window span. +Repro: `aura campaign run c0107_4_campaign_wf_toobig.json`. +→ debug (RED-pin the prose form). + +### F9 [doc-gap] The rankable / gate metric roster is enumerable by no verb, nor by the refusal +Block hints say `metric name (see metric_vocabulary)`, but no verb lists it +(`--vocabulary` is the block list; `--block metric_vocabulary` → `unknown +block`). `process validate` accepts **any** string (`profit_factor` passes +intrinsic), and the run-time refusal names no roster: +``` +aura: process stage 0: metric "profit_factor" is not rankable (winner selection needs one of the registry's rankable metrics) +``` +`profit_factor` is itself emitted in every member's metrics block, so the +exists-but-not-rankable split is invisible. A campaign author must guess the +sweep/gate/wf metric names (0106 F6, still open: #197). +→ tighten docs: expose the rankable + gate metric rosters via `process +introspect` (or enumerate them in the refusal). + +### F10 [spec_gap] Register-then-run stores the campaign before the gate — unrunnable docs accumulate +Every `campaign run ` issued left a `runs/campaigns/.json` (9 +stored), including campaigns that then failed the referential gate +(`prefixref`) or preflight (`mc`/`badmetric`/`plateauwf`/`deflateplateau`/ +`wf_toobig`). The store thus accumulates never-runnable and +referentially-broken documents, with no cleanup. The ledger is silent on +whether the file sugar should gate before storing, and whether the +content-addressed store should hold referentially-broken docs. +→ ratify (accept intrinsic-keyed store as-is) or tighten (gate before storing). + +## Verdict + +**Yes — the campaign+process pair now delivers the full loop the 0106 verdict +said was one wire short.** F7 (0106) is closed end to end: a campaign document ++ its referenced process document drive `aura campaign run` through +`sweep → gate → walk_forward` over the real GER40 archive, and the run's +realization is recorded as a thin, family-linking `CampaignRunRecord` that is +content-addressed, run-counted, and **bit-identical on re-run** — persisted +intent finally has a consumer, and every id, axis, gate, and selection earns +its reason to exist. The authoring on-ramp that 0106 flagged is substantially +repaired too: `graph register` + `introspect --params` (file and store-id) + +`--content-id` file mode give a blueprint ref a resolvable path (F5-0106), and +`--unwired {}` makes the whole envelope, `seed` included, derivable (F1-0106). +The honest-refusal surface is a genuine strength — v1 boundary, empty gate +(exit 0 + truncation), plateau/deflate composition, stale wf vocabulary, and +every bad target are refused loudly, precisely, and with the correct +disposition. + +What remains is friction concentrated at the *first-author* edge, not the +loop: the on-ramp verbs disagree on op-script vs envelope shape and hide the +`graph build` bridge (F5); the `content:` prefix that every +`register`/`--content-id` prints is the exact form that silently breaks a ref +(F6); `campaign validate` blesses a campaign the executor then rejects for an +uncovered open param (F7); one preflight fault leaks a raw `Debug` struct +(F8); and the metric roster a process must name is still discoverable nowhere +(F9). None block the loop; all tax the newcomer. One spec silence to settle: +whether register-then-run should store before or after the gate (F10). + +Counts: working 4 (F1–F4), friction 4 (F5–F8), doc-gap 1 (F9), spec-gap 1 +(F10), bugs 0. + +## Orthogonal concern (out of 0107 scope) + +`aura new` (cycle 0103) scaffolds a **nested `.git` repo** inside the project +directory — a gitlink/submodule hazard when the scaffold is embedded in the +tracked `fieldtests/` corpus. `demo_project/.git` (and the large +`demo_project/target/`) were removed so the corpus commits cleanly. Worth a +scaffold-side note (`--no-git` or skip when nested under a repo). diff --git a/fieldtests/cycle-0107-campaign-executor/c0107_1_smacross.json b/fieldtests/cycle-0107-campaign-executor/c0107_1_smacross.json new file mode 100644 index 0000000..9f6372d --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/c0107_1_smacross.json @@ -0,0 +1,12 @@ +[ + {"op": "source", "role": "price", "kind": "F64"}, + {"op": "add", "type": "SMA", "name": "fast", "bind": {"length": {"I64": 8}}}, + {"op": "add", "type": "SMA", "name": "slow", "bind": {"length": {"I64": 16}}}, + {"op": "feed", "role": "price", "into": ["fast.series", "slow.series"]}, + {"op": "add", "type": "Sub", "name": "sub"}, + {"op": "connect", "from": "fast.value", "to": "sub.lhs"}, + {"op": "connect", "from": "slow.value", "to": "sub.rhs"}, + {"op": "add", "type": "Bias", "name": "bias"}, + {"op": "connect", "from": "sub.value", "to": "bias.signal"}, + {"op": "expose", "from": "bias.bias", "as": "bias"} +] diff --git a/fieldtests/cycle-0107-campaign-executor/c0107_1_smacross_open.json b/fieldtests/cycle-0107-campaign-executor/c0107_1_smacross_open.json new file mode 100644 index 0000000..ccbeb1a --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/c0107_1_smacross_open.json @@ -0,0 +1,12 @@ +[ + {"op": "source", "role": "price", "kind": "F64"}, + {"op": "add", "type": "SMA", "name": "fast"}, + {"op": "add", "type": "SMA", "name": "slow"}, + {"op": "feed", "role": "price", "into": ["fast.series", "slow.series"]}, + {"op": "add", "type": "Sub", "name": "sub"}, + {"op": "connect", "from": "fast.value", "to": "sub.lhs"}, + {"op": "connect", "from": "slow.value", "to": "sub.rhs"}, + {"op": "add", "type": "Bias", "name": "bias"}, + {"op": "connect", "from": "sub.value", "to": "bias.signal"}, + {"op": "expose", "from": "bias.bias", "as": "bias"} +] diff --git a/fieldtests/cycle-0107-campaign-executor/c0107_1_smacross_open_built.json b/fieldtests/cycle-0107-campaign-executor/c0107_1_smacross_open_built.json new file mode 100644 index 0000000..83ba539 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/c0107_1_smacross_open_built.json @@ -0,0 +1 @@ +{"format_version":1,"blueprint":{"name":"graph","nodes":[{"primitive":{"type":"SMA","name":"fast"}},{"primitive":{"type":"SMA","name":"slow"}},{"primitive":{"type":"Sub","name":"sub"}},{"primitive":{"type":"Bias","name":"bias"}}],"edges":[{"from":0,"to":2,"slot":0,"from_field":0},{"from":1,"to":2,"slot":1,"from_field":0},{"from":2,"to":3,"slot":0,"from_field":0}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0},{"node":1,"slot":0}],"source":"F64"}],"output":[{"node":3,"field":0,"name":"bias"}]}} \ No newline at end of file diff --git a/fieldtests/cycle-0107-campaign-executor/c0107_2_campaign.json b/fieldtests/cycle-0107-campaign-executor/c0107_2_campaign.json new file mode 100644 index 0000000..8e8c9af --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/c0107_2_campaign.json @@ -0,0 +1,18 @@ +{ + "format_version": 1, + "kind": "campaign", + "name": "ger40-smacross-wf", + "seed": 42, + "data": { "instruments": ["GER40"], "windows": [ { "from_ms": 1725148800000, "to_ms": 1727740800000 } ] }, + "strategies": [ + { + "ref": { "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" }, + "axes": { + "fast.length": { "kind": "I64", "values": [2, 4] }, + "slow.length": { "kind": "I64", "values": [8, 16] } + } + } + ], + "process": { "ref": { "content_id": "5a88cec04917fdcb328a1de6a8eccac8dcb56655631771eff2151a8d551708ea" } }, + "presentation": { "persist_taps": ["bias", "equity"], "emit": ["family_table", "selection_report"] } +} diff --git a/fieldtests/cycle-0107-campaign-executor/c0107_2_campaign_full.json b/fieldtests/cycle-0107-campaign-executor/c0107_2_campaign_full.json new file mode 100644 index 0000000..97a67f2 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/c0107_2_campaign_full.json @@ -0,0 +1,19 @@ +{ + "format_version": 1, + "kind": "campaign", + "name": "ger40-smacross-wf", + "seed": 42, + "data": { "instruments": ["GER40"], "windows": [ { "from_ms": 1725148800000, "to_ms": 1727740800000 } ] }, + "strategies": [ + { + "ref": { "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" }, + "axes": { + "fast.length": { "kind": "I64", "values": [2, 4] }, + "slow.length": { "kind": "I64", "values": [8, 16] }, + "bias.scale": { "kind": "F64", "values": [0.5] } + } + } + ], + "process": { "ref": { "content_id": "5a88cec04917fdcb328a1de6a8eccac8dcb56655631771eff2151a8d551708ea" } }, + "presentation": { "persist_taps": ["bias", "equity"], "emit": ["family_table", "selection_report"] } +} diff --git a/fieldtests/cycle-0107-campaign-executor/c0107_2_process.json b/fieldtests/cycle-0107-campaign-executor/c0107_2_process.json new file mode 100644 index 0000000..756f9b5 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/c0107_2_process.json @@ -0,0 +1,11 @@ +{ + "format_version": 1, + "kind": "process", + "name": "robust-sweep-wf-v1", + "description": "Sweep with deflation, gate on positive expectancy, then rolling walk-forward confirm.", + "pipeline": [ + { "block": "std::sweep", "metric": "sqn", "select": "argmax", "deflate": true }, + { "block": "std::gate", "all": [ { "metric": "expectancy_r", "cmp": "gt", "value": 0.0 } ] }, + { "block": "std::walk_forward", "in_sample_ms": 1209600000, "out_of_sample_ms": 604800000, "step_ms": 604800000, "mode": "rolling", "metric": "sqn", "select": "argmax" } + ] +} diff --git a/fieldtests/cycle-0107-campaign-executor/c0107_2_realization_campaign_runs.jsonl b/fieldtests/cycle-0107-campaign-executor/c0107_2_realization_campaign_runs.jsonl new file mode 100644 index 0000000..8bc5c58 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/c0107_2_realization_campaign_runs.jsonl @@ -0,0 +1,4 @@ +{"campaign":"533aed18e20983ba40cae49de74ab2d1506ecefbcdd5872af6f860b6a1c22345","process":"5a88cec04917fdcb328a1de6a8eccac8dcb56655631771eff2151a8d551708ea","run":0,"seed":42,"cells":[{"strategy":"597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a","instrument":"GER40","window_ms":[1725148800000,1727740800000],"stages":[{"block":"std::sweep","family_id":"533aed18-0-GER40-w0-s0-0","selection":{"winner_ordinal":0,"params":[["bias.scale",{"F64":0.5}],["fast.length",{"I64":2}],["slow.length",{"I64":8}]],"selection":{"selection_metric":"sqn","n_trials":4,"raw_winner_metric":1.0540214890316064,"mode":"Argmax","deflated_score":-1.0290009962190139,"overfit_probability":0.3876123876123876,"n_resamples":1000,"block_len":5,"seed":42}}},{"block":"std::gate","survivor_ordinals":[0,1,2]},{"block":"std::walk_forward","family_id":"533aed18-0-GER40-w0-s2-0"}]}]} +{"campaign":"533aed18e20983ba40cae49de74ab2d1506ecefbcdd5872af6f860b6a1c22345","process":"5a88cec04917fdcb328a1de6a8eccac8dcb56655631771eff2151a8d551708ea","run":1,"seed":42,"cells":[{"strategy":"597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a","instrument":"GER40","window_ms":[1725148800000,1727740800000],"stages":[{"block":"std::sweep","family_id":"533aed18-0-GER40-w0-s0-1","selection":{"winner_ordinal":0,"params":[["bias.scale",{"F64":0.5}],["fast.length",{"I64":2}],["slow.length",{"I64":8}]],"selection":{"selection_metric":"sqn","n_trials":4,"raw_winner_metric":1.0540214890316064,"mode":"Argmax","deflated_score":-1.0290009962190139,"overfit_probability":0.3876123876123876,"n_resamples":1000,"block_len":5,"seed":42}}},{"block":"std::gate","survivor_ordinals":[0,1,2]},{"block":"std::walk_forward","family_id":"533aed18-0-GER40-w0-s2-1"}]}]} +{"campaign":"533aed18e20983ba40cae49de74ab2d1506ecefbcdd5872af6f860b6a1c22345","process":"5a88cec04917fdcb328a1de6a8eccac8dcb56655631771eff2151a8d551708ea","run":2,"seed":42,"cells":[{"strategy":"597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a","instrument":"GER40","window_ms":[1725148800000,1727740800000],"stages":[{"block":"std::sweep","family_id":"533aed18-0-GER40-w0-s0-2","selection":{"winner_ordinal":0,"params":[["bias.scale",{"F64":0.5}],["fast.length",{"I64":2}],["slow.length",{"I64":8}]],"selection":{"selection_metric":"sqn","n_trials":4,"raw_winner_metric":1.0540214890316064,"mode":"Argmax","deflated_score":-1.0290009962190139,"overfit_probability":0.3876123876123876,"n_resamples":1000,"block_len":5,"seed":42}}},{"block":"std::gate","survivor_ordinals":[0,1,2]},{"block":"std::walk_forward","family_id":"533aed18-0-GER40-w0-s2-2"}]}]} +{"campaign":"d849dc2f3278782729a0c07094a3862514063463cc3d9245688245e146e041c8","process":"944cc95f14e6908c702a70eea4ea4190dcb5ee7c06d91be85a223c045c786e4c","run":0,"seed":42,"cells":[{"strategy":"597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a","instrument":"GER40","window_ms":[1725148800000,1727740800000],"stages":[{"block":"std::sweep","family_id":"d849dc2f-0-GER40-w0-s0-0","selection":{"winner_ordinal":0,"params":[["bias.scale",{"F64":0.5}],["fast.length",{"I64":2}],["slow.length",{"I64":8}]],"selection":{"selection_metric":"sqn","n_trials":4,"raw_winner_metric":1.0540214890316064,"mode":"Argmax"}}},{"block":"std::gate","survivor_ordinals":[]}]}]} diff --git a/fieldtests/cycle-0107-campaign-executor/c0107_3_campaign_badmetric.json b/fieldtests/cycle-0107-campaign-executor/c0107_3_campaign_badmetric.json new file mode 100644 index 0000000..0889c7b --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/c0107_3_campaign_badmetric.json @@ -0,0 +1,8 @@ +{ + "format_version": 1, "kind": "campaign", "name": "camp-badmetric", "seed": 42, + "data": { "instruments": ["GER40"], "windows": [ { "from_ms": 1725148800000, "to_ms": 1727740800000 } ] }, + "strategies": [ { "ref": { "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" }, + "axes": { "fast.length": { "kind": "I64", "values": [2, 4] }, "slow.length": { "kind": "I64", "values": [8, 16] }, "bias.scale": { "kind": "F64", "values": [0.5] } } } ], + "process": { "ref": { "content_id": "363feac72afb69fd2384ce851a339856fd6d1981d4b353777a75cacf89783fd8" } }, + "presentation": { "persist_taps": [], "emit": ["family_table", "selection_report"] } +} diff --git a/fieldtests/cycle-0107-campaign-executor/c0107_3_campaign_gateall.json b/fieldtests/cycle-0107-campaign-executor/c0107_3_campaign_gateall.json new file mode 100644 index 0000000..050a4ff --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/c0107_3_campaign_gateall.json @@ -0,0 +1,8 @@ +{ + "format_version": 1, "kind": "campaign", "name": "camp-gateall", "seed": 42, + "data": { "instruments": ["GER40"], "windows": [ { "from_ms": 1725148800000, "to_ms": 1727740800000 } ] }, + "strategies": [ { "ref": { "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" }, + "axes": { "fast.length": { "kind": "I64", "values": [2, 4] }, "slow.length": { "kind": "I64", "values": [8, 16] }, "bias.scale": { "kind": "F64", "values": [0.5] } } } ], + "process": { "ref": { "content_id": "944cc95f14e6908c702a70eea4ea4190dcb5ee7c06d91be85a223c045c786e4c" } }, + "presentation": { "persist_taps": [], "emit": ["family_table", "selection_report"] } +} diff --git a/fieldtests/cycle-0107-campaign-executor/c0107_3_campaign_mc.json b/fieldtests/cycle-0107-campaign-executor/c0107_3_campaign_mc.json new file mode 100644 index 0000000..a3cb307 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/c0107_3_campaign_mc.json @@ -0,0 +1,8 @@ +{ + "format_version": 1, "kind": "campaign", "name": "camp-mc", "seed": 42, + "data": { "instruments": ["GER40"], "windows": [ { "from_ms": 1725148800000, "to_ms": 1727740800000 } ] }, + "strategies": [ { "ref": { "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" }, + "axes": { "fast.length": { "kind": "I64", "values": [2, 4] }, "slow.length": { "kind": "I64", "values": [8, 16] }, "bias.scale": { "kind": "F64", "values": [0.5] } } } ], + "process": { "ref": { "content_id": "47af2e65dc2388b644e8fc8fbb872fca52e70bdf5090b4b3dac818dc9d1dfdce" } }, + "presentation": { "persist_taps": [], "emit": ["family_table", "selection_report"] } +} diff --git a/fieldtests/cycle-0107-campaign-executor/c0107_3_process_badmetric.json b/fieldtests/cycle-0107-campaign-executor/c0107_3_process_badmetric.json new file mode 100644 index 0000000..91d2530 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/c0107_3_process_badmetric.json @@ -0,0 +1,2 @@ +{ "format_version": 1, "kind": "process", "name": "sweep-badmetric", + "pipeline": [ { "block": "std::sweep", "metric": "profit_factor", "select": "argmax" } ] } diff --git a/fieldtests/cycle-0107-campaign-executor/c0107_3_process_gateall.json b/fieldtests/cycle-0107-campaign-executor/c0107_3_process_gateall.json new file mode 100644 index 0000000..702db32 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/c0107_3_process_gateall.json @@ -0,0 +1,6 @@ +{ "format_version": 1, "kind": "process", "name": "sweep-gateall-wf", + "pipeline": [ + { "block": "std::sweep", "metric": "sqn", "select": "argmax" }, + { "block": "std::gate", "all": [ { "metric": "expectancy_r", "cmp": "gt", "value": 100.0 } ] }, + { "block": "std::walk_forward", "in_sample_ms": 1209600000, "out_of_sample_ms": 604800000, "step_ms": 604800000, "mode": "rolling", "metric": "sqn", "select": "argmax" } + ] } diff --git a/fieldtests/cycle-0107-campaign-executor/c0107_3_process_mc.json b/fieldtests/cycle-0107-campaign-executor/c0107_3_process_mc.json new file mode 100644 index 0000000..fc8fed3 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/c0107_3_process_mc.json @@ -0,0 +1,5 @@ +{ "format_version": 1, "kind": "process", "name": "sweep-then-mc", + "pipeline": [ + { "block": "std::sweep", "metric": "sqn", "select": "argmax" }, + { "block": "std::monte_carlo", "resamples": 1000, "block_len": 5 } + ] } diff --git a/fieldtests/cycle-0107-campaign-executor/c0107_4_campaign_deflateplateau.json b/fieldtests/cycle-0107-campaign-executor/c0107_4_campaign_deflateplateau.json new file mode 100644 index 0000000..778161f --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/c0107_4_campaign_deflateplateau.json @@ -0,0 +1,5 @@ +{ "format_version": 1, "kind": "campaign", "name": "camp-deflate-plateau", "seed": 42, + "data": { "instruments": ["GER40"], "windows": [ { "from_ms": 1725148800000, "to_ms": 1727740800000 } ] }, + "strategies": [ { "ref": { "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" }, "axes": { "fast.length": { "kind": "I64", "values": [2,4] }, "slow.length": { "kind": "I64", "values": [8,16] }, "bias.scale": { "kind": "F64", "values": [0.5] } } } ], + "process": { "ref": { "content_id": "c588f8ad06028a447768b8566737a0c51f0df855350a131a6d08c50ae3f0df0f" } }, + "presentation": { "persist_taps": [], "emit": ["family_table"] } } diff --git a/fieldtests/cycle-0107-campaign-executor/c0107_4_campaign_plateauwf.json b/fieldtests/cycle-0107-campaign-executor/c0107_4_campaign_plateauwf.json new file mode 100644 index 0000000..ada7f55 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/c0107_4_campaign_plateauwf.json @@ -0,0 +1,5 @@ +{ "format_version": 1, "kind": "campaign", "name": "camp-plateau-wf", "seed": 42, + "data": { "instruments": ["GER40"], "windows": [ { "from_ms": 1725148800000, "to_ms": 1727740800000 } ] }, + "strategies": [ { "ref": { "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" }, "axes": { "fast.length": { "kind": "I64", "values": [2,4] }, "slow.length": { "kind": "I64", "values": [8,16] }, "bias.scale": { "kind": "F64", "values": [0.5] } } } ], + "process": { "ref": { "content_id": "34d67ae1bdc029157fe36a68d6298e7869483a8a1d05c566fcf9e901dadc84d4" } }, + "presentation": { "persist_taps": [], "emit": ["family_table"] } } diff --git a/fieldtests/cycle-0107-campaign-executor/c0107_4_campaign_prefixref.json b/fieldtests/cycle-0107-campaign-executor/c0107_4_campaign_prefixref.json new file mode 100644 index 0000000..ca7e00a --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/c0107_4_campaign_prefixref.json @@ -0,0 +1,5 @@ +{ "format_version": 1, "kind": "campaign", "name": "prefix-trap", "seed": 42, + "data": { "instruments": ["GER40"], "windows": [ { "from_ms": 1725148800000, "to_ms": 1727740800000 } ] }, + "strategies": [ { "ref": { "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" }, "axes": { "fast.length": { "kind": "I64", "values": [2,4] }, "slow.length": { "kind": "I64", "values": [8,16] }, "bias.scale": { "kind": "F64", "values": [0.5] } } } ], + "process": { "ref": { "content_id": "content:5a88cec04917fdcb328a1de6a8eccac8dcb56655631771eff2151a8d551708ea" } }, + "presentation": { "persist_taps": [], "emit": ["family_table"] } } diff --git a/fieldtests/cycle-0107-campaign-executor/c0107_4_campaign_wf_toobig.json b/fieldtests/cycle-0107-campaign-executor/c0107_4_campaign_wf_toobig.json new file mode 100644 index 0000000..c0ffbf3 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/c0107_4_campaign_wf_toobig.json @@ -0,0 +1,5 @@ +{ "format_version": 1, "kind": "campaign", "name": "wf-toobig", "seed": 42, + "data": { "instruments": ["GER40"], "windows": [ { "from_ms": 1725148800000, "to_ms": 1727740800000 } ] }, + "strategies": [ { "ref": { "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" }, "axes": { "fast.length": { "kind": "I64", "values": [2,4] }, "slow.length": { "kind": "I64", "values": [8,16] }, "bias.scale": { "kind": "F64", "values": [0.5] } } } ], + "process": { "ref": { "content_id": "6e17d18baa2cfc27826bab5e0304d0d6e6e082921fcaad7fd585d858485db9cc" } }, + "presentation": { "persist_taps": [], "emit": ["family_table"] } } diff --git a/fieldtests/cycle-0107-campaign-executor/c0107_4_process_deflate_plateau.json b/fieldtests/cycle-0107-campaign-executor/c0107_4_process_deflate_plateau.json new file mode 100644 index 0000000..9756dee --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/c0107_4_process_deflate_plateau.json @@ -0,0 +1,2 @@ +{ "format_version": 1, "kind": "process", "name": "deflate-plateau", + "pipeline": [ { "block": "std::sweep", "metric": "sqn", "select": "plateau:worst", "deflate": true } ] } diff --git a/fieldtests/cycle-0107-campaign-executor/c0107_4_process_plateau_wf.json b/fieldtests/cycle-0107-campaign-executor/c0107_4_process_plateau_wf.json new file mode 100644 index 0000000..b8da259 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/c0107_4_process_plateau_wf.json @@ -0,0 +1,3 @@ +{ "format_version": 1, "kind": "process", "name": "plateau-in-wf", + "pipeline": [ { "block": "std::sweep", "metric": "sqn", "select": "argmax" }, + { "block": "std::walk_forward", "in_sample_ms": 1209600000, "out_of_sample_ms": 604800000, "step_ms": 604800000, "mode": "rolling", "metric": "sqn", "select": "plateau:mean" } ] } diff --git a/fieldtests/cycle-0107-campaign-executor/c0107_4_process_wf_toobig.json b/fieldtests/cycle-0107-campaign-executor/c0107_4_process_wf_toobig.json new file mode 100644 index 0000000..5435c10 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/c0107_4_process_wf_toobig.json @@ -0,0 +1,3 @@ +{ "format_version": 1, "kind": "process", "name": "wf-toobig", + "pipeline": [ { "block": "std::sweep", "metric": "sqn", "select": "argmax" }, + { "block": "std::walk_forward", "in_sample_ms": 315360000000, "out_of_sample_ms": 604800000, "step_ms": 604800000, "mode": "rolling", "metric": "sqn", "select": "argmax" } ] } diff --git a/fieldtests/cycle-0107-campaign-executor/c0107_probe_badmetric.json b/fieldtests/cycle-0107-campaign-executor/c0107_probe_badmetric.json new file mode 100644 index 0000000..d21e8a8 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/c0107_probe_badmetric.json @@ -0,0 +1 @@ +{ "format_version": 1, "kind": "process", "name": "bad", "pipeline": [ { "block": "std::sweep", "metric": "profit_factor", "select": "argmax" } ] } diff --git a/fieldtests/cycle-0107-campaign-executor/demo_project/.gitignore b/fieldtests/cycle-0107-campaign-executor/demo_project/.gitignore new file mode 100644 index 0000000..af5cf3d --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/demo_project/.gitignore @@ -0,0 +1,3 @@ +/target +Cargo.lock +/runs diff --git a/fieldtests/cycle-0107-campaign-executor/demo_project/Aura.toml b/fieldtests/cycle-0107-campaign-executor/demo_project/Aura.toml new file mode 100644 index 0000000..af335c1 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/demo_project/Aura.toml @@ -0,0 +1,3 @@ +# Static project context only (C17); paths only. +[paths] +runs = "runs" diff --git a/fieldtests/cycle-0107-campaign-executor/demo_project/CLAUDE.md b/fieldtests/cycle-0107-campaign-executor/demo_project/CLAUDE.md new file mode 100644 index 0000000..6215473 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/demo_project/CLAUDE.md @@ -0,0 +1,10 @@ +# demo_project — an aura research project + +This crate is an aura project: a cdylib of node/strategy blueprints the +`aura` host loads during research (see the engine's docs/project-layout.md). + +- Build: `cargo build` (the next `aura` invocation loads the fresh dylib) +- Run: `aura run blueprints/signal.json` (from anywhere inside this dir) +- Nodes live in `src/`; each is registered in `vocabulary()`/`type_ids()` + under the `demo_project::` namespace prefix. +- Topology is data (`blueprints/*.json`), node logic is Rust. diff --git a/fieldtests/cycle-0107-campaign-executor/demo_project/Cargo.toml b/fieldtests/cycle-0107-campaign-executor/demo_project/Cargo.toml new file mode 100644 index 0000000..a1a64b5 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/demo_project/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "demo_project" +version = "0.1.0" +edition = "2024" +publish = false + +[lib] +crate-type = ["cdylib"] + +[dependencies] +aura-core = { path = "/home/brummel/dev/aura/crates/aura-core" } + +# Standalone workspace root: never a member of an enclosing workspace. +[workspace] diff --git a/fieldtests/cycle-0107-campaign-executor/demo_project/blueprints/signal.json b/fieldtests/cycle-0107-campaign-executor/demo_project/blueprints/signal.json new file mode 100644 index 0000000..f5b0f4e --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/demo_project/blueprints/signal.json @@ -0,0 +1 @@ +{"format_version":1,"blueprint":{"name":"demo_project_signal","nodes":[{"primitive":{"type":"SMA","name":"fast","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":2}}]}},{"primitive":{"type":"SMA","name":"slow","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":4}}]}},{"primitive":{"type":"Sub"}},{"primitive":{"type":"Bias","name":"bias","bound":[{"pos":0,"name":"scale","kind":"F64","value":{"F64":0.5}}]}},{"primitive":{"type":"demo_project::Identity"}}],"edges":[{"from":0,"to":2,"slot":0,"from_field":0},{"from":1,"to":2,"slot":1,"from_field":0},{"from":2,"to":3,"slot":0,"from_field":0},{"from":3,"to":4,"slot":0,"from_field":0}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0},{"node":1,"slot":0}],"source":"F64"}],"output":[{"node":4,"field":0,"name":"bias"}]}} \ No newline at end of file diff --git a/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_2_campaign.json b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_2_campaign.json new file mode 100644 index 0000000..8e8c9af --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_2_campaign.json @@ -0,0 +1,18 @@ +{ + "format_version": 1, + "kind": "campaign", + "name": "ger40-smacross-wf", + "seed": 42, + "data": { "instruments": ["GER40"], "windows": [ { "from_ms": 1725148800000, "to_ms": 1727740800000 } ] }, + "strategies": [ + { + "ref": { "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" }, + "axes": { + "fast.length": { "kind": "I64", "values": [2, 4] }, + "slow.length": { "kind": "I64", "values": [8, 16] } + } + } + ], + "process": { "ref": { "content_id": "5a88cec04917fdcb328a1de6a8eccac8dcb56655631771eff2151a8d551708ea" } }, + "presentation": { "persist_taps": ["bias", "equity"], "emit": ["family_table", "selection_report"] } +} diff --git a/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_2_campaign_full.json b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_2_campaign_full.json new file mode 100644 index 0000000..97a67f2 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_2_campaign_full.json @@ -0,0 +1,19 @@ +{ + "format_version": 1, + "kind": "campaign", + "name": "ger40-smacross-wf", + "seed": 42, + "data": { "instruments": ["GER40"], "windows": [ { "from_ms": 1725148800000, "to_ms": 1727740800000 } ] }, + "strategies": [ + { + "ref": { "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" }, + "axes": { + "fast.length": { "kind": "I64", "values": [2, 4] }, + "slow.length": { "kind": "I64", "values": [8, 16] }, + "bias.scale": { "kind": "F64", "values": [0.5] } + } + } + ], + "process": { "ref": { "content_id": "5a88cec04917fdcb328a1de6a8eccac8dcb56655631771eff2151a8d551708ea" } }, + "presentation": { "persist_taps": ["bias", "equity"], "emit": ["family_table", "selection_report"] } +} diff --git a/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_3_campaign_badmetric.json b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_3_campaign_badmetric.json new file mode 100644 index 0000000..0889c7b --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_3_campaign_badmetric.json @@ -0,0 +1,8 @@ +{ + "format_version": 1, "kind": "campaign", "name": "camp-badmetric", "seed": 42, + "data": { "instruments": ["GER40"], "windows": [ { "from_ms": 1725148800000, "to_ms": 1727740800000 } ] }, + "strategies": [ { "ref": { "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" }, + "axes": { "fast.length": { "kind": "I64", "values": [2, 4] }, "slow.length": { "kind": "I64", "values": [8, 16] }, "bias.scale": { "kind": "F64", "values": [0.5] } } } ], + "process": { "ref": { "content_id": "363feac72afb69fd2384ce851a339856fd6d1981d4b353777a75cacf89783fd8" } }, + "presentation": { "persist_taps": [], "emit": ["family_table", "selection_report"] } +} diff --git a/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_3_campaign_gateall.json b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_3_campaign_gateall.json new file mode 100644 index 0000000..050a4ff --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_3_campaign_gateall.json @@ -0,0 +1,8 @@ +{ + "format_version": 1, "kind": "campaign", "name": "camp-gateall", "seed": 42, + "data": { "instruments": ["GER40"], "windows": [ { "from_ms": 1725148800000, "to_ms": 1727740800000 } ] }, + "strategies": [ { "ref": { "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" }, + "axes": { "fast.length": { "kind": "I64", "values": [2, 4] }, "slow.length": { "kind": "I64", "values": [8, 16] }, "bias.scale": { "kind": "F64", "values": [0.5] } } } ], + "process": { "ref": { "content_id": "944cc95f14e6908c702a70eea4ea4190dcb5ee7c06d91be85a223c045c786e4c" } }, + "presentation": { "persist_taps": [], "emit": ["family_table", "selection_report"] } +} diff --git a/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_3_campaign_mc.json b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_3_campaign_mc.json new file mode 100644 index 0000000..a3cb307 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_3_campaign_mc.json @@ -0,0 +1,8 @@ +{ + "format_version": 1, "kind": "campaign", "name": "camp-mc", "seed": 42, + "data": { "instruments": ["GER40"], "windows": [ { "from_ms": 1725148800000, "to_ms": 1727740800000 } ] }, + "strategies": [ { "ref": { "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" }, + "axes": { "fast.length": { "kind": "I64", "values": [2, 4] }, "slow.length": { "kind": "I64", "values": [8, 16] }, "bias.scale": { "kind": "F64", "values": [0.5] } } } ], + "process": { "ref": { "content_id": "47af2e65dc2388b644e8fc8fbb872fca52e70bdf5090b4b3dac818dc9d1dfdce" } }, + "presentation": { "persist_taps": [], "emit": ["family_table", "selection_report"] } +} diff --git a/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_3_process_badmetric.json b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_3_process_badmetric.json new file mode 100644 index 0000000..91d2530 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_3_process_badmetric.json @@ -0,0 +1,2 @@ +{ "format_version": 1, "kind": "process", "name": "sweep-badmetric", + "pipeline": [ { "block": "std::sweep", "metric": "profit_factor", "select": "argmax" } ] } diff --git a/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_3_process_gateall.json b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_3_process_gateall.json new file mode 100644 index 0000000..702db32 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_3_process_gateall.json @@ -0,0 +1,6 @@ +{ "format_version": 1, "kind": "process", "name": "sweep-gateall-wf", + "pipeline": [ + { "block": "std::sweep", "metric": "sqn", "select": "argmax" }, + { "block": "std::gate", "all": [ { "metric": "expectancy_r", "cmp": "gt", "value": 100.0 } ] }, + { "block": "std::walk_forward", "in_sample_ms": 1209600000, "out_of_sample_ms": 604800000, "step_ms": 604800000, "mode": "rolling", "metric": "sqn", "select": "argmax" } + ] } diff --git a/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_3_process_mc.json b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_3_process_mc.json new file mode 100644 index 0000000..fc8fed3 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_3_process_mc.json @@ -0,0 +1,5 @@ +{ "format_version": 1, "kind": "process", "name": "sweep-then-mc", + "pipeline": [ + { "block": "std::sweep", "metric": "sqn", "select": "argmax" }, + { "block": "std::monte_carlo", "resamples": 1000, "block_len": 5 } + ] } diff --git a/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_4_campaign_deflateplateau.json b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_4_campaign_deflateplateau.json new file mode 100644 index 0000000..778161f --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_4_campaign_deflateplateau.json @@ -0,0 +1,5 @@ +{ "format_version": 1, "kind": "campaign", "name": "camp-deflate-plateau", "seed": 42, + "data": { "instruments": ["GER40"], "windows": [ { "from_ms": 1725148800000, "to_ms": 1727740800000 } ] }, + "strategies": [ { "ref": { "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" }, "axes": { "fast.length": { "kind": "I64", "values": [2,4] }, "slow.length": { "kind": "I64", "values": [8,16] }, "bias.scale": { "kind": "F64", "values": [0.5] } } } ], + "process": { "ref": { "content_id": "c588f8ad06028a447768b8566737a0c51f0df855350a131a6d08c50ae3f0df0f" } }, + "presentation": { "persist_taps": [], "emit": ["family_table"] } } diff --git a/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_4_campaign_plateauwf.json b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_4_campaign_plateauwf.json new file mode 100644 index 0000000..ada7f55 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_4_campaign_plateauwf.json @@ -0,0 +1,5 @@ +{ "format_version": 1, "kind": "campaign", "name": "camp-plateau-wf", "seed": 42, + "data": { "instruments": ["GER40"], "windows": [ { "from_ms": 1725148800000, "to_ms": 1727740800000 } ] }, + "strategies": [ { "ref": { "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" }, "axes": { "fast.length": { "kind": "I64", "values": [2,4] }, "slow.length": { "kind": "I64", "values": [8,16] }, "bias.scale": { "kind": "F64", "values": [0.5] } } } ], + "process": { "ref": { "content_id": "34d67ae1bdc029157fe36a68d6298e7869483a8a1d05c566fcf9e901dadc84d4" } }, + "presentation": { "persist_taps": [], "emit": ["family_table"] } } diff --git a/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_4_campaign_prefixref.json b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_4_campaign_prefixref.json new file mode 100644 index 0000000..ca7e00a --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_4_campaign_prefixref.json @@ -0,0 +1,5 @@ +{ "format_version": 1, "kind": "campaign", "name": "prefix-trap", "seed": 42, + "data": { "instruments": ["GER40"], "windows": [ { "from_ms": 1725148800000, "to_ms": 1727740800000 } ] }, + "strategies": [ { "ref": { "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" }, "axes": { "fast.length": { "kind": "I64", "values": [2,4] }, "slow.length": { "kind": "I64", "values": [8,16] }, "bias.scale": { "kind": "F64", "values": [0.5] } } } ], + "process": { "ref": { "content_id": "content:5a88cec04917fdcb328a1de6a8eccac8dcb56655631771eff2151a8d551708ea" } }, + "presentation": { "persist_taps": [], "emit": ["family_table"] } } diff --git a/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_4_campaign_wf_toobig.json b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_4_campaign_wf_toobig.json new file mode 100644 index 0000000..c0ffbf3 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_4_campaign_wf_toobig.json @@ -0,0 +1,5 @@ +{ "format_version": 1, "kind": "campaign", "name": "wf-toobig", "seed": 42, + "data": { "instruments": ["GER40"], "windows": [ { "from_ms": 1725148800000, "to_ms": 1727740800000 } ] }, + "strategies": [ { "ref": { "content_id": "597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876dafba9a" }, "axes": { "fast.length": { "kind": "I64", "values": [2,4] }, "slow.length": { "kind": "I64", "values": [8,16] }, "bias.scale": { "kind": "F64", "values": [0.5] } } } ], + "process": { "ref": { "content_id": "6e17d18baa2cfc27826bab5e0304d0d6e6e082921fcaad7fd585d858485db9cc" } }, + "presentation": { "persist_taps": [], "emit": ["family_table"] } } diff --git a/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_4_process_deflate_plateau.json b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_4_process_deflate_plateau.json new file mode 100644 index 0000000..9756dee --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_4_process_deflate_plateau.json @@ -0,0 +1,2 @@ +{ "format_version": 1, "kind": "process", "name": "deflate-plateau", + "pipeline": [ { "block": "std::sweep", "metric": "sqn", "select": "plateau:worst", "deflate": true } ] } diff --git a/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_4_process_plateau_wf.json b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_4_process_plateau_wf.json new file mode 100644 index 0000000..b8da259 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_4_process_plateau_wf.json @@ -0,0 +1,3 @@ +{ "format_version": 1, "kind": "process", "name": "plateau-in-wf", + "pipeline": [ { "block": "std::sweep", "metric": "sqn", "select": "argmax" }, + { "block": "std::walk_forward", "in_sample_ms": 1209600000, "out_of_sample_ms": 604800000, "step_ms": 604800000, "mode": "rolling", "metric": "sqn", "select": "plateau:mean" } ] } diff --git a/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_4_process_wf_toobig.json b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_4_process_wf_toobig.json new file mode 100644 index 0000000..5435c10 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/demo_project/c0107_4_process_wf_toobig.json @@ -0,0 +1,3 @@ +{ "format_version": 1, "kind": "process", "name": "wf-toobig", + "pipeline": [ { "block": "std::sweep", "metric": "sqn", "select": "argmax" }, + { "block": "std::walk_forward", "in_sample_ms": 315360000000, "out_of_sample_ms": 604800000, "step_ms": 604800000, "mode": "rolling", "metric": "sqn", "select": "argmax" } ] } diff --git a/fieldtests/cycle-0107-campaign-executor/demo_project/src/lib.rs b/fieldtests/cycle-0107-campaign-executor/demo_project/src/lib.rs new file mode 100644 index 0000000..80ad233 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/demo_project/src/lib.rs @@ -0,0 +1,76 @@ +//! demo_project — an aura research project: node logic + the exported vocabulary. +//! +//! Every node type this crate provides is registered in `vocabulary()` / +//! `type_ids()` under the `demo_project::` namespace prefix; the `aura` host loads +//! this cdylib per invocation and merges it with the std vocabulary. + +use aura_core::{ + Cell, Ctx, FieldSpec, Firing, Node, NodeSchema, PortSpec, PrimitiveBuilder, + ScalarKind, +}; + +/// One-input f64 pass-through. Emits `None` until its input has a value. +pub struct Identity { + out: [Cell; 1], +} + +impl Identity { + pub fn new() -> Self { + Self { out: [Cell::from_f64(0.0)] } + } + pub fn builder() -> PrimitiveBuilder { + PrimitiveBuilder::new( + "demo_project::Identity", + NodeSchema { + inputs: vec![PortSpec { + kind: ScalarKind::F64, + firing: Firing::Any, + name: "value".into(), + }], + output: vec![FieldSpec { name: "value".into(), kind: ScalarKind::F64 }], + params: vec![], + }, + |_| Box::new(Identity::new()), + ) + } +} + +impl Default for Identity { + fn default() -> Self { + Self::new() + } +} + +impl Node for Identity { + fn lookbacks(&self) -> Vec { + vec![1] + } + fn eval(&mut self, ctx: Ctx<'_>) -> Option<&[Cell]> { + let w = ctx.f64_in(0); + if w.is_empty() { + return None; + } + self.out[0] = Cell::from_f64(w[0]); + Some(&self.out) + } + fn label(&self) -> String { + "demo_project::Identity".to_string() + } +} + +fn vocabulary(type_id: &str) -> Option { + match type_id { + "demo_project::Identity" => Some(Identity::builder()), + _ => None, + } +} + +fn type_ids() -> &'static [&'static str] { + &["demo_project::Identity"] +} + +aura_core::aura_project! { + namespace: "demo_project", + vocabulary: vocabulary, + type_ids: type_ids, +} diff --git a/fieldtests/cycle-0107-campaign-executor/runs/blueprints/573262f2650fd2749427adaec41c148744597c6923fd7e829cb46ceccd105777.json b/fieldtests/cycle-0107-campaign-executor/runs/blueprints/573262f2650fd2749427adaec41c148744597c6923fd7e829cb46ceccd105777.json new file mode 100644 index 0000000..f50e431 --- /dev/null +++ b/fieldtests/cycle-0107-campaign-executor/runs/blueprints/573262f2650fd2749427adaec41c148744597c6923fd7e829cb46ceccd105777.json @@ -0,0 +1 @@ +{"format_version":1,"blueprint":{"name":"graph","nodes":[{"primitive":{"type":"SMA","name":"fast","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":8}}]}},{"primitive":{"type":"SMA","name":"slow","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":16}}]}},{"primitive":{"type":"Sub","name":"sub"}},{"primitive":{"type":"Bias","name":"bias"}}],"edges":[{"from":0,"to":2,"slot":0,"from_field":0},{"from":1,"to":2,"slot":1,"from_field":0},{"from":2,"to":3,"slot":0,"from_field":0}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0},{"node":1,"slot":0}],"source":"F64"}],"output":[{"node":3,"field":0,"name":"bias"}]}} \ No newline at end of file