Files
fidc-backtest-engine/crates/fidc-core/src/rules.rs
T

94 lines
2.3 KiB
Rust

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<String>,
}
impl RuleCheck {
pub fn allow() -> Self {
Self {
allowed: true,
reason: None,
}
}
pub fn reject(reason: impl Into<String>) -> 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()
}
}