修正同批卖出资金复用
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 {
|
pub fn new(config: PlatformExprStrategyConfig) -> Self {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
engine.register_fn("round", |value: f64| value.round());
|
engine.register_fn("round", |value: f64| value.round());
|
||||||
@@ -9515,8 +9525,8 @@ impl Strategy for PlatformExprStrategy {
|
|||||||
self.forget_position_entry_date(&position.symbol);
|
self.forget_position_entry_date(&position.symbol);
|
||||||
let can_sell = defer_execution_risk
|
let can_sell = defer_execution_risk
|
||||||
|| self.can_sell_position(ctx, execution_date, &position.symbol);
|
|| self.can_sell_position(ctx, execution_date, &position.symbol);
|
||||||
if can_sell
|
if can_sell {
|
||||||
&& self
|
let close_submitted = self
|
||||||
.project_target_zero(
|
.project_target_zero(
|
||||||
ctx,
|
ctx,
|
||||||
&mut projected,
|
&mut projected,
|
||||||
@@ -9524,15 +9534,21 @@ impl Strategy for PlatformExprStrategy {
|
|||||||
&position.symbol,
|
&position.symbol,
|
||||||
&mut projected_execution_state,
|
&mut projected_execution_state,
|
||||||
)
|
)
|
||||||
.is_some()
|
.is_some();
|
||||||
&& Self::projected_position_is_flat(&projected, &position.symbol)
|
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());
|
same_day_sold_symbols.insert(position.symbol.clone());
|
||||||
slot_working_symbols.remove(&position.symbol);
|
slot_working_symbols.remove(&position.symbol);
|
||||||
if !persistent_model_lifecycle {
|
if !persistent_model_lifecycle {
|
||||||
self.pending_full_close_symbols.remove(&position.symbol);
|
self.pending_full_close_symbols.remove(&position.symbol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if debug_projection {
|
if debug_projection {
|
||||||
projection_debug_notes.push(format!(
|
projection_debug_notes.push(format!(
|
||||||
"max_holding_days_exit symbol={} holding_days={} max_holding_days={}",
|
"max_holding_days_exit symbol={} holding_days={} max_holding_days={}",
|
||||||
@@ -9610,7 +9626,7 @@ impl Strategy for PlatformExprStrategy {
|
|||||||
reason: "risk_forced_exit".to_string(),
|
reason: "risk_forced_exit".to_string(),
|
||||||
});
|
});
|
||||||
self.forget_position_entry_date(&symbol);
|
self.forget_position_entry_date(&symbol);
|
||||||
if self
|
let close_submitted = self
|
||||||
.project_target_zero_at_time(
|
.project_target_zero_at_time(
|
||||||
ctx,
|
ctx,
|
||||||
&mut projected,
|
&mut projected,
|
||||||
@@ -9619,9 +9635,13 @@ impl Strategy for PlatformExprStrategy {
|
|||||||
&mut projected_execution_state,
|
&mut projected_execution_state,
|
||||||
Some(risk_level_forced_exit_time),
|
Some(risk_level_forced_exit_time),
|
||||||
)
|
)
|
||||||
.is_some()
|
.is_some();
|
||||||
&& Self::projected_position_is_flat(&projected, &symbol)
|
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());
|
same_day_sold_symbols.insert(symbol.clone());
|
||||||
slot_working_symbols.remove(&symbol);
|
slot_working_symbols.remove(&symbol);
|
||||||
if !persistent_model_lifecycle {
|
if !persistent_model_lifecycle {
|
||||||
@@ -9629,6 +9649,7 @@ impl Strategy for PlatformExprStrategy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let stop_take_exit_signal_symbols = current_stop_take_exit_symbols.clone();
|
let stop_take_exit_signal_symbols = current_stop_take_exit_symbols.clone();
|
||||||
|
|
||||||
@@ -9834,6 +9855,10 @@ impl Strategy for PlatformExprStrategy {
|
|||||||
)
|
)
|
||||||
.is_some();
|
.is_some();
|
||||||
if close_submitted {
|
if close_submitted {
|
||||||
|
self.refresh_available_cash_after_projected_sell(
|
||||||
|
&mut aiquant_available_cash,
|
||||||
|
&projected,
|
||||||
|
);
|
||||||
slot_working_symbols.remove(&position.symbol);
|
slot_working_symbols.remove(&position.symbol);
|
||||||
if Self::projected_position_is_flat(&projected, &position.symbol) {
|
if Self::projected_position_is_flat(&projected, &position.symbol) {
|
||||||
same_day_sold_symbols.insert(position.symbol.clone());
|
same_day_sold_symbols.insert(position.symbol.clone());
|
||||||
@@ -9938,6 +9963,10 @@ impl Strategy for PlatformExprStrategy {
|
|||||||
)
|
)
|
||||||
.is_some();
|
.is_some();
|
||||||
if close_submitted {
|
if close_submitted {
|
||||||
|
self.refresh_available_cash_after_projected_sell(
|
||||||
|
&mut aiquant_available_cash,
|
||||||
|
&projected,
|
||||||
|
);
|
||||||
slot_working_symbols.remove(&position.symbol);
|
slot_working_symbols.remove(&position.symbol);
|
||||||
if Self::projected_position_is_flat(&projected, &position.symbol) {
|
if Self::projected_position_is_flat(&projected, &position.symbol) {
|
||||||
same_day_sold_symbols.insert(position.symbol.clone());
|
same_day_sold_symbols.insert(position.symbol.clone());
|
||||||
@@ -10022,6 +10051,10 @@ impl Strategy for PlatformExprStrategy {
|
|||||||
)
|
)
|
||||||
.is_some();
|
.is_some();
|
||||||
if close_submitted {
|
if close_submitted {
|
||||||
|
self.refresh_available_cash_after_projected_sell(
|
||||||
|
&mut aiquant_available_cash,
|
||||||
|
&projected,
|
||||||
|
);
|
||||||
if Self::projected_position_is_flat(&projected, &position.symbol) {
|
if Self::projected_position_is_flat(&projected, &position.symbol) {
|
||||||
same_day_sold_symbols.insert(position.symbol.clone());
|
same_day_sold_symbols.insert(position.symbol.clone());
|
||||||
if !persistent_model_lifecycle {
|
if !persistent_model_lifecycle {
|
||||||
@@ -10100,6 +10133,10 @@ impl Strategy for PlatformExprStrategy {
|
|||||||
)
|
)
|
||||||
.is_some();
|
.is_some();
|
||||||
if close_submitted {
|
if close_submitted {
|
||||||
|
self.refresh_available_cash_after_projected_sell(
|
||||||
|
&mut aiquant_available_cash,
|
||||||
|
&projected,
|
||||||
|
);
|
||||||
if Self::projected_position_is_flat(&projected, &position.symbol) {
|
if Self::projected_position_is_flat(&projected, &position.symbol) {
|
||||||
same_day_sold_symbols.insert(position.symbol.clone());
|
same_day_sold_symbols.insert(position.symbol.clone());
|
||||||
if !persistent_model_lifecycle {
|
if !persistent_model_lifecycle {
|
||||||
@@ -23911,12 +23948,16 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.expect("dataset");
|
.expect("dataset");
|
||||||
|
|
||||||
let mut portfolio = PortfolioState::new(5_000.0);
|
let mut portfolio = PortfolioState::new(0.0);
|
||||||
portfolio.position_mut(keep_first).buy(prev_date, 100, 10.0);
|
portfolio
|
||||||
portfolio.position_mut(take_profit).buy(prev_date, 100, 8.0);
|
.position_mut(keep_first)
|
||||||
|
.buy(prev_date, 1_000, 10.0);
|
||||||
|
portfolio
|
||||||
|
.position_mut(take_profit)
|
||||||
|
.buy(prev_date, 1_000, 8.0);
|
||||||
portfolio
|
portfolio
|
||||||
.position_mut(keep_second)
|
.position_mut(keep_second)
|
||||||
.buy(prev_date, 100, 10.0);
|
.buy(prev_date, 1_000, 10.0);
|
||||||
let subscriptions = BTreeSet::new();
|
let subscriptions = BTreeSet::new();
|
||||||
let ctx = StrategyContext {
|
let ctx = StrategyContext {
|
||||||
execution_date: date,
|
execution_date: date,
|
||||||
|
|||||||
Reference in New Issue
Block a user