From 00ec7a6d5573d14ee57303373867702cc898727c Mon Sep 17 00:00:00 2001 From: boris Date: Thu, 27 Aug 2026 08:37:12 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=A9=E6=98=BE=E5=BC=8F=E5=8A=A8=E4=BD=9C?= =?UTF-8?q?=E7=BB=A7=E6=89=BF=E8=BF=90=E8=A1=8C=E8=B0=83=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fidc-core/src/platform_strategy_spec.rs | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/crates/fidc-core/src/platform_strategy_spec.rs b/crates/fidc-core/src/platform_strategy_spec.rs index 9c3d7bc..4d42d5c 100644 --- a/crates/fidc-core/src/platform_strategy_spec.rs +++ b/crates/fidc-core/src/platform_strategy_spec.rs @@ -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!({