拒绝废弃的引擎配置档案字段

This commit is contained in:
boris
2026-08-01 12:47:23 +08:00
parent d21680ed4f
commit 51acdf1d31
+23 -83
View File
@@ -117,8 +117,6 @@ pub struct StrategyExecutionSpec {
pub struct StrategyEngineConfig {
#[serde(default)]
pub template_id: Option<String>,
#[serde(default, alias = "profile_name")]
pub profile_name: Option<String>,
#[serde(default, alias = "benchmark_symbol")]
pub benchmark_symbol: Option<String>,
#[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" },