diff --git a/crates/fidc-core/src/platform_strategy_spec.rs b/crates/fidc-core/src/platform_strategy_spec.rs index 25bfdc5..32331d9 100644 --- a/crates/fidc-core/src/platform_strategy_spec.rs +++ b/crates/fidc-core/src/platform_strategy_spec.rs @@ -117,8 +117,6 @@ pub struct StrategyExecutionSpec { pub struct StrategyEngineConfig { #[serde(default)] pub template_id: Option, - #[serde(default, alias = "profile_name")] - pub profile_name: Option, #[serde(default, alias = "benchmark_symbol")] pub benchmark_symbol: Option, #[serde(default, alias = "signal_symbol")] @@ -837,6 +835,16 @@ fn reject_removed_compatibility_fields(value: &Value) -> Result<(), String> { "{section_name}.{field_name} has been removed; configure matching, risk, fees and scheduling explicitly" )); } + if section_name != "execution" { + if let Some(field_name) = ["profileName", "profile_name"] + .iter() + .find(|field_name| section.contains_key(**field_name)) + { + return Err(format!( + "{section_name}.{field_name} has been removed; configure matching, risk, fees and scheduling explicitly" + )); + } + } } Ok(()) } @@ -2419,7 +2427,6 @@ mod tests { "signalSymbol": "000852.SH", "benchmark": { "instrumentId": "000852.SH" }, "universe": { "exclude": ["paused", "st", "kcb", "one_yuan"] }, - "engineConfig": { "profileName": "aiquant" }, "runtimeExpressions": { "prelude": "let stocknum = 8;", "selection": { @@ -2579,7 +2586,6 @@ mod tests { "stampTaxChangeDate": "2024-01-02" }, "engineConfig": { - "profileName": "aiquant", "commissionRate": 0.0008 } }); @@ -2868,7 +2874,6 @@ mod tests { "strictValueBudget": true }, "engineConfig": { - "profileName": "aiquant", "matchingType": "current_bar_close", "slippageModel": "none", "slippageValue": 0.0, @@ -3046,80 +3051,9 @@ mod tests { ); } - #[test] - fn profile_name_does_not_inject_trading_behaviors() { - let spec = serde_json::json!({ - "engineConfig": { - "profileName": "aiquant" - } - }); - - let cfg = platform_expr_config_from_value("", "", &spec).expect("config"); - - assert!(!cfg.daily_top_up_enabled); - assert!(!cfg.retry_empty_rebalance); - assert!(cfg.strict_value_budget); - - let explicit_off = serde_json::json!({ - "engineConfig": { - "profileName": "aiquant" - }, - "runtimeExpressions": { - "trading": { - "dailyTopUp": false, - "dailyPositionTargetAdjust": false, - "rebalanceExistingPositions": true, - "selectionBufferMultiple": 1.5, - "dailyReplacementLimit": 2, - "retryEmptyRebalance": false - } - } - }); - - let cfg = platform_expr_config_from_value("", "", &explicit_off).expect("config"); - - assert!(!cfg.daily_top_up_enabled); - assert!(!cfg.daily_position_target_adjust_enabled); - assert!(cfg.rebalance_existing_positions); - assert_eq!(cfg.selection_buffer_multiple, 1.5); - assert_eq!(cfg.daily_replacement_limit, 2); - assert!(!cfg.retry_empty_rebalance); - } - - #[test] - fn engine_config_profile_name_is_metadata_only() { - let spec = serde_json::json!({ - "engineConfig": { - "profileName": "aiquant" - } - }); - - let cfg = platform_expr_config_from_value("", "", &spec).expect("config"); - assert!(!cfg.daily_top_up_enabled); - assert!(!cfg.retry_empty_rebalance); - } - - #[test] - fn legacy_profile_name_does_not_inject_hidden_defaults() { - let spec = serde_json::json!({ - "engineConfig": { - "profileName": "aiquant_rqalpha" - } - }); - - let cfg = platform_expr_config_from_value("", "", &spec).expect("config"); - - assert!(!cfg.daily_top_up_enabled); - assert!(!cfg.retry_empty_rebalance); - assert!(cfg.strict_value_budget); - } - #[test] fn runtime_expressions_infer_ma_windows_from_literal_strategy_logic() { let spec = serde_json::json!({ - "engineConfig": { - "profileName": "aiquant" - }, "runtimeExpressions": { "selection": { "stockFilterExpr": "rolling_mean(\"close\", 5) > rolling_mean(\"close\", 10) && rolling_mean(\"close\", 10) > rolling_mean(\"close\", 30)" @@ -3177,7 +3111,6 @@ mod tests { "instrumentId": "932000.CSI" }, "engineConfig": { - "profileName": "aiquant", "indexThrottle": { "shortDays": 10, "longDays": 30, @@ -3206,7 +3139,6 @@ mod tests { #[test] fn parses_daily_schedule_time_for_execution_quotes() { let spec = serde_json::json!({ - "engineConfig": { "profileName": "aiquant" }, "runtimeExpressions": { "schedule": { "frequency": "daily", "time": "09:33" } } @@ -3225,7 +3157,6 @@ mod tests { #[test] fn multiple_trade_times_do_not_imply_delayed_limit_exit() { let spec = serde_json::json!({ - "engineConfig": { "profileName": "aiquant" }, "rebalance": { "tradeTimes": ["10:31", "10:40"] }, "runtimeExpressions": { "schedule": { "frequency": "daily", "time": "10:40" } @@ -3246,7 +3177,6 @@ mod tests { fn rejects_removed_compatibility_profile() { let spec = serde_json::json!({ "engineConfig": { - "profileName": "cn_a_microcap_v1", "compatibilityProfile": "aiquant_rqalpha" }, "rebalance": { "tradeTimes": ["09:31", "10:15"] }, @@ -3263,10 +3193,21 @@ mod tests { ); } + #[test] + fn rejects_removed_engine_profile_name() { + let spec = serde_json::json!({ + "engineConfig": { + "profileName": "aiquant" + } + }); + + let error = platform_expr_config_from_value("", "", &spec).expect_err("removed field"); + assert!(error.to_string().contains("profileName has been removed")); + } + #[test] fn parses_explicit_delayed_limit_open_exit() { let spec = serde_json::json!({ - "engineConfig": { "profileName": "aiquant" }, "runtimeExpressions": { "schedule": { "frequency": "daily", "time": "10:40" }, "trading": { @@ -3290,9 +3231,8 @@ mod tests { } #[test] - fn explicit_delayed_limit_open_exit_false_overrides_aiquant_trade_times() { + fn explicit_delayed_limit_open_exit_false_overrides_trade_times() { let spec = serde_json::json!({ - "engineConfig": { "profileName": "aiquant" }, "rebalance": { "tradeTimes": ["10:31", "10:40"] }, "runtimeExpressions": { "schedule": { "frequency": "daily", "time": "10:40" },