|
|
|
@@ -202,6 +202,7 @@ fn execute_single_value_order(
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
)
|
|
|
|
|
.with_volume_capacity_mode(fidc_core::execution_capacity::VolumeCapacityMode::SessionCapacityAudit)
|
|
|
|
|
.with_strict_value_budget(true);
|
|
|
|
|
let report = broker
|
|
|
|
|
.execute(
|
|
|
|
@@ -392,7 +393,7 @@ fn broker_executes_explicit_order_value_buy() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
);
|
|
|
|
|
).with_volume_capacity_mode(fidc_core::execution_capacity::VolumeCapacityMode::SessionCapacityAudit);
|
|
|
|
|
|
|
|
|
|
let report = broker
|
|
|
|
|
.execute(
|
|
|
|
@@ -682,7 +683,7 @@ fn broker_executes_order_shares_and_order_lots() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
);
|
|
|
|
|
).with_volume_capacity_mode(fidc_core::execution_capacity::VolumeCapacityMode::SessionCapacityAudit);
|
|
|
|
|
|
|
|
|
|
let report = broker
|
|
|
|
|
.execute(
|
|
|
|
@@ -802,7 +803,7 @@ fn broker_executes_target_shares_like_order_to() {
|
|
|
|
|
let broker = BrokerSimulator::new(
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
);
|
|
|
|
|
).with_volume_capacity_mode(fidc_core::execution_capacity::VolumeCapacityMode::SessionCapacityAudit);
|
|
|
|
|
|
|
|
|
|
let report = broker
|
|
|
|
|
.execute(
|
|
|
|
@@ -978,7 +979,7 @@ fn broker_executes_target_portfolio_smart_with_custom_prices() {
|
|
|
|
|
let broker = BrokerSimulator::new(
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
);
|
|
|
|
|
).with_volume_capacity_mode(fidc_core::execution_capacity::VolumeCapacityMode::SessionCapacityAudit);
|
|
|
|
|
|
|
|
|
|
let report = broker
|
|
|
|
|
.execute(
|
|
|
|
@@ -1252,7 +1253,7 @@ fn broker_executes_order_percent_and_target_percent() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
);
|
|
|
|
|
).with_volume_capacity_mode(fidc_core::execution_capacity::VolumeCapacityMode::SessionCapacityAudit);
|
|
|
|
|
|
|
|
|
|
let mut percent_portfolio = PortfolioState::new(1_000_000.0);
|
|
|
|
|
let percent_report = broker
|
|
|
|
@@ -1380,7 +1381,7 @@ fn broker_uses_day_open_price_for_open_auction_matching() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::DayOpen,
|
|
|
|
|
)
|
|
|
|
|
).with_volume_capacity_mode(fidc_core::execution_capacity::VolumeCapacityMode::SessionCapacityAudit)
|
|
|
|
|
.with_slippage_model(SlippageModel::PriceRatio(0.05));
|
|
|
|
|
|
|
|
|
|
let report = broker
|
|
|
|
@@ -1414,7 +1415,7 @@ fn broker_uses_day_open_price_for_open_auction_matching() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn broker_open_auction_uses_auction_volume_without_quote_liquidity() {
|
|
|
|
|
fn broker_rejects_unproven_auction_capacity_in_a_daily_snapshot() {
|
|
|
|
|
let date = NaiveDate::from_ymd_opt(2024, 1, 10).unwrap();
|
|
|
|
|
let data = DataSet::from_components(
|
|
|
|
|
vec![Instrument {
|
|
|
|
@@ -1511,11 +1512,10 @@ fn broker_open_auction_uses_auction_volume_without_quote_liquidity() {
|
|
|
|
|
risk_decisions: Vec::new(),
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
.expect("broker execution");
|
|
|
|
|
.expect_err("a timestamped daily total is not proof of auction volume");
|
|
|
|
|
|
|
|
|
|
assert_eq!(report.fill_events.len(), 1);
|
|
|
|
|
assert_eq!(report.fill_events[0].quantity, 200);
|
|
|
|
|
assert_eq!(report.fill_events[0].price, 9.8);
|
|
|
|
|
assert!(report.to_string().contains("execution-time capacity is missing"));
|
|
|
|
|
assert_eq!(portfolio.cash(), 1_000_000.0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
@@ -1710,7 +1710,7 @@ fn broker_applies_price_ratio_slippage_on_snapshot_fills() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
)
|
|
|
|
|
).with_volume_capacity_mode(fidc_core::execution_capacity::VolumeCapacityMode::SessionCapacityAudit)
|
|
|
|
|
.with_slippage_model(SlippageModel::PriceRatio(0.01));
|
|
|
|
|
|
|
|
|
|
let report = broker
|
|
|
|
@@ -2337,7 +2337,7 @@ fn broker_cancels_market_order_remainder_when_intraday_quote_liquidity_exhausted
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn broker_cancels_market_buy_when_minute_has_no_volume() {
|
|
|
|
|
fn broker_rejects_missing_execution_capacity_instead_of_declaring_suspension() {
|
|
|
|
|
let date = NaiveDate::from_ymd_opt(2024, 1, 10).unwrap();
|
|
|
|
|
let data = DataSet::from_components(
|
|
|
|
|
vec![Instrument {
|
|
|
|
@@ -2433,15 +2433,10 @@ fn broker_cancels_market_buy_when_minute_has_no_volume() {
|
|
|
|
|
risk_decisions: Vec::new(),
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
.expect("broker execution");
|
|
|
|
|
.expect_err("missing capacity is a contract error, not a normal no-volume cancellation");
|
|
|
|
|
|
|
|
|
|
assert_eq!(report.fill_events.len(), 0);
|
|
|
|
|
assert_eq!(report.order_events.len(), 1);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
report.order_events[0].status,
|
|
|
|
|
fidc_core::OrderStatus::Canceled
|
|
|
|
|
);
|
|
|
|
|
assert!(report.order_events[0].reason.contains("daily no volume"));
|
|
|
|
|
assert!(report.to_string().contains("execution-time capacity is missing"));
|
|
|
|
|
assert_eq!(portfolio.cash(), 1_000_000.0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
@@ -3679,7 +3674,7 @@ fn rebalance_uses_day_open_for_open_auction_valuation() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::DayOpen,
|
|
|
|
|
);
|
|
|
|
|
).with_volume_capacity_mode(fidc_core::execution_capacity::VolumeCapacityMode::SessionCapacityAudit);
|
|
|
|
|
|
|
|
|
|
let report = broker
|
|
|
|
|
.execute(
|
|
|
|
@@ -3864,7 +3859,7 @@ fn rebalance_optimizer_prioritizes_higher_target_weight_when_cash_is_tight() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
);
|
|
|
|
|
).with_volume_capacity_mode(fidc_core::execution_capacity::VolumeCapacityMode::SessionCapacityAudit);
|
|
|
|
|
|
|
|
|
|
let report = broker
|
|
|
|
|
.execute(
|
|
|
|
@@ -4049,7 +4044,7 @@ fn rebalance_optimizer_does_not_scale_targets_above_requested_weight() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
);
|
|
|
|
|
).with_volume_capacity_mode(fidc_core::execution_capacity::VolumeCapacityMode::SessionCapacityAudit);
|
|
|
|
|
|
|
|
|
|
broker
|
|
|
|
|
.execute(
|
|
|
|
@@ -4163,7 +4158,7 @@ fn broker_uses_board_specific_min_quantity_and_step_size_for_buy_sizing() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
)
|
|
|
|
|
).with_volume_capacity_mode(fidc_core::execution_capacity::VolumeCapacityMode::SessionCapacityAudit)
|
|
|
|
|
.with_risk_config(risk_config);
|
|
|
|
|
|
|
|
|
|
let report = broker
|
|
|
|
@@ -4269,7 +4264,7 @@ fn broker_allows_bjse_quantities_above_minimum_without_round_lot_step() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
)
|
|
|
|
|
).with_volume_capacity_mode(fidc_core::execution_capacity::VolumeCapacityMode::SessionCapacityAudit)
|
|
|
|
|
.with_risk_config(risk_config);
|
|
|
|
|
|
|
|
|
|
let report = broker
|
|
|
|
@@ -4377,7 +4372,7 @@ fn broker_allows_full_odd_lot_sell_when_liquidating_position() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
);
|
|
|
|
|
).with_volume_capacity_mode(fidc_core::execution_capacity::VolumeCapacityMode::SessionCapacityAudit);
|
|
|
|
|
|
|
|
|
|
let report = broker
|
|
|
|
|
.execute(
|
|
|
|
@@ -4511,7 +4506,7 @@ fn same_day_sell_then_rebuy_is_rejected_by_default() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
);
|
|
|
|
|
).with_volume_capacity_mode(fidc_core::execution_capacity::VolumeCapacityMode::SessionCapacityAudit);
|
|
|
|
|
|
|
|
|
|
broker
|
|
|
|
|
.execute(
|
|
|
|
@@ -4655,7 +4650,7 @@ fn same_day_sell_then_rebuy_can_be_allowed_by_policy() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
)
|
|
|
|
|
).with_volume_capacity_mode(fidc_core::execution_capacity::VolumeCapacityMode::SessionCapacityAudit)
|
|
|
|
|
.with_risk_config(risk_config);
|
|
|
|
|
|
|
|
|
|
broker
|
|
|
|
@@ -4708,7 +4703,7 @@ fn broker_configured_policy_can_allow_upper_limit_buy() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
)
|
|
|
|
|
).with_volume_capacity_mode(fidc_core::execution_capacity::VolumeCapacityMode::SessionCapacityAudit)
|
|
|
|
|
.with_risk_config(risk_config);
|
|
|
|
|
let mut portfolio = PortfolioState::new(1_000_000.0);
|
|
|
|
|
|
|
|
|
@@ -4752,7 +4747,7 @@ fn broker_configured_policy_can_allow_lower_limit_sell() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
)
|
|
|
|
|
).with_matching_type(MatchingType::MinuteLast).with_intraday_execution_start_time(NaiveTime::from_hms_opt(9, 30, 0).unwrap())
|
|
|
|
|
.with_risk_config(risk_config);
|
|
|
|
|
let mut portfolio = PortfolioState::new(1_000_000.0);
|
|
|
|
|
portfolio
|
|
|
|
@@ -4791,7 +4786,7 @@ fn broker_configured_policy_can_allow_lower_limit_sell() {
|
|
|
|
|
fn two_day_limit_order_data(day1_open: f64, day2_open: f64) -> DataSet {
|
|
|
|
|
let day1 = NaiveDate::from_ymd_opt(2024, 1, 10).unwrap();
|
|
|
|
|
let day2 = NaiveDate::from_ymd_opt(2024, 1, 11).unwrap();
|
|
|
|
|
DataSet::from_components(
|
|
|
|
|
DataSet::from_components_with_actions_and_quotes(
|
|
|
|
|
vec![Instrument {
|
|
|
|
|
symbol: "000002.SZ".to_string(),
|
|
|
|
|
name: "Test".to_string(),
|
|
|
|
@@ -4919,6 +4914,13 @@ fn two_day_limit_order_data(day1_open: f64, day2_open: f64) -> DataSet {
|
|
|
|
|
volume: 1_000_000,
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
Vec::new(),
|
|
|
|
|
[(day1, day1_open), (day2, day2_open)].into_iter().map(|(date, price)| IntradayExecutionQuote {
|
|
|
|
|
date, symbol: "000002.SZ".into(), timestamp: date.and_hms_opt(9, 30, 0).unwrap(),
|
|
|
|
|
last_price: price, bid1: price, ask1: price, bid1_volume: 0, ask1_volume: 0,
|
|
|
|
|
volume_delta: 100_000, amount_delta: 100_000.0 * price,
|
|
|
|
|
trading_phase: Some("synthetic_observation_fixture".into()),
|
|
|
|
|
}).collect(),
|
|
|
|
|
)
|
|
|
|
|
.expect("dataset")
|
|
|
|
|
}
|
|
|
|
@@ -4932,7 +4934,7 @@ fn broker_expires_day_limit_buy_at_market_close() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
);
|
|
|
|
|
).with_matching_type(MatchingType::MinuteLast).with_intraday_execution_start_time(NaiveTime::from_hms_opt(9, 30, 0).unwrap());
|
|
|
|
|
let mut portfolio = PortfolioState::new(1_000_000.0);
|
|
|
|
|
|
|
|
|
|
let day1_report = broker
|
|
|
|
@@ -5006,7 +5008,7 @@ fn broker_ioc_limit_order_fills_available_quantity_and_cancels_remainder() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
)
|
|
|
|
|
).with_matching_type(MatchingType::MinuteLast).with_intraday_execution_start_time(NaiveTime::from_hms_opt(9, 30, 0).unwrap())
|
|
|
|
|
.with_volume_limit(true)
|
|
|
|
|
.with_volume_percent(0.001)
|
|
|
|
|
.with_liquidity_limit(false);
|
|
|
|
@@ -5042,7 +5044,7 @@ fn broker_ioc_limit_order_fills_available_quantity_and_cancels_remainder() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn broker_persists_daily_volume_consumption_across_execute_calls() {
|
|
|
|
|
fn broker_persists_observed_volume_consumption_across_execute_calls() {
|
|
|
|
|
let day1 = NaiveDate::from_ymd_opt(2024, 1, 10).unwrap();
|
|
|
|
|
let day2 = NaiveDate::from_ymd_opt(2024, 1, 11).unwrap();
|
|
|
|
|
let data = two_day_limit_order_data(10.0, 10.0);
|
|
|
|
@@ -5051,6 +5053,8 @@ fn broker_persists_daily_volume_consumption_across_execute_calls() {
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
)
|
|
|
|
|
.with_matching_type(MatchingType::MinuteLast)
|
|
|
|
|
.with_intraday_execution_start_time(NaiveTime::from_hms_opt(9, 30, 0).unwrap())
|
|
|
|
|
.with_volume_limit(true)
|
|
|
|
|
.with_volume_percent(0.001)
|
|
|
|
|
.with_liquidity_limit(false);
|
|
|
|
@@ -5077,7 +5081,7 @@ fn broker_persists_daily_volume_consumption_across_execute_calls() {
|
|
|
|
|
assert_eq!(second.order_events.len(), 1);
|
|
|
|
|
assert_eq!(second.order_events[0].status, OrderStatus::Canceled);
|
|
|
|
|
assert_eq!(second.order_events[0].filled_quantity, 0);
|
|
|
|
|
assert!(second.order_events[0].reason.contains("daily volume limit"));
|
|
|
|
|
assert!(second.order_events[0].reason.contains("intraday quote liquidity exhausted"));
|
|
|
|
|
assert_eq!(portfolio.position("000002.SZ").unwrap().quantity, 100);
|
|
|
|
|
|
|
|
|
|
let next_day = broker
|
|
|
|
@@ -5294,7 +5298,7 @@ fn broker_day_market_order_cancels_remainder_without_creating_invalid_open_order
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
)
|
|
|
|
|
).with_matching_type(MatchingType::MinuteLast).with_intraday_execution_start_time(NaiveTime::from_hms_opt(9, 30, 0).unwrap())
|
|
|
|
|
.with_volume_limit(true)
|
|
|
|
|
.with_volume_percent(0.001)
|
|
|
|
|
.with_liquidity_limit(false);
|
|
|
|
@@ -5334,7 +5338,7 @@ fn broker_fok_order_is_atomic_when_liquidity_is_insufficient() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
)
|
|
|
|
|
).with_matching_type(MatchingType::MinuteLast).with_intraday_execution_start_time(NaiveTime::from_hms_opt(9, 30, 0).unwrap())
|
|
|
|
|
.with_volume_limit(true)
|
|
|
|
|
.with_volume_percent(0.001)
|
|
|
|
|
.with_liquidity_limit(false);
|
|
|
|
@@ -5421,7 +5425,7 @@ fn broker_gtc_limit_order_survives_close_and_fills_next_day() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
);
|
|
|
|
|
).with_matching_type(MatchingType::MinuteLast).with_intraday_execution_start_time(NaiveTime::from_hms_opt(9, 30, 0).unwrap());
|
|
|
|
|
let mut portfolio = PortfolioState::new(1_000_000.0);
|
|
|
|
|
|
|
|
|
|
let day1_report = broker
|
|
|
|
@@ -5469,7 +5473,7 @@ fn broker_gtc_partial_fills_preserve_cumulative_order_and_commission_state() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
)
|
|
|
|
|
).with_matching_type(MatchingType::MinuteLast).with_intraday_execution_start_time(NaiveTime::from_hms_opt(9, 30, 0).unwrap())
|
|
|
|
|
.with_volume_limit(true)
|
|
|
|
|
.with_volume_percent(0.001)
|
|
|
|
|
.with_liquidity_limit(false);
|
|
|
|
@@ -5536,7 +5540,7 @@ fn broker_modifies_gtc_limit_order_without_changing_order_identity() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
);
|
|
|
|
|
).with_matching_type(MatchingType::MinuteLast).with_intraday_execution_start_time(NaiveTime::from_hms_opt(9, 30, 0).unwrap());
|
|
|
|
|
let mut portfolio = PortfolioState::new(1_000_000.0);
|
|
|
|
|
|
|
|
|
|
let created = broker
|
|
|
|
@@ -5621,7 +5625,7 @@ fn broker_modifies_partially_filled_gtc_total_and_preserves_commission_state() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
)
|
|
|
|
|
).with_matching_type(MatchingType::MinuteLast).with_intraday_execution_start_time(NaiveTime::from_hms_opt(9, 30, 0).unwrap())
|
|
|
|
|
.with_volume_limit(true)
|
|
|
|
|
.with_volume_percent(0.001)
|
|
|
|
|
.with_liquidity_limit(false);
|
|
|
|
@@ -5699,7 +5703,7 @@ fn broker_rejected_modify_has_zero_side_effects() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
)
|
|
|
|
|
).with_matching_type(MatchingType::MinuteLast).with_intraday_execution_start_time(NaiveTime::from_hms_opt(9, 30, 0).unwrap())
|
|
|
|
|
.with_volume_limit(true)
|
|
|
|
|
.with_volume_percent(0.001)
|
|
|
|
|
.with_liquidity_limit(false);
|
|
|
|
@@ -5767,7 +5771,7 @@ fn broker_accepted_modify_resets_queue_priority_but_reduction_preserves_it() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
);
|
|
|
|
|
).with_matching_type(MatchingType::MinuteLast).with_intraday_execution_start_time(NaiveTime::from_hms_opt(9, 30, 0).unwrap());
|
|
|
|
|
let mut portfolio = PortfolioState::new(1_000_000.0);
|
|
|
|
|
let create = |reason: &str| StrategyDecision {
|
|
|
|
|
order_intents: vec![
|
|
|
|
@@ -5899,7 +5903,7 @@ fn broker_uses_limit_price_slippage_for_limit_orders() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
)
|
|
|
|
|
).with_matching_type(MatchingType::MinuteLast).with_intraday_execution_start_time(NaiveTime::from_hms_opt(9, 30, 0).unwrap())
|
|
|
|
|
.with_slippage_model(SlippageModel::LimitPrice);
|
|
|
|
|
let mut portfolio = PortfolioState::new(1_000_000.0);
|
|
|
|
|
|
|
|
|
@@ -5938,7 +5942,7 @@ fn broker_rejects_limit_buy_when_final_execution_price_reaches_upper_limit() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
)
|
|
|
|
|
).with_matching_type(MatchingType::MinuteLast).with_intraday_execution_start_time(NaiveTime::from_hms_opt(9, 30, 0).unwrap())
|
|
|
|
|
.with_slippage_model(SlippageModel::LimitPrice);
|
|
|
|
|
let mut portfolio = PortfolioState::new(1_000_000.0);
|
|
|
|
|
|
|
|
|
@@ -5984,7 +5988,7 @@ fn broker_executes_limit_value_and_limit_percent_intents() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
);
|
|
|
|
|
).with_matching_type(MatchingType::MinuteLast).with_intraday_execution_start_time(NaiveTime::from_hms_opt(9, 30, 0).unwrap());
|
|
|
|
|
|
|
|
|
|
let mut value_portfolio = PortfolioState::new(1_000_000.0);
|
|
|
|
|
let value_report = broker
|
|
|
|
@@ -6047,7 +6051,7 @@ fn broker_cancels_open_order_by_order_id() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
);
|
|
|
|
|
).with_matching_type(MatchingType::MinuteLast).with_intraday_execution_start_time(NaiveTime::from_hms_opt(9, 30, 0).unwrap());
|
|
|
|
|
let mut portfolio = PortfolioState::new(1_000_000.0);
|
|
|
|
|
|
|
|
|
|
let day1_report = broker
|
|
|
|
@@ -6225,7 +6229,7 @@ fn broker_reserves_sellable_quantity_for_open_limit_sells() {
|
|
|
|
|
ChinaAShareCostModel::default(),
|
|
|
|
|
ChinaEquityRuleHooks::default(),
|
|
|
|
|
PriceField::Open,
|
|
|
|
|
);
|
|
|
|
|
).with_volume_capacity_mode(fidc_core::execution_capacity::VolumeCapacityMode::SessionCapacityAudit);
|
|
|
|
|
let mut portfolio = PortfolioState::new(1_000_000.0);
|
|
|
|
|
portfolio
|
|
|
|
|
.position_mut("000002.SZ")
|
|
|
|
|