diff --git a/fieldtests/milestone-measurement-first-class/README.md b/fieldtests/milestone-measurement-first-class/README.md new file mode 100644 index 0000000..827c050 --- /dev/null +++ b/fieldtests/milestone-measurement-first-class/README.md @@ -0,0 +1,57 @@ +# Fieldtest corpus — "Measurement as a first-class citizen" milestone + +Downstream-consumer study blueprints authored from the public interface +(ledger C24/C26/C27, glossary, shipped example envelopes) to exercise the +milestone's three composing capabilities end to end: + +1. **normalized-time bucketing** — coarse bars / session anchoring bucket by + the nominal minute despite jittered provider stamps; +2. **the four new std cells** — `Sign`, `Select`, `CumSum`, `When`; +3. **declared taps** — named measurement points on interior wires, recorded + from one `aura run`. + +Each scenario ships three files: `*.ops.json` (the role-6a op-script, the +canonical authoring input), `*.bp.json` (the `aura graph build` output), and +`*.json` (the final runnable envelope — the built blueprint **plus a +hand-added `taps` field**, since no op-script verb and no documented surface +declares a tap; see the fieldtest spec). + +## Reproduce + +Build the CLI (`cargo build --release -p aura-cli`), then, inside a scratch +project (`aura new lab && cd lab`), copy a scenario's `*.json` in and run it. +Declared taps persist under `runs/traces//` only inside a +project; chart with `aura chart `. + +### 1 — `mfc_1_gated_rate` (cells + taps, synthetic) +``` +aura run mfc_1_gated_rate.json +``` +A gated-rate / mux / counter study over the synthetic close stream. `Gt` +drives a Bool gate; `Select` muxes it back to ±1 (the Bool→F64 bridge); +`Sign` reads the fast−slow spread direction; `When(1.0, gate)` forwards a 1 +only on gate-true cycles, and `CumSum` over it vs `CumSum` over the raw clock +gives the rate = qualifying/total. Verified: `dir_sign == sign(spread)`; +`mux_select == ±1` by the gate; `gated_when` records exactly the gate-true +subsequence; `count_above / count_all == 6 / 18`. + +### 2 — `mfc_2_session_anchor` (session anchoring + taps) +``` +aura run mfc_2_session_anchor.json --real GER40 --from 1725148800000 --to 1725321600000 +``` +`SessionFrankfurt` yields `bars_since_open`; `EqConst(·, 0)` flags the first +block of each session; `When` gates a momentum sign to it. Over real GER40 the +`isfirst_flag==1` set equals the `bars_since_open==0` set. On the synthetic +stream `bars_since_open` is a constant pre-open sentinel (toy timestamps), so +the anchoring is only meaningful over `--real`. + +### 3 — `mfc_3_first_candle_momentum` (all three axes, real) +``` +aura run mfc_3_first_candle_momentum.json --real GER40 --from 1725148800000 --to 1727740800000 +``` +The origin question — "is the first coarse candle after a session open a +momentum indicator?" `Resample` builds 15-minute bars (clean 15.0-min cadence +preserved across `:59.999` jittered stamps — the snap fix), `SessionFrankfurt` +anchors on the coarse close, and `When` gates `Sign(coarse close − coarse +open)` to the first coarse candle of each session. Records exactly one +`firstmom` sample per session (21 over September 2024), zero throwaway Rust. diff --git a/fieldtests/milestone-measurement-first-class/mfc_1_gated_rate.bp.json b/fieldtests/milestone-measurement-first-class/mfc_1_gated_rate.bp.json new file mode 100644 index 0000000..4825f86 --- /dev/null +++ b/fieldtests/milestone-measurement-first-class/mfc_1_gated_rate.bp.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":2}}]}},{"primitive":{"type":"SMA","name":"slow","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":8}}]}},{"primitive":{"type":"Gt","name":"above"}},{"primitive":{"type":"Sub","name":"spread"}},{"primitive":{"type":"Sign","name":"dir"}},{"primitive":{"type":"Const","name":"one","bound":[{"pos":0,"name":"value","kind":"F64","value":{"F64":1.0}}]}},{"primitive":{"type":"Const","name":"negone","bound":[{"pos":0,"name":"value","kind":"F64","value":{"F64":-1.0}}]}},{"primitive":{"type":"When","name":"gated"}},{"primitive":{"type":"CumSum","name":"count_above"}},{"primitive":{"type":"CumSum","name":"count_all"}},{"primitive":{"type":"Select","name":"mux"}},{"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":0,"to":3,"slot":0,"from_field":0},{"from":1,"to":3,"slot":1,"from_field":0},{"from":3,"to":4,"slot":0,"from_field":0},{"from":5,"to":7,"slot":0,"from_field":0},{"from":2,"to":7,"slot":1,"from_field":0},{"from":7,"to":8,"slot":0,"from_field":0},{"from":5,"to":9,"slot":0,"from_field":0},{"from":2,"to":10,"slot":0,"from_field":0},{"from":5,"to":10,"slot":1,"from_field":0},{"from":6,"to":10,"slot":2,"from_field":0},{"from":4,"to":11,"slot":0,"from_field":0}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0},{"node":1,"slot":0},{"node":5,"slot":0},{"node":6,"slot":0}],"source":"F64"}],"output":[{"node":11,"field":0,"name":"bias"}]}} \ No newline at end of file diff --git a/fieldtests/milestone-measurement-first-class/mfc_1_gated_rate.json b/fieldtests/milestone-measurement-first-class/mfc_1_gated_rate.json new file mode 100644 index 0000000..7345939 --- /dev/null +++ b/fieldtests/milestone-measurement-first-class/mfc_1_gated_rate.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":2}}]}},{"primitive":{"type":"SMA","name":"slow","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":8}}]}},{"primitive":{"type":"Gt","name":"above"}},{"primitive":{"type":"Sub","name":"spread"}},{"primitive":{"type":"Sign","name":"dir"}},{"primitive":{"type":"Const","name":"one","bound":[{"pos":0,"name":"value","kind":"F64","value":{"F64":1.0}}]}},{"primitive":{"type":"Const","name":"negone","bound":[{"pos":0,"name":"value","kind":"F64","value":{"F64":-1.0}}]}},{"primitive":{"type":"When","name":"gated"}},{"primitive":{"type":"CumSum","name":"count_above"}},{"primitive":{"type":"CumSum","name":"count_all"}},{"primitive":{"type":"Select","name":"mux"}},{"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":0,"to":3,"slot":0,"from_field":0},{"from":1,"to":3,"slot":1,"from_field":0},{"from":3,"to":4,"slot":0,"from_field":0},{"from":5,"to":7,"slot":0,"from_field":0},{"from":2,"to":7,"slot":1,"from_field":0},{"from":7,"to":8,"slot":0,"from_field":0},{"from":5,"to":9,"slot":0,"from_field":0},{"from":2,"to":10,"slot":0,"from_field":0},{"from":5,"to":10,"slot":1,"from_field":0},{"from":6,"to":10,"slot":2,"from_field":0},{"from":4,"to":11,"slot":0,"from_field":0}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0},{"node":1,"slot":0},{"node":5,"slot":0},{"node":6,"slot":0}],"source":"F64"}],"output":[{"node":11,"field":0,"name":"bias"}],"taps":[{"name":"spread","from":{"node":3,"field":0}},{"name":"dir_sign","from":{"node":4,"field":0}},{"name":"gated_when","from":{"node":7,"field":0}},{"name":"count_above","from":{"node":8,"field":0}},{"name":"count_all","from":{"node":9,"field":0}},{"name":"mux_select","from":{"node":10,"field":0}}]}} \ No newline at end of file diff --git a/fieldtests/milestone-measurement-first-class/mfc_1_gated_rate.ops.json b/fieldtests/milestone-measurement-first-class/mfc_1_gated_rate.ops.json new file mode 100644 index 0000000..2c289fb --- /dev/null +++ b/fieldtests/milestone-measurement-first-class/mfc_1_gated_rate.ops.json @@ -0,0 +1,31 @@ +[ + {"op": "source", "role": "price", "kind": "F64"}, + {"op": "add", "type": "SMA", "name": "fast", "bind": {"length": {"I64": 2}}}, + {"op": "add", "type": "SMA", "name": "slow", "bind": {"length": {"I64": 8}}}, + {"op": "feed", "role": "price", "into": ["fast.series", "slow.series"]}, + {"op": "add", "type": "Gt", "name": "above"}, + {"op": "connect", "from": "fast.value", "to": "above.a"}, + {"op": "connect", "from": "slow.value", "to": "above.b"}, + {"op": "add", "type": "Sub", "name": "spread"}, + {"op": "connect", "from": "fast.value", "to": "spread.lhs"}, + {"op": "connect", "from": "slow.value", "to": "spread.rhs"}, + {"op": "add", "type": "Sign", "name": "dir"}, + {"op": "connect", "from": "spread.value", "to": "dir.value"}, + {"op": "add", "type": "Const", "name": "one", "bind": {"value": {"F64": 1.0}}}, + {"op": "add", "type": "Const", "name": "negone", "bind": {"value": {"F64": -1.0}}}, + {"op": "feed", "role": "price", "into": ["one.clock", "negone.clock"]}, + {"op": "add", "type": "When", "name": "gated"}, + {"op": "connect", "from": "one.value", "to": "gated.value"}, + {"op": "connect", "from": "above.value", "to": "gated.gate"}, + {"op": "add", "type": "CumSum", "name": "count_above"}, + {"op": "connect", "from": "gated.value", "to": "count_above.series"}, + {"op": "add", "type": "CumSum", "name": "count_all"}, + {"op": "connect", "from": "one.value", "to": "count_all.series"}, + {"op": "add", "type": "Select", "name": "mux"}, + {"op": "connect", "from": "above.value", "to": "mux.cond"}, + {"op": "connect", "from": "one.value", "to": "mux.then"}, + {"op": "connect", "from": "negone.value", "to": "mux.otherwise"}, + {"op": "add", "type": "Bias", "name": "bias", "bind": {"scale": {"F64": 1.0}}}, + {"op": "connect", "from": "dir.value", "to": "bias.signal"}, + {"op": "expose", "from": "bias.bias", "as": "bias"} +] diff --git a/fieldtests/milestone-measurement-first-class/mfc_2_session_anchor.bp.json b/fieldtests/milestone-measurement-first-class/mfc_2_session_anchor.bp.json new file mode 100644 index 0000000..aa74647 --- /dev/null +++ b/fieldtests/milestone-measurement-first-class/mfc_2_session_anchor.bp.json @@ -0,0 +1 @@ +{"format_version":1,"blueprint":{"name":"graph","nodes":[{"primitive":{"type":"SessionFrankfurt","name":"sess","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":0}}]}},{"primitive":{"type":"Const","name":"one","bound":[{"pos":0,"name":"value","kind":"F64","value":{"F64":1.0}}]}},{"primitive":{"type":"Const","name":"zero","bound":[{"pos":0,"name":"value","kind":"F64","value":{"F64":0.0}}]}},{"primitive":{"type":"Select","name":"flag"}},{"primitive":{"type":"SMA","name":"fast","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":3}}]}},{"primitive":{"type":"Sub","name":"spread"}},{"primitive":{"type":"Sign","name":"dir"}},{"primitive":{"type":"When","name":"firstmom"}},{"primitive":{"type":"Bias","name":"bias","bound":[{"pos":0,"name":"scale","kind":"F64","value":{"F64":1.0}}]}}],"edges":[{"from":0,"to":1,"slot":0,"from_field":0},{"from":1,"to":4,"slot":0,"from_field":0},{"from":2,"to":4,"slot":1,"from_field":0},{"from":3,"to":4,"slot":2,"from_field":0},{"from":5,"to":6,"slot":0,"from_field":0},{"from":6,"to":7,"slot":0,"from_field":0},{"from":7,"to":8,"slot":0,"from_field":0},{"from":1,"to":8,"slot":1,"from_field":0},{"from":7,"to":9,"slot":0,"from_field":0}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0},{"node":2,"slot":0},{"node":3,"slot":0},{"node":5,"slot":0},{"node":6,"slot":1}],"source":"F64"}],"output":[{"node":9,"field":0,"name":"bias"}]}} \ No newline at end of file diff --git a/fieldtests/milestone-measurement-first-class/mfc_2_session_anchor.json b/fieldtests/milestone-measurement-first-class/mfc_2_session_anchor.json new file mode 100644 index 0000000..436a821 --- /dev/null +++ b/fieldtests/milestone-measurement-first-class/mfc_2_session_anchor.json @@ -0,0 +1 @@ +{"format_version":1,"blueprint":{"name":"graph","nodes":[{"primitive":{"type":"SessionFrankfurt","name":"sess","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":0}}]}},{"primitive":{"type":"Const","name":"one","bound":[{"pos":0,"name":"value","kind":"F64","value":{"F64":1.0}}]}},{"primitive":{"type":"Const","name":"zero","bound":[{"pos":0,"name":"value","kind":"F64","value":{"F64":0.0}}]}},{"primitive":{"type":"Select","name":"flag"}},{"primitive":{"type":"SMA","name":"fast","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":3}}]}},{"primitive":{"type":"Sub","name":"spread"}},{"primitive":{"type":"Sign","name":"dir"}},{"primitive":{"type":"When","name":"firstmom"}},{"primitive":{"type":"Bias","name":"bias","bound":[{"pos":0,"name":"scale","kind":"F64","value":{"F64":1.0}}]}}],"edges":[{"from":0,"to":1,"slot":0,"from_field":0},{"from":1,"to":4,"slot":0,"from_field":0},{"from":2,"to":4,"slot":1,"from_field":0},{"from":3,"to":4,"slot":2,"from_field":0},{"from":5,"to":6,"slot":0,"from_field":0},{"from":6,"to":7,"slot":0,"from_field":0},{"from":7,"to":8,"slot":0,"from_field":0},{"from":1,"to":8,"slot":1,"from_field":0},{"from":7,"to":9,"slot":0,"from_field":0}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0},{"node":2,"slot":0},{"node":3,"slot":0},{"node":5,"slot":0},{"node":6,"slot":1}],"source":"F64"}],"output":[{"node":9,"field":0,"name":"bias"}],"taps":[{"name":"bars_since_open","from":{"node":0,"field":0}},{"name":"isfirst_flag","from":{"node":4,"field":0}},{"name":"firstmom","from":{"node":8,"field":0}}]}} \ No newline at end of file diff --git a/fieldtests/milestone-measurement-first-class/mfc_2_session_anchor.ops.json b/fieldtests/milestone-measurement-first-class/mfc_2_session_anchor.ops.json new file mode 100644 index 0000000..23984fc --- /dev/null +++ b/fieldtests/milestone-measurement-first-class/mfc_2_session_anchor.ops.json @@ -0,0 +1,27 @@ +[ + {"op": "source", "role": "price", "kind": "F64"}, + {"op": "add", "type": "SessionFrankfurt", "name": "sess", "bind": {"period_minutes": {"I64": 15}}}, + {"op": "feed", "role": "price", "into": ["sess.trigger"]}, + {"op": "add", "type": "EqConst", "name": "isfirst", "bind": {"target": {"I64": 0}}}, + {"op": "connect", "from": "sess.bars_since_open", "to": "isfirst.value"}, + {"op": "add", "type": "Const", "name": "one", "bind": {"value": {"F64": 1.0}}}, + {"op": "add", "type": "Const", "name": "zero", "bind": {"value": {"F64": 0.0}}}, + {"op": "feed", "role": "price", "into": ["one.clock", "zero.clock"]}, + {"op": "add", "type": "Select", "name": "flag"}, + {"op": "connect", "from": "isfirst.value", "to": "flag.cond"}, + {"op": "connect", "from": "one.value", "to": "flag.then"}, + {"op": "connect", "from": "zero.value", "to": "flag.otherwise"}, + {"op": "add", "type": "SMA", "name": "fast", "bind": {"length": {"I64": 3}}}, + {"op": "feed", "role": "price", "into": ["fast.series"]}, + {"op": "add", "type": "Sub", "name": "spread"}, + {"op": "connect", "from": "fast.value", "to": "spread.lhs"}, + {"op": "feed", "role": "price", "into": ["spread.rhs"]}, + {"op": "add", "type": "Sign", "name": "dir"}, + {"op": "connect", "from": "spread.value", "to": "dir.value"}, + {"op": "add", "type": "When", "name": "firstmom"}, + {"op": "connect", "from": "dir.value", "to": "firstmom.value"}, + {"op": "connect", "from": "isfirst.value", "to": "firstmom.gate"}, + {"op": "add", "type": "Bias", "name": "bias", "bind": {"scale": {"F64": 1.0}}}, + {"op": "connect", "from": "dir.value", "to": "bias.signal"}, + {"op": "expose", "from": "bias.bias", "as": "bias"} +] diff --git a/fieldtests/milestone-measurement-first-class/mfc_3_first_candle_momentum.bp.json b/fieldtests/milestone-measurement-first-class/mfc_3_first_candle_momentum.bp.json new file mode 100644 index 0000000..5700373 --- /dev/null +++ b/fieldtests/milestone-measurement-first-class/mfc_3_first_candle_momentum.bp.json @@ -0,0 +1 @@ +{"format_version":1,"blueprint":{"name":"graph","nodes":[{"primitive":{"type":"Resample","name":"c15","bound":[{"pos":0,"name":"period_minutes","kind":"I64","value":{"I64":15}}]}},{"primitive":{"type":"Sub","name":"body"}},{"primitive":{"type":"Sign","name":"dir"}},{"primitive":{"type":"SessionFrankfurt","name":"sess","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":0}}]}},{"primitive":{"type":"When","name":"firstmom"}},{"primitive":{"type":"CumSum","name":"cum"}},{"primitive":{"type":"Bias","name":"bias","bound":[{"pos":0,"name":"scale","kind":"F64","value":{"F64":1.0}}]}}],"edges":[{"from":0,"to":1,"slot":0,"from_field":3},{"from":0,"to":1,"slot":1,"from_field":0},{"from":1,"to":2,"slot":0,"from_field":0},{"from":0,"to":3,"slot":0,"from_field":3},{"from":3,"to":4,"slot":0,"from_field":0},{"from":2,"to":5,"slot":0,"from_field":0},{"from":4,"to":5,"slot":1,"from_field":0},{"from":5,"to":6,"slot":0,"from_field":0},{"from":2,"to":7,"slot":0,"from_field":0}],"input_roles":[{"name":"open","targets":[{"node":0,"slot":0}],"source":"F64"},{"name":"high","targets":[{"node":0,"slot":1}],"source":"F64"},{"name":"low","targets":[{"node":0,"slot":2}],"source":"F64"},{"name":"close","targets":[{"node":0,"slot":3}],"source":"F64"}],"output":[{"node":7,"field":0,"name":"bias"}]}} \ No newline at end of file diff --git a/fieldtests/milestone-measurement-first-class/mfc_3_first_candle_momentum.json b/fieldtests/milestone-measurement-first-class/mfc_3_first_candle_momentum.json new file mode 100644 index 0000000..6c15876 --- /dev/null +++ b/fieldtests/milestone-measurement-first-class/mfc_3_first_candle_momentum.json @@ -0,0 +1 @@ +{"format_version":1,"blueprint":{"name":"graph","nodes":[{"primitive":{"type":"Resample","name":"c15","bound":[{"pos":0,"name":"period_minutes","kind":"I64","value":{"I64":15}}]}},{"primitive":{"type":"Sub","name":"body"}},{"primitive":{"type":"Sign","name":"dir"}},{"primitive":{"type":"SessionFrankfurt","name":"sess","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":0}}]}},{"primitive":{"type":"When","name":"firstmom"}},{"primitive":{"type":"CumSum","name":"cum"}},{"primitive":{"type":"Bias","name":"bias","bound":[{"pos":0,"name":"scale","kind":"F64","value":{"F64":1.0}}]}}],"edges":[{"from":0,"to":1,"slot":0,"from_field":3},{"from":0,"to":1,"slot":1,"from_field":0},{"from":1,"to":2,"slot":0,"from_field":0},{"from":0,"to":3,"slot":0,"from_field":3},{"from":3,"to":4,"slot":0,"from_field":0},{"from":2,"to":5,"slot":0,"from_field":0},{"from":4,"to":5,"slot":1,"from_field":0},{"from":5,"to":6,"slot":0,"from_field":0},{"from":2,"to":7,"slot":0,"from_field":0}],"input_roles":[{"name":"open","targets":[{"node":0,"slot":0}],"source":"F64"},{"name":"high","targets":[{"node":0,"slot":1}],"source":"F64"},{"name":"low","targets":[{"node":0,"slot":2}],"source":"F64"},{"name":"close","targets":[{"node":0,"slot":3}],"source":"F64"}],"output":[{"node":7,"field":0,"name":"bias"}],"taps":[{"name":"coarse_close","from":{"node":0,"field":3}},{"name":"body","from":{"node":1,"field":0}},{"name":"dir_sign","from":{"node":2,"field":0}},{"name":"bars_since_open","from":{"node":3,"field":0}},{"name":"isfirst","from":{"node":4,"field":0}},{"name":"firstmom","from":{"node":5,"field":0}},{"name":"cum_firstmom","from":{"node":6,"field":0}}]}} \ No newline at end of file diff --git a/fieldtests/milestone-measurement-first-class/mfc_3_first_candle_momentum.ops.json b/fieldtests/milestone-measurement-first-class/mfc_3_first_candle_momentum.ops.json new file mode 100644 index 0000000..ed10499 --- /dev/null +++ b/fieldtests/milestone-measurement-first-class/mfc_3_first_candle_momentum.ops.json @@ -0,0 +1,28 @@ +[ + {"op": "source", "role": "open", "kind": "F64"}, + {"op": "source", "role": "high", "kind": "F64"}, + {"op": "source", "role": "low", "kind": "F64"}, + {"op": "source", "role": "close", "kind": "F64"}, + {"op": "add", "type": "Resample", "name": "c15", "bind": {"period_minutes": {"I64": 15}}}, + {"op": "feed", "role": "open", "into": ["c15.open"]}, + {"op": "feed", "role": "high", "into": ["c15.high"]}, + {"op": "feed", "role": "low", "into": ["c15.low"]}, + {"op": "feed", "role": "close", "into": ["c15.close"]}, + {"op": "add", "type": "Sub", "name": "body"}, + {"op": "connect", "from": "c15.close", "to": "body.lhs"}, + {"op": "connect", "from": "c15.open", "to": "body.rhs"}, + {"op": "add", "type": "Sign", "name": "dir"}, + {"op": "connect", "from": "body.value", "to": "dir.value"}, + {"op": "add", "type": "SessionFrankfurt", "name": "sess", "bind": {"period_minutes": {"I64": 15}}}, + {"op": "connect", "from": "c15.close", "to": "sess.trigger"}, + {"op": "add", "type": "EqConst", "name": "isfirst", "bind": {"target": {"I64": 0}}}, + {"op": "connect", "from": "sess.bars_since_open", "to": "isfirst.value"}, + {"op": "add", "type": "When", "name": "firstmom"}, + {"op": "connect", "from": "dir.value", "to": "firstmom.value"}, + {"op": "connect", "from": "isfirst.value", "to": "firstmom.gate"}, + {"op": "add", "type": "CumSum", "name": "cum"}, + {"op": "connect", "from": "firstmom.value", "to": "cum.series"}, + {"op": "add", "type": "Bias", "name": "bias", "bind": {"scale": {"F64": 1.0}}}, + {"op": "connect", "from": "dir.value", "to": "bias.signal"}, + {"op": "expose", "from": "bias.bias", "as": "bias"} +]