从 Point-in-Time 股票筛选到统一 Web 前端的完整链路: 筛选 → 画像 → 策略 → 回测 → Walk-forward → 绩效分析 → 报告/前端。 架构 - 数据层与策略层分离;策略代码不写 SQL,只经 data/repo.py 取数 - 所有业务阈值集中在 config/*.yml,代码零硬编码(字段写错直接报错) - 报告只做「run_id → SQL → 渲染」,不做任何计算,数字可追溯 - 前后端分离:output/ 静态站点 + hdiv web 提供的 REST API 数据安全 - 只增不删:SQL 钩子拦截 DELETE/DROP/TRUNCATE,并有源码扫描测试守护 - qlib 原有表只读,本项目数据写入 hd_ 前缀表 - 回补使用 INSERT IGNORE,保证既有行零改动 - .env 存密钥且已 gitignore;output/、logs/、.venv/ 不入库 交付物 - 30 张 hd_* 表、7 个 YAML 配置、283 项自动化测试 - 统一 Web 前端(hash 路由 SPA)+ nginx 部署配置与 launchd 托管脚本 如实声明的限制 - 策略缺少稳定的样本外超额收益(Walk-forward 7 窗口均值 -0.95%, 基准 +2.29%);其价值体现在回撤控制,而非超额收益 - 涨跌停/停牌约束仅覆盖 2019 年起;index_weight 尚未填充 - AI Agent 层(plan.md 第四版 P8)未实现 详见 docs/user-guide.md 与 docs/implementation-status.md。
144 lines
6.2 KiB
YAML
144 lines
6.2 KiB
YAML
# ============================================================
|
||
# 股票筛选条件(★ 可直接修改)
|
||
# 对应 plan.md §4/§5 的 MarketFilter / RiskFilter / DividendFilter /
|
||
# FinancialQualityFilter。
|
||
#
|
||
# 所有阈值只允许出现在本文件;代码中不得硬编码。
|
||
# 修改后 config_hash 变化,历史 run 仍可完整复现。
|
||
# ============================================================
|
||
version: 1
|
||
name: high_dividend_universe
|
||
|
||
evaluation:
|
||
# point_in_time —— 每个 asof 日期独立求值(回测必须用这个)
|
||
# latest —— 仅在最新交易日求值一次
|
||
mode: point_in_time
|
||
asof: latest
|
||
|
||
# ------------------------------------------------------------
|
||
# MarketFilter —— 市场属性
|
||
# ------------------------------------------------------------
|
||
market:
|
||
# 交易所白名单。需要北交所时加 BSE。
|
||
exchanges: [SZSE, SSE]
|
||
# 板块白名单:主板 / 创业板 / 科创板 / 北交所
|
||
markets: [主板, 创业板, 科创板]
|
||
# 上市年限下限(年)—— plan.md §4「上市 ≥ 10 年」
|
||
min_listing_years: 10
|
||
# 总市值下限(元)—— plan.md §4「市值 ≥ 500 亿」
|
||
min_market_cap: 50000000000
|
||
# 流通市值下限(元);null = 不限制
|
||
min_float_market_cap: null
|
||
# 近 20 日日均成交额下限(元)—— 流动性过滤
|
||
min_avg_amount_20d: 20000000
|
||
# 要求 asof 当日正常交易(非停牌)
|
||
require_trading_on_asof: true
|
||
|
||
# ------------------------------------------------------------
|
||
# 行业豁免(对 RiskFilter 与 FinancialQualityFilter 同时生效)
|
||
# 银行/保险/证券的负债率天然在 90% 上下、且没有「自由现金流」的概念,
|
||
# 若不做豁免,高股息策略里最重要的银行板块会被全部误杀
|
||
# (实测:招商银行 90.2% 会被 risk.max_debt_to_assets 直接淘汰)。
|
||
# ------------------------------------------------------------
|
||
industry_exemptions:
|
||
# 豁免资产负债率上限的行业
|
||
leverage: [银行, 保险, 证券, 信托]
|
||
# 豁免「自由现金流为正 / FCF 覆盖分红 / 经营现金流对利润」要求的行业
|
||
free_cash_flow: [银行, 保险, 证券, 信托]
|
||
|
||
# ------------------------------------------------------------
|
||
# RiskFilter —— 风险过滤
|
||
# ------------------------------------------------------------
|
||
risk:
|
||
# 排除 ST / *ST(依据 stock_name_history 按日期还原,而非只看当前名)
|
||
exclude_st: true
|
||
st_lookback_from_history: true
|
||
# 排除退市整理 / 已退市
|
||
exclude_delisting: true
|
||
# 排除 asof 当日停牌
|
||
exclude_suspended: true
|
||
# 排除净资产为负
|
||
exclude_negative_equity: true
|
||
# 资产负债率上限;null = 不限制。金融股由 industry_exemptions.leverage 豁免
|
||
max_debt_to_assets: 0.80
|
||
# 大股东质押比例上限;null = 不限制(需额外数据源)
|
||
max_pledge_ratio: null
|
||
# 重大诉讼;当前无数据源,保持 false
|
||
exclude_major_litigation: false
|
||
# 商誉异常;当前无数据源,保持 false
|
||
exclude_goodwill_anomaly: false
|
||
|
||
# ------------------------------------------------------------
|
||
# DividendFilter —— 分红过滤
|
||
# ------------------------------------------------------------
|
||
dividend:
|
||
# 股息率口径:
|
||
# computed —— 自算 PIT-TTM(按 imp_ann_date 生效),无未来函数【回测主口径】
|
||
# dv_ttm —— 直接用 daily_basic.dv_ttm(仅交叉校验)
|
||
yield_source: computed
|
||
# 当前股息率下限 —— plan.md §4「股息率 ≥ 3%」
|
||
min_dividend_yield: 0.03
|
||
|
||
# 连续分红年限下限 —— plan.md §4「连续现金分红 ≥ 5 年」
|
||
min_continuous_years: 5
|
||
# 认定一次分红的规则(D6 决策):
|
||
# cash_div_tax_gt_0 —— 税前现金分红 > 0,且 div_proc='实施',且有 ex_date 或 pay_date
|
||
continuous_rule: cash_div_tax_gt_0
|
||
# 考察窗口(年)
|
||
window_years: 6
|
||
# 窗口内最少分红年数
|
||
min_dividend_years_in_window: 5
|
||
|
||
# 分红支付率上下限;null = 不限制
|
||
max_payout_ratio: 1.00
|
||
min_payout_ratio: null
|
||
# 5 年 DPS 复合增速下限;null = 不限制
|
||
min_dps_cagr_5y: null
|
||
# 要求自由现金流为正
|
||
require_positive_fcf: true
|
||
# 自由现金流对分红的覆盖倍数下限(FCF / 现金分红总额)
|
||
min_fcf_dividend_cover: 1.0
|
||
|
||
# 当「验证所需的数据缺失」时如何处理(安全边际策略的关键取舍):
|
||
# pass —— 放行(宽松)。避免因数据未同步而误杀,但会让「无法验证现金流」
|
||
# 的股票进入组合,与「安全边际」的初衷相悖。
|
||
# reject —— 淘汰(严格)。忠于「FCF 必须为正」的策略逻辑,
|
||
# 但结果会依赖数据完整度(数据补齐前后股票池会变化)。
|
||
# 实测:当前全部在市股票均有现金流数据,缺失的 10 只均为 1990 年代退市股
|
||
# (已被 risk.exclude_delisting 排除),因此两种设置结果相同。
|
||
# 若你希望「宁可错过、不可踩雷」,改为 reject。
|
||
on_missing_data: pass
|
||
|
||
# ------------------------------------------------------------
|
||
# FinancialQualityFilter —— 财务质量过滤
|
||
# ------------------------------------------------------------
|
||
quality:
|
||
# 5 年平均 ROE 下限
|
||
min_roe_5y_avg: 0.08
|
||
# 5 年平均 ROIC 下限;null = 不限制
|
||
min_roic_5y_avg: null
|
||
min_gross_margin: null
|
||
min_net_margin: null
|
||
# 经营现金流 / 净利润 下限(盈利质量)
|
||
min_ocf_to_profit: 0.60
|
||
# 覆盖 risk.max_debt_to_assets;null = 不覆盖
|
||
max_debt_to_assets: null
|
||
# 利息保障倍数下限;null = 不限制
|
||
min_interest_cover: null
|
||
# 兼容字段:留空则使用顶层的 industry_exemptions
|
||
exempt_industries: []
|
||
# PIT 纪律:只使用公告日 <= asof 的财报
|
||
pit_rule: announce_date_le_asof
|
||
# 用哪一期财报:latest_announced(最近已公告)/ ttm
|
||
report_basis: latest_announced
|
||
|
||
# ------------------------------------------------------------
|
||
# 输出控制
|
||
# ------------------------------------------------------------
|
||
output:
|
||
# 成员数少于该值触发 WARN(可能是条件过严或数据缺口)
|
||
min_members: 10
|
||
# 成员数上限;null = 不限制。用于回测时控制持仓候选规模
|
||
max_members: 200
|
||
warn_on_empty: true
|