修复开盘调仓估值价格口径
This commit is contained in:
@@ -5245,7 +5245,7 @@ where
|
|||||||
|
|
||||||
fn rebalance_valuation_price_field_name(&self) -> &'static str {
|
fn rebalance_valuation_price_field_name(&self) -> &'static str {
|
||||||
if self.is_open_auction_matching() {
|
if self.is_open_auction_matching() {
|
||||||
"prev_close"
|
"day_open"
|
||||||
} else {
|
} else {
|
||||||
price_field_name(self.execution_price_field)
|
price_field_name(self.execution_price_field)
|
||||||
}
|
}
|
||||||
@@ -5256,7 +5256,7 @@ where
|
|||||||
snapshot: &crate::data::DailyMarketSnapshot,
|
snapshot: &crate::data::DailyMarketSnapshot,
|
||||||
) -> Option<f64> {
|
) -> Option<f64> {
|
||||||
let price = if self.is_open_auction_matching() {
|
let price = if self.is_open_auction_matching() {
|
||||||
snapshot.prev_close
|
snapshot.price(PriceField::DayOpen)
|
||||||
} else {
|
} else {
|
||||||
snapshot.price(self.execution_price_field)
|
snapshot.price(self.execution_price_field)
|
||||||
};
|
};
|
||||||
@@ -7377,6 +7377,49 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn target_portfolio_smart_open_auction_uses_day_open_for_valuation() {
|
||||||
|
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 portfolio = PortfolioState::new(20_000.0);
|
||||||
|
let mut target_weights = BTreeMap::new();
|
||||||
|
target_weights.insert("000001.SZ".to_string(), 1.0);
|
||||||
|
|
||||||
|
let (target_quantities, diagnostics) = broker
|
||||||
|
.target_quantities(date, &portfolio, &data, &target_weights)
|
||||||
|
.expect("target quantities");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
target_quantities.get("000001.SZ").copied(),
|
||||||
|
Some(1_600),
|
||||||
|
"{diagnostics:?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[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