第 19 课 · 评估你的 Agent

情绪分到底有没有预测力——上线前,先让数据替你回答这个问题

预计用时:30 分钟 上一课:第 18 课 · 盘中工作流与告警

这节课你将得到什么

一套量化判据,用来回答第 3 课悬而未决的问题:你的情绪 Agent 打出来的分数,到底能不能预测明天的涨跌?第 3 课我们说"情绪分 ≠ 买入信号",当时只是定性警告;这节课你学会用 IC(信息系数)把这个警告变成一道可以打分的考题——任何信号,先考过这关,才配进入你的决策流程。

全程离线:脚本用固定种子生成 30 天合成数据(每日情绪分 + 次日收益),其中前 15 天埋了弱信号、后 15 天纯随机。你会亲眼看到"全样本看起来还行、分段后当场露馅"——这和第 7 课参数扫描的过拟合,是同一类陷阱的两个面孔。

一、IC:信号质量的统一考卷

IC(Information Coefficient,信息系数)的定义一句话就说完:信号值与未来收益的相关系数。本课用的是最小版本——同一只股票,情绪分序列对"次日收益"序列求相关:

指标算法特点
ICPearson 相关系数(情绪分 vs 次日收益)对数值本身敏感,直观但容易被极端值带偏
Rank ICSpearman 秩相关(先各自排名,再对名次算 Pearson)只关心"排序对不对",不在乎数值大小,抗离群值,业界更常用

IC 落在 -1 ~ +1。正 IC 表示"情绪分高的日子,次日倾向于涨";负 IC 表示信号是反的(反向用也能赚钱,但先确认它不是噪声);0 附近表示信号和收益没关系。经验值:在横截面选股因子的语境里,IC 均值 0.03 ~ 0.05 就已经是可用的信号(见 Grinold & Kahn《Active Portfolio Management》对 IC 与 IR 的经典讨论)——真实 alpha 就是这么微弱,淹没在噪声里的一点点倾斜,靠的是稳定重复而不是单点爆发。谁要是向你展示 IC 0.5 的"因子",先怀疑数据泄露。

口径说明:业界主流是"横截面 IC"(每天对全市场股票横着算一次相关,再对时间取统计),本课为了聚焦概念用"单标的时序 IC",数学是同一个数学。你的情绪 Agent 只盯自选股时,时序口径反而更贴近实盘用法。

二、单个数字不够:必须看 IC 序列

一个 IC 值只是一个点。哪怕它是 +0.15,也回答不了三个致命问题:它是稳定的还是碰运气的?它最近还在工作吗?它是全程有效还是只在某段历史里有效?所以专业做法是看 IC 序列:

这就是为什么脚本要分三步:全样本 → 分段 → 滚动。三步是同一份数据的三种审法,层层递进。

三、动手:跑起来(纯离线,无需 Key)

脚本 scripts/sentiment_ic.py 不联网、不调 LLM——数据是固定种子生成的,你每次跑、我每次跑,结果一字不差:

cd "$HOME/AI Project/Quant Learning"
source .venv/bin/activate
python scripts/sentiment_ic.py

你会看到(我已在你的环境实测通过,30 天数据明细较长,中间省略):

模拟数据:30 天(前 15 天埋入弱信号、之后纯随机),随机种子 20260719
  D01  情绪分 -0.17  次日收益 +0.75% <-- 信号期
  D02  情绪分 +0.61  次日收益 +2.98%
  ……
  D16  情绪分 +0.12  次日收益 -0.20% <-- 随机期
  ……

===== 第一步:全样本 IC(最容易被误用的数字) =====
IC (Pearson)       : +0.157
Rank IC (Spearman) : +0.106
只看这两个数,你会以为信号'还行'——且慢,分段看。

===== 第二步:分段 IC(样本内 vs 样本外) =====
              前 15 天    后 15 天
IC            +0.450    -0.083
Rank IC       +0.329    -0.043

===== 第三步:滚动 IC 序列(10 日窗口,共 21 个) =====
  D01~D10  IC +0.53  ##########
  ……
  D11~D20  IC +0.19  ###
  D12~D21  IC -0.24
  ……
  D21~D30  IC -0.26

滚动 IC 统计(窗口 10 日):
  全段:IC 均值 +0.125,IC>0 占比 52%
  信号期窗口:IC 均值 +0.418,IC>0 占比 100%
  随机期窗口:IC 均值 -0.140,IC>0 占比 0%

四、解剖:聚合数字是怎么撒谎的

审法结果单独看它,你会下什么结论
全样本 IC+0.157 / Rank IC +0.106"高于 0.05 的经验线,这信号能用"——错误结论
分段 IC前 15 天 +0.450,后 15 天 -0.083信号只在前半段存在,后半段已死——真相开始浮现
滚动 IC信号期窗口 100% 为正,随机期窗口 0% 为正死亡时间点清晰可见:IC 序列从 D12 起一路翻负,再没回来

全样本 +0.157 是"前半段真信号"被"后半段纯噪声"稀释后的残影——它为正,只是因为死人的体温还没凉透。任何只给你看一个全样本相关系数的策略报告,你都要追一句:分段看过吗?滚动看过吗?最近 20 天呢?

和第 7 课是同一个陷阱

第 7 课参数扫描的"孤峰",是参数维度上的样本内陷阱:3/60 这组参数只在这份数据里碰巧最优。这节课是时间维度上的样本内陷阱:信号只在前半段历史里碰巧有效。两处共享同一条解药——切一刀,看样本外。Agent 生成信号和参数的速度是你的 100 倍,制造"样本内幻觉"的速度也是 100 倍,分段检验是你手里最便宜的那把刀。

工程细节:Spearman 的定义就是"先排名再算 Pearson",环境里没有 scipy,脚本用 pandas 的 rank() 手动实现,数学上完全等价——读源码时可以顺手确认这一点。

五、接到你的真实 Agent 上

合成数据只是教具,接真家伙只需替换两列:

然后原样跑这三步。上线判据写在脚本结尾:IC / Rank IC 均值显著为正、IC>0 占比稳定过半、最近的滚动窗口还在工作。三条都过,这个信号才有资格出现在你的盘后报告里;任何一条不过,它的输出就降级为"参考信息",不许碰交易决策。

注意检验里"次日收益"这个口径天然契合 T+1:你的节奏本来就是"盘后打分 → 次日执行",IC 检验问的正是"今天的分预测明天的收益"——考题和实战是同一张时间表。

自测

凭记忆作答——答错比答对更能加固记忆。

动手挑战(可选,10 分钟)

把脚本里的 BETA = 0.012 改成 0.0(全程无信号)重跑,观察全样本 IC 变成多少、IC>0 占比还剩多少。你会得到一个重要直觉:纯噪声也能凭运气产出不为零的 IC——30 个样本的相关系数波动极大,这就是为什么"占比稳定 + 滚动不塌"比单点数值重要得多。

延伸阅读

下一课预告

第 20 课 · 毕业:实盘前检查清单——把 19 课学到的东西压缩成一张上线前的核对表:数据、成本、T+1、过拟合、IC、降级链,逐项打勾,然后你可以开始小仓位实盘了。

有任何不清楚的地方(比如 Pearson 与 Spearman 的区别、滚动窗口怎么切、怎么把第 3 课的输出落盘成 CSV),直接问我——我是你的老师。