diff --git a/crates/fidc-core/src/platform_strategy_spec.rs b/crates/fidc-core/src/platform_strategy_spec.rs index a255472..bbdf381 100644 --- a/crates/fidc-core/src/platform_strategy_spec.rs +++ b/crates/fidc-core/src/platform_strategy_spec.rs @@ -1001,6 +1001,22 @@ fn normalize_model_name(value: &str) -> String { value.trim().to_ascii_lowercase().replace('-', "_") } +fn normalize_slippage_model_name(value: &str) -> String { + match normalize_model_name(value).as_str() { + "percent" + | "percentage" + | "rate" + | "ratio" + | "price_percent" + | "price_percentage" + | "price_rate" + | "price_ratio_slippage" + | "priceratioslippage" => "price_ratio".to_string(), + "dynamic_volume_volatility" => "dynamic".to_string(), + other => other.to_string(), + } +} + fn parse_matching_type(value: Option<&str>) -> Result, String> { let Some(raw) = value.map(str::trim).filter(|item| !item.is_empty()) else { return Ok(None); @@ -1047,7 +1063,7 @@ fn parse_slippage_model( let volatility_coefficient = valid_non_negative(volatility_coefficient); let max_value = valid_non_negative(max_value); let model = model - .map(normalize_model_name) + .map(normalize_slippage_model_name) .filter(|item| !item.is_empty()) .unwrap_or_else(|| { if value.is_some_and(|item| item > 0.0) { @@ -1062,13 +1078,11 @@ fn parse_slippage_model( "price_ratio" => Some(SlippageModel::PriceRatio(value.unwrap_or(0.0))), "tick_size" => Some(SlippageModel::TickSize(value.unwrap_or(0.0))), "limit_price" => Some(SlippageModel::LimitPrice), - "dynamic" | "dynamic_volume_volatility" => { - Some(SlippageModel::Dynamic(DynamicSlippageConfig::new( - impact_coefficient.unwrap_or(0.5), - volatility_coefficient.unwrap_or(0.3), - max_value.or(value).unwrap_or(0.01), - ))) - } + "dynamic" => Some(SlippageModel::Dynamic(DynamicSlippageConfig::new( + impact_coefficient.unwrap_or(0.5), + volatility_coefficient.unwrap_or(0.3), + max_value.or(value).unwrap_or(0.01), + ))), _ => None, } } @@ -2718,6 +2732,20 @@ mod tests { assert!(cfg.strict_value_budget); } + #[test] + fn parses_percent_slippage_alias_into_platform_config() { + let spec = serde_json::json!({ + "execution": { + "slippageModel": "percent", + "slippageValue": 0.001 + } + }); + + let cfg = platform_expr_config_from_value("", "", &spec).expect("config"); + + assert_eq!(cfg.slippage_model, SlippageModel::PriceRatio(0.001)); + } + #[test] fn parses_rebalance_cash_mode_and_forces_minute_to_actual_sequence() { let spec = serde_json::json!({