Align order costs and rebalance priority with rqalpha

This commit is contained in:
boris
2026-04-22 23:36:20 -07:00
parent c85116c59d
commit ea2871a0f2
6 changed files with 436 additions and 36 deletions

View File

@@ -1,3 +1,5 @@
use std::collections::BTreeMap;
use chrono::NaiveDate;
use crate::events::OrderSide;
@@ -18,6 +20,17 @@ impl TradingCost {
pub trait CostModel {
fn calculate(&self, date: NaiveDate, side: OrderSide, gross_amount: f64) -> TradingCost;
fn calculate_with_order_state(
&self,
date: NaiveDate,
side: OrderSide,
gross_amount: f64,
_order_id: Option<u64>,
_commission_state: &mut BTreeMap<u64, f64>,
) -> TradingCost {
self.calculate(date, side, gross_amount)
}
}
#[derive(Debug, Clone, Copy)]
@@ -67,6 +80,43 @@ impl ChinaAShareCostModel {
}
gross_amount * self.stamp_tax_rate_for(date)
}
pub fn commission_for_order_fill(
&self,
gross_amount: f64,
order_id: Option<u64>,
commission_state: &mut BTreeMap<u64, f64>,
) -> f64 {
if gross_amount <= 0.0 {
return 0.0;
}
let raw_commission = gross_amount * self.commission_rate;
let Some(order_id) = order_id else {
return raw_commission.max(self.minimum_commission);
};
let remaining_minimum = commission_state
.entry(order_id)
.or_insert(self.minimum_commission);
if raw_commission > *remaining_minimum {
let charged = if (*remaining_minimum - self.minimum_commission).abs() < 1e-12 {
raw_commission
} else {
raw_commission - *remaining_minimum
};
*remaining_minimum = 0.0;
charged
} else {
let charged = if (*remaining_minimum - self.minimum_commission).abs() < 1e-12 {
self.minimum_commission
} else {
0.0
};
*remaining_minimum -= raw_commission;
charged
}
}
}
impl CostModel for ChinaAShareCostModel {
@@ -86,4 +136,28 @@ impl CostModel for ChinaAShareCostModel {
stamp_tax,
}
}
fn calculate_with_order_state(
&self,
date: NaiveDate,
side: OrderSide,
gross_amount: f64,
order_id: Option<u64>,
commission_state: &mut BTreeMap<u64, f64>,
) -> TradingCost {
if gross_amount <= 0.0 {
return TradingCost {
commission: 0.0,
stamp_tax: 0.0,
};
}
let commission = self.commission_for_order_fill(gross_amount, order_id, commission_state);
let stamp_tax = self.stamp_tax_for(date, side, gross_amount);
TradingCost {
commission,
stamp_tax,
}
}
}