修正同批卖出资金复用

This commit is contained in:
boris
2026-07-17 21:46:23 +08:00
parent 6e8eeb984f
commit b6df63c79e
+62 -21
View File
@@ -958,6 +958,16 @@ impl PlatformExprStrategy {
}
}
fn refresh_available_cash_after_projected_sell(
&self,
available_cash: &mut f64,
projected: &PortfolioState,
) {
if self.effective_rebalance_cash_mode() != RebalanceCashMode::PreOpenCash {
*available_cash = projected.cash().max(0.0);
}
}
pub fn new(config: PlatformExprStrategyConfig) -> Self {
let mut engine = Engine::new();
engine.register_fn("round", |value: f64| value.round());
@@ -9515,8 +9525,8 @@ impl Strategy for PlatformExprStrategy {
self.forget_position_entry_date(&position.symbol);
let can_sell = defer_execution_risk
|| self.can_sell_position(ctx, execution_date, &position.symbol);
if can_sell
&& self
if can_sell {
let close_submitted = self
.project_target_zero(
ctx,
&mut projected,
@@ -9524,13 +9534,19 @@ impl Strategy for PlatformExprStrategy {
&position.symbol,
&mut projected_execution_state,
)
.is_some()
&& Self::projected_position_is_flat(&projected, &position.symbol)
{
same_day_sold_symbols.insert(position.symbol.clone());
slot_working_symbols.remove(&position.symbol);
if !persistent_model_lifecycle {
self.pending_full_close_symbols.remove(&position.symbol);
.is_some();
if close_submitted {
self.refresh_available_cash_after_projected_sell(
&mut aiquant_available_cash,
&projected,
);
if Self::projected_position_is_flat(&projected, &position.symbol) {
same_day_sold_symbols.insert(position.symbol.clone());
slot_working_symbols.remove(&position.symbol);
if !persistent_model_lifecycle {
self.pending_full_close_symbols.remove(&position.symbol);
}
}
}
}
if debug_projection {
@@ -9610,7 +9626,7 @@ impl Strategy for PlatformExprStrategy {
reason: "risk_forced_exit".to_string(),
});
self.forget_position_entry_date(&symbol);
if self
let close_submitted = self
.project_target_zero_at_time(
ctx,
&mut projected,
@@ -9619,13 +9635,18 @@ impl Strategy for PlatformExprStrategy {
&mut projected_execution_state,
Some(risk_level_forced_exit_time),
)
.is_some()
&& Self::projected_position_is_flat(&projected, &symbol)
{
same_day_sold_symbols.insert(symbol.clone());
slot_working_symbols.remove(&symbol);
if !persistent_model_lifecycle {
self.pending_full_close_symbols.remove(&symbol);
.is_some();
if close_submitted {
self.refresh_available_cash_after_projected_sell(
&mut aiquant_available_cash,
&projected,
);
if Self::projected_position_is_flat(&projected, &symbol) {
same_day_sold_symbols.insert(symbol.clone());
slot_working_symbols.remove(&symbol);
if !persistent_model_lifecycle {
self.pending_full_close_symbols.remove(&symbol);
}
}
}
}
@@ -9834,6 +9855,10 @@ impl Strategy for PlatformExprStrategy {
)
.is_some();
if close_submitted {
self.refresh_available_cash_after_projected_sell(
&mut aiquant_available_cash,
&projected,
);
slot_working_symbols.remove(&position.symbol);
if Self::projected_position_is_flat(&projected, &position.symbol) {
same_day_sold_symbols.insert(position.symbol.clone());
@@ -9938,6 +9963,10 @@ impl Strategy for PlatformExprStrategy {
)
.is_some();
if close_submitted {
self.refresh_available_cash_after_projected_sell(
&mut aiquant_available_cash,
&projected,
);
slot_working_symbols.remove(&position.symbol);
if Self::projected_position_is_flat(&projected, &position.symbol) {
same_day_sold_symbols.insert(position.symbol.clone());
@@ -10022,6 +10051,10 @@ impl Strategy for PlatformExprStrategy {
)
.is_some();
if close_submitted {
self.refresh_available_cash_after_projected_sell(
&mut aiquant_available_cash,
&projected,
);
if Self::projected_position_is_flat(&projected, &position.symbol) {
same_day_sold_symbols.insert(position.symbol.clone());
if !persistent_model_lifecycle {
@@ -10100,6 +10133,10 @@ impl Strategy for PlatformExprStrategy {
)
.is_some();
if close_submitted {
self.refresh_available_cash_after_projected_sell(
&mut aiquant_available_cash,
&projected,
);
if Self::projected_position_is_flat(&projected, &position.symbol) {
same_day_sold_symbols.insert(position.symbol.clone());
if !persistent_model_lifecycle {
@@ -23911,12 +23948,16 @@ mod tests {
)
.expect("dataset");
let mut portfolio = PortfolioState::new(5_000.0);
portfolio.position_mut(keep_first).buy(prev_date, 100, 10.0);
portfolio.position_mut(take_profit).buy(prev_date, 100, 8.0);
let mut portfolio = PortfolioState::new(0.0);
portfolio
.position_mut(keep_first)
.buy(prev_date, 1_000, 10.0);
portfolio
.position_mut(take_profit)
.buy(prev_date, 1_000, 8.0);
portfolio
.position_mut(keep_second)
.buy(prev_date, 100, 10.0);
.buy(prev_date, 1_000, 10.0);
let subscriptions = BTreeSet::new();
let ctx = StrategyContext {
execution_date: date,