实现市值区间padding机制
- 添加padding_ratio、min_padding、max_padding配置参数 - 在市值区间计算中应用padding扩大选股范围 - 更新OmniMicroCapConfig、CnSmallCapRotationConfig和DynamicMarketCapBandSelector - AiQuant V1.0.4默认padding: ratio=0.5, min=12.5, max=30.0 - 目标:增加候选股票数量,匹配AiQuant行为
This commit is contained in:
@@ -114,6 +114,15 @@ pub struct DynamicRangeConfig {
|
||||
pub cap_span: Option<f64>,
|
||||
#[serde(default)]
|
||||
pub xs: Option<f64>,
|
||||
/// Padding ratio to expand the market cap range (e.g., 0.5 means 50% of span)
|
||||
#[serde(default)]
|
||||
pub padding_ratio: Option<f64>,
|
||||
/// Minimum padding in billion yuan
|
||||
#[serde(default)]
|
||||
pub min_padding: Option<f64>,
|
||||
/// Maximum padding in billion yuan
|
||||
#[serde(default)]
|
||||
pub max_padding: Option<f64>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
|
||||
|
||||
@@ -1090,6 +1090,9 @@ pub struct CnSmallCapRotationConfig {
|
||||
pub base_index_level: f64,
|
||||
pub base_cap_floor: f64,
|
||||
pub cap_span: f64,
|
||||
pub padding_ratio: f64,
|
||||
pub min_padding: f64,
|
||||
pub max_padding: f64,
|
||||
pub short_ma_days: usize,
|
||||
pub long_ma_days: usize,
|
||||
pub stock_short_ma_days: usize,
|
||||
@@ -1114,6 +1117,9 @@ impl CnSmallCapRotationConfig {
|
||||
base_index_level: 2000.0,
|
||||
base_cap_floor: 7.0,
|
||||
cap_span: 10.0,
|
||||
padding_ratio: 0.5,
|
||||
min_padding: 8.0,
|
||||
max_padding: 20.0,
|
||||
short_ma_days: 3,
|
||||
long_ma_days: 5,
|
||||
stock_short_ma_days: 3,
|
||||
@@ -1138,6 +1144,9 @@ impl CnSmallCapRotationConfig {
|
||||
base_index_level: 2000.0,
|
||||
base_cap_floor: 7.0,
|
||||
cap_span: 10.0,
|
||||
padding_ratio: 0.5,
|
||||
min_padding: 8.0,
|
||||
max_padding: 20.0,
|
||||
short_ma_days: 5,
|
||||
long_ma_days: 10,
|
||||
stock_short_ma_days: 5,
|
||||
@@ -1185,6 +1194,9 @@ impl CnSmallCapRotationStrategy {
|
||||
config.cap_span,
|
||||
config.xs,
|
||||
config.stocknum,
|
||||
config.padding_ratio,
|
||||
config.min_padding,
|
||||
config.max_padding,
|
||||
),
|
||||
config,
|
||||
last_gross_exposure: None,
|
||||
@@ -1508,6 +1520,9 @@ pub struct OmniMicroCapConfig {
|
||||
pub base_index_level: f64,
|
||||
pub base_cap_floor: f64,
|
||||
pub cap_span: f64,
|
||||
pub padding_ratio: f64,
|
||||
pub min_padding: f64,
|
||||
pub max_padding: f64,
|
||||
pub benchmark_signal_symbol: String,
|
||||
pub benchmark_short_ma_days: usize,
|
||||
pub benchmark_long_ma_days: usize,
|
||||
@@ -1531,6 +1546,9 @@ impl OmniMicroCapConfig {
|
||||
base_index_level: 2000.0,
|
||||
base_cap_floor: 7.0,
|
||||
cap_span: 10.0,
|
||||
padding_ratio: 0.5,
|
||||
min_padding: 8.0,
|
||||
max_padding: 20.0,
|
||||
benchmark_signal_symbol: "000001.SH".to_string(),
|
||||
benchmark_short_ma_days: 5,
|
||||
benchmark_long_ma_days: 10,
|
||||
@@ -1556,6 +1574,9 @@ impl OmniMicroCapConfig {
|
||||
base_index_level: 2000.0,
|
||||
base_cap_floor: 7.0,
|
||||
cap_span: 25.0,
|
||||
padding_ratio: 0.5,
|
||||
min_padding: 12.5,
|
||||
max_padding: 30.0,
|
||||
benchmark_signal_symbol: "000852.SH".to_string(),
|
||||
benchmark_short_ma_days: 5,
|
||||
benchmark_long_ma_days: 20,
|
||||
@@ -2167,7 +2188,18 @@ impl OmniMicroCapStrategy {
|
||||
let y = (index_level - self.config.base_index_level) * self.config.xs
|
||||
+ self.config.base_cap_floor;
|
||||
let start = y.round();
|
||||
(start, start + self.config.cap_span)
|
||||
let end = start + self.config.cap_span;
|
||||
|
||||
// Apply padding to expand the range
|
||||
let span = end - start;
|
||||
let padding = (span * self.config.padding_ratio)
|
||||
.max(self.config.min_padding)
|
||||
.min(self.config.max_padding);
|
||||
|
||||
let lower_bound = (start - padding).max(0.0);
|
||||
let upper_bound = end + padding;
|
||||
|
||||
(lower_bound, upper_bound)
|
||||
}
|
||||
|
||||
fn stock_passes_ma_filter(
|
||||
|
||||
@@ -78,6 +78,9 @@ pub struct DynamicMarketCapBandSelector {
|
||||
pub cap_span: f64,
|
||||
pub xs: f64,
|
||||
pub top_n: usize,
|
||||
pub padding_ratio: f64,
|
||||
pub min_padding: f64,
|
||||
pub max_padding: f64,
|
||||
}
|
||||
|
||||
impl DynamicMarketCapBandSelector {
|
||||
@@ -87,6 +90,9 @@ impl DynamicMarketCapBandSelector {
|
||||
cap_span: f64,
|
||||
xs: f64,
|
||||
top_n: usize,
|
||||
padding_ratio: f64,
|
||||
min_padding: f64,
|
||||
max_padding: f64,
|
||||
) -> Self {
|
||||
Self {
|
||||
base_index_level,
|
||||
@@ -94,11 +100,14 @@ impl DynamicMarketCapBandSelector {
|
||||
cap_span,
|
||||
xs,
|
||||
top_n,
|
||||
padding_ratio,
|
||||
min_padding,
|
||||
max_padding,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn demo(top_n: usize) -> Self {
|
||||
Self::new(2000.0, 7.0, 10.0, 4.0 / 500.0, top_n)
|
||||
Self::new(2000.0, 7.0, 10.0, 4.0 / 500.0, top_n, 0.5, 8.0, 20.0)
|
||||
}
|
||||
|
||||
pub fn regime(&self, benchmark_level: f64) -> BandRegime {
|
||||
@@ -114,7 +123,18 @@ impl DynamicMarketCapBandSelector {
|
||||
pub fn band_for_level(&self, benchmark_level: f64) -> (f64, f64) {
|
||||
let start = ((benchmark_level - self.base_index_level) * self.xs) + self.base_cap_floor;
|
||||
let low = start.round();
|
||||
(low, low + self.cap_span)
|
||||
let high = low + self.cap_span;
|
||||
|
||||
// Apply padding to expand the range
|
||||
let span = high - low;
|
||||
let padding = (span * self.padding_ratio)
|
||||
.max(self.min_padding)
|
||||
.min(self.max_padding);
|
||||
|
||||
let lower_bound = (low - padding).max(0.0);
|
||||
let upper_bound = high + padding;
|
||||
|
||||
(lower_bound, upper_bound)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user