因子表 my_cn_stock_bar1d,因子列 factor(表里有 factor、factor_pre、factor_raw 三列数值;docs 的因子名是「20日反转因子(行业市值中性化)」,与 factor(最终因子)一致)。基准 中证全指(000985.CSI)。数据区间 1896 个交易日,2019-01-02 至 2026-10-29。
总评规则(我自拟,你没有给定):因子含义只是猜测,最高「存疑」;测试段年化超额不为正,判「无效」;为正但近似 t 值小于 2,且训练段、验证段超额都为负,也判「无效」;其余判「存疑」。
只用训练段的月末信号日判定,验证段和测试段在这一步没有碰。
| 项目 | 训练段结果 |
|---|---|
| 训练段样本 | 月末信号日 46 个(2019-01-31 ~ 2022-10-31),平均每期 2369 只股票 |
| RankIC 均值 / 标准差 | 0.0536 / 0.0950(课程口径「强」) |
| t 值 = 均值 ÷ 标准差 × √期数 | 3.83(月度取样,收益区间不重叠,不需要 Newey-West) |
| IC 大于 0 的月份占比 | 65.2% |
| 前半段 / 后半段 IC 均值 | 0.0506 / 0.0567 |
| 5 分组下期平均收益(G1 最小 → G5 最大) | 0.56% / 1.51% / 1.53% / 1.73% / 1.61% |
| G5 − G1 | +1.06% |
| 方向 = sign(IC 均值) | +1,越大越好(选因子最大的 20 只) |
| 可信度检查 | 结果 | 说明 |
|---|---|---|
| |t| ≥ 2 | 通过 | t = 3.83 |
| 前后半段 IC 符号一致,且与方向一致 | 通过 | 0.0506 与 0.0567 同为正 |
| G5 − G1 的符号与方向一致 | 通过 | +1.06% |
| 是否 U 形(G1、G5 同时高于或低于 G3) | 通过 | G1 0.56%、G3 1.53%、G5 1.61%:G1 低于 G3,G5 高于 G3,不是 U 形 |
与文档核对:一致。因子表的说明写着「值越大表示近期跌得越多、越看涨」,方向为 +1,与训练段 IC 的符号相同。
| 之后的段 | RankIC 均值 | t 值 | IC>0 占比 | 信号日数 | G5 − G1 | 符号是否与方向一致 |
|---|---|---|---|---|---|---|
| 验证段 | 0.0399 | 1.70 | 66.7% | 15 | +0.74% | 一致 |
| 测试段 | 0.0870 | 3.27 | 77.8% | 27 | +1.79% | 一致 |
验证段只有 15 个信号日,t 值 1.70 没有到 2,只能说符号没变;方向在验证段、测试段都没有被改动。另外训练段 G5(1.61%)略低于 G4(1.73%):好处主要来自避开 G1(最近涨得最多的一档),不是越跌越好。
| 规则卡 | 内容 |
|---|---|
| 因子表与列 | my_cn_stock_bar1d · factor。表里有 factor、factor_pre、factor_raw 三列数值;docs 的因子名是「20日反转因子(行业市值中性化)」,与 factor(最终因子)一致 |
| 方向及依据 | 越大越好(+1)。训练段 RankIC 0.0536,t 3.83,前后半段 0.0506/0.0567,G5−G1 +1.06% |
| 候选池 | 全 A,剔除:ST/*ST、停牌、上市不足 250 个交易日(因子表已剔除)、近 20 日日均成交额低于 5000 万元。信号日涨停的股票没有剔除(过滤条件上限 4 个已用完);改为回测后检查被拒单与成交价 |
| 持仓与权重 | 得分 = 方向 × 因子值,取最高 20 只,等权,单票不超过 8%,投入比例 95%,初始资金 1,000,000 元 |
| 调仓与成交 | 月度;月末交易日收盘后生成信号,下一个交易日开盘成交(引擎本身 D 日下单 D+1 开盘成交,不额外加滞后) |
| 风控 | 无止损;停牌或无行情的股票当天不下单 |
| 成本 | 佣金买卖各 0.03%(最低 5 元),卖出印花税 0.1%,滑点单边 0.1%;用 param() 声明 |
| 基准 | 中证全指(000985.CSI)。与全A、不限市值的股票池口径最接近;但它是市值加权,本策略等权持有 20 只,口径仍不一致 |
| 三集切分 | 训练 2019-01-01 ~ 2022-11-30;验证 2023-01-01 ~ 2024-04-30;测试 2024-06-01 ~ 2026-10-29(因子表与行情的最后一天一致)。段间各留约 20 个交易日(训练段最后一个信号日 2022-10-31 的标签,卖出价是 2022-12-01 的开盘价,落在训练段之后的隔离期内,没有进入验证段 2023-01-01) |
| 候选池诊断(训练段月末信号日,汇总) | 数值 |
|---|---|
| 因子覆盖率(满足流动性与状态条件的股票里有因子值的比例) | 92.0% |
| 每期候选池大小:最小 / 中位数 | 1412 / 2392(低于 100 只的期数:0) |
| 剔除条数(各条件有重叠,不能相加) | ST 7,751;停牌 985;无因子值 24,618;成交额不足 72,137(总计 192,161 行) |
| 信号日涨停(没有剔除,只做事后检查) | 3,323 行 |
| 单行业最大持仓数(前 20 只) | 训练 10 · 验证 12 · 测试 17(阈值 30 只,未超) |
| 指标 | 训练 | 验证 | 测试 | 全程 |
|---|---|---|---|---|
| 交易日数 | 950 | 320 | 584 | 1,896 |
| 策略累计收益 | -34.89% | -29.87% | +22.94% | -48.99% |
| 基准累计收益 | +42.90% | -8.47% | +18.24% | +49.16% |
| 策略年化 | -10.76% | -24.38% | +9.32% | -8.56% |
| 基准年化 | +9.93% | -6.73% | +7.50% | +5.46% |
| 年化超额 | -20.69% | -17.65% | +1.82% | -14.02% |
| 夏普(扣无风险利率) | -0.40 | -0.98 | 0.35 | -0.27 |
| 基准夏普 | 0.42 | -0.53 | 0.30 | 0.22 |
| 最大回撤 | -62.72% | -44.96% | -27.70% | -80.46% |
| 超额净值最大回撤 | -63.30% | -28.50% | -25.23% | -77.39% |
| 信息比率 | -1.19 | -1.04 | 0.23 | -0.72 |
| 月换手(单边,月均) | 86% | 87% | 87% | 87% |
衰减判定。规则是验证段夏普不低于训练段的 60% 算正常衰减,符号翻转或夏普腰斩算过拟合。这里训练段夏普 -0.40 本身就是负的,验证段 -0.98 更低,没有「衰减」可言:训练段夏普就为负,谈不上衰减;验证段夏普更低,仍为负。验证段 RankIC 符号与锁定的方向一致(方向稳定),所以不按「方向不稳定」处理。测试段夏普回到 0.35,略高于基准的 0.30,但年化超额的近似 t 值只有 0.36,说不上有效。
测试段取自一次从 2019-01-02 开始的连续回测,期初持仓来自验证段末尾发出的信号;该连续回测的前 1292 个交易日与此前的训练+验证段回测逐日一致(日收益最大差 0)。夏普口径与引擎一致(日无风险利率 0.0001173):本报告按日收益算出的整段夏普 -0.275,与引擎报告的夏普相差不到 0.003。月换手 =(买入额 + 卖出额)÷ 2 ÷ 组合市值,按月累加,100% 表示一个月内整个组合换掉一遍。
每月把股票按因子从小到大分 5 组,看下一期平均收益。G1 最低(0.56%),G2 到 G5 在 1.51% 到 1.73% 之间。G5 − G1 为 +1.06%,方向取 +1。
一条从 2019-01-02 开始的连续净值,三段之间留有隔离期(不单独计算)。测试段的净值从训练、验证段亏损后的位置接着走,所以全程累计仍为负(-48.99%)。
超额净值在训练段持续下行,验证段继续下行,测试段小幅回升但没有回到起点;期末 0.342。
策略最大回撤 -80.46%,超额净值最大回撤 -77.39%;线尾是 2026-10-29 当天仍未修复的回撤。
持仓数 16~24(默认 20 的 ±20%)和三种调仓周期共 15 个组合,训练段夏普全部为负(-0.41 到 -0.26)。验证了 6 个组合,验证段夏普也全部为负(-1.13 到 -0.92)。这是一片平的低地,不是高原:参数不敏感,但整片都不赚钱。
成本 ×2 指佣金、最低佣金、印花税、滑点全部翻倍。×1 累计 -55.94%,×2 累计 -63.40%;年化超额从 -19.72% 降到 -22.75%。超额本来就是负的,所以「成本翻倍后超额是否仍为正」这项不成立。
八个年份里超额为正的只有 1 个(2026 年,这一年基准下跌 14.34%)。2024 年横跨验证段和测试段,是按整个自然年算的。
全程月均 87%,中位数 89%。每个月基本把组合换掉一遍,课程口径是 20%~50%,这个策略远高于上限。
| 课程口径 | 本策略 | 判定 |
|---|---|---|
| 年化超额 > 8% | 测试段 +1.82%(训练 -20.69%、验证 -17.65%) | 不达标 |
| 信息比率 > 1.0 | 测试段 0.23(训练 -1.19、验证 -1.04) | 不达标 |
| 最大回撤 > -20% | 测试段 -27.70%(验证段 -44.96%,全程 -80.46%) | 不达标 |
| 月换手 20%~50% | 87%(测试段 87%) | 不达标 |
| 容量 > 5 亿 | 粗估 1.52 亿(测试段信号日的中位数);训练 + 验证段 1.33 亿。规则:单票买入额不超过其 20 日日均成交额的 10%,逐期取 20 只里最紧的一只 | 不达标(粗估) |
五项都不达标,所以「三项都特别漂亮时先怀疑数据」的提示不适用;相反,数据一致性已经核对过(见第 8 节)。容量是粗估,没有考虑冲击成本曲线,也没有考虑卖出同时受限。
| 项目 | 结果 | 说明 |
|---|---|---|
| 试验次数与 DSR | 如实记录 | 回测共 26 次:训练 + 验证段 4 次(首跑、重跑存曲线、成本 ×2、零成本)、调参 15 次、调参验证 6 次、测试 1 次;调参搜了 2 个参数(上限 3),试验 15 次(上限 40)。调参最优者的 DSR 概率 0.25(< 0.95,出现 SELECTION_LUCK 警告):最优夏普 -0.26,15 次随机尝试期望能到 0.10。最终参数保持默认,没有采用调参结果。 |
| 验证集、测试集各看过几次 | 如实记录 | 验证段被看了 5 次(首跑、分段评估、调参验证、成本回测、体检);测试集开出 1 次,另有 1 次中断的尝试(没有产出结果)。开测试集之前有三处读到过测试段数据但没有看过数字(见 trials.json)。方向没有被改动。 |
| 中断的测试集尝试 | 已记录 | 第一次开测试集时脚本被自己的保护逻辑挡回,没有任何结果文件,AIStudio 无残留进程。原因我推断是命令先在本地执行一遍、再被转到 AIStudio 重跑一遍,第二次开测试集时留下的记录支持这一推断(两行记录相隔 1 秒、主机不同);第一次当时没有记进程号,无法直接证实。 |
| 成本与容量假设 | 粗估 | 佣金万三(最低 5 元)、卖出印花税 0.1%、滑点单边 0.1%;成本 ×2 全段累计 -63.40%。每月买卖额按组合市值平均计 87%,成本拖累年化约 3.77%。容量粗估见第 6 节,是成交额占比,没有冲击成本曲线。 |
| 涨跌停与被拒单 | 通过(有说明) | 引擎对涨停开盘的买单:训练 + 验证段 0 笔、测试段 4 笔开盘在涨停价,其中成交 4 笔(测试段)。跌停开盘的卖单:训练 + 验证段 25 笔里成交 6 笔,其余被取消(原因是「'open' price is lower limit」19 笔);测试段 7 笔里成交 3 笔。引擎在跌停开盘时取消了部分卖出,涨停开盘的买入没有被拒(只有测试段 4 笔);这是观察到的结果,不是文档规定。买单被拒:训练 + 验证段 16 笔([-114]Insufficient cash 13 笔, [-107]Market data not found 3 笔),测试段 2 笔([-107]Market data not found 2 笔)。成交价与当日开盘价的最大偏差 0.20%(训练 + 验证)和 0.20%(测试),买入中位数 +0.10%、卖出 -0.10%,与 0.1% 滑点一致。信号日涨停的股票没有剔除(过滤条件已满 4 个)。事后统计:买单在次日开盘处于涨停价的,训练 + 验证段 0 笔,测试段 4 笔,样本很小,不足以下结论。 |
| 未建模的交易细节 | 未建模 | 没有冲击成本曲线、没有融券、没有停牌期间的资金占用、没有手数以外的碎股处理、没有分红税;策略只在信号日下单,跌停开盘被取消的卖单要等下一个信号日才会重新下。 |
| 数据自检:被跳过的标的 | 已记录 | 因子加工时有 274 只标的缺上市天数、行业或市值被跳过,其中北交所 245 只(89%),集中在 920 开头的新代码;只有 3 只出现在本策略的成交里。 |
| 数据自检:退市标的 | 在样本内 | 策略交易过的 1006 只股票里有 31 只在 2024-04-30 前已无行情;引擎对退市股按最后行情结算(全程有 3 笔成交类型为 E 的记录,成交价 0.18~0.78 元,其中 2 笔在测试段;我推断它们是退市清算,没有核实)。退市整理期的真实成交没有建模。 |
| 因子体检:信号寿命 | 通过 | RankIC 滞后 0/1/2/3 期:0.0538 / 0.0190 / -0.0050 / 0.0084,逐步衰减,没有出现滞后后反而更高的怪象。 |
| 因子体检:随机因子对照 | 通过 | 300 次随机选 20 只,月均超额均值 -0.01%,范围(5%~95%)-0.58% 到 +0.55%;真实因子前 20 只 -1.22%,低于全部随机结果。随机对照应当无超额:通过。 |
| 超额拆解 | 部分做了 | 全程 β = 1.09、α 年化 -19.42%(t = -2.68);成本拖累年化约 3.77%。风格暴露未做(没有取风格因子)。 |
| 回测与独立计算对账 | 通过 | 回测的月度收益与 SQL 独立算出的「前 20 只等权」月度收益相关系数 0.956;回测每月低 0.58%,与成本方向一致。引擎整段夏普、年化、信息比率与本报告独立计算的差不超过 0.003。 |
| 引擎 SQL 的一个未解释现象 | 有未解释项 | 取标签的 SQL 在查询范围边缘偶尔让某一期候选池整期为空(训练段的 2022-10-31、验证段的 2023-01-31、2024-03-29),每次日期不同,原因没有查清。做法是多取一个月、在 Python 里按信号日精确裁剪并断言每期都在;候选池大小已与 pandas 独立统计对账(相对差最大 0.79%)。若还有我没发现的整期丢失,会让断言报错而不是静默。 |
| 单日异常 | 已核对 | 分红入账被记为 trade_type 'D',我曾把它误当作成交价偏离;重算时只用真实成交,最大偏离 0.2%。 |