Align China A-share costs with rqalpha rules

This commit is contained in:
boris
2026-04-22 21:57:24 -07:00
parent 650e2e8319
commit aca8292c72
5 changed files with 111 additions and 43 deletions

View File

@@ -54,15 +54,26 @@ fn snapshot(open: f64, upper_limit: f64, lower_limit: f64) -> DailyMarketSnapsho
fn china_cost_model_applies_minimum_commission_and_stamp_tax() {
let model = ChinaAShareCostModel::default();
let buy = model.calculate(OrderSide::Buy, 1_000.0);
let buy = model.calculate(d(2023, 8, 25), OrderSide::Buy, 1_000.0);
assert!((buy.commission - 5.0).abs() < 1e-9);
assert_eq!(buy.stamp_tax, 0.0);
let sell = model.calculate(OrderSide::Sell, 100_000.0);
let sell = model.calculate(d(2023, 8, 25), OrderSide::Sell, 100_000.0);
assert!((sell.commission - 30.0).abs() < 1e-9);
assert!((sell.stamp_tax - 100.0).abs() < 1e-9);
}
#[test]
fn china_cost_model_switches_stamp_tax_rate_after_2023_08_28() {
let model = ChinaAShareCostModel::default();
let before = model.calculate(d(2023, 8, 25), OrderSide::Sell, 100_000.0);
let after = model.calculate(d(2023, 8, 28), OrderSide::Sell, 100_000.0);
assert!((before.stamp_tax - 100.0).abs() < 1e-9);
assert!((after.stamp_tax - 50.0).abs() < 1e-9);
}
#[test]
fn china_rule_hooks_block_same_day_sell_under_t_plus_one() {
let hooks = ChinaEquityRuleHooks;
@@ -96,13 +107,11 @@ fn china_rule_hooks_block_buy_at_limit_up_and_sell_at_limit_down() {
PriceField::Open,
);
assert!(!buy_check.allowed);
assert!(
buy_check
.reason
.as_deref()
.unwrap_or_default()
.contains("upper limit")
);
assert!(buy_check
.reason
.as_deref()
.unwrap_or_default()
.contains("upper limit"));
let sell_check = hooks.can_sell(
d(2024, 1, 3),
@@ -112,13 +121,11 @@ fn china_rule_hooks_block_buy_at_limit_up_and_sell_at_limit_down() {
PriceField::Open,
);
assert!(!sell_check.allowed);
assert!(
sell_check
.reason
.as_deref()
.unwrap_or_default()
.contains("lower limit")
);
assert!(sell_check
.reason
.as_deref()
.unwrap_or_default()
.contains("lower limit"));
}
#[test]
@@ -180,6 +187,15 @@ fn china_rule_hooks_allow_sell_when_last_price_is_above_lower_limit() {
price_tick: 0.01,
};
let sell_check = hooks.can_sell(d(2024, 4, 7), &snapshot, &candidate, &position, PriceField::Last);
assert!(sell_check.allowed, "sell should be allowed when snapshot last is above lower limit");
let sell_check = hooks.can_sell(
d(2024, 4, 7),
&snapshot,
&candidate,
&position,
PriceField::Last,
);
assert!(
sell_check.allowed,
"sell should be allowed when snapshot last is above lower limit"
);
}