← 文档库
📄 文档adata/aohan/learn/ETF轮动/选基策略引擎-截面方案设计.md
🌱 创建于2026-05-12 02:21
✏️ 修改于2026-06-08 22:14
👁️ 浏览量—
🔗 短链接/~learn/s/af7e0961
🔐 可见性

选基策略引擎 — 截面方案设计

文档目标

本文档用于设计一套 截面 ETF 选基策略引擎,将现有量化系统从"纵向择时"扩展到"横向选基"能力,每日全市场扫描场内 ETF,通过多因子打分 + 截面排名选出最优品种并分配权重。

一句话结论

构建 ETFSelectionEngine,以"日频全市场截面扫描 → 多因子评分 → TopN 精选 → 权重分配 → 叠加择时信号"为完整链路,实现风格轮动自适应,解决牛市行业热点切换频繁、人工选基跟不上节奏的问题。

一、背景与问题

1. 现有系统的局限

当前系统在 StrategyAllocationManager 中固定配置了约 15 个品种的权重:

code_to_weight = {
    '399102.SZ': 0.05,
    '980092.CNI': 0.12,
    '510880': 0.05,
    '513180': 0.08,
    'GLD': 0.15,
    ...
}

2. 核心转变

维度 原有方式(纵向) 新方式(横向)
-- ------------------- -------------------
视角 单一品种的历史时序 全市场品种的截面比较
问题 何时买/卖这个品种 买哪个品种最好
数据 单个 DF 的时间序列 多品种同日期快照
策略 generate\_signals() rank\_and\_select()
输出 position (0/1) portfolio (权重列表)

二、整体架构

1. 架构总览

Mermaid Live View

Mermaid Live Edit: https://mermaid.live/edit#pako:eNp1U91u2jAYfRXk6_YFuJi0FugPP6UC7WJOL9xgIFISo9TRhqpK00YLlFLQqo5JUzuYNHXdtO5HYtPKVl4GO8lbzHHYGrXgK-ec830-Pp-zC1RSwCAKijp5opaRRSP5mGJGxNqxt0sWqpQjMUQRVAA__crbV-zbcwlEUqiKLQVsBWJ_PYTxfII1eu7gg3v8k3VebUUWFx9EliDvvU8612Pe_OXVO7zV9KnbsiWpWoa88dE7e8fGn5z9C35eY6PrqQibhTuOEkilxBKe2Js--9z1PQXQDFfLsn0MpomBTWobQck9QRw-Irpt4Dl0Am7aSNdodQ6_ArMWNrQZ7WOSX4UB4by99F4PQ3Q8oG-BxF1gJQzczyKnEguLKNwvNdY48KPwEc0szchiVbZam3rh_TqrH7Cj8DDWpGIdssM-P3vhjH6zbiPoHBKtS1FyOjF-_JJ123NnlcM6Vqkw6D1r8talNCghjZgzLCZl7xTMk0rG-X4jikJkSpJpKKx59bYw5e23Q3Ra0hnID0_dYc0Z1YT5ub7iT7FqUz853rxwB0e-sQCbbSwjm29AcQfe-zEZD1hHvPG-CCok2pCiLJyMTiZ_2s7VwOmGg8tKelPkf86HLffmhNVDjxwsAANbBtIK4n_c9WEF0DI2sAKiYlvARWTrVAGKuSekyKYkVzVVEKWWjReAXSkgimMaEtczQLSI9B2BWsQulf9_VZD5mBDjX0nJ8o_y93t_AQnShtA)
flowchart TD subgraph Data["数据层 Data Layer"] A[ETF列表获取
all_etf_exchange_traded_info] --> B[日K线批量拉取
fund_daily / get_market_etf] B --> C[截面快照构建
CrossSectionalSnapshot] end subgraph Factor["因子层 Factor Layer"] C --> D[Momentum因子
N日收益率] C --> E[Volume因子
量比/换手率] C --> F[Quality因子
波动率/回撤] C --> G[Premium因子
折价溢价率] D --> H[因子矩阵
FactorMatrix] E --> H F --> H G --> H end subgraph Score["评分层 Scoring Layer"] H --> I[因子标准化
Z-Score / Rank] I --> J[加权综合评分
CompositeScore] J --> K[截面排名
CrossSectionRank] end subgraph Select["选择层 Selection Layer"] K --> L[TopN精选
ETF筛选] L --> M[权重分配
等权/评分加权] M --> N[投资组合输出
Portfolio] end subgraph Execute["执行层 Execution Layer"] N --> O[择时信号叠加
现有Strategy] O --> P[仓位管理
PositionManager] P --> Q[回测/实盘输出
BacktestResult] end style Data fill:#e1f5fe,stroke:#0288d1 style Factor fill:#f3e5f5,stroke:#7b1fa2 style Score fill:#fff3e0,stroke:#f57c00 style Select fill:#e8f5e9,stroke:#388e3c style Execute fill:#fce4ec,stroke:#c62828

架构分为五个层面,每层职责清晰、接口明确:

2. 每日运行流程

Mermaid Live View

Mermaid Live Edit: https://mermaid.live/edit#pako:eNp1UttqGkEYfpVlC72KcU26pVlKbmzNRW1Qd0mgay6mOqPCHmSzS5EQ0LaJmnqihpiShMY2oRJoAj1YayB9GWfcfYuOu2uxF87VP_Md_n--mR02pachK7BI0V-lssAwmWgiqTF0SaJMDvvjk2PcajAhXuC4LSYQWGXWYrLd-IWbR3ivhwev8enwqRTBlY7d7T1-aQRXQRqYYBFZWnoxpyF9y3Nbi7niSEzGv_t2t0beVakF6Vw-Gw__uDpy0xwNrqgX85ALLPEc3YyGF-S4TUm-ScQziYdl-0fPKTfJ5yL5eOmqcfXQ-XCBS6fjai1IfpbwQY8Uv4wGdbv_3VfHw94Iomxfd8fXHVK5cs4-4ZNz_LXlejzXVaiZlhrc0BVLhcG4BZScWZg2F125GJbJeRmX93HtiLnP2DdvcWXfp4heh8S67HmTxnvcqvtgYt3TR2VJz4foFTmGXnb87c4pVqf6qEvZlGRy9sYp16mzszfVb0ouKIlLsn3XxuXh6PaARkNqpdFtm3I81rZZUCAlMSinKMI9hNAy5GYh-hAeBEOIR3AWisyHaHa-4TLkEf-fSpwLieG5Y9A05kE0BX-MR4iHK7MQzWAeRHOZOqbgA5hiF1gVGirIpenv3pkwk6yZhSpMsgIt0xABSzGTbFLbpVRgmbpY0FKsYBoWXGCtPP3F8EkOZAygsgICyjY9NXQrk_23ywPtha6rU0nGmLSa1Lt_AcZESvU)
flowchart LR TS[收盘后 15:00] --> GP[获取全市场ETF列表
adata.fund.info] GP --> FP[并行拉取日K线
每个ETF 60-250个交易日] FP --> QC[质量检查
剔除停牌/流动性不足] QC --> FS[计算截面因子
Momentum/Volume/Quality] FS --> SC[标准化 & 评分] SC --> RN[截面排名] RN --> SL[Top10-20 ETF精选] SL --> WT[权重分配] WT --> TS2[输出今日持仓] style TS fill:#fff3e0 style GP fill:#e1f5fe style FP fill:#e1f5fe style QC fill:#f3e5f5 style FS fill:#f3e5f5 style SC fill:#fff3e0 style RN fill:#fff3e0 style SL fill:#e8f5e9 style WT fill:#e8f5e9 style TS2 fill:#fce4ec

每日流程约需 3-5 分钟完成全市场扫描,关键路径说明:

3. 核心类设计

Mermaid Live View

Mermaid Live Edit: https://mermaid.live/edit#pako:eNqtVduK2zAQ_ZWgpywb_0AIgV523xZaUvpQAmIsj22xsiZIo4awzb9XjpJFbuylG9ZPks7ozGE8Z_QiFFUolkIZ8P6rhsZBt7Wz-J1OZg8_HjdoULEm-2AbbXH2kvD-u6-RVSvBGIlcS6M9z-8yuAzaVNJb2PmWeF4BYw67YKW_sA8uNshyR45rMpouyHFUGLlc0WoFpWcHitfrjC9lmQerf6PzuJhlUga0T9Sh5dBN0BeG6LkE9Sz32la09zflCIb1I_TcU2nqE5qxF3vUTcs35Uup_qNKFjrMtgqMCiaSvqNu17mKVKkbeX-SCR1-NOv3AEbz4aNpvzns9FgN3sXyxZH3m2QKMJ9jszF6xqFOf-6a7OjCLNtoQ3KHodHmnsHxYoa2uhsTJjtkp5UfNdsm9gpjc_hkDCnohT2BhWao6d6nKI1elgdZErgqQ6GKk-DMI5kSfmV6eM3gZU1uGBU1pcXIVCqKdT4T3oybqvCblyZr8M-t-OdXf4pibJJMRY7OgxQ8MSt6Qek0hZ1bbpB4Cs8tdY0OrHEND1pcLESHrgNdxRfk1AlbwS3GISKWcVlhDVH-VmztMYZCYNocrBJLdgEXIux6B5zfHLGswURXCEehaV93O7C_iLrLlcb1qfr18S_ReinW)
classDiagram class ETFSelectionEngine { +fetch_all_etf_list() +build_snapshot(date) +run_selection() +get_portfolio() } class ETFSelector { <> +select(universe, date) } class MomentumETFSelector { -lookback_windows +select(universe, date) } class MultiFactorETFSelector { -factors -weights +select(universe, date) } class Factor { <> +name +calculate(universe, date) } class MomentumFactor { -window +calculate(universe, date) } class VolumeFactor { -window +calculate(universe, date) } class QualityFactor { -window +calculate(universe, date) } class PremiumFactor { +calculate(universe, date) } class CrossSectionalBacktester { -selector -universe_history +run(start, end) +calculate_metrics() } class StrategyAllocationManager { +strategies_by_board +add_strategy_to_board() +get_allocations_for_board() } ETFSelectionEngine --> ETFSelector ETFSelectionEngine --> CrossSectionalBacktester ETFSelectionEngine --> StrategyAllocationManager ETFSelector <|-- MomentumETFSelector ETFSelector <|-- MultiFactorETFSelector MultiFactorETFSelector --> Factor Factor <|-- MomentumFactor Factor <|-- VolumeFactor Factor <|-- QualityFactor Factor <|-- PremiumFactor

核心类说明:

类名 职责
------------------------- --------------------------------------
ETFSelectionEngine 顶层入口,编排全流程(获取列表->拉数据->选基->输出)
ETFSelector 选基策略抽象基类,定义 select(universe, date) 接口
MultiFactorETFSelector 多因子选基实现,持有 Factor 列表和权重
Factor 因子抽象基类,定义 calculate(universe, date) 接口
CrossSectionalBacktester 截面回测框架,逐日模拟选基 + 调仓
StrategyAllocationManager 已有类,扩展支持动态品种配置

三、ETF 池管理

1. 数据源

数据源 接口 用途
------------------------------------------------ ----------- --------------
adata.fund.info.all\_etf\_exchange\_traded\_info 东方财富接口 获取全市场场内 ETF 列表
stock\_today\_client.fund\_daily tushare 代理 获取单 ETF 日 K 线
adata.fund.market.get\_market\_etf adata(降级备选) 同花顺数据源日 K 线
基金ETF列表-场内.csv 本地 CSV 静态备份 离线参考/快速测试

2. ETF 筛选规则

从全市场约 1500 只场内 ETF 中筛选出有效候选池:

筛选条件 标准 目的
----- ---------------- ------------------
上市天数 >= 60 个交易日 剔除次新 ETF,确保有足够历史数据
日均成交额 >= 500 万(近 20 日) 剔除流动性不足的品种
基金类型 股票型 排除债券、货币、REITs、商品
投资类型 被动指数型 排除主动管理 ETF
重复标的 同指数保留规模最大的一只 减少同质化竞争

3. 筛选后在册品种分类

经过筛选后,预计保留 200-300 只有效 ETF,覆盖以下主要板块:

四、因子系统

1. 因子类型

A. 动量因子 MomentumFactor

参数 默认值 说明
------------- --- -------------
window\_short 20 短期收益率(约 1 个月)
window\_mid 60 中期收益率(约 3 个月)
window\_long 120 长期收益率(约 6 个月)
window\_250 250 年化收益率

计算方式:

def calculate(self, universe, date):
    for etf in universe:
        df = etf.get_history(end_date=date, window=max_windows)
        etf['ret_20'] = df['close'].pct_change(20).iloc[-1]
        etf['ret_60'] = df['close'].pct_change(60).iloc[-1]
        etf['ret_120'] = df['close'].pct_change(120).iloc[-1]
        etf['ret_250'] = (df['close'].iloc[-1] / df['close'].iloc[-250] - 1)
    return universe

B. 量价因子 VolumeFactor

参数 默认值 说明
---------------- --- -------
vol\_window 20 量比计算窗口
turnover\_window 20 换手率计算窗口

核心指标:

C. 质量因子 QualityFactor

参数 默认值 说明
----------- --- -------
vol\_window 60 波动率计算窗口
dd\_window 252 回撤计算窗口

核心指标:

D. 折溢价因子 PremiumFactor

数据源 说明
-------------------- ----------
ETFPremiumCalculator 已实现的折溢价计算器

核心指标:

2. 因子矩阵

每日输出一个 (N_etfs, N_factors) 的因子矩阵 DataFrame:fund_code ret_20 ret_60 ret_120 ret_250 vol_ratio turnover volatility max_dd sharpe calmar premium

每行代表一只 ETF 在当前日期的所有因子值。

五、评分与排名

1. 因子标准化

在截面(横截面)上对每个因子做标准化处理,消除量纲差异:

方法 公式 适用场景
-------- ---------------- ------------
Z-Score (x - mean) / std 因子值近似正态分布
Rank Pct rank(x) / N 所有因子通用,鲁棒性好
Sigmoid 1 / (1 + e^-z) 需要压缩到 0-1 区间

推荐默认使用 Rank Pct 标准化,不依赖分布假设,对极端值不敏感。

2. 综合评分

multi_factor_score = (
    w1 * momentum_score +
    w2 * volume_score +
    w3 * quality_score +
    w4 * premium_score
)

其中 momentum\_score 由多个窗口的动量因子合成:

momentum_score = (
    0.4 * ret_20_rank +
    0.3 * ret_60_rank +
    0.2 * ret_120_rank +
    0.1 * ret_250_rank
)

3. 默认权重参考

大类因子 默认权重 说明
-------- ---- -----------
Momentum 0.50 动量是最核心的选基因子
Volume 0.20 成交量验证动量有效性
Quality 0.20 控制风险
Premium 0.10 折溢价辅助信号

4. 截面排名

按综合评分降序排列,输出全市场排名。

六、选择与权重分配

1. TopN 精选策略

策略 说明
---------------- -----------------------
Top10 等权 选取排名前 10 的 ETF,均分权重
Top10 评分加权 按评分比例分配权重
Top5 + Top5 不同权重 前 5 名重仓,6-10 名轻仓
阈值截断 评分 > 某个阈值则入选(可能多于 10 只)

2. 调仓规则

规则 说明
---- ----------------------
固定周期 每日/每周/每月调仓,简单可控
阈值触发 组合偏离度 > 5% 时调仓
成分变动 排名跌出前 15 或被新 ETF 取代时调仓

3. 与现有 StrategyAllocationManager 的关系

ETFSelectionEngine 输出:
    [('510880', 0.20), ('513180', 0.15), ('159941', 0.15), ...]

动态注入 StrategyAllocationManager:
    allocation_manager.add_strategy_to_board(
        TimingStrategy(code='510880'),
        ['510880'],
        weight=0.20
    )

两种模式:

七、截面回测框架

1. 与传统回测的区别

维度 传统择时回测 截面选基回测
-- ----------------- ---------------------
数据 单品种时间序列 多品种每日截面
信号 signal / position rank / selected\_list
交易 买卖点 调仓(买入新入选 + 卖出落选)
费用 单边手续费 双边手续费 + 滑点
基准 买入持有 等权全市场 / 基准指数

2. 回测流程

class CrossSectionalBacktester:
    def __init__(self, selector, universe_history, rebalance_freq='weekly'):
        self.selector = selector      # ETFSelector 实例
        self.universe = universe_history  # 多品种历史数据字典
        self.freq = rebalance_freq

    def run(self, start_date, end_date):
        # 逐日推进,在调仓日执行 select()
        # 记录持仓变化,计算每日组合收益
        # 输出:每日持仓明细 + 组合净值曲线

    def calculate_metrics(self):
        # 年化收益、最大回撤、夏普、换手率

3. 评估指标

指标 说明
----- ---------------------
年化收益率 组合 vs 基准
最大回撤 组合 vs 基准
信息比率 超额收益 / 跟踪误差
换手率 平均每期调仓比例(越低越好)
胜率 调仓后跑赢基准的比例
平均持仓数 每期持有的 ETF 数量
行业集中度 持仓的行业分布 Herfindahl 指数

八、与现有系统的集成方案

1. 代码目录结构

adata/aohan/quant/
├── selection/                        # 新增:选基引擎
│   ├── __init__.py
│   ├── engine.py                     # ETFSelectionEngine 主入口
│   ├── selector/
│   │   ├── base.py                   # ETFSelector 抽象基类
│   │   ├── momentum_selector.py      # 纯动量选基
│   │   └── multi_factor_selector.py  # 多因子选基
│   ├── factor/
│   │   ├── base.py                   # Factor 抽象基类
│   │   ├── momentum_factor.py        # 动量因子
│   │   ├── volume_factor.py          # 量价因子
│   │   ├── quality_factor.py         # 质量因子
│   │   └── premium_factor.py         # 折溢价因子
│   ├── universe/
│   │   └── etf_pool.py              # ETF 池管理 + 筛选
│   └── backtest/
│       └── cross_section_backtester.py  # 截面回测框架
├── backtest/
│   └── strategy/                     # 已有:策略(无变化)
├── chart_test/
│   ├── show_marker.py                # 已有:扩展支持选基模式
│   └── allocation_utils.py           # 已有:扩展动态品种
└── utils/
    └── df_loader.py                  # 已有:无变化

2. 集成方式

3. 依赖关系

show_marker.py
    └── MarketAnalysis
            └── ETFSelectionEngine (new)
                    ├── etf_pool.py (new) → adata.fund.info
                    ├── multi_factor_selector.py (new)
                    │       └── Factor 子类 (new)
                    └── cross_section_backtester.py (new)

StrategyAllocationManager (existing)
    └── 新增: update_board(code, weight) 动态更新品种配置

九、能力边界

1. 负责什么

2. 不负责什么

十、分阶段实施路线

第一阶段:MVP 核心链路

任务 预估工时
------------------------------------------------- -----
etf\_pool.py:ETF 列表获取 + 筛选逻辑 1 天
base.py:ETFSelector 抽象基类 + MultiFactorETFSelector 0.5 天
momentum\_factor.py + volume\_factor.py:动量因子 1 天
engine.py:ETFSelectionEngine 主流程 1 天
纯选基模式回测:固定调仓频率 1 天

可交付物:每日输出 Top10 精选 ETF 列表 + 权重

第二阶段:回测与调优

任务 预估工时
--------------------------------------- -----
cross\_section\_backtester.py:完整回测框架 2 天
quality\_factor.py + premium\_factor.py 1 天
因子权重调优(网格搜索或随机搜索) 1 天
集成到 StrategyAllocationManager 0.5 天

可交付物:选基策略回测报告 + 参数调优

第三阶段:生产运行

任务 预估工时
------------------------------ -----
show\_marker.py 选基入口 0.5 天
定时任务集成 0.5 天
消息推送(Server酱) 0.5 天
并行拉取性能优化(asyncio / ThreadPool) 1 天

可交付物:每日自动推送选基结果

十一、风险点与待确认

1. 数据风险

2. 策略风险

3. 待确认事项

十二、最终总结

***

十三、MVP 实现代码使用指南

代码目录结构

adata/aohan/quant/selection/                # 选基引擎根目录
├── __init__.py
├── engine.py                               # ETFSelectionEngine 主引擎
├── run_selection.py                        # 命令行运行入口
├── quick_test.py                           # 快速验证脚本
├── universe/
│   └── etf_pool.py                         # 精选 ETF 池(73只 × 7大类)
├── factor/
│   ├── __init__.py
│   ├── base.py                             # Factor 抽象基类(含 normalize)
│   ├── momentum_factor.py                  # 动量因子(20/60/120日收益率)
│   ├── volume_factor.py                    # 量价因子(量比 + 量价确认)
│   ├── quality_factor.py                   # 质量因子(夏普比率)
│   ├── mean_reversion_factor.py            # 反追高因子(RSI超买回避 + 波动率稳定)
│   └── regime.py                           # 市场状态识别(牛/熊/震荡/高波动)
├── selector/
│   ├── __init__.py
│   ├── base.py                             # ETFSelector 抽象基类
│   └── multi_factor_selector.py            # 多因子选基 + 纯动量 + 全池等权
└── backtest/
    ├── __init__.py
    ├── cross_section_backtester.py          # 截面回测框架(净值/回撤/夏普)
    └── historical_backtest.py              # 三策略对比回测入口

三种选基模式

模式 因子 权重 默认 适用场景
------------------------------------ ---------------------------------------------------------- ----------- :----: ------------
MultiFactorETFSelector.defensive() Momentum(60/120) + Sharpe + OverboughtAvoid + VolStability 25:15:35:25 默认 防御型,反追高,穿越牛熊
MultiFactorETFSelector.default() Momentum(20/60/120) + Sharpe + VolPriceConfirm 50:30:20 - 纯趋势跟踪,单边牛市
AllETFSelector() - - - 等权持有全池,对比基准

defensive 模式特点:

运行方式

1. Shell 脚本(推荐)

# 拉数据 + 选基 + 评分排名
./run_selection.sh

# 指定日期
./run_selection.sh -d 2025-01-15

# 回测模式
./run_selection.sh -b

# 跳过数据拉取(使用缓存)
./run_selection.sh -s

2. Python 模块

# 选基模式
PYTHONPATH=$(pwd) .venv/bin/python -m adata.aohan.quant.selection.run_selection select

# 回测模式
PYTHONPATH=$(pwd) .venv/bin/python -m adata.aohan.quant.selection.run_selection backtest --start 2024-01-01

# 历史回测对比(防御型 vs 纯动量 vs 等权持有 vs 沪深300)
PYTHONPATH=$(pwd) .venv/bin/python adata/aohan/quant/selection/backtest/historical_backtest.py

# 快速验证
PYTHONPATH=$(pwd) .venv/bin/python adata/aohan/quant/selection/quick_test.py

3. 编程调用

from adata.aohan.quant.selection.engine import ETFSelectionEngine
from adata.aohan.quant.selection.selector.multi_factor_selector import MultiFactorETFSelector
from adata.aohan.quant.selection.backtest.cross_section_backtester import CrossSectionalBacktester

# 默认防御型
engine = ETFSelectionEngine()

# 或用纯动量模式
engine = ETFSelectionEngine(selector=MultiFactorETFSelector.default())

# 拉取数据
engine.fetch_all_data(years_back=2)

# 选基评分
top_codes, ranked, result_df = engine.run_selection(top_n=10)

# 获取权重配置
portfolio = engine.get_portfolio(top_n=10, weight_method='score_weighted')

# 生成推送消息
msg = engine.generate_push_message()

# 回测
bt = CrossSectionalBacktester(engine, rebalance_freq='weekly')
results, metrics = bt.run(start_date='2024-01-01', end_date='2026-05-12', top_n=8)

4. 推送集成

运行 ./run_push.sh(不加 -c)时,截面引擎自动运行并插入推送消息最顶部。

消息推送.txt 结构:
  📊 截面选基策略引擎          ← 新增!全市场扫描
     📈 市场状态(牛/熊/震荡)
     🔥 TOP 10 推荐 + 仓位分级
     🧊 BOTTOM 10 回避品种
     📋 评分加权配置方案(含缩舱后的实际比例)
     📈 风格信号
     💡 操作建议
  ──────────────────────────
  📈 原有择时策略结果          ← 保持不变
     各品种的多策略回测...

使用 ./run_push.sh -c 399102.SZ 指定代码时,截面引擎自动跳过,只跑择时策略。

输出字段解读

📈 市场状态: 🟢 强势牛市           ← 市场处于什么阶段
   价格vs年线: +8.5%               ← 价格相对200日均线的偏离度
   波动率比: 0.85x                 ← 当前波动率/历史波动率比,>1.5为高波动预警
   建议总仓位上限: 95%             ← RegimeDetector计算的安全仓位上限

🔥 TOP 10 最强品种
  #1 512480.SH 半导体ETF  评分:0.911  行业主题  ● 重仓
  #2 588000.SH  科创50ETF  评分:0.880  宽基指数  ● 重仓
    ...
   评分 ≥ 0.85 = ● 重仓
   评分 ≥ 0.70 = ○ 中仓
   评分 < 0.70 = ◑ 轻仓
   熊市/高波动时评分<0.6 显示"观望"

📋 Top 10 配置方案 (总仓位上限 95%)   ← RegimeDetector算出的总仓位上限
  代码        名称      评分    配置比例    缩减后
  512480.SH  半导体ETF  0.911  11.1%    10.5% (中仓)
  ↑                                   ↑ 配置比例 × 仓位上限 = 实际建议

💡 操作建议
  ▶ 当前强势牛市,仓位上限 95%,积极参与强势板块
  ▶ 注意回避:REITs 3只垫底 Bottom 10

新增模块说明

1. RegimeDetector

市场状态识别器,基于沪深300指数的三个指标:

输出:BULL / MILD_BULL / RANGING / HIGH_VOL / BEAR / SEVERE_BEAR 六种状态

2. OverboughtAvoidFactor

RSI 超买回避因子:

3. VolatilityStabilityFactor

波动率稳定性因子:60日波动窗口内计算 Sharpe Ratio 和稳定度,低波动高夏普的品种评分更高。

4. AllETFSelector

等权持有全池的 selector,用作对比基准,调仓时维持全池等权。

回测调仓机制

回测框架 CrossSectionalBacktester 按固定频率调仓,模拟真实交易执行。

调仓频率

频率 参数 触发日 说明
--------- -- ------- ------------------------------
weekly 默认 每个周五收盘后 每周最后一个交易日执行一次 All in / All out
daily - 每个交易日 高频调仓,但换手率高
monthly - 每月第一个周五 低频但反应慢

每轮调仓执行流程

第 N 个周五收盘后:
  1. build_snapshot(date)                        → 取当日所有 ETF 的最近 250 日数据
  2. RegimeDetector.detect(沪深300数据)           → 判断 BULL/MILD_BULL/RANGING/BEAR/...
  3. selector.select(snapshot, top_n, regime)    → 算出当日 TopN 品种
  4. 计算调仓区间收益:
     持仓组合收益 = mean(每只持仓ETF (本周五close - 上周五close) / 上周五close)
     基准收益     = (沪深300本周五close - 上周五close) / 上周五close
     等权池收益   = mean(全池每只ETF同样公式)
  5. 更新净值: NAV = NAV * (1 + 持仓组合收益)
  6. 卖出旧持仓 + 买入新持仓(交易成本暂忽略)
  7. 记录: turnover = (新入选+被移除) / (2×top_n)

换手率含义

从你看到的输出:

2026-04-10: turnover=0.3  → 3只换出, 3只换入, 10只持仓, (3+3)/(2×10)=0.3
2026-05-08: turnover=0.1  → 1只调出, 1只调入, 很稳定
2026-04-24: turnover=0.4  → 4只换出, 4只换入, 风格切换较大

防御型平均换手率 28.86%,大概每周换 3 只;纯动量 36.79%,每周换 \~4 只。

交易规则

详细调仓日志

运行回测时加 verbose=True 会输出每期调仓明细:

  日期             Regime             ↕换手率        组合NAV        基准NAV  持仓
  ------------------------------------------------------------------------------------------
  2021-01-08     BULL              0.0%     1026450     1053717  [510300.SH, 511260.SH, 512100.SH ... +1]
  2021-06-04     MILD_BULL        43.8%     1032592     1001513  [159915.SZ, 159928.SZ, 511260.SH ... +3]
  2021-07-02     RANGING          12.5%      852891      967089  [...]
  2022-10-28     SEVERE_BEAR       6.2%      760700      783276  [511260.SH, 518880.SH, 159941.SZ ...]

Regime 列表示当期市场状态,换手率表示调仓比例,NAV 是策略净值,基准NAV 是沪深300净值。通过这个日志可以观察到熊市中 Regime 从 BULL → RANGING → BEAR 的转换过程,以及策略如何降低换手率和调整持仓方向。

回测结果(双区间:熊市 2021-2023 + 牛市 2024-2026)

使用 tushare 真实数据接口,基于 73 只场内 ETF 池,每周五收盘后调仓,等权持有 Top8 品种。

熊市区间:2021-01 \~ 2023-12(沪深300 下跌约 34%)

指标 防御型选基 纯动量选基 等权全池 沪深300(买入持有)
---------- :---------: :---------: :-----: :---------:
总收益率 -20.82% -25.63% -24.05% -33.82%
年化收益率 -7.49% -9.53% -8.85% -13.27%
最大回撤 -37.15% -37.17% -35.47% -37.17%
超额收益(vs基准) +13.00% +8.18% +9.77% -
夏普比率 -0.09 -0.14 -0.05 -
调仓期胜率 47.03% 47.03% 50.00% -
平均换手率 19.87% 25.98% - -

牛市区间:2024-01 \~ 2026-05(沪深300 上涨约 42%)

指标 防御型选基 纯动量选基 等权全池 沪深300(买入持有)
---------- :-----: :---------: :-----: :---------:
总收益率 +38.85% +56.33% +52.25% +41.84%
年化收益率 +14.91% +20.83% +19.48% +15.95%
最大回撤 -13.17% -11.27% -9.55% -12.19%
超额收益(vs基准) -2.99% +14.49% +10.41% -
夏普比率 0.30 0.34 1.21 -
调仓期胜率 56.56% 57.38% 57.14% -
平均换手率 29.88% 35.77% - -

双区间对比汇总

指标 熊市(2021-23) 牛市(2024-26)
------- :---------: :---------:
防御型总收益率 -20.82% +38.85%
防御型年化 -7.49% +14.91%
防御型最大回撤 -37.15% -13.17%
防御型超额收益 +13.00% -2.99%
沪深300基准 -33.82% +41.84%
纯动量总收益率 -25.63% +56.33%
纯动量超额收益 +8.18% +14.49%

核心结论

          ┌────────────────────────────────────────────┐
          │  策略选择 = f(市场状态)                      │
          │                                            │
          │  熊市(2021)  防御型 -> -20% (基准则 -34%)   │
          │  牛市(2024)  动量型 -> +56% (基准则 +42%)   │
          │  震荡市      防御型 -> 动量衰减时抗跌        │
          └────────────────────────────────────────────┘

***

十四、评分机制深度解析 & 当前已知问题

一、"强势"的定义:多因子加权综合评分,不是单纯涨跌幅

选基引擎的"强势"不是简单的「谁涨得多谁排前面」,而是四个独立因子做 Rank 标准化后加权求和。

防御型(当前默认)因子构成

综合评分 = 0.25 × momentum_score
         + 0.15 × sharpe_score
         + 0.35 × overbought_avoid_score
         + 0.25 × volatility_stability_score
因子 权重 计算方式 倾向
------------------ :-----: ----------------------------- -------------
momentum 25% 最近60日+120日的绝对收益率,Rank Pct 标准化 涨幅大的分高
sharpe 15% 近60日年化收益率 / 年化波动率 性价比高的分高
overbought_avoid 35% RSI超买 + 短期暴涨 → 低分;跌幅大 → 高分 惩罚上涨,奖励超跌
vol_stability 25% 近60日夏普+趋势稳定性 低波动稳定品种分高

排行榜单里的每一位是怎么算出来的

以你看的那一期为例,以 511010.SH(国债ETF) 排第6名为例,逐因子解构:

511010.SH(国债ETF):
  momentum (25%)   = 近半年涨了约 +2~3%,Rank 约 0.35  → 大部分股票涨幅比它大
  sharpe (15%)      = 涨幅虽小但标准差极低,Sharpe ≈ 1.8  → Rank 约 0.95
  overbought (35%)  = RSI~50,绝对没超买                     → 得分 0.6(中性)
  vol_stability (25%)= 波动率接近0,稳定性极高                  → 得分 0.95

  综合 = 0.25×0.35 + 0.15×0.95 + 0.35×0.6 + 0.25×0.95 = 0.694

与此同时,512480.SH(半导体ETF) 可能:

512480.SH(半导体ETF):
  momentum (25%)   = 近半年涨了 +30%+                         → Rank 0.95
  sharpe (15%)      = 高收益但高波动,Sharpe 约 0.6              → Rank 0.6
  overbought (35%)  = RSI~72 + 涨幅>25%                      → 得分 0.0(强烈回避!)
  vol_stability (25%)= 波动率是国债50倍                           → 得分 0.3

  综合 = 0.25×0.95 + 0.15×0.6 + 0.35×0.0 + 0.25×0.3 = 0.403

结论:半导体在 OverboughtAvoid 上被完全打成了 0 分,因为这个因子占权重的 35%,它专门把涨太多的品种踢下去。国债反而因为"没超买"获得了高分。

为什么会变成这样

这其实是设计上的一个平衡问题。当前防御型策略里,有两个因子各占超过 20%——OverboughtAvoid(35%) 和 VolStability(25%),合起来 60% 的权重都在"防御"上而不是"选强"上。

在牛市中,这就产生了矛盾——防御型策略看到涨多了的品种就降分,看到低波动的防御品种就加分,结果就是把国债推到了排行榜前面。

这个行为在熊市里是对的(熊市确实该持国债),但在当前温和牛市里属于"过度防御"。 RegimeDetector 已经识别出当前是 MILD\_BULL 并切换到中性权重,但 OverboughtAvoid 的权重仍然是 25%,对牛市品种的杀伤力依然不小。

现状不是 Bug,是防御型在当前市场状态下的自然表现——它认为追高风险 > 踏空风险,所以选择了更安全的品种。

> 已修复:_get_regime_weights 新增 BULL 分支。当前市场为牛市/温和牛市时,权重自动切换为 45:25:10:20(动量45%, Sharpe25%, 反追高10%, 稳定性20%),OverboughtAvoid 权重从 35% 降至 10%,极大减少国债上榜概率。震荡市保持 30:20:25:25,熊市/高波为 15:5:35:45。

二、选基时机问题:信号是滞后还是领先?

当前全部是滞后指标

Momentum、Sharpe、RSI、Volatility——所有这些因子的输入都来自于已经发生的历史价格数据。引擎并没有任何"预测"能力,它做的事情是:

观察过去60~180天的价格走势 → 归类哪些品种"历史表现好" → 下注这些品种会继续好

这个逻辑叫"动量延续"假设,在学术界有充分支撑(Jegadeesh and Titman, 1993; Moskowitz et al., 2012),但问题也很清楚:

什么时候会"高位站岗"

用 2021 年的数据来模拟:2021 年 2 月(核心资产见顶前),动量因子会把消费、医药推到最前面。但 A 股从 2021 年 2 月到 2022 年 10 月跌了 2 年,期间动量策略会不断在"高点买入 → 新低止损 → 再买下一个反弹高点 → 再止损"中反复亏损。

这就是为什么防御型策略必需存在——OverboughtAvoid 和 VolStability 的存在不是为了选强,而是为了在动量崩溃前降低"追高"品种的仓位。

但这也带来了代价:防御型对真正的牛市突破反应迟钝。2024 年 9 月的 A 股暴力反弹中,防御型的反追高因子把初涨品种全部降权,错过了最早的一波收益。

解法:从「涨了多少」升级为「涨得怎么样」

高位站岗的根因不是「动量因子本身有问题」,而是我们用来衡量动量的维度太单一了。当前的 momentum 因子只看一件事:

momentum = (当前价格 - 60天前价格) / 60天前价格   ← 只问了"涨了多少"

学术研究和实战经验表明,应该同时问三个问题:

维度 问题 高位站岗时的表现 真牛市突破时的表现
------------:---::---:
涨了多少 (magnitude) 过去N天涨了多少? 涨幅大 涨幅大
涨得稳不稳 (quality) 上涨过程中回撤小吗?涨跌日比例如何? 波动大,经常大阴线 稳步推升,阴线小
涨了多久 (age) 这波趋势已经走了多久?是否接近尾声? 趋势已经走了6个月+ 刚开始2-4周

高位站岗的品种通常是「涨幅大 + 波动剧烈 + 趋势已老」,而真正值得追的品种是「涨幅开始放大 + 波动收敛 + 趋势年轻」。

解决方案矩阵

以下五种解法按实现成本从低到高排列,各自独立可叠加:

##### 解法 A:趋势年龄衰减(最轻量,0.3天)

原理:动量因子按趋势持续时间做衰减。趋势越老,动量得分越低。

young_trend_bonus = 1.0                              # 趋势 < 4 周:全额动量
middle_trend       = 0.8                              # 趋势 4~8 周:八折
old_trend_penalty  = 0.5                              # 趋势 > 12 周:五折
final_momentum = raw_momentum × age_factor

判断趋势年龄的方式:记录该 ETF 的收盘价首次突破 60 日均线的时间,计算距今的周数。年龄越大 → 衰减越重 → 高位站岗的概率越低。

##### 解法 B:趋势质量过滤(推荐首实现)

原理:用 R²(线性拟合度)衡量过去N天的上涨是否为「稳步推升」而非「剧烈震荡后偶然收高」。

trend_quality = R²(close[t-N:t] 对 时间轴做线性回归)
smoothed_momentum = raw_momentum × max(trend_quality, 0.3)
场景 raw_momentum trend_quality 最终得分
------:---::---::---:
稳步推升型 0.8 0.95 0.76
高位剧烈震荡型 0.8 0.35 0.28 ← 被大幅降权

实现简单——numpy 的 np.polyfit 一行即可计算 R²。半导体 ETF 在 2021 年 7 月(高位剧烈震荡)的 R² 约为 0.3~0.4,而 2024 年 2 月(牛市初期稳步推升)的 R² 约为 0.85+。

##### 解法 C:距高点回撤惩罚

原理:如果该 ETF 当前价格比 120 日最高点回撤超过 15%,说明动量信号是「反弹」而非「趋势」,应当降权。

drawdown_from_peak = (当前价 - 120日最高价) / 120日最高价
dd_penalty = 1.0  if drawdown_from_peak > -5%   else   # 接近新高,正常
             0.7  if drawdown_from_peak > -15%  else   # 回撤中,谨慎
             0.3                                      # 深度回撤,忽略动量
final_momentum = raw_momentum × dd_penalty

这解决了「追反弹高位站岗」的问题——2022 年熊市中反复反弹的品种,距高点回撤都超过 -15%,会被大幅降权。

##### 解法 D:涨跌日比例确认

原理:计算过去 N 个交易日中阳线占比。真正的牛市趋势中阳线占比通常 > 55%,而高位震荡中阳线占比接近 50%。

up_day_ratio = count(close > open) / N
up_day_bonus = clip(up_day_ratio / 0.55, 0.5, 1.2)   # 低于 55% 阳线率降权

这是最简单的趋势质量 proxy,不依赖任何统计模型。

##### 解法 E:多周期动量背离检测(最深度)

原理:当短期动量(20日)极高但中期动量(60日)已经在减速时,这是经典的动量背离信号——往往是趋势末期的特征。

M20 = 20日动量
M60 = 60日动量
M120 = 120日动量

if M20 > 0.95 and M60 < 0.5:      # 短期暴涨但中期已经在减速
    danger_signal = True
    momentum_score *= 0.3          # 大幅降权,因为这是"末路狂奔"

这对应的是 2021 年春节前核心资产冲顶的特征:20 日动量排名极高(最后一波冲刺),但 60 日动量已经从前 3 名滑到前 10 名。

推荐实施路线

第一阶段(立即,约 1 天):
  实现 解法 B(趋势质量 R²) + 解法 C(距高点回撤惩罚)
  → 两种解法互补:B 看走势形态,C 看绝对位置
  → 预期效果:高位站岗概率降低 50%+

第二阶段(后续):
  实现 解法 A(趋势年龄衰减)
  → 配合 SignalTracker 的 streak 数据,天然适配

第三阶段(研究级):
  实现 解法 E(多周期动量背离)
  → 需要历史回测验证参数,作为长期优化方向

> 实现状态:解法 B(趋势质量 R²)+ 解法 C(距高点回撤惩罚)已合入 MomentumFactor,通过 use_trend_quality=True 和 use_drawdown_penalty=True 启用。defensive/adaptive 模式默认开启。详见下方「实现记录」。

实现记录:趋势质量动量因子

已完成:MomentumFactor 新增两个参数,在计算原始动量收益率后自动乘以趋势质量乘数和回撤惩罚因子。

final_momentum = raw_momentum × max(trend_r_squared, 0.3) × drawdown_penalty

> 通俗解释:动量乘数永远 ≤ 1.0,越接近 1.0 说明趋势越健康、动量被保留得越多。×0.8 =「稳步上涨,动量留八成」;×0.3 =「走势震荡,扣掉七成」;×0.09 =「高位烂趋势,几乎全扣」。这个乘数只打折不加杠杆——它防止追高,不会错杀真趋势。

实测效果(2026-05-24,73 只 ETF 截面):

品种 旧 rank 新 rank 变化 原因
------:---::---::---:------
508000.SH 张江REIT 0.222 0.067 ↓ 0.156 震荡盘整,R² 接近 0
515060.SH 房地产 0.156 0.022 ↓ 0.133 距高点回撤 > 15%
511010.SH 国债 0.533 0.622 ↑ 0.089 趋势极其稳定,R² ≈ 0.95
563000.SH A500 0.756 0.844 ↑ 0.089 稳步推升,R² 高

> 正常现象说明:国债因 R² 极高会在动量排名中上升,但其综合评分仍会被 OverboughtAvoid(反追高)拉回——趋势质量过滤主要影响的是「震荡型品种被错误归类为动量强势」的场景,而非「低波动品种排名过高」的问题(后者由因子权重和 RegimeDetector 负责)。

在选基流水线中的位置

趋势质量过滤不是一个新的独立因子,而是在 MomentumFactor 内部对原始动量值做乘数修正,发生在因子标准化之前。

完整选基流水线 (每个调仓日执行一次)
═══════════════════════════════════════════════════════════════

 45只ETF日K数据
      │
      ├─→ MomentumFactor.calculate()
      │       │
      │       ├─ 1. 计算60日+120日加权收益率 = raw_momentum
      │       ├─ 2. ★ use_trend_quality?  → R² = 60日线性回归拟合度
      │       │      raw_momentum ×= max(R², 0.3)
      │       │      (R²<0.3 的震荡品种被打三折)
      │       └─ 3. ★ use_drawdown_penalty?  → dd_penalty
      │              raw_momentum ×= dd_penalty
      │              (距高点回撤<-15% 打三折,-5%~-15%打七折)
      │       └─→ 输出: filtered_momentum  ← 已经是过滤后的值
      │
      ├─→ SharpeFactor.calculate()        → 夏普比率
      ├─→ OverboughtAvoidFactor.calculate() → RSI超买回避
      └─→ VolatilityStabilityFactor.calculate() → 波动稳定性
              │
              ▼
      4因子 Rank 标准化 (0~1)
              │
              ▼
      RegimeDetector 检测市场状态 (BULL/MILD_BULL/RANGING/BEAR...)
              │
              ▼
      AdaptiveWeightEngine 计算各因子权重
      (BULL→动量45%  熊市→动量15%)
              │
              ▼
      综合评分 = Σ(因子分 × 权重)
              │
              ▼
      Top N 截面选基 + SignalTracker 时效标记
              │
              ▼
      推送消息输出

▶ 在线查看完整流程图

✏️ 编辑流程图

直观对比

                   纯动量策略                       防御型策略
                 ┌──────────┐                  ┌──────────┐
牛市(2024)        │  +56%    │                  │  +39%    │
                 │ 追得猛    │                  │ 部分踏空  │
                 └──────────┘                  └──────────┘
                      │                              │
熊市(2021)        ┌──┴───────┐                  ┌──┴───────┐
                 │  -26%    │                  │  -21%    │
                 │ 追高挨打  │                  │ 回撤更小  │
                 └──────────┘                  └──────────┘

三、不同板块之间的调仓是怎么调的

调仓规则非常简单:每周五收盘后,根据当日全部 ETF 的截面评分重新排名,取 Top N,全部替换。

上周五持仓: [半导体, 科创50, 创业板, 纳指, 煤炭, 红利, 国债, A500]
本周五评分: [半导体 0.95, 纳指 0.85, 创新药 0.78, ... 国债 0.69, ... 红利 0.32]

→ 卖出: 科创50(掉出Top8) + 创业板(掉出) + 煤炭(掉出) + 红利(掉出) + A500(掉出)
→ 买入: 创新药(新进) + 新能源(新进) + ...

本周五新持仓: [半导体, 纳指, 创新药, 新能源, 碳中和, 黄金, 国债, 军工]

这意味着:

四、已知局限 & 后续迭代路线

V1 现状(已实现)

V2 待实现(评级:高优先级)

任务 说明 预估
---------------------------------------------- ------------------------------------------------------------------------------------------------------- ----
✅ 因子动态权重 ~~牛市自动切换为动量主导权重(50%+),熊市保持防御权重~~ 已实现 _get_regime_weights 离散切换 + AdaptiveWeightEngine 自适应融合 ✅
✅ OverboughtAvoid 牛市减重 ~~牛市应将 OverboughtAvoid 降至 10%,动量提到 40%~~ 已实现 BULL:45:25:10:20 ✅
类债券品种排除开关 给 defensive() 增加 exclude\_bonds 参数,牛市模式自动排除国债/国开债,让选基在权益品种内做排名 0.5天
✅ 品种相关性约束 ~~Herfindahl 集中度 + 同指数去重~~ 已实现 DiversificationFilter(同指数去重 + 类别上限 ≤4只/类),自动集成到 engine/backtester ✅
交易成本 & 滑点模型 回测引入 ETF 手续费(万 0.5)+ 冲击成本(日均成交额的 1% 作为上限),让牛熊对比更真实 1天
分阶段回测 除 2021-2023 / 2024-2026 外,增加更多时间切片:2018熊市、2020疫情暴跌-反弹、2022单边下跌,验证策略稳定性 0.5天
🆕 SharpeFactor 计算公式修正 当前 total_return / (daily_std * sqrt(n/252)) 不标准,应改为标准公式 mean_return / std * sqrt(252)。这会系统性改变夏普因子排序 0.5天
✅ DataFetcher 并行化 ~~串行改并行~~ 已实现 ThreadPoolExecutor(max_workers=6),16 只 ETF 从 6.7s→1.3s,5.3x 加速 ✅
🆕 补齐动量因子 250 日窗口 defensive/adaptive 模式只有 60/120 日动量,缺少 250 日(年化)窗口。长周期动量对区分「短期反弹」和「趋势反转」至关重要 0.5天
🆕 本地数据缓存层 引入 DataCache 类,API 拉取结果存为 Parquet。回测直接读本地,只在需要最新交易日数据时拉增量。避免每次重跑回测都从 tushare 拉数 1天
🆕 weight\_engine as\_factor\_weights 映射修复 当前 volume→momentum、vol_price_conf→overbought_avoid 为错误映射。应改为从 factor.name 精确匹配 0.5天

V3 研究级方向(评级:中等优先级)

方向 说明
-------------------------------------------------- -----------------------------------------------------------------------------------------------------------------------------------
引入领先指标 用资金流(北向资金、融资余额变化)代替价格动量做先行选基,捕捉爆发前迹象而非爆发后追入
事件驱动截面 政策、业绩预告、行业轮动日历效应——如每年四季度倾向买消费,一季度买科技
多周期动量合成 同时考察 5日/10日/20日/60日/120日动量,短周期权重高时表示"动能强劲初期",长周期权重高时表示"趋势确立后期"
行业中性化 对每个 ETF 的因子值做行业(大类)去均值处理,消除"当前热的是整个行业而非该 ETF"的噪声
极致中性 vs 极致动量 双翼策略 同时持有两个子组合:50%仓位用动量选 Top 5 科技成长类,50%仓位用低波动选 Top 5 防御类,按 Regime 动态调节比例
引入 XGBoost/LightGBM 用机器学习做因子合成——当前是人工定权重,ML 可以从历史数据中学到最优因子权重和交互效应
🆕 ETF 池全市场动态化 从当前 48 只静态手选池升级为从 adata.fund.info.all_etf_exchange_traded_info 动态拉取全市场 1000+ ETF,经流动性筛选(上市>60天、日均成交>500万)后自动生成候选池。确保新上市 ETF 不会被遗漏
🆕 PremiumFactor 折溢价因子 设计方案中规划但未实现的因子。跨境 ETF 在 A 股交易时段折溢价可达 10%+,缺失该因子会在极端行情下推荐高溢价品种。需要先接入 IOPV 数据源(akshare 可能有)
🆕 VolatilityStabilityFactor 改用 Sortino/Calmar 当前公式 (stability×2 + sharpe×0.5)/3 中两个子项高度相关(分母相同),缺乏理论依据。改用 Sortino Ratio(只惩罚下行波动)或 Calmar Ratio(年化收益/最大回撤)更合理
🆕 RegimeDetector 多资产基准 当前固定用沪深300(510300.SH)判断全市场状态。但债券 ETF 的状态应由国债收益率曲线判断,商品 ETF 由美元/商品指数判断,跨境 ETF 由对应海外指数判断。不同大类资产应有各自的 Regime 基准
🆕 MomentumFactor 日期对齐 当前用 close[-w-1] 整数索引而非 trade\_date 对齐计算收益率。如数据中存在非交易日缺口,会导致窗口长度不准确。应改为按实际日期窗口计算

***

十五、因子动态权重方案

设计背景

上一节分析了防御型策略在牛市中"过度防御"的问题——OverboughtAvoid(35%)和 VolStability(25%) 合占 60% 权重,导致国债等低波品种霸榜。解决思路不只是调一两个数字,而是构建一套能感知市场状态、平滑调节各因子权重的系统。

四种方案对比

方案 A:离散状态切换 (Discrete Regime Switch) — 已实现

当前 _get_regime_weights 的实现:

状态 momentum sharpe overbought vol\_stability
---------- :------: :----: :--------: :------------:
BULL 45% 25% 10% 20%
MILD\_BULL 30% 20% 25% 25%
RANGING 30% 20% 25% 25%
BEAR 15% 5% 35% 45%

方案 B:波动率自适应 (Volatility-Adaptive)

纯连续调节,不依赖离散状态:

momentum_weight = base_momentum / max(vol_ratio, 0.3)
defense_weight   = 1.0 - momentum_weight - sharpe_weight

方案 C:趋势强度加权 (Trend-Strength Weighted)

用趋势强度作为唯一的连续调节器:

trend_factor = clip(trend_strength × 3, 0.5, 1.5)
momentum_weight = base_momentum × trend_factor

方案 D:自适应融合 (Adaptive Blending) ← 已实现,推荐使用

三层连续融合,取三者之长:

Layer 1 (状态锚点):   base_momentum = regime_lookup[regime]
Layer 2 (波动调节):   vol_factor    = clip(1.0 / max(vol_ratio, 0.3), 0.3, 1.0)
Layer 3 (趋势微调):   trend_factor  = clip(trend_strength × 3.0, 0.5, 1.5)

adjustment = vol_factor × trend_factor      (取值范围 0.15 ~ 1.5)
momentum_weight = base_momentum × adjustment

权重计算示例

BULL,  vol_ratio=0.8, trend=0.25  → adjustment=1.0×0.75=0.75  → momentum=0.55×0.75=0.412  ← 牛市低波强趋势: 激进
BULL,  vol_ratio=1.5, trend=0.10  → adjustment=0.667×0.5=0.333 → momentum=0.55×0.333=0.183 ← 牛市高波弱趋势: 保守(防御)
BEAR,  vol_ratio=1.0, trend=0.05  → adjustment=1.0×0.5=0.5    → momentum=0.15×0.5=0.075   ← 熊市: 几乎不动量
BEAR,  vol_ratio=2.0, trend=0.30  → adjustment=0.5×0.9=0.45   → momentum=0.15×0.45=0.068  ← 高波熊市: 极度保守

与方案 A(离散切换)的关键区别

市场场景 离散切换(A) 自适应融合(D)
---------------- :--------------: :---------------:
BULL + 波动率正常 动量 45% 动量 41%
BULL + 波动率 1.5x 动量 45%(不感知波动) 动量 18%(自动缩仓)
MILD\_BULL + 趋势强 动量 30%(和震荡共用一个档) 动量 30%\~40%(趋势微调)
RANGING + 趋势强 动量 30% 动量 27%\~40%(趋势推动)

核心优势:方案 D 在同状态内可根据波动和趋势做更精细的调节,避免方案 A 的"一刀切"。

代码实现

文件:weight\_engine.py

from adata.aohan.quant.selection.factor.weight_engine import AdaptiveWeightEngine
from adata.aohan.quant.selection.selector.multi_factor_selector import MultiFactorETFSelector

# 使用自适应权重
selector = MultiFactorETFSelector.adaptive()
engine = ETFSelectionEngine(selector=selector)

# 回测时自动启用自适应权重(run 内部调用 selector.select 时传入 regime_info)
bt = CrossSectionalBacktester(engine, rebalance_freq='weekly')
results, metrics = bt.run(start_date='2024-01-01', end_date='2026-05-12', top_n=8)

也可以通过 use_adaptive_weights=True 参数直接从构造函数启用:

selector = MultiFactorETFSelector(
    factors=[MomentumFactor(windows=[60,120], weights=[0.5,0.5]),
             SharpeFactor(), OverboughtAvoidFactor(), VolatilityStabilityFactor()],
    weights=[0.25, 0.15, 0.35, 0.25],
    use_adaptive_weights=True  # 启用自适应
)

待优化超参数

参数 当前值(已调优) 作用 调优方向
-------------------- :------------------: -------------------- -------------------
vol_ratio 下限 0.2 波动率低于0.2倍历史时不再继续放大动量 调优后从0.3降至0.2
trend_factor 上下界 0.6 \~ 1.3 趋势强度的映射范围 调优后收窄到0.6~1.3
各状态的 base_momentum BULL:0.60, BEAR:0.10 状态锚点的绝对动量权重 调优后BULL更激进、BEAR更防御

TODO(短期需处理)

***

十六、信号时效性追踪

问题背景

纯截面选基只看当天的因子排名,无法区分「一只 ETF 是因为真有资金持续加仓所以连续上榜」和「一只 ETF 因为短线爆冲刚好排进前十、下周就掉出」。没有历史维度的追踪,用户面对 TOP 10 榜单时无法判断哪些品种是真正在走趋势、哪些只是偶发性的假突破。

SignalTracker 设计

文件:signal\_tracker.py

核心概念

状态分级

streak 图标 状态名 含义
:-------: :-: ------ ------------------------
1 🆕 新晋 本周首次进入 Top 10,可能是假突破,需观察
2 📈 第2周在榜 连续两周在榜,初步确认不是一日游
3 📈 第3周在榜 接近确认,再持续一周即为强势
≥4 🔥 连续N周强势 趋势确立,主力持续加仓,置信度高
曾上榜→掉出→再进 ⚡ 回榜 轮动快,不够稳定
上周在榜本周掉出 🔻 掉出榜单 信号衰减,建议评估减仓

跨脚本持久化

SignalTracker 不只在内存中运行——每次 record() 后自动保存到本地小数据库文件 signal_streaks_db.json(与 signal\_tracker.py 同目录),下次创建 ETFSelectionEngine 时自动加载。

第1次 push_preview.py → streak=1 (🆕) → save → signal_streaks_db.json
第2次 push_preview.py → load → streak=2 (📈) → save
第3次 push_preview.py → load → streak=3 (📈) → save
第4次 push_preview.py → load → streak=4 (🔥) → save

> 重要:持久化文件按「日期」去重,同一日期多次调用 run_selection() 只会记录一次,避免重复累加。

推送消息输出

📊 信号时效性
------------------------------------------------
  📈 趋势确认(2-3周): 588000(2周), 159941(2周), 563000(2周)
  🔻 本周掉出: 510880, 513050

🔥 TOP 10 最强品种
① 159949.SZ  创业板50ETF  [0.804]  📈 第2周在榜
   宽基指数 · 配置 10.6%
② 512480.SH  半导体ETF    [0.752]  🆕 新晋
   行业主题 · 配置 9.9%
③ 512100.SH  中证1000ETF  [0.687]  🔥 连续4周强势
   宽基指数 · 配置 9.1%

集成方式

ETFSelectionEngine.__init__() 自动创建 SignalTracker()(默认 load_persisted=True),run_selection() 每次选基后自动调用 signal_tracker.record()。用户无需额外操作,每次跑推送脚本自动累积。

# 查看当前状态
engine.signal_tracker.summary()
#  {'streaks': {'512480': 4, '159915': 2}, 'dropouts': ['510880'], ...}

# 手动清空历史重新开始
os.remove(os.path.join(os.path.dirname(__file__), 'signal_streaks_db.json'))

***

固定关注板块 (WATCHLIST)

推送消息中除了 TOP 10 / BOTTOM 10 外,还会固定打印 10 个用户关注的 ETF 的综合评分和操作建议,不论这些 ETF 排名高低。这 10 个板块与择时策略 show_marker.py 中的 codes_to_process 保持一致。

代码 简称 说明
------------------
513180.SH 恒生科技 跨境-港股科技
513330.SH 恒生互联网 跨境-港股互联网
159908.SZ 创业综指 宽基-创业板综
159915.SZ 创业板 宽基-创业板指
159941.SZ 纳指 跨境-纳斯达克100
159937.SZ 黄金 商品-黄金
510210.SH 上证指数 宽基-上证综指
159903.SZ 深证成指 宽基-深证成指
512890.SH 红利低波 策略-红利低波
159201.SZ 自由现金流 策略-自由现金流

> 配置位置:ETFSelectionEngine.__init__() → self.WATCHLIST,修改列表即可增减关注板块。51 前缀的 ETF(如上证/恒生/红利低波)使用 DataFetcher 通过 tushare fund_daily 接口拉取,与 15/16 开头的 ETF 走同一数据通道。

十七、超参数调优方案

1. 为什么要调优

AdaptiveWeightEngine 有 4 个连续超参数和 6 组状态 base weights,在方案 D(自适应融合)中共同决定了最终因子权重分配:

vol_ratio_lower      — 波动率比的裁剪下限(默认 0.3)
vol_factor_lower     — 波动率调节因子的裁剪下限(默认 0.3)
trend_factor_lower   — 趋势强度映射下限(默认 0.5)
trend_factor_upper   — 趋势强度映射上限(默认 1.5)
base_weights         — 6 种市场状态下 momentum/sharpe/overbought/vol_stability 的基础配比

这些超参数当前基于经验设定(参考了学术论文和 A 股历史特征),但并不保证在回测数据上最优。需要通过双区间回测 + 网格搜索来量化评估,找到 Pareto 最优解。

2. 调优策略:三阶段纵贯搜索

Phase 1 — 连续参数粗搜(\~96 组)

目标:在宽范围内确定 vol\_ratio\_lower、vol\_factor\_lower、trend\_factor 上下界的大致最优区间。

vol_ratio_lower    ∈ {0.2, 0.3, 0.4, 0.5}
vol_factor_lower   ∈ {0.2, 0.3, 0.4}
trend_factor_lower ∈ {0.3, 0.4, 0.5, 0.6}
trend_factor_upper ∈ {1.3, 1.5, 1.7, 2.0}

每组参数同时跑熊市(2021-01 \~ 2023-12)和牛市(2024-01 \~ 2026-05)双区间回测,算出综合评分,选 Top 5。

Phase 2 — Base weights 精搜(\~48 组)

目标:在 Phase 1 最佳连续参数基础上,调优三组状态的动量/防御配比。

状态组 变量 含义
----------------------------------- ------------------- -----------
BULL(牛市) momentum 0.45\~0.60 牛市应该给动量多大胆量
MILD\_BULL + RANGING(震荡) momentum 0.25\~0.35 震荡市均衡点在哪
BEAR + HIGH\_VOL + SEVERE\_BEAR(熊市) momentum 0.10\~0.20 熊市防御要多极致

其余三个因子权重(sharpe、overbought\_avoid、vol\_stability)按比例分配剩余权重。

Phase 3 — 最终验证

将最佳参数组合与三个基准策略做最终对比:

基准 含义
----------------------- -------------------------------------------------------------
离散切换(Discrete) 原始 \_get\_regime\_weights 离散查表
默认自适应(Adaptive Default) AdaptiveWeightEngine 当前默认值
纯动量(Momentum) MomentumFactor + SharpeFactor + VolumePriceConfirmationFactor
最佳参数(Best) Phase 1 + 2 找到的最优组合

3. 综合评分公式

单一个指标无法全面衡量策略质量——熊市抗跌和牛市跟随是矛盾目标。使用加权评分:

综合评分 = 
   熊市超额收益 × 25%          ← 熊市跑赢基准的能力(最核心)
  + 牛市总收益率 × 25%         ← 牛市跟得上行情的能力
  + (熊市收益 - 熊市回撤) × 10% ← 熊市的收益-回撤性价比
  + (牛市收益 - 牛市回撤) × 15% ← 牛市的收益-回撤性价比
  + 熊市夏普 × 10%             ← 熊市风险调整后收益
  + 牛市夏普 × 10%             ← 牛市风险调整后收益
  - 平均换手率 × 2.5%          ← 惩罚过度交易(两区间平均)

权重设计的核心思想:

4. 调优脚本

文件:weight\_tuning.py

cd /Users/aohan/PycharmProjects/adata
PYTHONPATH=$(pwd) .venv/bin/python adata/aohan/quant/selection/backtest/weight_tuning.py

运行流程:

总耗时:首次运行约 10\~15 分钟(含数据拉取),缓存后约 3\~5 分钟。

5. 调优结果是否固定

不固定。 调优结果存在两个层面的时效性:

层面 频率 说明
:----------------------- :---------- :-----------------------------------------------------------------------------------------------------------
Phase 1 连续参数 稳定,季度/半年度重检 vol_ratio_lower 和 trend_factor 边界反映的是市场波动率的长期统计特征,变化慢
Phase 2 base weights 需随市场结构变化重检 各状态的权重配比取决于因子有效性——如果动量因子在某段时期的有效性大幅下降(如长期震荡市),BULL 状态的 momentum 基础权重可能需要下调。建议每 3\~6 个月或市场结构发生重大变化后重新跑一次调优脚本。

实践中建议:

***

十七、代码质量与架构改进(新发现项)

> 以下条目来源于代码审查中发现的具体问题,与上一节 V2/V3 中规划的功能性需求不同。这些是当前代码中真实存在的 Bug、设计缺陷和优化机会。

1. SharpeFactor 计算公式不标准

文件: quality\_factor.py:L66

当前代码:

sharpe = total_return / (daily_std * np.sqrt(len(daily_returns) / 252))

问题:

影响:所有使用 SharpeFactor 的选基排名都会系统性偏离标准 Sharpe Ratio。由于当前 Sharpe 只占 15-25% 权重,影响可控但需修正。

***

2. DataFetcher 伪并行

文件: engine.py:L42-L89

构造函数声明了 max_workers=5,但 fetch_batch() 中从未实例化 ThreadPoolExecutor。实际是串行循环:

for i, code in enumerate(codes):
    df = self.fetch_single(code, start_date, end_date)  # 阻塞等待
    if (i + 1) % 5 == 0:
        time.sleep(0.5)

应改为:

with ThreadPoolExecutor(max_workers=self.max_workers) as executor:
    futures = {executor.submit(self.fetch_single, code, start, end): code for code in codes}
    for future in as_completed(futures):
        ...

48 只 ETF 串行约 5 分钟,并行可压缩到 1 分钟以内。

***

3. weight\_engine.as\_factor\_weights 映射错误

文件: weight\_engine.py:L103-L112

key_map = {
    'volume': 'momentum',              # ❌ 量价确认 ≠ 动量
    'vol_price_conf': 'overbought_avoid', # ❌ 量价确认 ≠ 反追高
}

当调用 as_factor_weights(result, list(factor_df.columns)) 时,如果因子名为 volume 或 vol_price_conf,会被错误映射。虽然当前 adaptive 模式只用 defensive 因子集(暂无 volume/vol\_price\_conf),但这是未来的炸弹。应改为精确匹配或抛出明确异常。

***

4. MomentumFactor 使用整数索引而非日期对齐

文件: momentum\_factor.py:L28-L31

ret = (close[-1] - close[-w - 1]) / close[-w - 1]

这里假设 DataFrame 按日期连续排列、无缺失。如果源数据中存在非交易日缺口(如长假、停牌),close[-w-1] 对应的实际日历天数可能远超 w 个交易日。应改为按 trade_date 列过滤后再计算。

***

5. ETF 池存在同指数重复

文件: etf\_pool.py:L50-L53

底层指数 重复 ETF
------- --------------------
纳斯达克100 159941.SZ, 513100.SH
黄金 518880.SH, 159937.SZ
中证1000 512100.SH, 159845.SZ
自由现金流 159399.SZ, 159201.SZ
农业 159825.SZ (出现两次)

当这些品种同时动量好时,会在 TopN 中占用多名额却不分散风险。需要增加 underlying_index 字段并在 select 后去重。

***

6. VolatilityStabilityFactor 指标相关性

文件: mean\_reversion\_factor.py:L127-L129

stability = abs(avg_return) / vol      # = |mean| / σ
score = min(1.0, max(0.0, (stability * 2 + sharpe * 0.5) / 3))

stability 和 sharpe 都除以 vol(标准差),高度相关,组合权重 2:0.5 ad-hoc。建议调研 Sortino Ratio(只惩罚下行波动率)或 Calmar Ratio(收益/最大回撤)作为替代。

***

7. 与择时系统未集成

设计方案规划的集成路径是 ETFSelectionEngine → StrategyAllocationManager,但实际实现中选基引擎完全独立运行。当前需要通过 run_push.sh 将选基结果和择时结果分别生成后拼接。未实现:

***

8. 缺少单元测试

整个 selection/ 包(18 个 Python 文件)没有任何单元测试。关键逻辑(因子计算、权重调节、回测净值)缺乏回归保护。建议至少覆盖:

***

9. 文档中的设计-实现断链

设计方案中规划了但从未在代码中引用或预留接口的模块:

建议定期对比设计文档与代码,清理已废弃的路径描述或新增实现说明。

***

十八、策略执行纪律与心理防线设计

> 背景:当前系统存在两条独立信号链——截面选基引擎(中长期配置,输出仓位上限和品种选择)和择时策略层(中短期交易,33+子策略加权合成每日建仓建议)。但两个信号链之间没有互锁机制,且策略输出到人工执行之间存在未定义的地带——操作者需要凭感觉解读信号并决定买卖。这导致两个典型错误模式:(1) 把择时仓位的短期下降误解成悲观信号而恐慌清仓;(2) 不信任新开发的截面引擎而不敢按上限配置。本节解决"系统有信号,人不知道怎么执行"的断层问题。

1. 择时仓位百分比的正确解读

择时策略输出的百分比(如 59.77%)的含义是:

> 该品种下 N 个子策略中,加权平均后有 59.77% 的子策略当前看多。

格式说明(以创业板 33 策略为例):

[399102.SZ 创业板 (5.0%) :]         ← 品种级权重 5%
策略总数: 33
2026-05-25  59.77%  仓位: 2.99%(预测值-量价平开)  ← 择时仓位 59.77% × 5% = 2.99%
2026-05-22  82.76%  仓位: 4.14% [当日操作建议,加仓: 0.11%]

仓位-信号映射表(替代凭感觉看数字):

择时仓位区间 含义 正确操作
---------------------------
>80% 极强共识做多 正常满配(按截面上限)
60-80% 多数策略看多,分歧可控 正常配置,关注分歧加大的子策略
40-60% 多空分歧加大 配置但不加仓,检查分歧来源
20-40% 看多策略已成少数 减仓至该比例附近,保留底仓观察
<20% 极少数策略看多 大幅减仓,但不清零(防踏空)

核心原则:

2. 信号链互锁:截面与择时的关系

两条信号链的时间维度和职责不同:

维度 截面选基引擎 择时策略层
---------------------------
时间尺度 周度(下次调仓日) 每日
职责 判断能不能买(仓位上限)+ 买什么(选品种) 判断现在该不该在场(每日建仓建议)
信号性质 中长期趋势判断 短期多空共识度量

互锁规则:

最终执行仓位 = min(截面上限, 择时仓位建议) × 品种权重

截面「BULL 96%上限」+ 择时「59.77%」
  → 执行仓位 = min(96%, 59.77%) × 5% = 2.99%  ← 正确,已自动执行

截面「BULL 96%上限」+ 择时「<20%」
  → 执行仓位 = min(96%, <20%) × 5% = <1%
  → 大幅减仓但保留底仓,等择时回暖

不要在截面上限很高时绕过择时大幅加仓,也不要在择时短期波动时忽略截面的牛熊判断而清仓。

3. 分层减仓纪律(替代二元清仓)

当前问题:操作者看到回撤 → 恐慌 → 直接清零。需要用事前约定的分级减仓规则替代情绪决策。

当前仓位 X%
   │
   ├─ 触发条件 A:择时仓位跨区间下降 ≥ 两档(如 80%+ → 40-60%)
   │    → 减至 max(X% × 0.5, 截面上限 × 0.5)
   │    → 冷却期:至少等 2 个交易日才能再次减仓
   │
   ├─ 触发条件 B:截面牛熊降级(如 BULL → RANGING)
   │    → 仓位重置为新的截面上限
   │    → 例:96%上限 → 60%上限,立即执行
   │
   ├─ 触发条件 C:单日回撤 > 预设最大回撤容忍度(推荐 3-5%)
   │    → 减 20% 仓位(非清零)
   │    → 次日择时回暖则补回,否则继续观察
   │
   └─ 触发条件 D:截面降级 + 择时 < 20%(双重确认)
        → 可清仓至 10% 底仓
        → 除非截面 = SEVERE_BEAR,否则永不归零

关键设计原则:

4. 截面引擎的信任度渐进加仓机制

截面选基引擎仅运行 1-2 周,不信任是理性的。应设计验证流程让系统自己证明自己:

阶段 1:影子跟踪期(2-4 周)
  - 生成信号但只记录不执行
  - 每日对比「截面选出的 Top ETF」vs「基准收益率」
  - 验证指标:选出品种是否跑赢等权基准

阶段 2:小仓位验证期(4-8 周)
  - 按截面上限的 30% 执行(如 96% → 实际配 ~29%)
  - 继续追踪信号准确性
  - 验证指标:实际收益是否在回测预期区间内

阶段 3:正常执行期
  - 按截面上限的 70-80% 执行
  - 永远不打满 100%(留 20% 安全边际 = 有弹药应对黑天鹅 + 心理舒适区)
  - 每月复盘截面预测 vs 实际表现

为什么永远留 20% 安全边际?

5. 持仓相关性监控(待实现)

当前截面选出的品种(科技/半导体/创业板/纳指)在特定市场环境下可能高度相关,导致单日集中回撤。

待实现:

6. 执行纪律检查清单(每日推送应包含)

当前推送消息缺少一个给操作者看的简明行动指南。建议在推送末尾增加:

📋 今日执行建议
--------------------------------------------------------------------------------
 截面状态: 🟢 强势牛市 | 仓位上限于 96%
 择时共识: 加权平均仓位 65%(跨品种均值)
 相关性: 待计算
 → 建议执行仓位: min(96%, 65%) = 65%(不高于截面,跟随择时)

 今日操作:
  ✅ 维持现有仓位,无需调整
  ⚠️ 若择时单日下降 > 20 个百分点,触发条件 A,减仓 50%
  🚫 禁止操作: 盘中恐慌清仓、因单一品种下跌而全盘抛售

7. 已确认的心理认知陷阱(不需要代码,需要内化)

陷阱 表现 纠正
------------------
锚定近期收益高点 收益新高后患得患失,任何回撤都难以接受 回撤是持有风险资产的「门票」,没有门票就没有收益
用短期噪音覆盖长期信号 看到一日择时下降就否定截面的牛市判断 截面看周线,择时看日线,日线波动不应推翻周线趋势
亏损厌恶 宁愿错过反弹也不愿承受回撤 但「错过反弹」也是亏损——机会成本亏得更隐蔽
不信任新系统 截面只跑了 1-2 周就不敢用 正确,但不该因此回到情绪决策。应进入「阶段 1:影子跟踪期」——让系统用数据自证,而非用情绪投票

持续承担风险获取收益的唯一方法:不是变得「更勇敢」,而是让系统替你承担决策压力。当回撤发生时,你看的不是账户数字,而是规则表——「条件 C 触发了吗?触发了,减 20%。没触发,不动。」规则执行不需要勇气,只需要纪律。

***

十九、择时与截面集成 TODO

> 以下条目为系统待实现项,与本节分析直接相关。

▶ 📜 变更历史(14 次提交)

85391b92026-06-08 22:14feat: 校准etf名称
2e2d8e22026-06-01 00:48feat: 纳斯达克ETF溢价、官方数据统计以及双源校准。
cd322602026-05-26 01:23feat: 融合截面与测试策略,列出当日的操作建议,初稿未完成。
a644a9f2026-05-25 03:08feat: 截面策略参数从离散权重数值切换为自适应
44fcce52026-05-25 02:48feat: 补充固定关注板块,数据缺失待修复
bce5e1f2026-05-25 00:27feat: 趋势质量因子调参后打印消息推送
fdc81de2026-05-25 00:18feat: 补充趋势质量因子优化牛熊切换时超参调节等;数据抓取耗时打印
c6881aa2026-05-24 23:55feat: 实现工程优化-数据并行抓取
2fd0e172026-05-24 23:38feat: 实现截面选基去重,与基础回测超参调优代码
48a28222026-05-14 00:45feat: 因子权重动态适应 文档里四种方案(离散切换/波动率自适应/趋势强度加权/自适应融合)都有完整对比,你可以后续判断是否需要额外实现方案 B 或 C。
be8783e2026-05-14 00:20feat: 调整牛市下的截面选机策略的4个因子的配比;补充现有截面选区策略的说明文档。
5a431772026-05-12 23:27feat: 截面策略回测数据补充
7ed32542026-05-12 21:56feat: 截面选基策略MVP版本-补充回测逻辑;优化项目md文档与推送数据过期提醒
724828b2026-05-12 02:21feat: 设计截面策略方案
🍃quant 知识库
by 伊甸园和枫

🔊 播放设置

勾选音源后调节配比,总和自动归一化
已选 0 个 · 合计:0%
合成中...
00:00/00:00
1.0x

分享图片

生成中...