use chrono::NaiveDate; use crate::data::{CandidateEligibility, DailyMarketSnapshot, PriceField}; use crate::portfolio::Position; use crate::risk_control::ChinaAShareRiskControl; #[derive(Debug, Clone)] pub struct RuleCheck { pub allowed: bool, pub reason: Option, } impl RuleCheck { pub fn allow() -> Self { Self { allowed: true, reason: None, } } pub fn reject(reason: impl Into) -> Self { Self { allowed: false, reason: Some(reason.into()), } } } pub trait EquityRuleHooks { fn can_buy( &self, execution_date: NaiveDate, snapshot: &DailyMarketSnapshot, candidate: &CandidateEligibility, price_field: PriceField, ) -> RuleCheck; fn can_sell( &self, execution_date: NaiveDate, snapshot: &DailyMarketSnapshot, candidate: &CandidateEligibility, position: &Position, price_field: PriceField, ) -> RuleCheck; } #[derive(Debug, Clone, Default)] pub struct ChinaEquityRuleHooks; impl EquityRuleHooks for ChinaEquityRuleHooks { fn can_buy( &self, _execution_date: NaiveDate, snapshot: &DailyMarketSnapshot, candidate: &CandidateEligibility, price_field: PriceField, ) -> RuleCheck { 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() } fn can_sell( &self, execution_date: NaiveDate, snapshot: &DailyMarketSnapshot, candidate: &CandidateEligibility, position: &Position, price_field: PriceField, ) -> RuleCheck { 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() } }