让显式动作继承运行调度

This commit is contained in:
boris
2026-08-27 08:37:33 +08:00
parent 9b00a0777a
commit 801a27dace
@@ -1980,6 +1980,12 @@ pub fn platform_expr_config_from_spec(
explicit_actions.push(parsed);
}
cfg.explicit_actions = explicit_actions;
// An explicit action follows the strategy's declared schedule when
// it does not have a separate trading schedule. Otherwise the
// action can be parsed successfully but never be dispatched.
if cfg.explicit_action_schedule.is_none() && !cfg.explicit_actions.is_empty() {
cfg.explicit_action_schedule = cfg.rebalance_schedule.clone();
}
}
} else if let Some(engine) = spec.engine_config.as_ref() {
if let Some(dynamic_range) = engine.dynamic_range.as_ref() {
@@ -2765,6 +2771,38 @@ mod tests {
assert_eq!(cfg.explicit_actions.len(), 1);
}
#[test]
fn explicit_actions_inherit_top_level_runtime_schedule() {
let spec = serde_json::json!({
"runtimeExpressions": {
"schedule": {"frequency": "daily", "time": "15:00"},
"trading": {
"rotationEnabled": false,
"actions": [{
"kind": "modify_order",
"orderIdExpr": "42",
"quantityExpr": "200",
"limitPriceExpr": "10.25",
"symbol": "000001.SZ",
"reason": "modify_test"
}]
}
}
});
let cfg = platform_expr_config_from_value("modify", "000300.SH", &spec)
.expect("explicit action config");
assert_eq!(cfg.explicit_actions.len(), 1);
assert_eq!(
cfg.explicit_action_schedule,
Some(PlatformRebalanceSchedule {
frequency: PlatformScheduleFrequency::Daily,
time_rule: Some(ScheduleTimeRule::physical_time(15, 0)),
})
);
}
#[test]
fn parses_typed_time_in_force_for_explicit_orders() {
let spec = serde_json::json!({