Files
NewStock/main/factor/special_factors.py

135 lines
3.8 KiB
Python
Raw Normal View History

2025-11-29 00:23:12 +08:00
"""
特殊因子模块
包含基于股票截面的特殊因子实现
"""
import numpy as np
import polars as pl
from main.factor.operator_framework import StockWiseFactor
class LimitFactor(StockWiseFactor):
"""涨跌停因子"""
def __init__(self):
super().__init__(
name="limit",
parameters={},
required_factor_ids=["close", "up_limit", "down_limit"]
)
def calc_factor(self, group_df: pl.DataFrame) -> pl.Series:
# 计算是否涨停或跌停
close = group_df["close"]
up_limit = group_df["up_limit"]
down_limit = group_df["down_limit"]
# 是否涨停
is_up_limit = (close == up_limit).cast(pl.Int32)
# 是否跌停
is_down_limit = (close == down_limit).cast(pl.Int32)
# 合并为一个因子
limit_factor = is_up_limit - is_down_limit
return limit_factor.alias(self.factor_id)
class VolumeRatioFactor(StockWiseFactor):
"""量比因子"""
def __init__(self):
super().__init__(
name="volume_ratio",
parameters={},
required_factor_ids=["vol"]
)
def calc_factor(self, group_df: pl.DataFrame) -> pl.Series:
# 计算量比:当日成交量 / 5日平均成交量
vol = group_df["vol"]
avg_vol_5d = vol.rolling_mean(5)
# 避免除零
volume_ratio = vol / (avg_vol_5d + 1e-8)
return volume_ratio.alias(self.factor_id)
class BBI_RATIO_FACTOR(StockWiseFactor):
"""BBI比率因子"""
def __init__(self):
super().__init__(
name="bbi_ratio",
parameters={},
required_factor_ids=["close"]
)
def calc_factor(self, group_df: pl.DataFrame) -> pl.Series:
# 计算BBI比率
close = group_df["close"]
# 计算不同周期的SMA
sma3 = close.rolling_mean(3)
sma6 = close.rolling_mean(6)
sma12 = close.rolling_mean(12)
sma24 = close.rolling_mean(24)
# 计算BBI
bbi = (sma3 + sma6 + sma12 + sma24) / 4
# 计算BBI比率
bbi_ratio = bbi / (close + 1e-8) # 避免除零
return bbi_ratio.alias(self.factor_id)
class VolatilitySlopeFactor(StockWiseFactor):
"""波动率斜率因子"""
def __init__(self, window_vol: int = 20, window_slope: int = 5):
super().__init__(
name="volatility_slope",
parameters={"window_vol": window_vol, "window_slope": window_slope},
required_factor_ids=["pct_chg"]
)
def calc_factor(self, group_df: pl.DataFrame) -> pl.Series:
window_vol = self.parameters["window_vol"]
window_slope = self.parameters["window_slope"]
# 计算滚动标准差
volatility = group_df["pct_chg"].rolling_std(window_vol)
# 计算斜率
# 这里简化处理,直接计算最后一个窗口的斜率
# 实际应用中可能需要更复杂的线性回归计算
volatility_slope = volatility.diff().alias(self.factor_id)
return volatility_slope
class PriceVolumeTrendFactor(StockWiseFactor):
"""价格量能趋势因子"""
def __init__(self):
super().__init__(
name="price_volume_trend",
parameters={},
required_factor_ids=["close", "vol"]
)
def calc_factor(self, group_df: pl.DataFrame) -> pl.Series:
# 计算价格量能趋势
close = group_df["close"]
vol = group_df["vol"]
# 计算价格变化
price_change = close.diff()
# 计算成交量变化
vol_change = vol.diff()
# 计算趋势因子
trend_factor = price_change * vol_change
return trend_factor.alias(self.factor_id)