修正同批卖出资金复用
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user