From 9f188f6313190482469e9e353778fbe3712ae213 Mon Sep 17 00:00:00 2001 From: boris Date: Wed, 1 Jul 2026 14:32:52 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3AiQuant=E5=9B=BA=E5=AE=9A?= =?UTF-8?q?=E7=8E=B0=E9=87=91=E8=B0=83=E4=BB=93=E9=A2=84=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fidc-core/src/platform_expr_strategy.rs | 55 ++++++++++++------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/crates/fidc-core/src/platform_expr_strategy.rs b/crates/fidc-core/src/platform_expr_strategy.rs index 62d75f5..9629164 100644 --- a/crates/fidc-core/src/platform_expr_strategy.rs +++ b/crates/fidc-core/src/platform_expr_strategy.rs @@ -7970,7 +7970,11 @@ impl Strategy for PlatformExprStrategy { if !self.config.aiquant_transaction_cost { aiquant_available_cash = projected.cash(); } - let fixed_buy_cash = aiquant_total_value * trading_ratio / selection_limit as f64; + let fixed_buy_cash = if self.config.aiquant_transaction_cost { + aiquant_available_cash * trading_ratio / selection_limit as f64 + } else { + aiquant_total_value * trading_ratio / selection_limit as f64 + }; let target_budget = aiquant_total_value * trading_ratio; let mut rebalance_working_symbols = slot_working_symbols.clone(); if self.config.release_slot_on_exit_signal { @@ -8052,17 +8056,21 @@ impl Strategy for PlatformExprStrategy { { continue; } - let slot_buy_cash = self.remaining_buy_cash_per_slot( - ctx, - &projected, - execution_date, - target_budget, - selection_limit, - &rebalance_working_symbols, - &rebalance_value_symbols, - rebalance_pending_buy_value, - ); - let target_cash = slot_buy_cash * stock_scale; + let target_cash = if self.config.aiquant_transaction_cost { + fixed_buy_cash * stock_scale + } else { + let slot_buy_cash = self.remaining_buy_cash_per_slot( + ctx, + &projected, + execution_date, + target_budget, + selection_limit, + &rebalance_working_symbols, + &rebalance_value_symbols, + rebalance_pending_buy_value, + ); + slot_buy_cash * stock_scale + }; let buy_cash = target_cash.min(aiquant_available_cash); if buy_cash <= 0.0 { break; @@ -18383,14 +18391,14 @@ mod tests { .count(); assert_eq!( - aiquant_periodic_buys, 1, + aiquant_periodic_buys, 2, "{:?}", aiquant_decision.order_intents ); } #[test] - fn platform_aiquant_periodic_rebalance_does_not_reuse_same_callback_sell_cash() { + fn platform_aiquant_periodic_rebalance_uses_cash_divided_by_top_n_buy_budget() { let prev_date = d(2025, 5, 13); let date = d(2025, 5, 14); let retained_symbols = (1..=17) @@ -18580,13 +18588,18 @@ mod tests { "{:?}", decision.order_intents ); - assert_eq!(periodic_buys, 2, "{:?}", decision.order_intents); + assert_eq!( + periodic_buys, + new_symbols.len(), + "{:?}", + decision.order_intents + ); assert!( - !decision.order_intents.iter().any(|intent| matches!( - intent, - OrderIntent::Value { symbol, reason, .. } - if symbol == &new_symbols[2] && reason == "periodic_rebalance_buy" - )), + decision.order_intents.iter().all(|intent| match intent { + OrderIntent::Value { value, reason, .. } if reason == "periodic_rebalance_buy" => + (*value - 6_500.0).abs() < 1e-6, + _ => true, + }), "{:?}", decision.order_intents ); @@ -18742,7 +18755,7 @@ mod tests { reason, } if symbol == "000002.SZ" && reason == "periodic_rebalance_buy" - && (*value - 10_000.0).abs() < 1e-6 + && (*value - 5_000.0).abs() < 1e-6 )), "{:?}", decision.order_intents