修正延迟调仓剩余仓位预算

This commit is contained in:
boris
2026-07-17 12:43:53 +08:00
parent bdd5a41106
commit 81ac623fca
@@ -2578,6 +2578,7 @@ impl PlatformExprStrategy {
working_symbols: &BTreeSet<String>,
value_symbols: &BTreeSet<String>,
pending_buy_value: f64,
deferred_target_values: Option<&BTreeMap<String, f64>>,
slot_blocking_symbols: &BTreeSet<String>,
) -> f64 {
if selection_limit == 0 || !target_budget.is_finite() || target_budget <= 0.0 {
@@ -2597,6 +2598,7 @@ impl PlatformExprStrategy {
date,
working_symbols,
value_symbols,
deferred_target_values,
);
let working_value = active_value + pending_buy_value.max(0.0);
let per_slot_budget = (target_budget - working_value).max(0.0) / slots_remaining as f64;
@@ -2632,6 +2634,7 @@ impl PlatformExprStrategy {
delayed_sold_symbols: &BTreeSet<String>,
intraday_attempted_buys: &mut BTreeSet<String>,
pending_buy_value: &mut f64,
deferred_target_values: &BTreeMap<String, f64>,
debug_daily_top_up: bool,
daily_top_up_debug_notes: &mut Vec<String>,
) -> Result<bool, BacktestError> {
@@ -2668,6 +2671,7 @@ impl PlatformExprStrategy {
projection_date,
&budget_working_symbols,
&value_symbols,
Some(deferred_target_values),
)
} else {
0.0
@@ -2681,6 +2685,7 @@ impl PlatformExprStrategy {
&budget_working_symbols,
&value_symbols,
*pending_buy_value,
Some(deferred_target_values),
slot_blocking_symbols,
);
let available_buy_cash = slot_buy_cash.min(*aiquant_available_cash);
@@ -2832,11 +2837,18 @@ impl PlatformExprStrategy {
date: NaiveDate,
working_symbols: &BTreeSet<String>,
value_symbols: &BTreeSet<String>,
deferred_target_values: Option<&BTreeMap<String, f64>>,
) -> f64 {
working_symbols
.iter()
.filter(|symbol| value_symbols.contains(*symbol))
.map(|symbol| {
if let Some(target_value) = deferred_target_values
.and_then(|target_values| target_values.get(symbol))
.filter(|target_value| target_value.is_finite() && **target_value >= 0.0)
{
return *target_value;
}
if self.config.aiquant_transaction_cost {
self.projected_strategy_visible_position_value_for_remaining_buy_cash(
ctx, projected, date, symbol,
@@ -9261,6 +9273,7 @@ impl Strategy for PlatformExprStrategy {
&& selection_limit > 0;
let daily_top_up_target_budget = aiquant_total_value * trading_ratio;
let mut daily_top_up_pending_buy_value = 0.0_f64;
let mut deferred_daily_target_values = BTreeMap::<String, f64>::new();
let mut pending_full_close_symbols = BTreeSet::<String>::new();
let mut slot_blocking_symbols = BTreeSet::<String>::new();
let should_block_partial_exit_residual_slot = trading_ratio < 1.0;
@@ -9506,6 +9519,10 @@ impl Strategy for PlatformExprStrategy {
target_value,
reason: "daily_position_target_adjust".to_string(),
});
if defer_execution_risk {
deferred_daily_target_values
.insert(position.symbol.clone(), target_value);
}
if quantity_delta > 0 {
same_bar_buy_symbols.insert(position.symbol.clone());
}
@@ -9592,6 +9609,7 @@ impl Strategy for PlatformExprStrategy {
&delayed_sold_symbols,
&mut intraday_attempted_buys,
&mut daily_top_up_pending_buy_value,
&deferred_daily_target_values,
debug_daily_top_up,
&mut daily_top_up_debug_notes,
)?;
@@ -9691,6 +9709,7 @@ impl Strategy for PlatformExprStrategy {
&delayed_sold_symbols,
&mut intraday_attempted_buys,
&mut daily_top_up_pending_buy_value,
&deferred_daily_target_values,
debug_daily_top_up,
&mut daily_top_up_debug_notes,
)?;
@@ -9766,6 +9785,7 @@ impl Strategy for PlatformExprStrategy {
&delayed_sold_symbols,
&mut intraday_attempted_buys,
&mut daily_top_up_pending_buy_value,
&deferred_daily_target_values,
debug_daily_top_up,
&mut daily_top_up_debug_notes,
)?;
@@ -9835,6 +9855,7 @@ impl Strategy for PlatformExprStrategy {
&delayed_sold_symbols,
&mut intraday_attempted_buys,
&mut daily_top_up_pending_buy_value,
&deferred_daily_target_values,
debug_daily_top_up,
&mut daily_top_up_debug_notes,
)?;
@@ -10084,6 +10105,7 @@ impl Strategy for PlatformExprStrategy {
&rebalance_working_symbols,
&rebalance_value_symbols,
rebalance_pending_buy_value,
None,
&pending_full_close_symbols,
);
let target_cash = slot_buy_cash * stock_scale;
@@ -21850,6 +21872,7 @@ mod tests {
&working_symbols,
&value_symbols,
0.0,
None,
&BTreeSet::new(),
);
@@ -21857,6 +21880,24 @@ mod tests {
(cash - 5_000.0).abs() < 1e-6,
"remaining cash should use strategy-visible price and projected 500-share quantity, got {cash}"
);
let deferred_targets = BTreeMap::from([("000001.SZ".to_string(), 2_000.0)]);
let deferred_cash = strategy.remaining_buy_cash_per_slot(
&ctx,
&projected,
date,
6_000.0,
2,
&working_symbols,
&value_symbols,
0.0,
Some(&deferred_targets),
&BTreeSet::new(),
);
assert!(
(deferred_cash - 3_000.0).abs() < 1e-6,
"lagged target reductions should reserve their frozen target value, got {deferred_cash}"
);
}
#[test]