chore: 更新 fidc-backtest-engine - 2026-05-22

This commit is contained in:
boris
2026-05-22 17:22:33 +08:00
parent 7dbd66b467
commit 3499d4aa74
8 changed files with 526 additions and 125 deletions
+18 -36
View File
@@ -17,6 +17,7 @@ use crate::events::{FillEvent, OrderEvent, OrderSide, OrderStatus, ProcessEvent}
use crate::futures::{FuturesAccountState, FuturesOrderIntent};
use crate::instrument::Instrument;
use crate::portfolio::PortfolioState;
use crate::risk_control::ChinaAShareRiskControl;
use crate::scheduler::ScheduleRule;
use crate::universe::{DynamicMarketCapBandSelector, SelectionContext, UniverseSelector};
@@ -2330,18 +2331,6 @@ impl OmniMicroCapStrategy {
true
}
fn special_name(&self, ctx: &StrategyContext<'_>, symbol: &str) -> bool {
let instrument_name = ctx
.data
.instruments()
.get(symbol)
.map(|instrument| instrument.name.as_str())
.unwrap_or("");
instrument_name.contains("ST")
|| instrument_name.contains('*')
|| instrument_name.contains('退')
}
fn can_sell_position(&self, ctx: &StrategyContext<'_>, date: NaiveDate, symbol: &str) -> bool {
let Some(position) = ctx.portfolio.position(symbol) else {
return false;
@@ -2355,11 +2344,15 @@ impl OmniMicroCapStrategy {
let Ok(candidate) = ctx.data.require_candidate(date, symbol) else {
return false;
};
let lower_limit_check_price = market.price(PriceField::Last);
!(market.paused
|| candidate.is_paused
|| !candidate.allow_sell
|| market.is_at_lower_limit_price(lower_limit_check_price))
ChinaAShareRiskControl::sell_rejection_reason(
date,
candidate,
market,
ctx.data.instrument(symbol),
Some(position),
ChinaAShareRiskControl::sell_check_price(market, PriceField::Last),
)
.is_none()
}
fn buy_rejection_reason(
@@ -2371,25 +2364,14 @@ impl OmniMicroCapStrategy {
let market = ctx.data.require_market(date, symbol)?;
let candidate = ctx.data.require_candidate(date, symbol)?;
if market.paused || candidate.is_paused {
return Ok(Some("paused".to_string()));
}
if candidate.is_st || self.special_name(ctx, symbol) {
return Ok(Some("st_or_special_name".to_string()));
}
if candidate.is_kcb {
return Ok(Some("kcb".to_string()));
}
if !candidate.allow_buy {
return Ok(Some("buy_disabled".to_string()));
}
if market.is_at_upper_limit_price(market.day_open)
|| market.is_at_upper_limit_price(market.buy_price(PriceField::Last))
{
return Ok(Some("upper_limit".to_string()));
}
if market.day_open <= 1.0 {
return Ok(Some("one_yuan".to_string()));
if let Some(reason) = ChinaAShareRiskControl::buy_rejection_reason(
date,
candidate,
market,
ctx.data.instrument(symbol),
ChinaAShareRiskControl::buy_check_price(market, PriceField::Last),
) {
return Ok(Some(reason.to_string()));
}
if !self.truth_selection_contains(date, symbol)
&& !self.stock_passes_ma_filter(ctx, date, symbol)