From c7d213bf3582cc7fb0062f016f971401cfea2342 Mon Sep 17 00:00:00 2001 From: boris Date: Sun, 6 Sep 2026 20:02:33 +0800 Subject: [PATCH] Revert "perf: skip unused explicit-action stock state" This reverts commit b5934085da061dd34890437c90d23c0baf0c0aa9. --- .../fidc-core/src/platform_expr_strategy.rs | 208 +----------------- 1 file changed, 6 insertions(+), 202 deletions(-) diff --git a/crates/fidc-core/src/platform_expr_strategy.rs b/crates/fidc-core/src/platform_expr_strategy.rs index e8d9700..a46cc1c 100644 --- a/crates/fidc-core/src/platform_expr_strategy.rs +++ b/crates/fidc-core/src/platform_expr_strategy.rs @@ -1130,7 +1130,6 @@ pub struct PlatformExprStrategy { numeric_vm_scratch: RefCell, numeric_vm_hits: RefCell, numeric_vm_fallbacks: RefCell, - explicit_action_stock_state_required: Vec, prelude_dependency_plan: PreludeDependencyPlan, prelude_identifier_candidates: BTreeSet, prelude_declared_identifiers: BTreeSet, @@ -1438,7 +1437,7 @@ impl PlatformExprStrategy { .portfolio_drawdown_control .clone() .map(PlatformPortfolioDrawdownController::new); - let mut strategy = Self { + Self { config, engine, rebalance_day_counter: 0, @@ -1458,7 +1457,6 @@ impl PlatformExprStrategy { numeric_vm_scratch: RefCell::new(NumericVmScratch::default()), numeric_vm_hits: RefCell::new(0), numeric_vm_fallbacks: RefCell::new(0), - explicit_action_stock_state_required: Vec::new(), prelude_dependency_plan, prelude_identifier_candidates, prelude_declared_identifiers, @@ -1476,14 +1474,7 @@ impl PlatformExprStrategy { stock_state_cache_date: RefCell::new(None), stock_state_cache_calendar_index: RefCell::new(None), stock_state_cache: RefCell::new(AHashMap::new()), - }; - strategy.explicit_action_stock_state_required = strategy - .config - .explicit_actions - .iter() - .map(|action| strategy.explicit_action_requires_stock_state(action)) - .collect(); - strategy + } } /// AST 缓存命中次数(仅用于测试与诊断)。 @@ -8650,140 +8641,6 @@ impl PlatformExprStrategy { || self.config.signal_rebalance_dates.contains(&decision_date) } - fn numeric_vm_identifier_requires_stock_state(identifier: &str) -> bool { - !matches!( - identifier, - "trade_date" - | "current_date" - | "date" - | "decision_date" - | "execution_date" - | "signal_open" - | "signal_close" - | "benchmark_open" - | "benchmark_close" - | "benchmark_signal_close" - | "signal_ma5" - | "signal_ma10" - | "signal_ma20" - | "signal_ma30" - | "signal_ma_short" - | "signal_ma_long" - | "benchmark_ma5" - | "benchmark_ma10" - | "benchmark_ma20" - | "benchmark_ma30" - | "benchmark_ma_short" - | "benchmark_ma_long" - | "cash" - | "available_cash" - | "frozen_cash" - | "market_value" - | "total_equity" - | "total_value" - | "portfolio_value" - | "starting_cash" - | "unit_net_value" - | "static_unit_net_value" - | "daily_pnl" - | "daily_returns" - | "total_returns" - | "transaction_cost" - | "trading_pnl" - | "position_pnl" - | "cash_liabilities" - | "management_fee_rate" - | "management_fees" - | "current_exposure" - | "position_count" - | "max_positions" - | "refresh_rate" - | "year" - | "month" - | "quarter" - | "day_of_month" - | "day_of_year" - | "week_of_year" - | "weekday" - | "is_month_start" - | "is_month_end" - | "has_open_orders" - | "open_order_count" - | "open_buy_order_count" - | "open_sell_order_count" - | "open_buy_qty" - | "open_sell_qty" - | "latest_open_order_id" - | "latest_open_order_unfilled_qty" - | "has_dynamic_universe" - | "dynamic_universe_count" - | "has_subscriptions" - | "subscription_count" - | "subscription_guard_required" - | "has_process_events" - | "process_event_count" - | "current_process_order_id" - | "latest_process_order_id" - ) - } - - fn expression_requires_stock_state(&self, expression: &str) -> bool { - let plan = self.expression_eval_plan(expression); - let Some(numeric_vm) = plan.numeric_vm.as_ref() else { - return true; - }; - numeric_vm - .program - .variables() - .iter() - .zip(&numeric_vm.helper_bindings) - .any(|(identifier, helper)| { - helper.is_some() || Self::numeric_vm_identifier_requires_stock_state(identifier) - }) - } - - fn explicit_action_requires_stock_state(&self, action: &PlatformTradeAction) -> bool { - match action { - PlatformTradeAction::Order { - amount_expr, - limit_price_expr, - start_time_expr, - end_time_expr, - when_expr, - .. - } => std::iter::once(amount_expr.as_str()) - .chain(limit_price_expr.as_deref()) - .chain(start_time_expr.as_deref()) - .chain(end_time_expr.as_deref()) - .chain(when_expr.as_deref()) - .any(|expression| self.expression_requires_stock_state(expression)), - PlatformTradeAction::Cancel { - order_id_expr, - when_expr, - .. - } => order_id_expr - .as_deref() - .into_iter() - .chain(when_expr.as_deref()) - .any(|expression| self.expression_requires_stock_state(expression)), - PlatformTradeAction::Modify { - order_id_expr, - new_total_quantity_expr, - new_limit_price_expr, - when_expr, - .. - } => std::iter::once(order_id_expr.as_str()) - .chain(new_total_quantity_expr.as_deref()) - .chain(new_limit_price_expr.as_deref()) - .chain(when_expr.as_deref()) - .any(|expression| self.expression_requires_stock_state(expression)), - PlatformTradeAction::TargetPortfolioSmart { .. } - | PlatformTradeAction::Universe { .. } - | PlatformTradeAction::Account { .. } - | PlatformTradeAction::Futures { .. } => false, - } - } - fn action_when_matches( &self, ctx: &StrategyContext<'_>, @@ -8805,7 +8662,7 @@ impl PlatformExprStrategy { ) -> Result<(Vec, Vec), BacktestError> { let mut intents = Vec::new(); let mut diagnostics = Vec::new(); - for (action_index, action) in self.config.explicit_actions.iter().enumerate() { + for action in &self.config.explicit_actions { match action { PlatformTradeAction::Order { kind, @@ -8818,11 +8675,7 @@ impl PlatformExprStrategy { when_expr, reason, } => { - let stock_state = if self.explicit_action_stock_state_required[action_index] { - self.action_stock_state(ctx, date, Some(symbol))? - } else { - None - }; + let stock_state = self.action_stock_state(ctx, date, Some(symbol))?; if !self.action_when_matches( ctx, day, @@ -9286,11 +9139,7 @@ impl PlatformExprStrategy { when_expr, reason, } => { - let stock_state = if self.explicit_action_stock_state_required[action_index] { - self.action_stock_state(ctx, date, symbol.as_deref())? - } else { - None - }; + let stock_state = self.action_stock_state(ctx, date, symbol.as_deref())?; if !self.action_when_matches( ctx, day, @@ -9340,11 +9189,7 @@ impl PlatformExprStrategy { when_expr, reason, } => { - let stock_state = if self.explicit_action_stock_state_required[action_index] { - self.action_stock_state(ctx, date, symbol.as_deref())? - } else { - None - }; + let stock_state = self.action_stock_state(ctx, date, symbol.as_deref())?; if !self.action_when_matches( ctx, day, @@ -34576,47 +34421,6 @@ mod tests { ); } - #[test] - fn explicit_action_stock_state_dependency_is_compiled_conservatively() { - let mut config = PlatformExprStrategyConfig::generic(); - config.explicit_actions = vec![ - PlatformTradeAction::Order { - kind: PlatformExplicitOrderKind::TargetPercent, - symbol: "000001.SZ".to_string(), - amount_expr: "if decision_date == \"2025-02-03\" { 0.5 } else { 0.0 }".to_string(), - limit_price_expr: None, - time_in_force: None, - start_time_expr: None, - end_time_expr: None, - when_expr: None, - reason: "date_only".to_string(), - }, - PlatformTradeAction::Order { - kind: PlatformExplicitOrderKind::TargetPercent, - symbol: "000002.SZ".to_string(), - amount_expr: "allow_buy ? 0.5 : 0.0".to_string(), - limit_price_expr: None, - time_in_force: None, - start_time_expr: None, - end_time_expr: None, - when_expr: None, - reason: "stock_dependent".to_string(), - }, - ]; - let strategy = PlatformExprStrategy::new(config); - assert_eq!( - strategy.explicit_action_stock_state_required, - vec![false, true] - ); - assert!(!strategy.expression_requires_stock_state( - "if decision_date == \"2025-02-03\" { cash * 0.1 } else { 0.0 }" - )); - assert!(!strategy.expression_requires_stock_state("cash * 0.1")); - assert!(strategy.expression_requires_stock_state("allow_buy")); - assert!(strategy.expression_requires_stock_state("factor_value(\"quality\") > 0")); - assert!(strategy.expression_requires_stock_state("symbol == \"000001.SZ\"")); - } - #[test] fn expression_plan_only_executes_prelude_when_expression_depends_on_it() { let mut cfg = PlatformExprStrategyConfig::microcap_rotation();