修正目标组合卖出后统一补仓
This commit is contained in:
@@ -9728,7 +9728,7 @@ impl Strategy for PlatformExprStrategy {
|
|||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
let quantity_delta = after_qty as i32 - before_qty as i32;
|
let quantity_delta = after_qty as i32 - before_qty as i32;
|
||||||
if stop_take_exit_signal_symbols.contains(&position.symbol)
|
if stop_take_exit_signal_symbols.contains(&position.symbol)
|
||||||
&& quantity_delta >= 0
|
&& (self.config.target_portfolio_daily_enabled || quantity_delta >= 0)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -9874,7 +9874,7 @@ impl Strategy for PlatformExprStrategy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if daily_top_up_active {
|
if daily_top_up_active && !self.config.target_portfolio_daily_enabled {
|
||||||
self.try_daily_top_up_at_position(
|
self.try_daily_top_up_at_position(
|
||||||
ctx,
|
ctx,
|
||||||
&day,
|
&day,
|
||||||
@@ -9986,7 +9986,7 @@ impl Strategy for PlatformExprStrategy {
|
|||||||
} else if stop_hit {
|
} else if stop_hit {
|
||||||
unresolved_stop_loss_symbols.insert(position.symbol.clone());
|
unresolved_stop_loss_symbols.insert(position.symbol.clone());
|
||||||
}
|
}
|
||||||
if daily_top_up_active {
|
if daily_top_up_active && !self.config.target_portfolio_daily_enabled {
|
||||||
self.try_daily_top_up_at_position(
|
self.try_daily_top_up_at_position(
|
||||||
ctx,
|
ctx,
|
||||||
&day,
|
&day,
|
||||||
@@ -10073,7 +10073,7 @@ impl Strategy for PlatformExprStrategy {
|
|||||||
} else {
|
} else {
|
||||||
unresolved_stop_loss_symbols.insert(position.symbol.clone());
|
unresolved_stop_loss_symbols.insert(position.symbol.clone());
|
||||||
}
|
}
|
||||||
if daily_top_up_active {
|
if daily_top_up_active && !self.config.target_portfolio_daily_enabled {
|
||||||
self.try_daily_top_up_at_position(
|
self.try_daily_top_up_at_position(
|
||||||
ctx,
|
ctx,
|
||||||
&day,
|
&day,
|
||||||
@@ -10154,7 +10154,7 @@ impl Strategy for PlatformExprStrategy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if daily_top_up_active {
|
if daily_top_up_active && !self.config.target_portfolio_daily_enabled {
|
||||||
self.try_daily_top_up_at_position(
|
self.try_daily_top_up_at_position(
|
||||||
ctx,
|
ctx,
|
||||||
&day,
|
&day,
|
||||||
@@ -10188,6 +10188,39 @@ impl Strategy for PlatformExprStrategy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if daily_top_up_active && self.config.target_portfolio_daily_enabled {
|
||||||
|
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,
|
||||||
|
None,
|
||||||
|
&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,
|
||||||
|
&slot_blocking_symbols,
|
||||||
|
&same_day_sold_symbols,
|
||||||
|
&exit_symbols,
|
||||||
|
&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,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
if periodic_rebalance {
|
if periodic_rebalance {
|
||||||
let rebalance_existing_positions = self.config.rebalance_existing_positions
|
let rebalance_existing_positions = self.config.rebalance_existing_positions
|
||||||
|| self
|
|| self
|
||||||
@@ -23988,6 +24021,8 @@ mod tests {
|
|||||||
cfg.exposure_expr = "1.0".to_string();
|
cfg.exposure_expr = "1.0".to_string();
|
||||||
cfg.take_profit_expr = "1.1".to_string();
|
cfg.take_profit_expr = "1.1".to_string();
|
||||||
cfg.daily_top_up_enabled = true;
|
cfg.daily_top_up_enabled = true;
|
||||||
|
cfg.daily_position_target_adjust_enabled = true;
|
||||||
|
cfg.target_portfolio_daily_enabled = true;
|
||||||
cfg.release_slot_on_exit_signal = true;
|
cfg.release_slot_on_exit_signal = true;
|
||||||
cfg.aiquant_transaction_cost = true;
|
cfg.aiquant_transaction_cost = true;
|
||||||
cfg.intraday_execution_time = Some(NaiveTime::from_hms_opt(10, 18, 0).unwrap());
|
cfg.intraday_execution_time = Some(NaiveTime::from_hms_opt(10, 18, 0).unwrap());
|
||||||
@@ -23995,13 +24030,15 @@ mod tests {
|
|||||||
strategy.rebalance_day_counter = 2;
|
strategy.rebalance_day_counter = 2;
|
||||||
|
|
||||||
let decision = strategy.on_day(&ctx).expect("platform decision");
|
let decision = strategy.on_day(&ctx).expect("platform decision");
|
||||||
let top_up_symbols = decision
|
let top_ups = decision
|
||||||
.order_intents
|
.order_intents
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|intent| match intent {
|
.filter_map(|intent| match intent {
|
||||||
OrderIntent::Value { symbol, reason, .. } if reason == "daily_top_up_buy" => {
|
OrderIntent::Value {
|
||||||
Some(symbol.as_str())
|
symbol,
|
||||||
}
|
value,
|
||||||
|
reason,
|
||||||
|
} if reason == "daily_top_up_buy" => Some((symbol.as_str(), *value)),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
@@ -24019,11 +24056,19 @@ mod tests {
|
|||||||
decision.order_intents
|
decision.order_intents
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
top_up_symbols,
|
top_ups
|
||||||
|
.iter()
|
||||||
|
.map(|(symbol, _)| *symbol)
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
vec![buy_first, buy_second],
|
vec![buy_first, buy_second],
|
||||||
"{:?}",
|
"{:?}",
|
||||||
decision.order_intents
|
decision.order_intents
|
||||||
);
|
);
|
||||||
|
assert!(
|
||||||
|
top_ups.iter().all(|(_, value)| *value >= 6_900.0),
|
||||||
|
"top ups must be sized after all same-batch sells: {:?}",
|
||||||
|
decision.order_intents
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn partial_stop_loss_top_up_symbols_for_exposure(exposure_expr: &str) -> Vec<String> {
|
fn partial_stop_loss_top_up_symbols_for_exposure(exposure_expr: &str) -> Vec<String> {
|
||||||
|
|||||||
Reference in New Issue
Block a user