按持仓顺序处理未完成清仓补仓

This commit is contained in:
boris
2026-07-08 01:53:00 +08:00
parent 8c4156948e
commit 51ee4a3f54
+81 -11
View File
@@ -8323,7 +8323,15 @@ impl Strategy for PlatformExprStrategy {
.filter(|symbol| !delayed_sold_symbols.contains(*symbol)) .filter(|symbol| !delayed_sold_symbols.contains(*symbol))
.cloned() .cloned()
.collect::<BTreeSet<_>>(); .collect::<BTreeSet<_>>();
let daily_top_up_active = self.config.daily_top_up_enabled
&& self.config.rotation_enabled
&& !periodic_rebalance
&& trading_ratio > 0.0
&& 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 pending_full_close_symbols = BTreeSet::<String>::new(); let mut pending_full_close_symbols = BTreeSet::<String>::new();
let mut interleaved_pending_full_close_symbols = BTreeSet::<String>::new();
let risk_level_forced_exit_time = self.risk_level_forced_exit_time(); let risk_level_forced_exit_time = self.risk_level_forced_exit_time();
self.pending_full_close_symbols.retain(|symbol| { self.pending_full_close_symbols.retain(|symbol| {
ctx.portfolio ctx.portfolio
@@ -8350,6 +8358,10 @@ impl Strategy for PlatformExprStrategy {
continue; continue;
} }
pending_full_close_symbols.insert(symbol.clone()); pending_full_close_symbols.insert(symbol.clone());
if daily_top_up_active {
interleaved_pending_full_close_symbols.insert(symbol);
continue;
}
exit_symbols.insert(symbol.clone()); exit_symbols.insert(symbol.clone());
order_intents.push(OrderIntent::TargetValue { order_intents.push(OrderIntent::TargetValue {
symbol: symbol.clone(), symbol: symbol.clone(),
@@ -8640,18 +8652,76 @@ impl Strategy for PlatformExprStrategy {
} }
} }
let daily_top_up_active = self.config.daily_top_up_enabled
&& self.config.rotation_enabled
&& !periodic_rebalance
&& trading_ratio > 0.0
&& 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;
for position in ctx.portfolio.positions().values() { for position in ctx.portfolio.positions().values() {
if delayed_sold_symbols.contains(&position.symbol) if delayed_sold_symbols.contains(&position.symbol) {
|| pending_full_close_symbols.contains(&position.symbol) continue;
{ }
if interleaved_pending_full_close_symbols.contains(&position.symbol) {
exit_symbols.insert(position.symbol.clone());
order_intents.push(OrderIntent::TargetValue {
symbol: position.symbol.clone(),
target_value: 0.0,
reason: "pending_full_close_exit".to_string(),
});
self.forget_position_entry_date(&position.symbol);
slot_working_symbols.remove(&position.symbol);
let can_sell = defer_execution_risk
|| self.can_sell_position(ctx, execution_date, &position.symbol);
if can_sell {
let close_submitted = self
.project_target_zero(
ctx,
&mut projected,
projection_date,
&position.symbol,
&mut projected_execution_state,
)
.is_some();
if close_submitted {
if Self::projected_position_is_flat(&projected, &position.symbol) {
same_day_sold_symbols.insert(position.symbol.clone());
pending_full_close_symbols.remove(&position.symbol);
self.pending_full_close_symbols.remove(&position.symbol);
} else {
pending_full_close_symbols.insert(position.symbol.clone());
self.pending_full_close_symbols
.insert(position.symbol.clone());
}
}
}
if daily_top_up_active {
self.try_daily_top_up_at_position(
ctx,
&day,
&stock_list,
decision_date,
execution_date,
projection_date,
selection_factor_date,
signal_date,
daily_top_up_target_budget,
selection_limit,
defer_execution_risk,
Some(position.symbol.as_str()),
&mut projected,
&mut projected_execution_state,
&mut order_intents,
&mut aiquant_available_cash,
&mut slot_working_symbols,
&mut same_bar_buy_symbols,
&pending_full_close_symbols,
&same_day_sold_symbols,
&exit_symbols,
&delayed_sold_symbols,
&mut intraday_attempted_buys,
&mut daily_top_up_pending_buy_value,
debug_daily_top_up,
&mut daily_top_up_debug_notes,
)?;
}
continue;
}
if pending_full_close_symbols.contains(&position.symbol) {
continue; continue;
} }
let projected_position = projected.position(&position.symbol).unwrap_or(position); let projected_position = projected.position(&position.symbol).unwrap_or(position);