fieldtest: cycle-0107 campaign executor + on-ramp corpus (GREEN-core)
Verdict: the 0106 F7 wire is closed — campaign+process documents drive aura campaign run through sweep -> gate -> walk_forward over the real GER40 archive, realization recorded as a thin family-linking CampaignRunRecord, bit-identical on re-run and across file/id addressing (C1). 0106 F1/F5 on-ramp gaps confirmed repaired; the honest-refusal surface (v1 boundary, empty gate exit 0 + truncation, plateau/deflate composition, stale wf vocabulary, bad targets, persist_taps loud deferral) exercised and clean. 0 bugs. Findings triaged: F5 -> #202 (op-script vs envelope shape on the on-ramp verbs), F6 -> #194 comment (content: prefix trap re-confirmed, now spans graph register), F7 -> #203 (open-param coverage at validate; raw-vs-wrapped path prose), F8 -> RED-first fix follows this commit (SpanTooShort Debug leak), F9 -> #197 comment (rankable/per-member roster split undiscoverable), F10 -> ratified store-before-gate on #198 (derived: consistent with campaign register's intrinsic-only gate; content-addressed store is an idempotent intent archive). Orthogonal: #204 (aura new nested-.git gitlink hazard). refs #198
This commit is contained in:
@@ -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 <bare {}>` 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 <id> in the project store` / `campaign run needs a
|
||||
project: … no Aura.toml found up from <cwd>`).
|
||||
- `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:<hash>`, 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 <file>` issued left a `runs/campaigns/<id>.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).
|
||||
@@ -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"}
|
||||
]
|
||||
@@ -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"}
|
||||
]
|
||||
@@ -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"}]}}
|
||||
@@ -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"] }
|
||||
}
|
||||
@@ -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"] }
|
||||
}
|
||||
@@ -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" }
|
||||
]
|
||||
}
|
||||
@@ -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":[]}]}]}
|
||||
@@ -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"] }
|
||||
}
|
||||
@@ -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"] }
|
||||
}
|
||||
@@ -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"] }
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
{ "format_version": 1, "kind": "process", "name": "sweep-badmetric",
|
||||
"pipeline": [ { "block": "std::sweep", "metric": "profit_factor", "select": "argmax" } ] }
|
||||
@@ -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" }
|
||||
] }
|
||||
@@ -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 }
|
||||
] }
|
||||
@@ -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"] } }
|
||||
@@ -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"] } }
|
||||
@@ -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"] } }
|
||||
@@ -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"] } }
|
||||
@@ -0,0 +1,2 @@
|
||||
{ "format_version": 1, "kind": "process", "name": "deflate-plateau",
|
||||
"pipeline": [ { "block": "std::sweep", "metric": "sqn", "select": "plateau:worst", "deflate": true } ] }
|
||||
@@ -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" } ] }
|
||||
@@ -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" } ] }
|
||||
@@ -0,0 +1 @@
|
||||
{ "format_version": 1, "kind": "process", "name": "bad", "pipeline": [ { "block": "std::sweep", "metric": "profit_factor", "select": "argmax" } ] }
|
||||
@@ -0,0 +1,3 @@
|
||||
/target
|
||||
Cargo.lock
|
||||
/runs
|
||||
@@ -0,0 +1,3 @@
|
||||
# Static project context only (C17); paths only.
|
||||
[paths]
|
||||
runs = "runs"
|
||||
@@ -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.
|
||||
@@ -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]
|
||||
@@ -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"}]}}
|
||||
@@ -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"] }
|
||||
}
|
||||
@@ -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"] }
|
||||
}
|
||||
@@ -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"] }
|
||||
}
|
||||
@@ -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"] }
|
||||
}
|
||||
@@ -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"] }
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
{ "format_version": 1, "kind": "process", "name": "sweep-badmetric",
|
||||
"pipeline": [ { "block": "std::sweep", "metric": "profit_factor", "select": "argmax" } ] }
|
||||
@@ -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" }
|
||||
] }
|
||||
@@ -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 }
|
||||
] }
|
||||
+5
@@ -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"] } }
|
||||
@@ -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"] } }
|
||||
@@ -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"] } }
|
||||
@@ -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"] } }
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
{ "format_version": 1, "kind": "process", "name": "deflate-plateau",
|
||||
"pipeline": [ { "block": "std::sweep", "metric": "sqn", "select": "plateau:worst", "deflate": true } ] }
|
||||
@@ -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" } ] }
|
||||
@@ -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" } ] }
|
||||
@@ -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<usize> {
|
||||
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<PrimitiveBuilder> {
|
||||
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,
|
||||
}
|
||||
+1
@@ -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"}]}}
|
||||
Reference in New Issue
Block a user