Skip market buys below one lot
This commit is contained in:
@@ -5796,6 +5796,9 @@ where
|
|||||||
self.minimum_order_quantity(data, symbol),
|
self.minimum_order_quantity(data, symbol),
|
||||||
self.order_step_size(data, symbol),
|
self.order_step_size(data, symbol),
|
||||||
);
|
);
|
||||||
|
if requested_qty == 0 {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
self.process_buy(
|
self.process_buy(
|
||||||
date,
|
date,
|
||||||
portfolio,
|
portfolio,
|
||||||
@@ -10345,6 +10348,53 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn market_share_buy_skips_quantity_that_rounds_below_one_lot() {
|
||||||
|
let date = chrono::NaiveDate::from_ymd_opt(2025, 1, 2).expect("valid date");
|
||||||
|
let data = DataSet::from_components_with_actions_and_quotes(
|
||||||
|
vec![limit_test_instrument()],
|
||||||
|
vec![limit_test_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::Open,
|
||||||
|
)
|
||||||
|
.with_volume_limit(false)
|
||||||
|
.with_liquidity_limit(false)
|
||||||
|
.with_inactive_limit(false);
|
||||||
|
let mut portfolio = PortfolioState::new(20_000.0);
|
||||||
|
let mut report = BrokerExecutionReport::default();
|
||||||
|
|
||||||
|
broker
|
||||||
|
.process_shares(
|
||||||
|
date,
|
||||||
|
&mut portfolio,
|
||||||
|
&data,
|
||||||
|
"000001.SZ",
|
||||||
|
1,
|
||||||
|
"sub_lot_target_delta",
|
||||||
|
&mut BTreeMap::new(),
|
||||||
|
&mut IntradayExecutionLedger::default(),
|
||||||
|
&mut None,
|
||||||
|
&mut BTreeMap::new(),
|
||||||
|
None,
|
||||||
|
&mut report,
|
||||||
|
)
|
||||||
|
.expect("sub-lot buy must be a no-op");
|
||||||
|
|
||||||
|
assert!(report.order_events.is_empty());
|
||||||
|
assert!(report.fill_events.is_empty());
|
||||||
|
assert!(portfolio.position("000001.SZ").is_none());
|
||||||
|
report.validate().expect("empty report remains valid");
|
||||||
|
}
|
||||||
|
|
||||||
#[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