统一次日开盘新仓目标市值指令

This commit is contained in:
boris
2026-07-12 05:55:55 +08:00
parent 214872dfbf
commit 0ea5fae69d
+101 -34
View File
@@ -2287,8 +2287,14 @@ impl PlatformExprStrategy {
};
if self.config.matching_type == MatchingType::NextBarOpen {
if let Some(market) = ctx.data.market(date, symbol) {
if market.prev_close.is_finite() && market.prev_close > 0.0 {
return position.quantity as f64 * market.prev_close;
let signal_visible_price = if ctx.is_lagged_execution() && date == ctx.decision_date
{
market.close
} else {
market.prev_close
};
if signal_visible_price.is_finite() && signal_visible_price > 0.0 {
return position.quantity as f64 * signal_visible_price;
}
}
}
@@ -9579,22 +9585,57 @@ impl Strategy for PlatformExprStrategy {
{
continue;
}
let target_cash = if self.config.aiquant_transaction_cost {
fixed_buy_cash * stock_scale
} else {
let slot_buy_cash = self.remaining_buy_cash_per_slot(
if self.config.aiquant_transaction_cost {
let target_value = fixed_buy_cash * stock_scale;
if target_value <= 0.0 {
continue;
}
if !defer_execution_risk
&& self
.buy_rejection_reason(
ctx,
execution_date,
symbol,
&self.stock_state(ctx, execution_date, symbol)?,
)?
.is_some()
{
continue;
}
if !self.stock_passes_expr(ctx, &day, &decision_stock)? {
continue;
}
self.project_order_value(
ctx,
&projected,
&mut projected,
projection_date,
target_budget,
selection_limit,
&rebalance_working_symbols,
&rebalance_value_symbols,
rebalance_pending_buy_value,
&pending_full_close_symbols,
symbol,
target_value,
&mut projected_execution_state,
);
slot_buy_cash * stock_scale
};
order_intents.push(OrderIntent::TargetValue {
symbol: symbol.clone(),
target_value,
reason: "periodic_rebalance_buy".to_string(),
});
self.remember_position_entry_date(symbol, signal_date);
aiquant_available_cash = projected.cash().max(0.0);
rebalance_working_symbols.insert(symbol.clone());
slot_working_symbols.insert(symbol.clone());
continue;
}
let slot_buy_cash = self.remaining_buy_cash_per_slot(
ctx,
&projected,
projection_date,
target_budget,
selection_limit,
&rebalance_working_symbols,
&rebalance_value_symbols,
rebalance_pending_buy_value,
&pending_full_close_symbols,
);
let target_cash = slot_buy_cash * stock_scale;
let buy_cash = target_cash.min(aiquant_available_cash);
if buy_cash <= 0.0 {
if debug_projection {
@@ -18579,6 +18620,11 @@ mod tests {
OrderIntent::Value { symbol, value, .. } => {
symbol == limit_symbol && *value > 0.0
}
OrderIntent::TargetValue {
symbol,
target_value,
..
} => symbol == limit_symbol && *target_value > 0.0,
_ => false,
}),
"{:?}",
@@ -18779,6 +18825,13 @@ mod tests {
intent,
OrderIntent::Value { symbol, value, .. }
if symbol == candidate_symbol && *value > 0.0
) || matches!(
intent,
OrderIntent::TargetValue {
symbol,
target_value,
..
} if symbol == candidate_symbol && *target_value > 0.0
)),
"{:?}",
decision.order_intents
@@ -25251,7 +25304,11 @@ mod tests {
.filter(|intent| {
matches!(
intent,
OrderIntent::Value { reason, .. } if reason == "periodic_rebalance_buy"
OrderIntent::TargetValue {
target_value,
reason,
..
} if *target_value > 0.0 && reason == "periodic_rebalance_buy"
)
})
.count();
@@ -25429,8 +25486,13 @@ mod tests {
assert!(
!decision.order_intents.iter().any(|intent| matches!(
intent,
OrderIntent::Value { symbol, reason, .. }
if symbol == "000001.SZ" && reason == "periodic_rebalance_buy"
OrderIntent::TargetValue {
symbol,
target_value,
reason,
} if symbol == "000001.SZ"
&& *target_value > 0.0
&& reason == "periodic_rebalance_buy"
)),
"{:?}",
decision.order_intents
@@ -25438,8 +25500,13 @@ mod tests {
assert!(
decision.order_intents.iter().any(|intent| matches!(
intent,
OrderIntent::Value { symbol, reason, .. }
if symbol == "000003.SZ" && reason == "periodic_rebalance_buy"
OrderIntent::TargetValue {
symbol,
target_value,
reason,
} if symbol == "000003.SZ"
&& *target_value > 0.0
&& reason == "periodic_rebalance_buy"
)),
"{:?}",
decision.order_intents
@@ -25629,7 +25696,11 @@ mod tests {
.filter(|intent| {
matches!(
intent,
OrderIntent::Value { reason, .. } if reason == "periodic_rebalance_buy"
OrderIntent::TargetValue {
target_value,
reason,
..
} if *target_value > 0.0 && reason == "periodic_rebalance_buy"
)
})
.count();
@@ -25650,8 +25721,12 @@ mod tests {
.order_intents
.iter()
.filter_map(|intent| match intent {
OrderIntent::Value { value, reason, .. } if reason == "periodic_rebalance_buy" => {
Some(*value)
OrderIntent::TargetValue {
target_value,
reason,
..
} if *target_value > 0.0 && reason == "periodic_rebalance_buy" => {
Some(*target_value)
}
_ => None,
})
@@ -25660,18 +25735,10 @@ mod tests {
assert!(
periodic_buy_values
.iter()
.take(periodic_buy_values.len().saturating_sub(1))
.all(|value| (*value - equal_weight_target).abs() < 1e-6),
"{:?}",
decision.order_intents
);
assert!(
periodic_buy_values
.last()
.is_some_and(|value| *value > 0.0 && *value <= equal_weight_target),
"{:?}",
decision.order_intents
);
}
#[test]
@@ -25819,13 +25886,13 @@ mod tests {
assert!(
decision.order_intents.iter().any(|intent| matches!(
intent,
OrderIntent::Value {
OrderIntent::TargetValue {
symbol,
value,
target_value,
reason,
} if symbol == "000002.SZ"
&& reason == "periodic_rebalance_buy"
&& (*value - 10_000.0).abs() < 1e-6
&& (*target_value - 10_000.0).abs() < 1e-6
)),
"{:?}",
decision.order_intents