修正AiQuant等权调仓预算

This commit is contained in:
boris
2026-07-01 15:00:55 +08:00
parent eae82128ee
commit cad8877b7a
3 changed files with 26 additions and 26 deletions
+1 -5
View File
@@ -2884,11 +2884,7 @@ where
}); });
let note = format!( let note = format!(
"cash_dividend_receivable {} share_cash={:.6} quantity={} payable_date={} cash={:.2}", "cash_dividend_receivable {} share_cash={:.6} quantity={} payable_date={} cash={:.2}",
action.symbol, action.symbol, action.share_cash, quantity_after, payable_date, cash_delta
action.share_cash,
quantity_after,
payable_date,
cash_delta
); );
notes.push(note.clone()); notes.push(note.clone());
report.account_events.push(AccountEvent { report.account_events.push(AccountEvent {
+4 -10
View File
@@ -7967,14 +7967,8 @@ impl Strategy for PlatformExprStrategy {
slot_working_symbols.remove(symbol); slot_working_symbols.remove(symbol);
} }
if !self.config.aiquant_transaction_cost {
aiquant_available_cash = projected.cash(); aiquant_available_cash = projected.cash();
} let fixed_buy_cash = aiquant_total_value * trading_ratio / selection_limit as f64;
let fixed_buy_cash = if self.config.aiquant_transaction_cost {
aiquant_available_cash * trading_ratio / selection_limit as f64
} else {
aiquant_total_value * trading_ratio / selection_limit as f64
};
let target_budget = aiquant_total_value * trading_ratio; let target_budget = aiquant_total_value * trading_ratio;
let mut rebalance_working_symbols = slot_working_symbols.clone(); let mut rebalance_working_symbols = slot_working_symbols.clone();
if self.config.release_slot_on_exit_signal { if self.config.release_slot_on_exit_signal {
@@ -18398,7 +18392,7 @@ mod tests {
} }
#[test] #[test]
fn platform_aiquant_periodic_rebalance_uses_cash_divided_by_top_n_buy_budget() { fn platform_aiquant_periodic_rebalance_uses_total_value_equal_weight_buy_budget() {
let prev_date = d(2025, 5, 13); let prev_date = d(2025, 5, 13);
let date = d(2025, 5, 14); let date = d(2025, 5, 14);
let retained_symbols = (1..=17) let retained_symbols = (1..=17)
@@ -18597,7 +18591,7 @@ mod tests {
assert!( assert!(
decision.order_intents.iter().all(|intent| match intent { decision.order_intents.iter().all(|intent| match intent {
OrderIntent::Value { value, reason, .. } if reason == "periodic_rebalance_buy" => OrderIntent::Value { value, reason, .. } if reason == "periodic_rebalance_buy" =>
(*value - 6_500.0).abs() < 1e-6, (*value - 126_500.0).abs() < 1e-6,
_ => true, _ => true,
}), }),
"{:?}", "{:?}",
@@ -18755,7 +18749,7 @@ mod tests {
reason, reason,
} if symbol == "000002.SZ" } if symbol == "000002.SZ"
&& reason == "periodic_rebalance_buy" && reason == "periodic_rebalance_buy"
&& (*value - 5_000.0).abs() < 1e-6 && (*value - 10_000.0).abs() < 1e-6
)), )),
"{:?}", "{:?}",
decision.order_intents decision.order_intents
+16 -6
View File
@@ -410,8 +410,14 @@ fn engine_settles_same_day_dividend_after_split_for_aiquant_semantics() {
delisted_at: None, delisted_at: None,
status: "active".to_string(), status: "active".to_string(),
}], }],
vec![stock_market_snapshot(buy_date), stock_market_snapshot(ex_date)], vec![
vec![stock_factor_snapshot(buy_date), stock_factor_snapshot(ex_date)], stock_market_snapshot(buy_date),
stock_market_snapshot(ex_date),
],
vec![
stock_factor_snapshot(buy_date),
stock_factor_snapshot(ex_date),
],
vec![stock_candidate(buy_date), stock_candidate(ex_date)], vec![stock_candidate(buy_date), stock_candidate(ex_date)],
vec![benchmark_snapshot(buy_date), benchmark_snapshot(ex_date)], vec![benchmark_snapshot(buy_date), benchmark_snapshot(ex_date)],
vec![CorporateAction { vec![CorporateAction {
@@ -469,12 +475,16 @@ fn engine_settles_same_day_dividend_after_split_for_aiquant_semantics() {
assert_eq!(reinvest_fill.quantity, 100); assert_eq!(reinvest_fill.quantity, 100);
assert!((reinvest_fill.price - ((10.0 - 1.05) / 1.2)).abs() < 1e-9); assert!((reinvest_fill.price - ((10.0 - 1.05) / 1.2)).abs() < 1e-9);
assert!(result assert!(
result
.position_events .position_events
.iter() .iter()
.any(|event| event.reason == "stock_split 1.200000" && event.quantity_after == 1_200)); .any(|event| event.reason == "stock_split 1.200000" && event.quantity_after == 1_200)
assert!(result );
assert!(
result
.account_events .account_events
.iter() .iter()
.any(|event| event.note.contains("cash_receivable_reinvested"))); .any(|event| event.note.contains("cash_receivable_reinvested"))
);
} }