修正调仓后剩余买入预算

This commit is contained in:
boris
2026-07-17 12:32:25 +08:00
parent 60457389a3
commit bdd5a41106
+29 -17
View File
@@ -2540,28 +2540,31 @@ impl PlatformExprStrategy {
self.projected_position_value_at_execution_price(ctx, projected, date, symbol)
}
fn context_position_value_for_remaining_buy_cash(
fn projected_strategy_visible_position_value_for_remaining_buy_cash(
&self,
ctx: &StrategyContext<'_>,
projected: &PortfolioState,
date: NaiveDate,
symbol: &str,
) -> f64 {
let Some(position) = ctx.portfolio.position(symbol) else {
let Some(projected_position) = projected.position(symbol) else {
return 0.0;
};
if position.quantity == 0 {
if projected_position.quantity == 0 {
return 0.0;
}
let context_position = ctx.portfolio.position(symbol);
let mark_price = self
.aiquant_scheduled_last_price(ctx, date, symbol)
.or_else(|| ctx.data.price(date, symbol, PriceField::Last))
.or_else(|| ctx.data.price_on_or_before(date, symbol, PriceField::Last))
.or_else(|| context_position.map(|position| position.last_price))
.filter(|price| price.is_finite() && *price > 0.0)
.unwrap_or(position.last_price);
.unwrap_or(projected_position.last_price);
if mark_price.is_finite() && mark_price > 0.0 {
mark_price * position.quantity as f64
mark_price * projected_position.quantity as f64
} else {
position.market_value()
projected_position.market_value()
}
}
@@ -2775,7 +2778,9 @@ impl PlatformExprStrategy {
*aiquant_available_cash = (*aiquant_available_cash - spent).max(0.0);
slot_working_symbols.insert(symbol.clone());
same_bar_buy_symbols.insert(symbol.clone());
*pending_buy_value += available_buy_cash;
if order_result.filled_quantity == 0 {
*pending_buy_value += available_buy_cash;
}
if debug_daily_top_up {
daily_top_up_debug_notes.push(format!(
"daily_top_up_fill date={} symbol={} requested_cash={:.4} filled_qty={} spent={:.4} remaining_cash={:.4}",
@@ -2833,7 +2838,9 @@ impl PlatformExprStrategy {
.filter(|symbol| value_symbols.contains(*symbol))
.map(|symbol| {
if self.config.aiquant_transaction_cost {
self.context_position_value_for_remaining_buy_cash(ctx, date, symbol)
self.projected_strategy_visible_position_value_for_remaining_buy_cash(
ctx, projected, date, symbol,
)
} else {
self.projected_position_value_at_execution_price(ctx, projected, date, symbol)
}
@@ -17610,7 +17617,7 @@ mod tests {
}
#[test]
fn platform_aiquant_weak_market_threshold_top_up_uses_remaining_budget() {
fn platform_aiquant_weak_market_threshold_top_up_uses_projected_remaining_budget() {
let prev_date = d(2023, 5, 4);
let date = d(2023, 5, 5);
let symbols = ["000001.SZ", "000002.SZ", "000003.SZ"];
@@ -17766,10 +17773,15 @@ mod tests {
"{:?}",
decision.order_intents
);
assert!(!decision.order_intents.iter().any(|intent| matches!(
intent,
OrderIntent::Value { reason, .. } if reason == "daily_top_up_buy"
)));
assert!(
decision.order_intents.iter().any(|intent| matches!(
intent,
OrderIntent::Value { value, reason, .. }
if reason == "daily_top_up_buy" && (*value - 13_000.0).abs() < 1e-6
)),
"{:?}",
decision.order_intents
);
}
#[test]
@@ -21713,7 +21725,7 @@ mod tests {
}
#[test]
fn platform_aiquant_remaining_buy_cash_uses_strategy_visible_positions() {
fn platform_aiquant_remaining_buy_cash_uses_strategy_visible_price_and_projected_quantity() {
let prev_date = d(2025, 2, 2);
let date = d(2025, 2, 3);
let symbols = ["000001.SZ", "000002.SZ"];
@@ -21842,8 +21854,8 @@ mod tests {
);
assert!(
(cash - 1_000.0).abs() < 1e-6,
"remaining cash should use strategy-visible 900-share position, got {cash}"
(cash - 5_000.0).abs() < 1e-6,
"remaining cash should use strategy-visible price and projected 500-share quantity, got {cash}"
);
}
@@ -22000,7 +22012,7 @@ mod tests {
reason,
} if symbol == "000002.SZ"
&& reason == "daily_top_up_buy"
&& (*value - 1_500.0).abs() < 1e-6
&& (*value - 4_500.0).abs() < 1e-6
)),
"{:?}",
decision.order_intents