chore: 更新 fidc-backtest-engine - 2026-05-22
This commit is contained in:
@@ -2,6 +2,7 @@ use chrono::NaiveDate;
|
||||
|
||||
use crate::data::{CandidateEligibility, DailyMarketSnapshot, PriceField};
|
||||
use crate::portfolio::Position;
|
||||
use crate::risk_control::ChinaAShareRiskControl;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RuleCheck {
|
||||
@@ -47,20 +48,6 @@ pub trait EquityRuleHooks {
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct ChinaEquityRuleHooks;
|
||||
|
||||
impl ChinaEquityRuleHooks {
|
||||
fn at_upper_limit(snapshot: &DailyMarketSnapshot, price_field: PriceField) -> bool {
|
||||
snapshot.is_at_upper_limit_price(snapshot.buy_price(price_field))
|
||||
}
|
||||
|
||||
fn at_lower_limit(snapshot: &DailyMarketSnapshot, price_field: PriceField) -> bool {
|
||||
let check_price = match price_field {
|
||||
PriceField::Last => snapshot.price(PriceField::Last),
|
||||
_ => snapshot.sell_price(price_field),
|
||||
};
|
||||
snapshot.is_at_lower_limit_price(check_price)
|
||||
}
|
||||
}
|
||||
|
||||
impl EquityRuleHooks for ChinaEquityRuleHooks {
|
||||
fn can_buy(
|
||||
&self,
|
||||
@@ -69,14 +56,14 @@ impl EquityRuleHooks for ChinaEquityRuleHooks {
|
||||
candidate: &CandidateEligibility,
|
||||
price_field: PriceField,
|
||||
) -> RuleCheck {
|
||||
if snapshot.paused || candidate.is_paused {
|
||||
return RuleCheck::reject("paused");
|
||||
}
|
||||
if !candidate.allow_buy {
|
||||
return RuleCheck::reject("buy disabled by eligibility flags");
|
||||
}
|
||||
if Self::at_upper_limit(snapshot, price_field) {
|
||||
return RuleCheck::reject("open at or above upper limit");
|
||||
if let Some(reason) = ChinaAShareRiskControl::buy_rejection_reason(
|
||||
_execution_date,
|
||||
candidate,
|
||||
snapshot,
|
||||
None,
|
||||
ChinaAShareRiskControl::buy_check_price(snapshot, price_field),
|
||||
) {
|
||||
return RuleCheck::reject(reason);
|
||||
}
|
||||
|
||||
RuleCheck::allow()
|
||||
@@ -90,17 +77,15 @@ impl EquityRuleHooks for ChinaEquityRuleHooks {
|
||||
position: &Position,
|
||||
price_field: PriceField,
|
||||
) -> RuleCheck {
|
||||
if snapshot.paused || candidate.is_paused {
|
||||
return RuleCheck::reject("paused");
|
||||
}
|
||||
if !candidate.allow_sell {
|
||||
return RuleCheck::reject("sell disabled by eligibility flags");
|
||||
}
|
||||
if Self::at_lower_limit(snapshot, price_field) {
|
||||
return RuleCheck::reject("open at or below lower limit");
|
||||
}
|
||||
if position.sellable_qty(execution_date) == 0 {
|
||||
return RuleCheck::reject("t+1 sellable quantity is zero");
|
||||
if let Some(reason) = ChinaAShareRiskControl::sell_rejection_reason(
|
||||
execution_date,
|
||||
candidate,
|
||||
snapshot,
|
||||
None,
|
||||
Some(position),
|
||||
ChinaAShareRiskControl::sell_check_price(snapshot, price_field),
|
||||
) {
|
||||
return RuleCheck::reject(reason);
|
||||
}
|
||||
|
||||
RuleCheck::allow()
|
||||
|
||||
Reference in New Issue
Block a user