feat(engine, market, strategy, backtest): NodeSchema.doc threading across the domain crates
C29 compile/unit seam, tasks 4+5 of the self-description plan. aura-engine (task 4): derive_signature stamps doc: "" with the stance recorded in-code -- a derived composite signature is graph wiring, not a vocabulary entry; no seam walks its doc, the described surface is the composite's own doc at the register seam. All in-crate test literals thread doc: "test-only schema". Domain crates (task 5): the 12 production builder sites in aura-market / aura-strategy / aura-backtest carry authored meaning lines; test sites in aura-backtest / aura-composites / aura-ingest thread the test-only doc. Three texts were corrected against the actual node semantics after quality review rather than kept from the first authoring pass: SimBroker is the frictionless integrator of held exposure times price return into cumulative pip equity (no fills/stops/lifecycle -- that is PositionManagement's domain), the shared cost-node line names the PM-geometry inputs and both charge modes (AtClose / PerHeldCycle) instead of a "per-trade gross R" mapping, and LongOnly's line conditions on its enabled param and speaks port-term "exposure". Gates: cargo test green for all six touched crates (engine, market, strategy, backtest, composites, ingest); the workspace-wide gate follows task 6 (aura-runner is the one remaining unthreaded site, E0063 by design until then). refs #316
This commit is contained in:
@@ -1214,6 +1214,7 @@ mod tests {
|
|||||||
inputs: vec![PortSpec { kind: ScalarKind::F64, firing: Firing::Any, name: "in".into() }],
|
inputs: vec![PortSpec { kind: ScalarKind::F64, firing: Firing::Any, name: "in".into() }],
|
||||||
output: vec![],
|
output: vec![],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,12 @@ impl PositionManagement {
|
|||||||
.collect();
|
.collect();
|
||||||
PrimitiveBuilder::new(
|
PrimitiveBuilder::new(
|
||||||
"PositionManagement",
|
"PositionManagement",
|
||||||
NodeSchema { inputs, output, params: vec![] },
|
NodeSchema {
|
||||||
|
inputs,
|
||||||
|
output,
|
||||||
|
params: vec![],
|
||||||
|
doc: "turns bias plus protective stop into a managed position in R",
|
||||||
|
},
|
||||||
|_| Box::new(PositionManagement::new()),
|
|_| Box::new(PositionManagement::new()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ impl SimBroker {
|
|||||||
],
|
],
|
||||||
output: vec![FieldSpec { name: "equity".into(), kind: ScalarKind::F64 }],
|
output: vec![FieldSpec { name: "equity".into(), kind: ScalarKind::F64 }],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "frictionless sim-optimal broker: integrates held exposure times price return into cumulative pip equity",
|
||||||
},
|
},
|
||||||
move |_| Box::new(SimBroker::new(pip_size)),
|
move |_| Box::new(SimBroker::new(pip_size)),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ impl ConstLongBias {
|
|||||||
inputs: vec![PortSpec { kind: ScalarKind::F64, firing: Firing::Any, name: "price".into() }],
|
inputs: vec![PortSpec { kind: ScalarKind::F64, firing: Firing::Any, name: "price".into() }],
|
||||||
output: vec![FieldSpec { name: "bias".into(), kind: ScalarKind::F64 }],
|
output: vec![FieldSpec { name: "bias".into(), kind: ScalarKind::F64 }],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
},
|
},
|
||||||
|_| Box::new(ConstLongBias { out: [Cell::from_f64(0.0)] }),
|
|_| Box::new(ConstLongBias { out: [Cell::from_f64(0.0)] }),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -129,7 +129,15 @@ fn derive_signature(c: &Composite) -> NodeSchema {
|
|||||||
.collect();
|
.collect();
|
||||||
let mut params = Vec::new();
|
let mut params = Vec::new();
|
||||||
collect_params(c.nodes(), c.gangs(), "", &mut params);
|
collect_params(c.nodes(), c.gangs(), "", &mut params);
|
||||||
NodeSchema { inputs, output, params }
|
NodeSchema {
|
||||||
|
inputs,
|
||||||
|
output,
|
||||||
|
params,
|
||||||
|
// A derived composite signature is graph wiring, not a vocabulary entry:
|
||||||
|
// no seam walks this doc. The described surface is the composite's own
|
||||||
|
// `doc`, gated at register (C29, register seam).
|
||||||
|
doc: "",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The scalar kind of the interior input slot a composite target addresses,
|
/// The scalar kind of the interior input slot a composite target addresses,
|
||||||
@@ -1838,6 +1846,7 @@ mod tests {
|
|||||||
inputs: vec![],
|
inputs: vec![],
|
||||||
output: vec![FieldSpec { name: "v".into(), kind: ScalarKind::F64 }],
|
output: vec![FieldSpec { name: "v".into(), kind: ScalarKind::F64 }],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
};
|
};
|
||||||
let to = NodeSchema {
|
let to = NodeSchema {
|
||||||
inputs: vec![
|
inputs: vec![
|
||||||
@@ -1846,6 +1855,7 @@ mod tests {
|
|||||||
],
|
],
|
||||||
output: vec![],
|
output: vec![],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
};
|
};
|
||||||
assert!(edge_kind_check(&from, 0, &to, 0).is_ok());
|
assert!(edge_kind_check(&from, 0, &to, 0).is_ok());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -2269,7 +2279,7 @@ mod tests {
|
|||||||
fn pass1() -> BlueprintNode {
|
fn pass1() -> BlueprintNode {
|
||||||
PrimitiveBuilder::new(
|
PrimitiveBuilder::new(
|
||||||
"Pass1",
|
"Pass1",
|
||||||
NodeSchema { inputs: vec![f64_any()], output: out_v(), params: vec![] },
|
NodeSchema { inputs: vec![f64_any()], output: out_v(), params: vec![], doc: "test-only schema" },
|
||||||
|_| Box::new(Pass1 { out: [Cell::from_f64(0.0)] }),
|
|_| Box::new(Pass1 { out: [Cell::from_f64(0.0)] }),
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
@@ -2277,7 +2287,12 @@ mod tests {
|
|||||||
fn join2() -> BlueprintNode {
|
fn join2() -> BlueprintNode {
|
||||||
PrimitiveBuilder::new(
|
PrimitiveBuilder::new(
|
||||||
"Join2",
|
"Join2",
|
||||||
NodeSchema { inputs: vec![f64_any(), f64_any()], output: out_v(), params: vec![] },
|
NodeSchema {
|
||||||
|
inputs: vec![f64_any(), f64_any()],
|
||||||
|
output: out_v(),
|
||||||
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
|
},
|
||||||
|_| Box::new(Join2 { out: [Cell::from_f64(0.0)] }),
|
|_| Box::new(Join2 { out: [Cell::from_f64(0.0)] }),
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
@@ -2285,7 +2300,7 @@ mod tests {
|
|||||||
fn sink_f64() -> BlueprintNode {
|
fn sink_f64() -> BlueprintNode {
|
||||||
PrimitiveBuilder::new(
|
PrimitiveBuilder::new(
|
||||||
"SinkF64",
|
"SinkF64",
|
||||||
NodeSchema { inputs: vec![f64_any()], output: vec![], params: vec![] },
|
NodeSchema { inputs: vec![f64_any()], output: vec![], params: vec![], doc: "test-only schema" },
|
||||||
|_| Box::new(SinkF64),
|
|_| Box::new(SinkF64),
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
@@ -2297,6 +2312,7 @@ mod tests {
|
|||||||
inputs: vec![PortSpec { kind: ScalarKind::I64, firing: Firing::Any, name: "in".into() }],
|
inputs: vec![PortSpec { kind: ScalarKind::I64, firing: Firing::Any, name: "in".into() }],
|
||||||
output: vec![],
|
output: vec![],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
},
|
},
|
||||||
|_| Box::new(SinkI64),
|
|_| Box::new(SinkI64),
|
||||||
)
|
)
|
||||||
@@ -2849,6 +2865,7 @@ mod tests {
|
|||||||
inputs: vec![f64_any()],
|
inputs: vec![f64_any()],
|
||||||
output: vec![],
|
output: vec![],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
};
|
};
|
||||||
let h = Harness::bootstrap(FlatGraph {
|
let h = Harness::bootstrap(FlatGraph {
|
||||||
nodes: vec![
|
nodes: vec![
|
||||||
@@ -3454,6 +3471,7 @@ mod tests {
|
|||||||
inputs: vec![PortSpec { kind: ScalarKind::I64, firing: Firing::Any, name: "in".into() }],
|
inputs: vec![PortSpec { kind: ScalarKind::I64, firing: Firing::Any, name: "in".into() }],
|
||||||
output: vec![FieldSpec { name: "v".into(), kind: ScalarKind::I64 }],
|
output: vec![FieldSpec { name: "v".into(), kind: ScalarKind::I64 }],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
},
|
},
|
||||||
|_| panic!("build must not run when validation fails pre-build"),
|
|_| panic!("build must not run when validation fails pre-build"),
|
||||||
);
|
);
|
||||||
@@ -3556,7 +3574,7 @@ mod tests {
|
|||||||
// cannot take .named).
|
// cannot take .named).
|
||||||
let paramless_sma = PrimitiveBuilder::new(
|
let paramless_sma = PrimitiveBuilder::new(
|
||||||
"Pass1",
|
"Pass1",
|
||||||
NodeSchema { inputs: vec![f64_any()], output: out_v(), params: vec![] },
|
NodeSchema { inputs: vec![f64_any()], output: out_v(), params: vec![], doc: "test-only schema" },
|
||||||
|_| Box::new(Pass1 { out: [Cell::from_f64(0.0)] }),
|
|_| Box::new(Pass1 { out: [Cell::from_f64(0.0)] }),
|
||||||
)
|
)
|
||||||
.named("sma");
|
.named("sma");
|
||||||
|
|||||||
@@ -348,6 +348,7 @@ mod tests {
|
|||||||
],
|
],
|
||||||
output: vec![FieldSpec { name: "diff".into(), kind: ScalarKind::F64 }],
|
output: vec![FieldSpec { name: "diff".into(), kind: ScalarKind::F64 }],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
},
|
},
|
||||||
|_| Box::new(Bare),
|
|_| Box::new(Bare),
|
||||||
)
|
)
|
||||||
@@ -462,6 +463,7 @@ mod tests {
|
|||||||
FieldSpec { name: "lo".into(), kind: ScalarKind::I64 },
|
FieldSpec { name: "lo".into(), kind: ScalarKind::I64 },
|
||||||
],
|
],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
},
|
},
|
||||||
|_| Box::new(Bare),
|
|_| Box::new(Bare),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -878,6 +878,7 @@ mod tests {
|
|||||||
inputs: kinds.iter().enumerate().map(|(i, &kind)| PortSpec { kind, firing, name: format!("col[{i}]") }).collect(),
|
inputs: kinds.iter().enumerate().map(|(i, &kind)| PortSpec { kind, firing, name: format!("col[{i}]") }).collect(),
|
||||||
output: vec![],
|
output: vec![],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -895,6 +896,7 @@ mod tests {
|
|||||||
inputs: vec![f64_port(Firing::Any), f64_port(Firing::Any)],
|
inputs: vec![f64_port(Firing::Any), f64_port(Firing::Any)],
|
||||||
output: vec![FieldSpec { name: "value".into(), kind: ScalarKind::F64 }],
|
output: vec![FieldSpec { name: "value".into(), kind: ScalarKind::F64 }],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -924,6 +926,7 @@ mod tests {
|
|||||||
inputs: vec![f64_port(Firing::Barrier(0)), f64_port(Firing::Barrier(0))],
|
inputs: vec![f64_port(Firing::Barrier(0)), f64_port(Firing::Barrier(0))],
|
||||||
output: vec![FieldSpec { name: "value".into(), kind: ScalarKind::F64 }],
|
output: vec![FieldSpec { name: "value".into(), kind: ScalarKind::F64 }],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -951,6 +954,7 @@ mod tests {
|
|||||||
inputs: vec![f64_port(Firing::Any)],
|
inputs: vec![f64_port(Firing::Any)],
|
||||||
output: vec![FieldSpec { name: "value".into(), kind: ScalarKind::Bool }],
|
output: vec![FieldSpec { name: "value".into(), kind: ScalarKind::Bool }],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -984,6 +988,7 @@ mod tests {
|
|||||||
],
|
],
|
||||||
output: vec![FieldSpec { name: "value".into(), kind: ScalarKind::F64 }],
|
output: vec![FieldSpec { name: "value".into(), kind: ScalarKind::F64 }],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1022,6 +1027,7 @@ mod tests {
|
|||||||
FieldSpec { name: "volume".into(), kind: ScalarKind::F64 },
|
FieldSpec { name: "volume".into(), kind: ScalarKind::F64 },
|
||||||
],
|
],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1057,6 +1063,7 @@ mod tests {
|
|||||||
FieldSpec { name: "i".into(), kind: ScalarKind::I64 },
|
FieldSpec { name: "i".into(), kind: ScalarKind::I64 },
|
||||||
],
|
],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1084,6 +1091,7 @@ mod tests {
|
|||||||
inputs: vec![f64_port(Firing::Any)],
|
inputs: vec![f64_port(Firing::Any)],
|
||||||
output: vec![FieldSpec { name: "value".into(), kind: ScalarKind::F64 }],
|
output: vec![FieldSpec { name: "value".into(), kind: ScalarKind::F64 }],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2442,6 +2450,7 @@ mod tests {
|
|||||||
FieldSpec { name: "i".into(), kind: ScalarKind::I64 },
|
FieldSpec { name: "i".into(), kind: ScalarKind::I64 },
|
||||||
],
|
],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ fn recorder_sig(kinds: &[ScalarKind]) -> NodeSchema {
|
|||||||
.collect(),
|
.collect(),
|
||||||
output: vec![],
|
output: vec![],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ fn run_sample_over(prices: Vec<(Timestamp, Scalar)>) -> RunReport {
|
|||||||
inputs: vec![PortSpec { kind: ScalarKind::F64, firing: Firing::Any, name: "in".into() }],
|
inputs: vec![PortSpec { kind: ScalarKind::F64, firing: Firing::Any, name: "in".into() }],
|
||||||
output: vec![],
|
output: vec![],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
};
|
};
|
||||||
let mut h = Harness::bootstrap(FlatGraph {
|
let mut h = Harness::bootstrap(FlatGraph {
|
||||||
nodes: vec![
|
nodes: vec![
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ fn run_sample(window: (Timestamp, Timestamp), source: Box<dyn Source>) -> RunRep
|
|||||||
inputs: vec![PortSpec { kind: ScalarKind::F64, firing: Firing::Any, name: "in".into() }],
|
inputs: vec![PortSpec { kind: ScalarKind::F64, firing: Firing::Any, name: "in".into() }],
|
||||||
output: vec![],
|
output: vec![],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "test-only schema",
|
||||||
};
|
};
|
||||||
let mut h = Harness::bootstrap(FlatGraph {
|
let mut h = Harness::bootstrap(FlatGraph {
|
||||||
nodes: vec![
|
nodes: vec![
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ impl Resample {
|
|||||||
FieldSpec { name: "close".into(), kind: ScalarKind::F64 },
|
FieldSpec { name: "close".into(), kind: ScalarKind::F64 },
|
||||||
],
|
],
|
||||||
params: vec![ParamSpec { name: "period_minutes".into(), kind: ScalarKind::I64 }],
|
params: vec![ParamSpec { name: "period_minutes".into(), kind: ScalarKind::I64 }],
|
||||||
|
doc: "emits a completed bar once per resample boundary, never mid-bar",
|
||||||
},
|
},
|
||||||
|p| Box::new(Resample::new(p[0].i64())),
|
|p| Box::new(Resample::new(p[0].i64())),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ impl Session {
|
|||||||
inputs: vec![PortSpec { kind: ScalarKind::F64, firing: Firing::Any, name: "trigger".into() }],
|
inputs: vec![PortSpec { kind: ScalarKind::F64, firing: Firing::Any, name: "trigger".into() }],
|
||||||
output: vec![FieldSpec { name: "bars_since_open".into(), kind: ScalarKind::I64 }],
|
output: vec![FieldSpec { name: "bars_since_open".into(), kind: ScalarKind::I64 }],
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "bars elapsed since the session open, from the configured open time and timezone",
|
||||||
},
|
},
|
||||||
move |_| Box::new(Session::new(open_hour, open_minute, tz, period_minutes)),
|
move |_| Box::new(Session::new(open_hour, open_minute, tz, period_minutes)),
|
||||||
)
|
)
|
||||||
@@ -99,6 +100,7 @@ impl SessionFrankfurt {
|
|||||||
inputs: vec![PortSpec { kind: ScalarKind::F64, firing: Firing::Any, name: "trigger".into() }],
|
inputs: vec![PortSpec { kind: ScalarKind::F64, firing: Firing::Any, name: "trigger".into() }],
|
||||||
output: vec![FieldSpec { name: "bars_since_open".into(), kind: ScalarKind::I64 }],
|
output: vec![FieldSpec { name: "bars_since_open".into(), kind: ScalarKind::I64 }],
|
||||||
params: vec![ParamSpec { name: "period_minutes".into(), kind: ScalarKind::I64 }],
|
params: vec![ParamSpec { name: "period_minutes".into(), kind: ScalarKind::I64 }],
|
||||||
|
doc: "bars elapsed since the Frankfurt session open (09:00 Europe/Berlin)",
|
||||||
},
|
},
|
||||||
|p| Box::new(Session::new(9, 0, chrono_tz::Europe::Berlin, p[0].i64())),
|
|p| Box::new(Session::new(9, 0, chrono_tz::Europe::Berlin, p[0].i64())),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ impl Bias {
|
|||||||
inputs: vec![PortSpec { kind: ScalarKind::F64, firing: Firing::Any, name: "signal".into() }],
|
inputs: vec![PortSpec { kind: ScalarKind::F64, firing: Firing::Any, name: "signal".into() }],
|
||||||
output: vec![FieldSpec { name: "bias".into(), kind: ScalarKind::F64 }],
|
output: vec![FieldSpec { name: "bias".into(), kind: ScalarKind::F64 }],
|
||||||
params: vec![ParamSpec { name: "scale".into(), kind: ScalarKind::F64 }],
|
params: vec![ParamSpec { name: "scale".into(), kind: ScalarKind::F64 }],
|
||||||
|
doc: "clamps the strategy signal into the bias contract [-1,+1]",
|
||||||
},
|
},
|
||||||
|p| Box::new(Bias::new(p[0].f64())),
|
|p| Box::new(Bias::new(p[0].f64())),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -224,7 +224,16 @@ pub fn cost_node_builder(
|
|||||||
) -> PrimitiveBuilder {
|
) -> PrimitiveBuilder {
|
||||||
let mut inputs = geometry_input_ports();
|
let mut inputs = geometry_input_ports();
|
||||||
inputs.extend(extra_inputs);
|
inputs.extend(extra_inputs);
|
||||||
PrimitiveBuilder::new(name, NodeSchema { inputs, output: cost_output_fields(), params }, build)
|
PrimitiveBuilder::new(
|
||||||
|
name,
|
||||||
|
NodeSchema {
|
||||||
|
inputs,
|
||||||
|
output: cost_output_fields(),
|
||||||
|
params,
|
||||||
|
doc: "cost-model node: charges its cost in R from position geometry, at close or accrued per held cycle",
|
||||||
|
},
|
||||||
|
build,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ impl CostSum {
|
|||||||
.map(|n| FieldSpec { name: (*n).into(), kind: ScalarKind::F64 })
|
.map(|n| FieldSpec { name: (*n).into(), kind: ScalarKind::F64 })
|
||||||
.collect(),
|
.collect(),
|
||||||
params: vec![],
|
params: vec![],
|
||||||
|
doc: "sums cost-model contributions into one cost-in-R stream",
|
||||||
},
|
},
|
||||||
move |_| Box::new(CostSum::new(n_costs)),
|
move |_| Box::new(CostSum::new(n_costs)),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ impl LongOnly {
|
|||||||
inputs: vec![PortSpec { kind: ScalarKind::F64, firing: Firing::Any, name: "exposure".into() }],
|
inputs: vec![PortSpec { kind: ScalarKind::F64, firing: Firing::Any, name: "exposure".into() }],
|
||||||
output: vec![FieldSpec { name: "exposure".into(), kind: ScalarKind::F64 }],
|
output: vec![FieldSpec { name: "exposure".into(), kind: ScalarKind::F64 }],
|
||||||
params: vec![ParamSpec { name: "enabled".into(), kind: ScalarKind::Bool }],
|
params: vec![ParamSpec { name: "enabled".into(), kind: ScalarKind::Bool }],
|
||||||
|
doc: "when enabled, clamps negative exposure to flat (long-only); otherwise passes exposure through",
|
||||||
},
|
},
|
||||||
|p| Box::new(LongOnly::new(p[0].bool())),
|
|p| Box::new(LongOnly::new(p[0].bool())),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ impl Sizer {
|
|||||||
],
|
],
|
||||||
output: vec![FieldSpec { name: "size".into(), kind: ScalarKind::F64 }],
|
output: vec![FieldSpec { name: "size".into(), kind: ScalarKind::F64 }],
|
||||||
params: vec![ParamSpec { name: "risk_budget".into(), kind: ScalarKind::F64 }],
|
params: vec![ParamSpec { name: "risk_budget".into(), kind: ScalarKind::F64 }],
|
||||||
|
doc: "size = risk_budget / stop_distance at the deploy edge; bias only gates firing, research runs flat-1R",
|
||||||
},
|
},
|
||||||
|p| Box::new(Sizer::new(p[0].f64())),
|
|p| Box::new(Sizer::new(p[0].f64())),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ impl FixedStop {
|
|||||||
inputs: vec![PortSpec { kind: ScalarKind::F64, firing: Firing::Any, name: "price".into() }],
|
inputs: vec![PortSpec { kind: ScalarKind::F64, firing: Firing::Any, name: "price".into() }],
|
||||||
output: vec![FieldSpec { name: "stop_distance".into(), kind: ScalarKind::F64 }],
|
output: vec![FieldSpec { name: "stop_distance".into(), kind: ScalarKind::F64 }],
|
||||||
params: vec![ParamSpec { name: "distance".into(), kind: ScalarKind::F64 }],
|
params: vec![ParamSpec { name: "distance".into(), kind: ScalarKind::F64 }],
|
||||||
|
doc: "derives the protective stop that defines the risk unit R",
|
||||||
},
|
},
|
||||||
|p| Box::new(FixedStop::new(p[0].f64())),
|
|p| Box::new(FixedStop::new(p[0].f64())),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ impl VolTfStop {
|
|||||||
ParamSpec { name: "length".into(), kind: ScalarKind::I64 },
|
ParamSpec { name: "length".into(), kind: ScalarKind::I64 },
|
||||||
ParamSpec { name: "k".into(), kind: ScalarKind::F64 },
|
ParamSpec { name: "k".into(), kind: ScalarKind::F64 },
|
||||||
],
|
],
|
||||||
|
doc: "volatility- and timeframe-scaled protective stop rule",
|
||||||
},
|
},
|
||||||
|p| Box::new(VolTfStop::new(p[0].i64(), p[1].i64(), p[2].f64())),
|
|p| Box::new(VolTfStop::new(p[0].i64(), p[1].i64(), p[2].f64())),
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user