补充目标仓位估值价回归测试
This commit is contained in:
@@ -7420,6 +7420,83 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn target_portfolio_smart_custom_valuation_does_not_create_limit_orders() {
|
||||||
|
let date = chrono::NaiveDate::from_ymd_opt(2025, 1, 2).expect("valid date");
|
||||||
|
let mut snapshot = limit_test_snapshot();
|
||||||
|
snapshot.day_open = 12.0;
|
||||||
|
snapshot.open = 12.0;
|
||||||
|
snapshot.last_price = 12.0;
|
||||||
|
snapshot.prev_close = 10.0;
|
||||||
|
snapshot.upper_limit = 20.0;
|
||||||
|
snapshot.lower_limit = 1.0;
|
||||||
|
let data = DataSet::from_components_with_actions_and_quotes(
|
||||||
|
vec![limit_test_instrument()],
|
||||||
|
vec![snapshot],
|
||||||
|
Vec::new(),
|
||||||
|
vec![limit_test_candidate(true, true)],
|
||||||
|
vec![limit_test_benchmark()],
|
||||||
|
Vec::new(),
|
||||||
|
Vec::new(),
|
||||||
|
)
|
||||||
|
.expect("valid dataset");
|
||||||
|
let broker = BrokerSimulator::new_with_execution_price(
|
||||||
|
ChinaAShareCostModel::default(),
|
||||||
|
ChinaEquityRuleHooks,
|
||||||
|
PriceField::DayOpen,
|
||||||
|
)
|
||||||
|
.with_volume_limit(false)
|
||||||
|
.with_liquidity_limit(false)
|
||||||
|
.with_inactive_limit(false);
|
||||||
|
let mut portfolio = PortfolioState::new(20_000.0);
|
||||||
|
let mut target_weights = BTreeMap::new();
|
||||||
|
target_weights.insert("000001.SZ".to_string(), 1.0);
|
||||||
|
let mut valuation_prices = BTreeMap::new();
|
||||||
|
valuation_prices.insert("000001.SZ".to_string(), 12.0);
|
||||||
|
let mut report = BrokerExecutionReport::default();
|
||||||
|
|
||||||
|
broker
|
||||||
|
.process_target_portfolio_smart(
|
||||||
|
date,
|
||||||
|
&mut portfolio,
|
||||||
|
&data,
|
||||||
|
&target_weights,
|
||||||
|
None,
|
||||||
|
Some(&valuation_prices),
|
||||||
|
"custom_valuation_market_order_test",
|
||||||
|
&mut BTreeMap::new(),
|
||||||
|
&mut BTreeMap::new(),
|
||||||
|
&mut None,
|
||||||
|
&mut BTreeMap::new(),
|
||||||
|
&mut report,
|
||||||
|
)
|
||||||
|
.expect("custom valuation should not turn rebalance into limit order");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
report
|
||||||
|
.order_events
|
||||||
|
.iter()
|
||||||
|
.any(|event| event.symbol == "000001.SZ" && event.status == OrderStatus::Filled),
|
||||||
|
"{:?}",
|
||||||
|
report.order_events
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
report
|
||||||
|
.order_events
|
||||||
|
.iter()
|
||||||
|
.all(|event| !event.reason.contains("limit price not marketable yet")),
|
||||||
|
"{:?}",
|
||||||
|
report.order_events
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
portfolio
|
||||||
|
.position("000001.SZ")
|
||||||
|
.is_some_and(|position| position.quantity == 1_600),
|
||||||
|
"{:?}",
|
||||||
|
portfolio.position("000001.SZ")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn target_value_zero_rejects_sell_when_market_snapshot_missing() {
|
fn target_value_zero_rejects_sell_when_market_snapshot_missing() {
|
||||||
let trade_date = chrono::NaiveDate::from_ymd_opt(2025, 1, 2).expect("valid date");
|
let trade_date = chrono::NaiveDate::from_ymd_opt(2025, 1, 2).expect("valid date");
|
||||||
|
|||||||
Reference in New Issue
Block a user