fieldtest: construction-args — 4 examples, 0 bugs / 1 friction / 2 spec-gap / 4 working

Source-blind consumer run over the #271 surface: a NY first-bar-
momentum Session authored purely as data and run e2e over --real
US500; a LinComb{arity:3} blend binding the arity-unlocked weights
with the Session period swept (4 members, reproduced 4/4
bit-identically); eight strict-form refusal probes (all exit 1,
actionable prose); an args composite registered and use-spliced into
a consumer (v2 propagates, ids stable, C29 doc gate holds).

Findings routed: Count lexical form + asymmetry ratified into
glossary/guide (follow-up commit); introspect dead-end on arg-bearing
ports and the missing CostSum wiring path absorbed into #341.

refs #271
This commit is contained in:
2026-07-24 22:05:34 +02:00
parent 6ca359ae00
commit 14c43474ab
24 changed files with 512 additions and 0 deletions
+217
View File
@@ -0,0 +1,217 @@
# Fieldtest transcript — cycle #271 (typed construction args)
Verbatim command/output capture for the `fieldtests/construction-args/` fixtures.
Binary: `target/debug/aura` built from HEAD `6ca359a` via `cargo build --workspace`
(debug profile). Runs used a scratch project `aura new ca_lab` (in `/tmp/ca_lab`);
real data resolved from the built-in archive (`/mnt/tickdata/Pepperstone`). All
op-scripts authored from the public interface only (README, authoring guide,
glossary, design ledger C24, `aura graph introspect`).
Public interface only — no crate source read.
---
## Discovery loop (axis 3) — is the args grammar learnable from the binary?
```
$ aura graph introspect --vocabulary | wc -l
36
$ aura graph introspect --node Session
Session — bars elapsed since the session open, from the configured open time and timezone
arg tz: Tz (IANA timezone name, e.g. Europe/Berlin)
arg open: TimeOfDay (local wall-clock HH:MM)
note ports and params form at construction; args are required
$ aura graph introspect --node LinComb
LinComb — linear combination of its inputs with constant weights
arg arity: Count (positive integer count)
note ports and params form at construction; args are required
$ aura graph introspect --node CostSum
CostSum — sums cost-model contributions into one cost-in-R stream
arg n_costs: Count (positive integer count)
note ports and params form at construction; args are required
```
The arg *grammar* (name, kind, hint) is fully self-describing. But `--node <T>`
stops at the note — it does NOT reveal the post-construction ports/params. To
learn the port names you must author a partial op-list carrying the args and pipe
it through `--unwired`; to learn the param names you must build and `--list-axes`.
Nothing on the `--node` surface names those follow-up steps. First naive guess at
LinComb's input port was `lc.in0` — wrong:
```
$ echo '[{"op":"add","type":"LinComb","name":"lc","args":{"arity":"3"}}]' \
| aura graph introspect --unwired
lc.term[0]:F64
lc.term[1]:F64
lc.term[2]:F64
$ echo '[{"op":"add","type":"CostSum","name":"cs","args":{"n_costs":"3"}}]' \
| aura graph introspect --unwired
cs.cost[0].cost_in_r:F64
cs.cost[0].cum_cost_in_r:F64
cs.cost[0].open_cost_in_r:F64
cs.cost[1].cost_in_r:F64 (… ×3 slots, 3 fields each)
```
Weight param names, discovered only after a build:
```
$ aura graph build < lc_probe.ops.json > lc_probe.bp.json
$ aura sweep lc_probe.bp.json --list-axes
graph.lc.weights[0]:F64 # open by default → sweepable (C24)
graph.lc.weights[1]:F64
...
```
---
## Example 1 — `ca_1_ny_session` (axis 1: non-Frankfurt Session as data)
```
$ aura graph build < ca_1_ny_session.ops.json > ca_1_ny_session.bp.json
$ head -c 25 ca_1_ny_session.bp.json
{"format_version":2,"blue # arg-bearing → v2
$ aura graph introspect --content-id --identity-id < ca_1_ny_session.ops.json
5b085a5b3f411072e48d4b54717b3d09e88be50b0bd797d345c2ee90baa41c37 # content id
4bf0513a4d2e852ab580fd8846737f57c1825b944ff9df1a48040a07fe92446b # identity id
# --- inside ca_lab/ ---
$ aura run ca_1_ny_session.bp.json --real US500 --from 1725148800000 --to 1725580800000
{"manifest":{... "topology_hash":"5b085a5b...b40d95cf"? -> 5b085a5b... (== content id) ...},
"metrics":{... "expectancy_r":0.7853745294474523,"n_trades":18 ...}} (exit 0)
# synthetic refuses cleanly (OHLC strategy, close-only synthetic stream):
$ aura run ca_1_ny_session.bp.json
aura: strategy "graph" consumes columns beyond close (open, high, low) —
synthetic data generates a close series only; run with --real <SYMBOL>
```
Full report captured in `ca_1_ny_session.run.json`.
---
## Example 2 — `ca_2_lincomb_blend` (axis 2: LinComb arity + weights + swept period)
Three SMA spreads blended through `LinComb(arity 3)` with bound `weights[i]`,
NY-session-gated, `Session.period_minutes` left OPEN (sweepable).
```
$ aura graph build < ca_2_lincomb_blend.ops.json > ca_2_lincomb_blend.bp.json
$ head -c 25 ca_2_lincomb_blend.bp.json
{"format_version":2,"blue
$ aura sweep ca_2_lincomb_blend.bp.json --list-axes
graph.sess.period_minutes:I64 # open
graph.lc.weights[0]:F64 default=0.5 # bound (re-openable by --axis)
graph.lc.weights[1]:F64 default=0.3
graph.lc.weights[2]:F64 default=0.2
...
# --- inside ca_lab/ --- sweep the arity-unlocked weight AND the period param:
$ aura sweep ca_2_lincomb_blend.bp.json --real US500 --from 1725148800000 --to 1725580800000 \
--axis graph.sess.period_minutes=15,30 --axis 'graph.lc.weights[0]=0.3,0.5' --name ca2_blend
{"family_id":"caa3508a-0-US500-w0-r0-s0-0", ... 4 members ...} (exit 0)
$ aura reproduce caa3508a-0-US500-w0-r0-s0-0
... member graph.lc.weights[0]=0.3, graph.sess.period_minutes=15 ... reproduced: bit-identical
... (×4)
reproduced 4/4 members bit-identically
```
Sweep output in `ca_2_lincomb_blend.sweep.jsonl`. NB: at this gating, the two
`weights[0]` values yield identical member metrics (the gated blend's sign is
weight-insensitive here) — a semantic property of the strategy, not the arg
channel; the params bound and swept correctly.
CostSum arity probe: `ca_2b_costsum_arity.ops.json``--unwired` shows
`cost[i].{cost_in_r,cum_cost_in_r,open_cost_in_r}` (3 slots × 3 fields). Wiring
CostSum end to end needs the RiskExecutor context (cost nodes take
`closed/open/entry_price/stop_price`) — no op-script path for that exists in the
public corpus (see finding SG2).
---
## Example 3 — refusal battery (axis 4: strict-form refusal prose)
Every case: `aura graph build < FIXTURE`, stderr + exit code.
```
ca_3a_bad_tz aura: op 1 (add): node sess arg "tz" expects Tz (IANA timezone name, e.g. Europe/Berlin) — got "berlin" exit 1
ca_3b_unpadded_time aura: op 1 (add): node sess arg "open" expects TimeOfDay (local wall-clock HH:MM) — got "9:30" exit 1
ca_3c_zero_count aura: op 2 (add): node lc arg "arity" expects Count (positive integer count) — got "0" exit 1
ca_3d_garbage_count aura: op 1 (add): node lc arg "arity" expects Count (positive integer count) — got "three" exit 1
ca_3e_missing_arg aura: op 1 (add): node sess is missing required arg "tz" exit 1
ca_3f_args_on_argless aura: op 1 (add): node a takes no construction args exit 1
ca_3g_unknown_arg_key aura: op 1 (add): node sess has no construction arg "region" exit 1
ca_3h_partial_args aura: op 1 (add): node sess is missing required arg "open" exit 1
```
Edge-form strictness (ad-hoc, `--unwired`):
```
Count arity: "3"→ok "03"→refuse "+3"→refuse "3.0"→refuse "1e1"→refuse "-2"→refuse " 3"→refuse "0x3"→refuse
Time open: "09:30"→ok "00:00"→ok "23:59"→ok "24:00"→refuse "09:60"→refuse "9:05"→refuse "09:5"→refuse "09:30:00"→refuse "0930"→refuse
```
Note the padding asymmetry: `open` REQUIRES a zero-padded hour (`09:05`), but
`arity` REFUSES a leading zero (`03`). See finding SG1.
---
## Example 4 — `ca_4` register → use (axis 5: #317 interplay)
```
$ aura graph build < ca_4_ny_anchor_pattern.ops.json > ca_4_ny_anchor_pattern.bp.json
$ head -c 25 ca_4_ny_anchor_pattern.bp.json
{"format_version":2,"blue
$ aura graph introspect --content-id --identity-id < ca_4_ny_anchor_pattern.ops.json
d51132463b2d1780b3ed9b83dc9f9a229a9d6b93fce3e15c7c0572970e2e4564
863c89ddeaa2dfe7d79c7e55944263145399c67397a27c0955bdd768cc6ed72e
# --- inside ca_lab/ ---
$ aura graph register .../ca_4_ny_anchor_pattern.bp.json --name ny_anchor
registered blueprint d51132463b2d... (.../runs/blueprints/d51132463b2d....json)
label "ny_anchor" -> d51132463b2d...
$ aura graph introspect --registered
ny_anchor d51132463b2d NY cash-open session anchor: bars elapsed since the 09:30 America/New_York open
$ aura graph build < ca_4_consumer.ops.json > consumer.bp.json
# stderr: aura: note: use "anchor": ny_anchor -> d51132463b2d...
$ head -c 25 consumer.bp.json
{"format_version":2,"blue # v2 propagates THROUGH the splice
$ aura graph introspect --content-id --identity-id < ca_4_consumer.ops.json
985991f62cc6b92895018312c5ea86e493ef1c09dd53cf6e0813551baa97b671
bbe7060f4136255e594e1b01242ae80c3f5decfc543f23198d66adff6ce52a7b
$ aura run consumer.bp.json --real US500 --from 1725148800000 --to 1725580800000
{"manifest":{... "topology_hash":"985991f6..." (== content id),
"defaults":[["graph.anchor.sess.period_minutes",{"I64":15}], ...] ...},
"metrics":{... "n_trades":8 ...}} (exit 0)
# doc gate on the args-bearing composite (doc stripped):
$ aura graph register ca4_docless.bp.json --name ny_docless
aura: blueprint: composite `graph` carries no doc — a registered composite
describes itself (C29); add a doc line (...) before register exit 1
```
Consumer report captured in `ca_4_consumer.run.json`.
---
## Cross-cutting confirmations
```
# args-free document stays format_version 1 (byte-stability invariant, C18):
$ echo '[{"op":"source",...},{"op":"add","type":"SMA",...},...]' | aura graph build | head -c 25
{"format_version":1,"blue
# content id deterministic across builds:
$ aura graph introspect --content-id < ca_1_ny_session.ops.json (×2) -> identical
5b085a5b3f411072e48d4b54717b3d09e88be50b0bd797d345c2ee90baa41c37
5b085a5b3f411072e48d4b54717b3d09e88be50b0bd797d345c2ee90baa41c37
```
@@ -0,0 +1 @@
{"format_version":2,"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":"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":"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":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}],"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":6,"field":0,"name":"bias"}]}}
@@ -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": "Session", "name": "sess",
"args": {"tz": "America/New_York", "open": "09:30"},
"bind": {"period_minutes": {"I64": 15}}},
{"op": "connect", "from": "c15.close", "to": "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": "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": "firstmom.value", "to": "bias.signal"},
{"op": "expose", "from": "bias.bias", "as": "bias"}
]
@@ -0,0 +1,65 @@
{
"manifest": {
"commit": "6ca359ae00e8e7921f08557be383bc2d0a2ce199",
"params": [],
"defaults": [
[
"graph.c15.period_minutes",
{
"I64": 15
}
],
[
"graph.sess.period_minutes",
{
"I64": 15
}
],
[
"graph.isfirst.target",
{
"I64": 1
}
],
[
"graph.bias.scale",
{
"F64": 1.0
}
]
],
"window": [
1725235200000000000,
1725580800000000000
],
"seed": 0,
"broker": "sim-optimal+risk-executor(pip_size=1)",
"topology_hash": "5b085a5b3f411072e48d4b54717b3d09e88be50b0bd797d345c2ee90baa41c37",
"project": {
"commit": "d7e3a8f39881cc8eba42a906fa846676bfbb1010"
}
},
"metrics": {
"total_pips": 8.700000000000728,
"max_drawdown": 77.0,
"bias_sign_flips": 2,
"r": {
"expectancy_r": 0.7853745294474523,
"n_trades": 18,
"win_rate": 0.1111111111111111,
"avg_win_r": 17.115118267387366,
"avg_loss_r": -1.2558434377950367,
"profit_factor": 1.7035481645543986,
"max_r_drawdown": 16.041140339815094,
"n_open_at_end": 1,
"sqn": 0.4343599983483773,
"sqn_normalized": 0.4343599983483773,
"net_expectancy_r": 0.7853745294474523,
"conviction_terciles_r": [
-1.3650686711197901,
-1.2338202185443914,
4.955012478006539
]
}
}
}
@@ -0,0 +1 @@
{"format_version":2,"blueprint":{"name":"graph","doc":"NY-session-gated blend of three SMA spreads via a LinComb(arity 3); sweepable session period","nodes":[{"primitive":{"type":"SMA","name":"a","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":2}}]}},{"primitive":{"type":"SMA","name":"b","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":5}}]}},{"primitive":{"type":"SMA","name":"c","bound":[{"pos":0,"name":"length","kind":"I64","value":{"I64":10}}]}},{"primitive":{"type":"Sub","name":"sA"}},{"primitive":{"type":"Sub","name":"sB"}},{"primitive":{"type":"Sub","name":"sC"}},{"primitive":{"type":"LinComb","name":"lc","args":[{"name":"arity","value":"3"}],"bound":[{"pos":0,"name":"weights[0]","kind":"F64","value":{"F64":0.5}},{"pos":1,"name":"weights[1]","kind":"F64","value":{"F64":0.3}},{"pos":2,"name":"weights[2]","kind":"F64","value":{"F64":0.2}}]}},{"primitive":{"type":"Session","name":"sess","args":[{"name":"tz","value":"America/New_York"},{"name":"open","value":"09:30"}]}},{"primitive":{"type":"EqConst","name":"insession","bound":[{"pos":0,"name":"target","kind":"I64","value":{"I64":1}}]}},{"primitive":{"type":"When","name":"gated"}},{"primitive":{"type":"Bias","name":"bias","bound":[{"pos":0,"name":"scale","kind":"F64","value":{"F64":1.0}}]}}],"edges":[{"from":0,"to":3,"slot":0,"from_field":0},{"from":2,"to":3,"slot":1,"from_field":0},{"from":1,"to":4,"slot":0,"from_field":0},{"from":2,"to":4,"slot":1,"from_field":0},{"from":0,"to":5,"slot":0,"from_field":0},{"from":1,"to":5,"slot":1,"from_field":0},{"from":3,"to":6,"slot":0,"from_field":0},{"from":4,"to":6,"slot":1,"from_field":0},{"from":5,"to":6,"slot":2,"from_field":0},{"from":7,"to":8,"slot":0,"from_field":0},{"from":6,"to":9,"slot":0,"from_field":0},{"from":8,"to":9,"slot":1,"from_field":0},{"from":9,"to":10,"slot":0,"from_field":0}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0},{"node":1,"slot":0},{"node":2,"slot":0},{"node":7,"slot":0}],"source":"F64"}],"output":[{"node":10,"field":0,"name":"bias"}]}}
@@ -0,0 +1,33 @@
[
{"op": "doc", "text": "NY-session-gated blend of three SMA spreads via a LinComb(arity 3); sweepable session period"},
{"op": "source", "role": "price", "kind": "F64"},
{"op": "add", "type": "SMA", "name": "a", "bind": {"length": {"I64": 2}}},
{"op": "add", "type": "SMA", "name": "b", "bind": {"length": {"I64": 5}}},
{"op": "add", "type": "SMA", "name": "c", "bind": {"length": {"I64": 10}}},
{"op": "feed", "role": "price", "into": ["a.series", "b.series", "c.series"]},
{"op": "add", "type": "Sub", "name": "sA"},
{"op": "connect", "from": "a.value", "to": "sA.lhs"},
{"op": "connect", "from": "c.value", "to": "sA.rhs"},
{"op": "add", "type": "Sub", "name": "sB"},
{"op": "connect", "from": "b.value", "to": "sB.lhs"},
{"op": "connect", "from": "c.value", "to": "sB.rhs"},
{"op": "add", "type": "Sub", "name": "sC"},
{"op": "connect", "from": "a.value", "to": "sC.lhs"},
{"op": "connect", "from": "b.value", "to": "sC.rhs"},
{"op": "add", "type": "LinComb", "name": "lc", "args": {"arity": "3"},
"bind": {"weights[0]": {"F64": 0.5}, "weights[1]": {"F64": 0.3}, "weights[2]": {"F64": 0.2}}},
{"op": "connect", "from": "sA.value", "to": "lc.term[0]"},
{"op": "connect", "from": "sB.value", "to": "lc.term[1]"},
{"op": "connect", "from": "sC.value", "to": "lc.term[2]"},
{"op": "add", "type": "Session", "name": "sess",
"args": {"tz": "America/New_York", "open": "09:30"}},
{"op": "feed", "role": "price", "into": ["sess.trigger"]},
{"op": "add", "type": "EqConst", "name": "insession", "bind": {"target": {"I64": 1}}},
{"op": "connect", "from": "sess.bars_since_open", "to": "insession.value"},
{"op": "add", "type": "When", "name": "gated"},
{"op": "connect", "from": "lc.value", "to": "gated.value"},
{"op": "connect", "from": "insession.value", "to": "gated.gate"},
{"op": "add", "type": "Bias", "name": "bias", "bind": {"scale": {"F64": 1.0}}},
{"op": "connect", "from": "gated.value", "to": "bias.signal"},
{"op": "expose", "from": "bias.bias", "as": "bias"}
]
@@ -0,0 +1,4 @@
{"family_id":"a457bcb1-0-US500-w0-r0-s0-0","report":{"manifest":{"commit":"6ca359ae00e8e7921f08557be383bc2d0a2ce199","params":[["graph.lc.weights[0]",{"F64":0.3}],["graph.sess.period_minutes",{"I64":15}],["stop_length",{"I64":3}],["stop_k",{"F64":2.0}]],"defaults":[["graph.a.length",{"I64":2}],["graph.b.length",{"I64":5}],["graph.c.length",{"I64":10}],["graph.lc.weights[1]",{"F64":0.3}],["graph.lc.weights[2]",{"F64":0.2}],["graph.insession.target",{"I64":1}],["graph.bias.scale",{"F64":1.0}]],"window":[1725235200000000000,1725580800000000000],"seed":0,"broker":"sim-optimal+risk-executor(pip_size=1)","instrument":"US500","topology_hash":"ef8e0a4eb23bda78ae3914bb3bcc742314750827498e841fb2a2a7f9aea4c864","project":{"commit":"d7e3a8f39881cc8eba42a906fa846676bfbb1010"}},"metrics":{"total_pips":-96.06109999999117,"max_drawdown":137.94459999999816,"bias_sign_flips":10,"r":{"expectancy_r":-0.709681826087026,"n_trades":37,"win_rate":0.13513513513513514,"avg_win_r":3.454890860540305,"avg_loss_r":-1.3603963083725465,"profit_factor":0.3968157614344175,"max_r_drawdown":28.676655116297415,"n_open_at_end":1,"sqn":-1.7501753655158518,"sqn_normalized":-1.7501753655158518,"net_expectancy_r":-0.709681826087026,"conviction_terciles_r":[0.010138828240044861,-1.4112281254600723,-0.7265504614292024]}}}}
{"family_id":"a457bcb1-0-US500-w0-r0-s0-0","report":{"manifest":{"commit":"6ca359ae00e8e7921f08557be383bc2d0a2ce199","params":[["graph.lc.weights[0]",{"F64":0.3}],["graph.sess.period_minutes",{"I64":30}],["stop_length",{"I64":3}],["stop_k",{"F64":2.0}]],"defaults":[["graph.a.length",{"I64":2}],["graph.b.length",{"I64":5}],["graph.c.length",{"I64":10}],["graph.lc.weights[1]",{"F64":0.3}],["graph.lc.weights[2]",{"F64":0.2}],["graph.insession.target",{"I64":1}],["graph.bias.scale",{"F64":1.0}]],"window":[1725235200000000000,1725580800000000000],"seed":0,"broker":"sim-optimal+risk-executor(pip_size=1)","instrument":"US500","topology_hash":"ef8e0a4eb23bda78ae3914bb3bcc742314750827498e841fb2a2a7f9aea4c864","project":{"commit":"d7e3a8f39881cc8eba42a906fa846676bfbb1010"}},"metrics":{"total_pips":-53.55989999998029,"max_drawdown":120.4151999999832,"bias_sign_flips":18,"r":{"expectancy_r":-0.05940492516372425,"n_trades":34,"win_rate":0.23529411764705882,"avg_win_r":3.3843995517241234,"avg_loss_r":-1.1190370718984466,"profit_factor":0.9305801696597508,"max_r_drawdown":18.95335695076066,"n_open_at_end":1,"sqn":-0.13880221854288846,"sqn_normalized":-0.13880221854288846,"net_expectancy_r":-0.05940492516372425,"conviction_terciles_r":[0.92760843970395,-1.1133959931000275,0.001991302649185419]}}}}
{"family_id":"a457bcb1-0-US500-w0-r0-s0-0","report":{"manifest":{"commit":"6ca359ae00e8e7921f08557be383bc2d0a2ce199","params":[["graph.lc.weights[0]",{"F64":0.5}],["graph.sess.period_minutes",{"I64":15}],["stop_length",{"I64":3}],["stop_k",{"F64":2.0}]],"defaults":[["graph.a.length",{"I64":2}],["graph.b.length",{"I64":5}],["graph.c.length",{"I64":10}],["graph.lc.weights[1]",{"F64":0.3}],["graph.lc.weights[2]",{"F64":0.2}],["graph.insession.target",{"I64":1}],["graph.bias.scale",{"F64":1.0}]],"window":[1725235200000000000,1725580800000000000],"seed":0,"broker":"sim-optimal+risk-executor(pip_size=1)","instrument":"US500","topology_hash":"ef8e0a4eb23bda78ae3914bb3bcc742314750827498e841fb2a2a7f9aea4c864","project":{"commit":"d7e3a8f39881cc8eba42a906fa846676bfbb1010"}},"metrics":{"total_pips":-90.72209999998813,"max_drawdown":138.7875999999975,"bias_sign_flips":10,"r":{"expectancy_r":-0.709681826087026,"n_trades":37,"win_rate":0.13513513513513514,"avg_win_r":3.454890860540305,"avg_loss_r":-1.3603963083725465,"profit_factor":0.3968157614344175,"max_r_drawdown":28.676655116297415,"n_open_at_end":1,"sqn":-1.7501753655158518,"sqn_normalized":-1.7501753655158518,"net_expectancy_r":-0.709681826087026,"conviction_terciles_r":[0.010138828240044861,-1.294302553607114,-0.8344817585242409]}}}}
{"family_id":"a457bcb1-0-US500-w0-r0-s0-0","report":{"manifest":{"commit":"6ca359ae00e8e7921f08557be383bc2d0a2ce199","params":[["graph.lc.weights[0]",{"F64":0.5}],["graph.sess.period_minutes",{"I64":30}],["stop_length",{"I64":3}],["stop_k",{"F64":2.0}]],"defaults":[["graph.a.length",{"I64":2}],["graph.b.length",{"I64":5}],["graph.c.length",{"I64":10}],["graph.lc.weights[1]",{"F64":0.3}],["graph.lc.weights[2]",{"F64":0.2}],["graph.insession.target",{"I64":1}],["graph.bias.scale",{"F64":1.0}]],"window":[1725235200000000000,1725580800000000000],"seed":0,"broker":"sim-optimal+risk-executor(pip_size=1)","instrument":"US500","topology_hash":"ef8e0a4eb23bda78ae3914bb3bcc742314750827498e841fb2a2a7f9aea4c864","project":{"commit":"d7e3a8f39881cc8eba42a906fa846676bfbb1010"}},"metrics":{"total_pips":-49.96429999999597,"max_drawdown":125.2664000000041,"bias_sign_flips":18,"r":{"expectancy_r":-0.05940492516372425,"n_trades":34,"win_rate":0.23529411764705882,"avg_win_r":3.3843995517241234,"avg_loss_r":-1.1190370718984466,"profit_factor":0.9305801696597508,"max_r_drawdown":18.95335695076066,"n_open_at_end":1,"sqn":-0.13880221854288846,"sqn_normalized":-0.13880221854288846,"net_expectancy_r":-0.05940492516372425,"conviction_terciles_r":[0.92760843970395,-0.9291244696270301,-0.16692426053439502]}}}}
@@ -0,0 +1,3 @@
[
{"op": "add", "type": "CostSum", "name": "cs", "args": {"n_costs": "3"}}
]
@@ -0,0 +1,8 @@
[
{"op": "source", "role": "price", "kind": "F64"},
{"op": "add", "type": "Session", "name": "sess",
"args": {"tz": "berlin", "open": "09:30"},
"bind": {"period_minutes": {"I64": 15}}},
{"op": "feed", "role": "price", "into": ["sess.trigger"]},
{"op": "expose", "from": "sess.bars_since_open", "as": "bars"}
]
@@ -0,0 +1,8 @@
[
{"op": "source", "role": "price", "kind": "F64"},
{"op": "add", "type": "Session", "name": "sess",
"args": {"tz": "America/New_York", "open": "9:30"},
"bind": {"period_minutes": {"I64": 15}}},
{"op": "feed", "role": "price", "into": ["sess.trigger"]},
{"op": "expose", "from": "sess.bars_since_open", "as": "bars"}
]
@@ -0,0 +1,7 @@
[
{"op": "source", "role": "price", "kind": "F64"},
{"op": "add", "type": "SMA", "name": "a", "bind": {"length": {"I64": 2}}},
{"op": "add", "type": "LinComb", "name": "lc", "args": {"arity": "0"}},
{"op": "feed", "role": "price", "into": ["a.series"]},
{"op": "expose", "from": "lc.value", "as": "out"}
]
@@ -0,0 +1,5 @@
[
{"op": "source", "role": "price", "kind": "F64"},
{"op": "add", "type": "LinComb", "name": "lc", "args": {"arity": "three"}},
{"op": "expose", "from": "lc.value", "as": "out"}
]
@@ -0,0 +1,7 @@
[
{"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"}
]
@@ -0,0 +1,8 @@
[
{"op": "source", "role": "price", "kind": "F64"},
{"op": "add", "type": "SMA", "name": "a",
"args": {"window": "3"},
"bind": {"length": {"I64": 2}}},
{"op": "feed", "role": "price", "into": ["a.series"]},
{"op": "expose", "from": "a.value", "as": "out"}
]
@@ -0,0 +1,8 @@
[
{"op": "source", "role": "price", "kind": "F64"},
{"op": "add", "type": "Session", "name": "sess",
"args": {"tz": "America/New_York", "open": "09:30", "region": "east"},
"bind": {"period_minutes": {"I64": 15}}},
{"op": "feed", "role": "price", "into": ["sess.trigger"]},
{"op": "expose", "from": "sess.bars_since_open", "as": "bars"}
]
@@ -0,0 +1,8 @@
[
{"op": "source", "role": "price", "kind": "F64"},
{"op": "add", "type": "Session", "name": "sess",
"args": {"tz": "America/New_York"},
"bind": {"period_minutes": {"I64": 15}}},
{"op": "feed", "role": "price", "into": ["sess.trigger"]},
{"op": "expose", "from": "sess.bars_since_open", "as": "bars"}
]
@@ -0,0 +1 @@
{"format_version":2,"blueprint":{"name":"graph","doc":"consumer: splice the NY session anchor by name, go long 1.0 on the first session bar, flat otherwise","nodes":[{"composite":{"name":"anchor","doc":"NY cash-open session anchor: bars elapsed since the 09:30 America/New_York open","nodes":[{"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}}]}}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0}]}],"output":[{"node":0,"field":0,"name":"bars"}]}},{"primitive":{"type":"EqConst","name":"isfirst","bound":[{"pos":0,"name":"target","kind":"I64","value":{"I64":1}}]}},{"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":"sel"}},{"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":4,"to":5,"slot":0,"from_field":0}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0},{"node":2,"slot":0},{"node":3,"slot":0}],"source":"F64"}],"output":[{"node":5,"field":0,"name":"bias"}]}}
@@ -0,0 +1,19 @@
[
{"op": "doc", "text": "consumer: splice the NY session anchor by name, go long 1.0 on the first session bar, flat otherwise"},
{"op": "source", "role": "price", "kind": "F64"},
{"op": "use", "ref": {"name": "ny_anchor"}, "name": "anchor"},
{"op": "feed", "role": "price", "into": ["anchor.price"]},
{"op": "add", "type": "EqConst", "name": "isfirst", "bind": {"target": {"I64": 1}}},
{"op": "connect", "from": "anchor.bars", "to": "isfirst.value"},
{"op": "add", "type": "Const", "name": "one", "bind": {"value": {"F64": 1.0}}},
{"op": "feed", "role": "price", "into": ["one.clock"]},
{"op": "add", "type": "Const", "name": "zero", "bind": {"value": {"F64": 0.0}}},
{"op": "feed", "role": "price", "into": ["zero.clock"]},
{"op": "add", "type": "Select", "name": "sel"},
{"op": "connect", "from": "isfirst.value", "to": "sel.cond"},
{"op": "connect", "from": "one.value", "to": "sel.then"},
{"op": "connect", "from": "zero.value", "to": "sel.otherwise"},
{"op": "add", "type": "Bias", "name": "bias", "bind": {"scale": {"F64": 1.0}}},
{"op": "connect", "from": "sel.value", "to": "bias.signal"},
{"op": "expose", "from": "bias.bias", "as": "bias"}
]
@@ -0,0 +1,71 @@
{
"manifest": {
"commit": "6ca359ae00e8e7921f08557be383bc2d0a2ce199",
"params": [],
"defaults": [
[
"graph.anchor.sess.period_minutes",
{
"I64": 15
}
],
[
"graph.isfirst.target",
{
"I64": 1
}
],
[
"graph.one.value",
{
"F64": 1.0
}
],
[
"graph.zero.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": "985991f62cc6b92895018312c5ea86e493ef1c09dd53cf6e0813551baa97b671",
"project": {
"commit": "d7e3a8f39881cc8eba42a906fa846676bfbb1010"
}
},
"metrics": {
"total_pips": -19.5,
"max_drawdown": 35.5,
"bias_sign_flips": 8,
"r": {
"expectancy_r": -0.7143093152455215,
"n_trades": 8,
"win_rate": 0.125,
"avg_win_r": 2.704952265814223,
"avg_loss_r": -1.2027752553969135,
"profit_factor": 0.32127510981397456,
"max_r_drawdown": 7.371844351604779,
"n_open_at_end": 0,
"sqn": -1.3625154866298599,
"sqn_normalized": -1.3625154866298599,
"net_expectancy_r": -0.7143093152455215,
"conviction_terciles_r": [
-1.0191864862283455,
-1.1307276003565727,
-0.09463958281258789
]
}
}
}
@@ -0,0 +1 @@
{"format_version":2,"blueprint":{"name":"graph","doc":"NY cash-open session anchor: bars elapsed since the 09:30 America/New_York open","nodes":[{"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}}]}}],"input_roles":[{"name":"price","targets":[{"node":0,"slot":0}]}],"output":[{"node":0,"field":0,"name":"bars"}]}}
@@ -0,0 +1,9 @@
[
{"op": "doc", "text": "NY cash-open session anchor: bars elapsed since the 09:30 America/New_York open"},
{"op": "input", "role": "price"},
{"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": "expose", "from": "sess.bars_since_open", "as": "bars"}
]