Files
myquant/finance/factors/registry.py
T
Simon 73d191b43a feat: 量化引擎加固 — 新增测试 + 数据/因子/回测层优化
- 新增 finance/tests/ 6 个测试套件(agents/backtest/dao_upsert/factors/features/fundamental_lookahead)
- 数据层: data_manager / dao 优化,新增 upsert 逻辑
- 因子层: 基本面因子抽象定位 _mapping、ROE/PE/PB 重构
- 回测层: vectorbt/engine 大改动(251 行),report 增强
- ML 层: features/backtest_integration 特征工程与回测优化
- CLI: agent_cli 重构
- config/settings 扩充配置项
2026-08-31 14:01:06 +08:00

132 lines
5.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
因子注册表。
通过名称获取因子实例,方便回测和策略配置时引用。
"""
from factors.base import BaseFactor
from factors.technical.momentum import MomentumFactor
from factors.technical.rsi import RSIFactor
from factors.technical.macd import MACDFactor
from factors.technical.volume import VolumeFactor, VolumeChangeFactor
from factors.technical.bollinger import BollingerFactor, BollingerWidthFactor
from factors.technical.atr import ATRFactor, ATRRatioFactor
from factors.technical.ma_cross import MACrossFactor, MADeviationFactor
from factors.technical.volatility import VolatilityFactor, DownsideVolatilityFactor
from factors.technical.turnover import TurnoverFactor, TurnoverChangeFactor
from factors.technical.amplitude import AmplitudeFactor
from factors.fundamental.roe import ROEFactor
from factors.fundamental.pe_pb import PEFactor, PBFactor, EPFactor
from factors.sentiment.sentiment_factor import (
NewsSentimentFactor,
SentimentMomentumFactor,
SentimentConfidenceFactor,
)
# ── 内置因子工厂函数 ──────────────────────────────────────
_BUILTIN_FACTORIES: dict[str, callable] = { # type: ignore
# 动量
"momentum_5": lambda: MomentumFactor(period=5),
"momentum_10": lambda: MomentumFactor(period=10),
"momentum_20": lambda: MomentumFactor(period=20),
"momentum_60": lambda: MomentumFactor(period=60),
# RSI
"rsi_7": lambda: RSIFactor(period=7),
"rsi_14": lambda: RSIFactor(period=14),
# MACD
"macd": lambda: MACDFactor(),
"macd_5_35_5": lambda: MACDFactor(fast=5, slow=35, signal=5),
# 量价
"vol_ratio_5": lambda: VolumeFactor(period=5),
"vol_ratio_20": lambda: VolumeFactor(period=20),
"vol_chg_5": lambda: VolumeChangeFactor(period=5),
# 布林
"boll": lambda: BollingerFactor(),
"boll_width": lambda: BollingerWidthFactor(),
# ATR
"atr_14": lambda: ATRFactor(period=14),
"atr_ratio_14": lambda: ATRRatioFactor(period=14),
# 均线
"ma_cross_5_20": lambda: MACrossFactor(fast=5, slow=20),
"ma_cross_10_60": lambda: MACrossFactor(fast=10, slow=60),
"ma_dev_20": lambda: MADeviationFactor(period=20),
"ma_dev_60": lambda: MADeviationFactor(period=60),
# 波动率
"volatility_20": lambda: VolatilityFactor(period=20),
"volatility_60": lambda: VolatilityFactor(period=60),
"down_vol_20": lambda: DownsideVolatilityFactor(period=20),
# 换手率
"turnover_5": lambda: TurnoverFactor(period=5),
"turnover_chg_5": lambda: TurnoverChangeFactor(period=5),
# 振幅
"amplitude_5": lambda: AmplitudeFactor(period=5),
"amplitude_20": lambda: AmplitudeFactor(period=20),
# 基本面
"roe": lambda: ROEFactor(),
"pe": lambda: PEFactor(),
"pb": lambda: PBFactor(),
"ep": lambda: EPFactor(),
# 情绪
"news_sent_5": lambda: NewsSentimentFactor(window=5),
"news_sent_20": lambda: NewsSentimentFactor(window=20),
"news_conf_5": lambda: SentimentConfidenceFactor(window=5),
"sent_delta_5": lambda: SentimentMomentumFactor(period=5),
}
# ── 分类映射 ──────────────────────────────────────────────
FACTOR_CATEGORIES: dict[str, list[str]] = {
"动量": ["momentum_5", "momentum_10", "momentum_20", "momentum_60"],
"RSI": ["rsi_7", "rsi_14"],
"MACD": ["macd", "macd_5_35_5"],
"量价": ["vol_ratio_5", "vol_ratio_20", "vol_chg_5"],
"布林": ["boll", "boll_width"],
"ATR": ["atr_14", "atr_ratio_14"],
"均线": ["ma_cross_5_20", "ma_cross_10_60", "ma_dev_20", "ma_dev_60"],
"波动率": ["volatility_20", "volatility_60", "down_vol_20"],
"换手率": ["turnover_5", "turnover_chg_5"],
"振幅": ["amplitude_5", "amplitude_20"],
"基本面": ["roe", "pe", "pb", "ep"],
"情绪": ["news_sent_5", "news_sent_20", "news_conf_5", "sent_delta_5"],
}
def get_factor(name: str, **overrides) -> BaseFactor:
"""按名称获取因子实例。
参数:
name: 因子名称(如 'momentum_20')
**overrides: 覆盖默认参数
返回:
BaseFactor 实例
说明: 返回实例的 .name 恒等于注册键 name,即使构造器默认生成的
.name 与注册键不同(如 boll 的构造器默认 .name='boll_20')——
注册键是列名的唯一事实源,避免 FactorEngine.compute 的列名漂移。
"""
if name not in _BUILTIN_FACTORIES:
raise KeyError(f"未知因子: '{name}'。可用: {list(_BUILTIN_FACTORIES)}")
factor = _BUILTIN_FACTORIES[name]()
if overrides:
for k, v in overrides.items():
if hasattr(factor, k):
setattr(factor, k, v)
# 无论是否覆盖参数,都强制 .name = 注册键,保证与分类/策略的引用一致
if hasattr(factor, "name"):
factor.name = name
return factor
def list_factors(category: str | None = None) -> list[str]:
"""列出所有可用因子名称。"""
if category and category in FACTOR_CATEGORIES:
return FACTOR_CATEGORIES[category]
return list(_BUILTIN_FACTORIES)
def list_categories() -> list[str]:
"""列出所有因子分类。"""
return list(FACTOR_CATEGORIES)