From 1de96494b395a279ff0c196e168723f42b11a235 Mon Sep 17 00:00:00 2001 From: boris Date: Fri, 11 Sep 2026 01:03:22 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=9F=E4=B8=80=E7=AD=96=E7=95=A5=E6=95=B0?= =?UTF-8?q?=E5=80=BC=E5=88=AB=E5=90=8D=E5=B9=B6=E4=BF=9D=E7=95=99=E7=B2=BE?= =?UTF-8?q?=E7=A1=AE=E5=86=B2=E7=AA=81=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fidc-core/src/platform_strategy_spec.rs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/crates/fidc-core/src/platform_strategy_spec.rs b/crates/fidc-core/src/platform_strategy_spec.rs index 24c824c..c7236cc 100644 --- a/crates/fidc-core/src/platform_strategy_spec.rs +++ b/crates/fidc-core/src/platform_strategy_spec.rs @@ -745,6 +745,16 @@ fn strategy_alias_values_semantically_equal(left: &Value, right: &Value) -> bool return true; } match (left, right) { + (Value::Number(left), Value::Number(right)) => { + const MAX_EXACT: i64 = 9_007_199_254_740_992; + let exact_integer = |value: &serde_json::Number| { + value.as_i64().filter(|v| (-MAX_EXACT..=MAX_EXACT).contains(v)).map(|v| v as f64) + .or_else(|| value.as_u64().filter(|v| *v <= MAX_EXACT as u64).map(|v| v as f64)) + }; + if left.is_f64() && !right.is_f64() { exact_integer(right).zip(left.as_f64()).is_some_and(|(a,b)| a==b) } + else if right.is_f64() && !left.is_f64() { exact_integer(left).zip(right.as_f64()).is_some_and(|(a,b)| a==b) } + else { false } + } (Value::String(left), Value::String(right)) => left.trim() == right.trim(), (Value::String(left), Value::Number(right)) | (Value::Number(right), Value::String(left)) => left @@ -3180,6 +3190,16 @@ fn normalize_board(symbol: &str, raw_board: Option<&str>) -> String { mod tests { use super::*; + #[test] + fn numeric_strategy_aliases_accept_exact_zero_but_never_hide_rounding_or_conflicts() { + let cfg = platform_expr_config_from_value("fees", "000001.SZ", &serde_json::json!({ + "execution":{"minimumCommission":0.0,"minimum_commission":0} + })).unwrap(); + assert_eq!(cfg.minimum_commission, Some(0.0)); + assert!(!strategy_alias_values_semantically_equal(&serde_json::json!(9007199254740992u64), &serde_json::json!(9007199254740993u64))); + assert!(!strategy_alias_values_semantically_equal(&serde_json::json!(0.0), &serde_json::json!(1))); + } + #[test] fn parses_buy_filter_as_a_separate_trading_condition() { let cfg = platform_expr_config_from_value("buy-guard", "000001.SZ", &serde_json::json!({