From 697d81dd22616979f45a4250991b85cbdae2a3d8 Mon Sep 17 00:00:00 2001 From: claude Date: Fri, 24 Jul 2026 23:43:53 +0200 Subject: [PATCH] =?UTF-8?q?fieldtest:=20m37=20data-authorability-boundary?= =?UTF-8?q?=20=E2=80=94=203=20scenarios,=200=20bugs=20/=202=20friction=20/?= =?UTF-8?q?=201=20spec-gap=20/=204=20working?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Milestone-close gate for milestone 37 (data-authorability boundary, #310/#317/#271): source-blind consumer fieldtest against the release binary at eb2b0a1, scenarios derived top-down from the milestone promise rather than per-cycle axes. - m37_1: NY Session authored via args + fold-selected taps, run e2e over US500 (default and --tap plans; summaries correct, unlisted tap inert). - m37_2: London anchor registered by name, spliced via use into a consumer with open SMA lengths, swept over GER40, reproduced 2/2 bit-identical (v2 propagates through the splice). - m37_3a-e: five-way boundary-refusal battery; all exit 1 with actionable prose, escalation path named for namespaced types. Gate verdict: green — all three boundary mechanisms deliver the promise; genuinely-new logic is turned away toward Rust. Findings routed: fold-summary read-back absorbed into #309, cross-run tap-file lifecycle evidence onto #311, bare-refusal escalation-pointer parity onto #341 (refs #309, refs #311, refs #341). --- .../TRANSCRIPT.md | 134 ++++++++++++++++++ .../m37_1_build.err | 0 .../m37_1_fold_summary_rows.txt | 10 ++ .../m37_1_ny_momentum.bp.json | 1 + .../m37_1_ny_momentum.folds.run.json | 1 + .../m37_1_ny_momentum.ops.json | 31 ++++ .../m37_1_ny_momentum.run.json | 1 + .../m37_2_consumer.bp.json | 1 + .../m37_2_consumer.echo.txt | 1 + .../m37_2_consumer.ops.json | 25 ++++ .../m37_2_london_anchor.bp.json | 1 + .../m37_2_london_anchor.ops.json | 9 ++ .../m37_2_sweep.err | 0 .../m37_2_sweep.jsonl | 2 + .../m37_3a_new_logic.ops.json | 9 ++ .../m37_3b_session_no_args.ops.json | 7 + .../m37_3c_args_on_argless.ops.json | 9 ++ .../m37_3e_unknown_label.ops.json | 9 ++ 18 files changed, 251 insertions(+) create mode 100644 fieldtests/m37-data-authorability-boundary/TRANSCRIPT.md create mode 100644 fieldtests/m37-data-authorability-boundary/m37_1_build.err create mode 100644 fieldtests/m37-data-authorability-boundary/m37_1_fold_summary_rows.txt create mode 100644 fieldtests/m37-data-authorability-boundary/m37_1_ny_momentum.bp.json create mode 100644 fieldtests/m37-data-authorability-boundary/m37_1_ny_momentum.folds.run.json create mode 100644 fieldtests/m37-data-authorability-boundary/m37_1_ny_momentum.ops.json create mode 100644 fieldtests/m37-data-authorability-boundary/m37_1_ny_momentum.run.json create mode 100644 fieldtests/m37-data-authorability-boundary/m37_2_consumer.bp.json create mode 100644 fieldtests/m37-data-authorability-boundary/m37_2_consumer.echo.txt create mode 100644 fieldtests/m37-data-authorability-boundary/m37_2_consumer.ops.json create mode 100644 fieldtests/m37-data-authorability-boundary/m37_2_london_anchor.bp.json create mode 100644 fieldtests/m37-data-authorability-boundary/m37_2_london_anchor.ops.json create mode 100644 fieldtests/m37-data-authorability-boundary/m37_2_sweep.err create mode 100644 fieldtests/m37-data-authorability-boundary/m37_2_sweep.jsonl create mode 100644 fieldtests/m37-data-authorability-boundary/m37_3a_new_logic.ops.json create mode 100644 fieldtests/m37-data-authorability-boundary/m37_3b_session_no_args.ops.json create mode 100644 fieldtests/m37-data-authorability-boundary/m37_3c_args_on_argless.ops.json create mode 100644 fieldtests/m37-data-authorability-boundary/m37_3e_unknown_label.ops.json diff --git a/fieldtests/m37-data-authorability-boundary/TRANSCRIPT.md b/fieldtests/m37-data-authorability-boundary/TRANSCRIPT.md new file mode 100644 index 0000000..4c97b59 --- /dev/null +++ b/fieldtests/m37-data-authorability-boundary/TRANSCRIPT.md @@ -0,0 +1,134 @@ +# Fieldtest transcript — milestone-37 (data-authorability boundary) + +Milestone-scope field test: the three data-authorability sites as ONE +downstream story — fold selection as run-mode data (#310), a registered +composite spliced by name (#317), construction args configuring non-scalar +structure (#271) — and the boundary refusing what stays Rust-only. + +Binary: `target/release/aura`, built from HEAD `eb2b0a1` via +`cargo build --workspace --release` (Finished in 5.53s, incremental — HEAD +builds clean). Scratch project `aura new m37_lab` in `/tmp/m37_lab`; real data +from the built-in Pepperstone archive. Public interface only (README, +authoring-guide, glossary, design ledger, `aura … --help`, `graph introspect`) — +no crate source read. + +--- + +## Scenario 1 — `m37_1_ny_momentum` — Session args + fold-selected taps, e2e + +A NY first-session-bar momentum strategy authored purely as data: `Session` +configured to `America/New_York` / `09:30` through the `args` channel, gating a +SMA(5)−SMA(20) sign onto the first 15m session bar. Four declared taps +(`spread`, `first_bar`, `gated_signal`, `slow_ma`). + +``` +$ aura graph build < m37_1_ny_momentum.ops.json > m37_1_ny_momentum.bp.json +$ head -c 25 m37_1_ny_momentum.bp.json +{"format_version":2,"blue # arg-bearing Session -> v2 +$ aura graph introspect --params m37_1_ny_momentum.ops.json + # (empty = closed, runnable) +$ aura graph introspect --content-id --identity-id < m37_1_ny_momentum.ops.json +c8e123f0a8948034592eb5b15f32e9a3d6b0705c4c942e7563f655faa0d1e9f1 +31de7ebd09122b9cef690618dbbdc08257056745b948840734982cd62a611265 + +# default plan (record all four taps): +$ aura run m37_1_ny_momentum.bp.json --real US500 --from 1725148800000 --to 1725580800000 +{"manifest":{... "topology_hash":"c8e123f0..." ...},"metrics":{"total_pips":-2.099..., + "r":{"expectancy_r":0.1566...,"n_trades":10, ...}}} (exit 0, no stderr) + +# fold-selected plan: spread=mean, first_bar=count, gated_signal=last; slow_ma unlisted +$ aura run m37_1_ny_momentum.bp.json --real US500 --from 1725148800000 --to 1725580800000 \ + --tap spread=mean --tap first_bar=count --tap gated_signal=last +{"manifest":{...IDENTICAL manifest+metrics as the default run...}} (exit 0) +# stderr: aura: note: declared tap "slow_ma" unbound this run +``` + +The fold summary rows (the reason to pick a fold over `record`) land ONLY in +the trace store, not on the run's stdout (see `m37_1_fold_summary_rows.txt`): + +``` +runs/traces/graph/index.json "taps":["spread","first_bar","gated_signal"] # slow_ma excluded +spread.json {"tap":"spread","kinds":["F64"],"ts":[...],"columns":[[-0.2033544...]]} # mean +first_bar.json {"tap":"first_bar","kinds":["I64"],"ts":[...],"columns":[[5239.0]]} # count = warm rows +gated_signal.json {"tap":"gated_signal","kinds":["F64"],"ts":[...],"columns":[[0.0]]} # last +``` + +`aura run` prints only manifest+metrics; `aura chart graph` emits HTML (exit 0), +index-gated (the stale `slow_ma.json` from the default run lingers on disk but +is NOT in the index and does NOT leak into the chart). There is no CLI verb that +prints a fold's scalar summary as text. (Findings F1, SG1.) + +--- + +## Scenario 2 — `m37_2` — registered composite spliced by name + args, swept + +A London-open session anchor (open `input` pattern, `Session` → `Europe/London` +/ `08:00` via `args`) registered under a label, then spliced by name into a +swept consumer. + +``` +$ aura graph build < m37_2_london_anchor.ops.json > m37_2_london_anchor.bp.json # v2 +$ aura graph register m37_2_london_anchor.bp.json --name london_anchor +registered blueprint 2deeddd943c9... +label "london_anchor" -> 2deeddd943c9... +$ aura graph introspect --registered +london_anchor 2deeddd943c9 London cash-open session anchor: bars elapsed since the 08:00 Europe/London open + +$ aura graph build < m37_2_consumer.ops.json > m37_2_consumer.bp.json +# stderr: aura: note: use "anchor": london_anchor -> 2deeddd943c9... +$ head -c 25 m37_2_consumer.bp.json +{"format_version":2,"blue # v2 propagates THROUGH the splice +$ aura graph introspect --content-id --identity-id < m37_2_consumer.ops.json +38369f968b9c10e6a56bca6ac1c347955492e4f58b125510cb09f4609502ad46 +f964f3b0dadb8d04e73696bc61119222755c7feef81c55e35e5b85b91bcee7ec + +$ aura sweep m37_2_consumer.bp.json --list-axes +graph.fast.length:I64 +graph.slow.length:I64 +graph.anchor.sess.period_minutes:I64 default=15 # spliced-instance param, path-qualified +... +$ aura sweep m37_2_consumer.bp.json --real GER40 --from 1725148800000 --to 1725580800000 \ + --axis graph.fast.length=5,10 --axis graph.slow.length=20 --name m37_london +# 2 members, exit 0 +$ aura reproduce d5259c94-0-GER40-w0-r0-s0-0 +... member graph.fast.length=5, ... reproduced: bit-identical +... member graph.fast.length=10, ... reproduced: bit-identical +reproduced 2/2 members bit-identically +``` + +Everything worked first try. (Finding W3.) + +--- + +## Scenario 3 — the boundary refuses what stays Rust-only + +``` +# genuinely-new logic as a namespaced type -> refused, NAMES the Rust escalation verb +$ aura graph build < m37_3a_new_logic.ops.json +aura: op 2 (add): unknown node type "my_lab::ThirdCandle" — type id looks + project-namespaced but this project binds no node crate — attach one + with `aura nodes new ` (exit 1) + +# same, but bare (un-namespaced) type -> refused, but NO escalation pointer +$ echo '[...{"op":"add","type":"ThirdCandle",...}...]' | aura graph build +aura: op 1 (add): unknown node type "ThirdCandle" (exit 1) # F2 + +# arg-bearing type entered half-configured -> MissingArg +$ aura graph build < m37_3b_session_no_args.ops.json +aura: op 2 (add): node sess is missing required arg "tz" (exit 1) + +# construction args on an arg-less type -> refused +$ aura graph build < m37_3c_args_on_argless.ops.json +aura: op 2 (add): node fast takes no construction args (exit 1) + +# a fold that is not a registered fold -> roster-enumerating refusal +$ aura run m37_1_ny_momentum.bp.json --real US500 --from ... --to ... --tap spread=median +aura: unknown fold 'median' — available: count, first, last, max, mean, min, record, sum (exit 1) + +# splice a composite that was never registered -> refused, enumerates labels +$ aura graph build < m37_3e_unknown_label.ops.json +aura: op 2 (use "anchor"): no registered blueprint labeled "tokyo_anchor" + — registered labels: london_anchor (exit 1) +``` + +Every boundary holds: exit 1, actionable prose. (Finding W4.) diff --git a/fieldtests/m37-data-authorability-boundary/m37_1_build.err b/fieldtests/m37-data-authorability-boundary/m37_1_build.err new file mode 100644 index 0000000..e69de29 diff --git a/fieldtests/m37-data-authorability-boundary/m37_1_fold_summary_rows.txt b/fieldtests/m37-data-authorability-boundary/m37_1_fold_summary_rows.txt new file mode 100644 index 0000000..a1ed25e --- /dev/null +++ b/fieldtests/m37-data-authorability-boundary/m37_1_fold_summary_rows.txt @@ -0,0 +1,10 @@ +# fold summary rows persisted by the --tap plan (spread=mean, first_bar=count, gated_signal=last) +## index.json taps: +"taps":["spread","first_bar","gated_signal"] + +## spread (mean): +{"tap":"spread","kinds":["F64"],"ts":[1725580800000000000],"columns":[[-0.20335440613026667]]} +## first_bar (count): +{"tap":"first_bar","kinds":["I64"],"ts":[1725580800000000000],"columns":[[5239.0]]} +## gated_signal (last): +{"tap":"gated_signal","kinds":["F64"],"ts":[1725580800000000000],"columns":[[0.0]]} \ No newline at end of file diff --git a/fieldtests/m37-data-authorability-boundary/m37_1_ny_momentum.bp.json b/fieldtests/m37-data-authorability-boundary/m37_1_ny_momentum.bp.json new file mode 100644 index 0000000..6a2bfa4 --- /dev/null +++ b/fieldtests/m37-data-authorability-boundary/m37_1_ny_momentum.bp.json @@ -0,0 +1 @@ +{"format_version":2,"blueprint":{"name":"graph","doc":"NY first-session-bar momentum: SMA(5)-SMA(20) sign, traded only on the first 09:30 America/New_York 15m session bar","nodes":[{"primitive":{"type":"SMA","name":"fast","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":5}}]}},{"primitive":{"type":"SMA","name":"slow","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":20}}]}},{"primitive":{"type":"Sub","name":"sub"}},{"primitive":{"type":"Sign","name":"sgn"}},{"primitive":{"type":"Session","name":"sess","args":[{"name":"tz","value":"America/New_York"},{"name":"open","value":"09:30"}],"bound":[{"pos":0,"name":"period_minutes","kind":"I64","value":{"I64":15}}]}},{"primitive":{"type":"EqConst","name":"isfirst","bound":[{"pos":0,"name":"target","kind":"I64","value":{"I64":1}}]}},{"primitive":{"type":"Const","name":"flat","bound":[{"pos":0,"name":"value","kind":"F64","value":{"F64":0.0}}]}},{"primitive":{"type":"Select","name":"gate"}},{"primitive":{"type":"Bias","name":"bias","bound":[{"pos":0,"name":"scale","kind":"F64","value":{"F64":1.0}}]}}],"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":4,"to":5,"slot":0,"from_field":0},{"from":5,"to":7,"slot":0,"from_field":0},{"from":3,"to":7,"slot":1,"from_field":0},{"from":6,"to":7,"slot":2,"from_field":0},{"from":7,"to":8,"slot":0,"from_field":0}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0},{"node":1,"slot":0},{"node":4,"slot":0},{"node":6,"slot":0}],"source":"F64"}],"output":[{"node":8,"field":0,"name":"bias"}],"taps":[{"name":"spread","from":{"node":2,"field":0}},{"name":"first_bar","from":{"node":5,"field":0}},{"name":"gated_signal","from":{"node":7,"field":0}},{"name":"slow_ma","from":{"node":1,"field":0}}]}} \ No newline at end of file diff --git a/fieldtests/m37-data-authorability-boundary/m37_1_ny_momentum.folds.run.json b/fieldtests/m37-data-authorability-boundary/m37_1_ny_momentum.folds.run.json new file mode 100644 index 0000000..736a4de --- /dev/null +++ b/fieldtests/m37-data-authorability-boundary/m37_1_ny_momentum.folds.run.json @@ -0,0 +1 @@ +{"manifest":{"commit":"eb2b0a132c9d07b2435981e6e9494a3527515304","params":[],"defaults":[["graph.fast.length",{"I64":5}],["graph.slow.length",{"I64":20}],["graph.sess.period_minutes",{"I64":15}],["graph.isfirst.target",{"I64":1}],["graph.flat.value",{"F64":0.0}],["graph.bias.scale",{"F64":1.0}]],"window":[1725235200000000000,1725580800000000000],"seed":0,"broker":"sim-optimal+risk-executor(pip_size=1)","topology_hash":"c8e123f0a8948034592eb5b15f32e9a3d6b0705c4c942e7563f655faa0d1e9f1","project":{"commit":"1a838a8eb2ff0610ba90b5ec28052eb8abf14ae2-dirty"}},"metrics":{"total_pips":-2.0999999999994543,"max_drawdown":29.899999999999636,"bias_sign_flips":12,"r":{"expectancy_r":0.15668981035489754,"n_trades":10,"win_rate":0.3,"avg_win_r":2.6354203218756065,"avg_loss_r":-0.9056232660111208,"profit_factor":1.2471696505846321,"max_r_drawdown":5.2917804259042285,"n_open_at_end":0,"sqn":0.23053858556757656,"sqn_normalized":0.23053858556757656,"net_expectancy_r":0.15668981035489754,"conviction_terciles_r":[-0.2831414429722934,0.6217793811679744,0.13774607224048319]}}} diff --git a/fieldtests/m37-data-authorability-boundary/m37_1_ny_momentum.ops.json b/fieldtests/m37-data-authorability-boundary/m37_1_ny_momentum.ops.json new file mode 100644 index 0000000..fe2df27 --- /dev/null +++ b/fieldtests/m37-data-authorability-boundary/m37_1_ny_momentum.ops.json @@ -0,0 +1,31 @@ +[ + {"op": "doc", "text": "NY first-session-bar momentum: SMA(5)-SMA(20) sign, traded only on the first 09:30 America/New_York 15m session bar"}, + {"op": "source", "role": "price", "kind": "F64"}, + {"op": "add", "type": "SMA", "name": "fast", "bind": {"length": {"I64": 5}}}, + {"op": "add", "type": "SMA", "name": "slow", "bind": {"length": {"I64": 20}}}, + {"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": "Sign", "name": "sgn"}, + {"op": "connect", "from": "sub.value", "to": "sgn.value"}, + {"op": "add", "type": "Session", "name": "sess", + "args": {"tz": "America/New_York", "open": "09:30"}, + "bind": {"period_minutes": {"I64": 15}}}, + {"op": "feed", "role": "price", "into": ["sess.trigger"]}, + {"op": "add", "type": "EqConst", "name": "isfirst", "bind": {"target": {"I64": 1}}}, + {"op": "connect", "from": "sess.bars_since_open", "to": "isfirst.value"}, + {"op": "add", "type": "Const", "name": "flat", "bind": {"value": {"F64": 0.0}}}, + {"op": "feed", "role": "price", "into": ["flat.clock"]}, + {"op": "add", "type": "Select", "name": "gate"}, + {"op": "connect", "from": "isfirst.value", "to": "gate.cond"}, + {"op": "connect", "from": "sgn.value", "to": "gate.then"}, + {"op": "connect", "from": "flat.value", "to": "gate.otherwise"}, + {"op": "add", "type": "Bias", "name": "bias", "bind": {"scale": {"F64": 1.0}}}, + {"op": "connect", "from": "gate.value", "to": "bias.signal"}, + {"op": "tap", "from": "sub.value", "as": "spread"}, + {"op": "tap", "from": "isfirst.value", "as": "first_bar"}, + {"op": "tap", "from": "gate.value", "as": "gated_signal"}, + {"op": "tap", "from": "slow.value", "as": "slow_ma"}, + {"op": "expose", "from": "bias.bias", "as": "bias"} +] diff --git a/fieldtests/m37-data-authorability-boundary/m37_1_ny_momentum.run.json b/fieldtests/m37-data-authorability-boundary/m37_1_ny_momentum.run.json new file mode 100644 index 0000000..736a4de --- /dev/null +++ b/fieldtests/m37-data-authorability-boundary/m37_1_ny_momentum.run.json @@ -0,0 +1 @@ +{"manifest":{"commit":"eb2b0a132c9d07b2435981e6e9494a3527515304","params":[],"defaults":[["graph.fast.length",{"I64":5}],["graph.slow.length",{"I64":20}],["graph.sess.period_minutes",{"I64":15}],["graph.isfirst.target",{"I64":1}],["graph.flat.value",{"F64":0.0}],["graph.bias.scale",{"F64":1.0}]],"window":[1725235200000000000,1725580800000000000],"seed":0,"broker":"sim-optimal+risk-executor(pip_size=1)","topology_hash":"c8e123f0a8948034592eb5b15f32e9a3d6b0705c4c942e7563f655faa0d1e9f1","project":{"commit":"1a838a8eb2ff0610ba90b5ec28052eb8abf14ae2-dirty"}},"metrics":{"total_pips":-2.0999999999994543,"max_drawdown":29.899999999999636,"bias_sign_flips":12,"r":{"expectancy_r":0.15668981035489754,"n_trades":10,"win_rate":0.3,"avg_win_r":2.6354203218756065,"avg_loss_r":-0.9056232660111208,"profit_factor":1.2471696505846321,"max_r_drawdown":5.2917804259042285,"n_open_at_end":0,"sqn":0.23053858556757656,"sqn_normalized":0.23053858556757656,"net_expectancy_r":0.15668981035489754,"conviction_terciles_r":[-0.2831414429722934,0.6217793811679744,0.13774607224048319]}}} diff --git a/fieldtests/m37-data-authorability-boundary/m37_2_consumer.bp.json b/fieldtests/m37-data-authorability-boundary/m37_2_consumer.bp.json new file mode 100644 index 0000000..0188033 --- /dev/null +++ b/fieldtests/m37-data-authorability-boundary/m37_2_consumer.bp.json @@ -0,0 +1 @@ +{"format_version":2,"blueprint":{"name":"graph","doc":"London-open breakout: SMA-fast>slow sign traded only on the first London session bar, blend period and MA lengths left open to sweep","nodes":[{"composite":{"name":"anchor","doc":"London cash-open session anchor: bars elapsed since the 08:00 Europe/London open","nodes":[{"primitive":{"type":"Session","name":"sess","args":[{"name":"tz","value":"Europe/London"},{"name":"open","value":"08:00"}],"bound":[{"pos":0,"name":"period_minutes","kind":"I64","value":{"I64":15}}]}}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0}]}],"output":[{"node":0,"field":0,"name":"bars"}]}},{"primitive":{"type":"SMA","name":"fast"}},{"primitive":{"type":"SMA","name":"slow"}},{"primitive":{"type":"Sub","name":"sub"}},{"primitive":{"type":"Sign","name":"sgn"}},{"primitive":{"type":"EqConst","name":"isfirst","bound":[{"pos":0,"name":"target","kind":"I64","value":{"I64":1}}]}},{"primitive":{"type":"Const","name":"flat","bound":[{"pos":0,"name":"value","kind":"F64","value":{"F64":0.0}}]}},{"primitive":{"type":"Select","name":"gate"}},{"primitive":{"type":"Bias","name":"bias","bound":[{"pos":0,"name":"scale","kind":"F64","value":{"F64":1.0}}]}}],"edges":[{"from":1,"to":3,"slot":0,"from_field":0},{"from":2,"to":3,"slot":1,"from_field":0},{"from":3,"to":4,"slot":0,"from_field":0},{"from":0,"to":5,"slot":0,"from_field":0},{"from":5,"to":7,"slot":0,"from_field":0},{"from":4,"to":7,"slot":1,"from_field":0},{"from":6,"to":7,"slot":2,"from_field":0},{"from":7,"to":8,"slot":0,"from_field":0}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0},{"node":1,"slot":0},{"node":2,"slot":0},{"node":6,"slot":0}],"source":"F64"}],"output":[{"node":8,"field":0,"name":"bias"}]}} \ No newline at end of file diff --git a/fieldtests/m37-data-authorability-boundary/m37_2_consumer.echo.txt b/fieldtests/m37-data-authorability-boundary/m37_2_consumer.echo.txt new file mode 100644 index 0000000..c546031 --- /dev/null +++ b/fieldtests/m37-data-authorability-boundary/m37_2_consumer.echo.txt @@ -0,0 +1 @@ +aura: note: use "anchor": london_anchor -> 2deeddd943c92252a401e33563f4ba8f1b85cd8a14cdf269fa1b795e4cc88eb3 diff --git a/fieldtests/m37-data-authorability-boundary/m37_2_consumer.ops.json b/fieldtests/m37-data-authorability-boundary/m37_2_consumer.ops.json new file mode 100644 index 0000000..3bf1191 --- /dev/null +++ b/fieldtests/m37-data-authorability-boundary/m37_2_consumer.ops.json @@ -0,0 +1,25 @@ +[ + {"op": "doc", "text": "London-open breakout: SMA-fast>slow sign traded only on the first London session bar, blend period and MA lengths left open to sweep"}, + {"op": "source", "role": "price", "kind": "F64"}, + {"op": "use", "ref": {"name": "london_anchor"}, "name": "anchor"}, + {"op": "feed", "role": "price", "into": ["anchor.price"]}, + {"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": "Sign", "name": "sgn"}, + {"op": "connect", "from": "sub.value", "to": "sgn.value"}, + {"op": "add", "type": "EqConst", "name": "isfirst", "bind": {"target": {"I64": 1}}}, + {"op": "connect", "from": "anchor.bars", "to": "isfirst.value"}, + {"op": "add", "type": "Const", "name": "flat", "bind": {"value": {"F64": 0.0}}}, + {"op": "feed", "role": "price", "into": ["flat.clock"]}, + {"op": "add", "type": "Select", "name": "gate"}, + {"op": "connect", "from": "isfirst.value", "to": "gate.cond"}, + {"op": "connect", "from": "sgn.value", "to": "gate.then"}, + {"op": "connect", "from": "flat.value", "to": "gate.otherwise"}, + {"op": "add", "type": "Bias", "name": "bias", "bind": {"scale": {"F64": 1.0}}}, + {"op": "connect", "from": "gate.value", "to": "bias.signal"}, + {"op": "expose", "from": "bias.bias", "as": "bias"} +] diff --git a/fieldtests/m37-data-authorability-boundary/m37_2_london_anchor.bp.json b/fieldtests/m37-data-authorability-boundary/m37_2_london_anchor.bp.json new file mode 100644 index 0000000..d66c5d6 --- /dev/null +++ b/fieldtests/m37-data-authorability-boundary/m37_2_london_anchor.bp.json @@ -0,0 +1 @@ +{"format_version":2,"blueprint":{"name":"graph","doc":"London cash-open session anchor: bars elapsed since the 08:00 Europe/London open","nodes":[{"primitive":{"type":"Session","name":"sess","args":[{"name":"tz","value":"Europe/London"},{"name":"open","value":"08:00"}],"bound":[{"pos":0,"name":"period_minutes","kind":"I64","value":{"I64":15}}]}}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0}]}],"output":[{"node":0,"field":0,"name":"bars"}]}} \ No newline at end of file diff --git a/fieldtests/m37-data-authorability-boundary/m37_2_london_anchor.ops.json b/fieldtests/m37-data-authorability-boundary/m37_2_london_anchor.ops.json new file mode 100644 index 0000000..4b0270c --- /dev/null +++ b/fieldtests/m37-data-authorability-boundary/m37_2_london_anchor.ops.json @@ -0,0 +1,9 @@ +[ + {"op": "doc", "text": "London cash-open session anchor: bars elapsed since the 08:00 Europe/London open"}, + {"op": "input", "role": "price"}, + {"op": "add", "type": "Session", "name": "sess", + "args": {"tz": "Europe/London", "open": "08:00"}, + "bind": {"period_minutes": {"I64": 15}}}, + {"op": "feed", "role": "price", "into": ["sess.trigger"]}, + {"op": "expose", "from": "sess.bars_since_open", "as": "bars"} +] diff --git a/fieldtests/m37-data-authorability-boundary/m37_2_sweep.err b/fieldtests/m37-data-authorability-boundary/m37_2_sweep.err new file mode 100644 index 0000000..e69de29 diff --git a/fieldtests/m37-data-authorability-boundary/m37_2_sweep.jsonl b/fieldtests/m37-data-authorability-boundary/m37_2_sweep.jsonl new file mode 100644 index 0000000..668099b --- /dev/null +++ b/fieldtests/m37-data-authorability-boundary/m37_2_sweep.jsonl @@ -0,0 +1,2 @@ +{"family_id":"d5259c94-0-GER40-w0-r0-s0-0","report":{"manifest":{"commit":"eb2b0a132c9d07b2435981e6e9494a3527515304","params":[["graph.fast.length",{"I64":5}],["graph.slow.length",{"I64":20}],["stop_length",{"I64":3}],["stop_k",{"F64":2.0}]],"defaults":[["graph.anchor.sess.period_minutes",{"I64":15}],["graph.isfirst.target",{"I64":1}],["graph.flat.value",{"F64":0.0}],["graph.bias.scale",{"F64":1.0}]],"window":[1725236099999000000,1725566340000000000],"seed":0,"broker":"sim-optimal+risk-executor(pip_size=1)","instrument":"GER40","topology_hash":"38369f968b9c10e6a56bca6ac1c347955492e4f58b125510cb09f4609502ad46","project":{"commit":"1a838a8eb2ff0610ba90b5ec28052eb8abf14ae2-dirty"}},"metrics":{"total_pips":6.5,"max_drawdown":73.5,"bias_sign_flips":11,"r":{"expectancy_r":-0.12406127289073887,"n_trades":8,"win_rate":0.25,"avg_win_r":1.9588513586755996,"avg_loss_r":-0.8183654834128516,"profit_factor":0.7978714475699166,"max_r_drawdown":4.3468217126941955,"n_open_at_end":0,"sqn":-0.22997299620402561,"sqn_normalized":-0.22997299620402561,"net_expectancy_r":-0.12406127289073887,"conviction_terciles_r":[1.2415119190137232,-0.23860471549936846,-0.9198999582184172]}}}} +{"family_id":"d5259c94-0-GER40-w0-r0-s0-0","report":{"manifest":{"commit":"eb2b0a132c9d07b2435981e6e9494a3527515304","params":[["graph.fast.length",{"I64":10}],["graph.slow.length",{"I64":20}],["stop_length",{"I64":3}],["stop_k",{"F64":2.0}]],"defaults":[["graph.anchor.sess.period_minutes",{"I64":15}],["graph.isfirst.target",{"I64":1}],["graph.flat.value",{"F64":0.0}],["graph.bias.scale",{"F64":1.0}]],"window":[1725236099999000000,1725566340000000000],"seed":0,"broker":"sim-optimal+risk-executor(pip_size=1)","instrument":"GER40","topology_hash":"38369f968b9c10e6a56bca6ac1c347955492e4f58b125510cb09f4609502ad46","project":{"commit":"1a838a8eb2ff0610ba90b5ec28052eb8abf14ae2-dirty"}},"metrics":{"total_pips":-22.5,"max_drawdown":87.5,"bias_sign_flips":12,"r":{"expectancy_r":-0.31488681817637804,"n_trades":11,"win_rate":0.2727272727272727,"avg_win_r":1.3490747111619477,"avg_loss_r":-0.9388723916782501,"profit_factor":0.5388410833781364,"max_r_drawdown":6.818086529508443,"n_open_at_end":0,"sqn":-0.7651422293114423,"sqn_normalized":-0.7651422293114423,"net_expectancy_r":-0.31488681817637804,"conviction_terciles_r":[0.27036658787590495,-0.6769671918050129,-0.3917464990869556]}}}} diff --git a/fieldtests/m37-data-authorability-boundary/m37_3a_new_logic.ops.json b/fieldtests/m37-data-authorability-boundary/m37_3a_new_logic.ops.json new file mode 100644 index 0000000..f76111e --- /dev/null +++ b/fieldtests/m37-data-authorability-boundary/m37_3a_new_logic.ops.json @@ -0,0 +1,9 @@ +[ + {"op": "doc", "text": "attempt to author genuinely-new logic as data: a node type that is not in the closed vocabulary"}, + {"op": "source", "role": "price", "kind": "F64"}, + {"op": "add", "type": "my_lab::ThirdCandle", "name": "tc"}, + {"op": "feed", "role": "price", "into": ["tc.series"]}, + {"op": "add", "type": "Bias", "name": "bias", "bind": {"scale": {"F64": 1.0}}}, + {"op": "connect", "from": "tc.value", "to": "bias.signal"}, + {"op": "expose", "from": "bias.bias", "as": "bias"} +] diff --git a/fieldtests/m37-data-authorability-boundary/m37_3b_session_no_args.ops.json b/fieldtests/m37-data-authorability-boundary/m37_3b_session_no_args.ops.json new file mode 100644 index 0000000..be5cc4f --- /dev/null +++ b/fieldtests/m37-data-authorability-boundary/m37_3b_session_no_args.ops.json @@ -0,0 +1,7 @@ +[ + {"op": "doc", "text": "attempt to enter an arg-bearing type half-configured: Session with no construction args"}, + {"op": "source", "role": "price", "kind": "F64"}, + {"op": "add", "type": "Session", "name": "sess", "bind": {"period_minutes": {"I64": 15}}}, + {"op": "feed", "role": "price", "into": ["sess.trigger"]}, + {"op": "expose", "from": "sess.bars_since_open", "as": "bars"} +] diff --git a/fieldtests/m37-data-authorability-boundary/m37_3c_args_on_argless.ops.json b/fieldtests/m37-data-authorability-boundary/m37_3c_args_on_argless.ops.json new file mode 100644 index 0000000..a1c2826 --- /dev/null +++ b/fieldtests/m37-data-authorability-boundary/m37_3c_args_on_argless.ops.json @@ -0,0 +1,9 @@ +[ + {"op": "doc", "text": "attempt to pass construction args to an arg-less type: SMA with an args object"}, + {"op": "source", "role": "price", "kind": "F64"}, + {"op": "add", "type": "SMA", "name": "fast", "args": {"window": "5"}, "bind": {"length": {"I64": 5}}}, + {"op": "add", "type": "Bias", "name": "bias", "bind": {"scale": {"F64": 1.0}}}, + {"op": "feed", "role": "price", "into": ["fast.series"]}, + {"op": "connect", "from": "fast.value", "to": "bias.signal"}, + {"op": "expose", "from": "bias.bias", "as": "bias"} +] diff --git a/fieldtests/m37-data-authorability-boundary/m37_3e_unknown_label.ops.json b/fieldtests/m37-data-authorability-boundary/m37_3e_unknown_label.ops.json new file mode 100644 index 0000000..042a442 --- /dev/null +++ b/fieldtests/m37-data-authorability-boundary/m37_3e_unknown_label.ops.json @@ -0,0 +1,9 @@ +[ + {"op": "doc", "text": "attempt to splice a composite that was never registered: use by an unknown label"}, + {"op": "source", "role": "price", "kind": "F64"}, + {"op": "use", "ref": {"name": "tokyo_anchor"}, "name": "anchor"}, + {"op": "feed", "role": "price", "into": ["anchor.price"]}, + {"op": "add", "type": "Bias", "name": "bias", "bind": {"scale": {"F64": 1.0}}}, + {"op": "connect", "from": "anchor.bars", "to": "bias.signal"}, + {"op": "expose", "from": "bias.bias", "as": "bias"} +]