修正延迟调仓剩余仓位预算
This commit is contained in:
@@ -2578,6 +2578,7 @@ impl PlatformExprStrategy {
|
||||
working_symbols: &BTreeSet<String>,
|
||||
value_symbols: &BTreeSet<String>,
|
||||
pending_buy_value: f64,
|
||||
deferred_target_values: Option<&BTreeMap<String, f64>>,
|
||||
slot_blocking_symbols: &BTreeSet<String>,
|
||||
) -> f64 {
|
||||
if selection_limit == 0 || !target_budget.is_finite() || target_budget <= 0.0 {
|
||||
@@ -2597,6 +2598,7 @@ impl PlatformExprStrategy {
|
||||
date,
|
||||
working_symbols,
|
||||
value_symbols,
|
||||
deferred_target_values,
|
||||
);
|
||||
let working_value = active_value + pending_buy_value.max(0.0);
|
||||
let per_slot_budget = (target_budget - working_value).max(0.0) / slots_remaining as f64;
|
||||
@@ -2632,6 +2634,7 @@ impl PlatformExprStrategy {
|
||||
delayed_sold_symbols: &BTreeSet<String>,
|
||||
intraday_attempted_buys: &mut BTreeSet<String>,
|
||||
pending_buy_value: &mut f64,
|
||||
deferred_target_values: &BTreeMap<String, f64>,
|
||||
debug_daily_top_up: bool,
|
||||
daily_top_up_debug_notes: &mut Vec<String>,
|
||||
) -> Result<bool, BacktestError> {
|
||||
@@ -2668,6 +2671,7 @@ impl PlatformExprStrategy {
|
||||
projection_date,
|
||||
&budget_working_symbols,
|
||||
&value_symbols,
|
||||
Some(deferred_target_values),
|
||||
)
|
||||
} else {
|
||||
0.0
|
||||
@@ -2681,6 +2685,7 @@ impl PlatformExprStrategy {
|
||||
&budget_working_symbols,
|
||||
&value_symbols,
|
||||
*pending_buy_value,
|
||||
Some(deferred_target_values),
|
||||
slot_blocking_symbols,
|
||||
);
|
||||
let available_buy_cash = slot_buy_cash.min(*aiquant_available_cash);
|
||||
@@ -2832,11 +2837,18 @@ impl PlatformExprStrategy {
|
||||
date: NaiveDate,
|
||||
working_symbols: &BTreeSet<String>,
|
||||
value_symbols: &BTreeSet<String>,
|
||||
deferred_target_values: Option<&BTreeMap<String, f64>>,
|
||||
) -> f64 {
|
||||
working_symbols
|
||||
.iter()
|
||||
.filter(|symbol| value_symbols.contains(*symbol))
|
||||
.map(|symbol| {
|
||||
if let Some(target_value) = deferred_target_values
|
||||
.and_then(|target_values| target_values.get(symbol))
|
||||
.filter(|target_value| target_value.is_finite() && **target_value >= 0.0)
|
||||
{
|
||||
return *target_value;
|
||||
}
|
||||
if self.config.aiquant_transaction_cost {
|
||||
self.projected_strategy_visible_position_value_for_remaining_buy_cash(
|
||||
ctx, projected, date, symbol,
|
||||
@@ -9261,6 +9273,7 @@ impl Strategy for PlatformExprStrategy {
|
||||
&& 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 deferred_daily_target_values = BTreeMap::<String, f64>::new();
|
||||
let mut pending_full_close_symbols = BTreeSet::<String>::new();
|
||||
let mut slot_blocking_symbols = BTreeSet::<String>::new();
|
||||
let should_block_partial_exit_residual_slot = trading_ratio < 1.0;
|
||||
@@ -9506,6 +9519,10 @@ impl Strategy for PlatformExprStrategy {
|
||||
target_value,
|
||||
reason: "daily_position_target_adjust".to_string(),
|
||||
});
|
||||
if defer_execution_risk {
|
||||
deferred_daily_target_values
|
||||
.insert(position.symbol.clone(), target_value);
|
||||
}
|
||||
if quantity_delta > 0 {
|
||||
same_bar_buy_symbols.insert(position.symbol.clone());
|
||||
}
|
||||
@@ -9592,6 +9609,7 @@ impl Strategy for PlatformExprStrategy {
|
||||
&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,
|
||||
)?;
|
||||
@@ -9691,6 +9709,7 @@ impl Strategy for PlatformExprStrategy {
|
||||
&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,
|
||||
)?;
|
||||
@@ -9766,6 +9785,7 @@ impl Strategy for PlatformExprStrategy {
|
||||
&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,
|
||||
)?;
|
||||
@@ -9835,6 +9855,7 @@ impl Strategy for PlatformExprStrategy {
|
||||
&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,
|
||||
)?;
|
||||
@@ -10084,6 +10105,7 @@ impl Strategy for PlatformExprStrategy {
|
||||
&rebalance_working_symbols,
|
||||
&rebalance_value_symbols,
|
||||
rebalance_pending_buy_value,
|
||||
None,
|
||||
&pending_full_close_symbols,
|
||||
);
|
||||
let target_cash = slot_buy_cash * stock_scale;
|
||||
@@ -21850,6 +21872,7 @@ mod tests {
|
||||
&working_symbols,
|
||||
&value_symbols,
|
||||
0.0,
|
||||
None,
|
||||
&BTreeSet::new(),
|
||||
);
|
||||
|
||||
@@ -21857,6 +21880,24 @@ mod tests {
|
||||
(cash - 5_000.0).abs() < 1e-6,
|
||||
"remaining cash should use strategy-visible price and projected 500-share quantity, got {cash}"
|
||||
);
|
||||
|
||||
let deferred_targets = BTreeMap::from([("000001.SZ".to_string(), 2_000.0)]);
|
||||
let deferred_cash = strategy.remaining_buy_cash_per_slot(
|
||||
&ctx,
|
||||
&projected,
|
||||
date,
|
||||
6_000.0,
|
||||
2,
|
||||
&working_symbols,
|
||||
&value_symbols,
|
||||
0.0,
|
||||
Some(&deferred_targets),
|
||||
&BTreeSet::new(),
|
||||
);
|
||||
assert!(
|
||||
(deferred_cash - 3_000.0).abs() < 1e-6,
|
||||
"lagged target reductions should reserve their frozen target value, got {deferred_cash}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user