阶段4Python 基础进阶●●●●●

rolling:时序因子的"移动窗口"引擎

我的掌握程度:
q-314精讲

先掌握这个答案

标准用法:s.rolling(20).mean()/std()/sum()——窗口默认「含当日」向过去看20格(防前视安全);若要"截至昨日"先shift(1)再rolling。min_periods:窗口不满时默认产NaN——设min_periods=10允许"至少10天"的半窗结果(数据利用率与稳定性的权衡)。组内滚动:df.groupby('code')['close'].rolling(20).mean()——输出会多一层组索引(需要reset或droplevel);更顺手的等价写法是transform+lambda或直接df.groupby('code')['x'].transform(lambda s: s.rolling(20).mean())。expanding:窗口从首个观测一直扩大到当前——"历史所有"而非"最近N"(历史分位数因子用它)。

先读结论,再核对下方使用边界;数字例题为教学情景,涉及实际行情与规则时请核对原始来源。

从理解到使用

本阶段实战方法 · 一条能复现的数据流水线

把接口返回的数据变成可用于因子研究的面板时,先处理时点、主键与单位。

  1. 建立数据字典:字段、单位、时区、交易日历、数据源、抓取时间、原始价与复权因子。
  2. 用(date, code)查重,区分停牌、未上市、窗口不足和真实缺失;不要用向后填充把未来值带回过去。
  3. 保存原始快照与清洗日志,固定随机种子和环境版本;接口字段变化时先核对官方文档。

使用边界

  • 报告期不等于公告可用日,盘后公告通常不能用于当天收盘前决策。
  • API输出名为“动态市盈率”时不能直接改名TTM;浏览器练习不支持任意原生库或行情抓取接口。
背景 · 从一个困惑说起
动量=过去20天涨了多少;波动=过去20天收益的标准差;均线=过去20天收盘的均值——所有"过去N天"类因子的共同引擎是rolling:一个在时间轴上滑动的计算窗口。
由此产生的问题
rolling的标准用法与「包含当日」的语义?窗口边界(min_periods)与组内滚动(groupby+rolling)的正确组合?它与expanding的区别?
核心概念
标准用法:s.rolling(20).mean()/std()/sum()——窗口默认「含当日」向过去看20格(防前视安全);若要"截至昨日"先shift(1)再rolling。min_periods:窗口不满时默认产NaN——设min_periods=10允许"至少10天"的半窗结果(数据利用率与稳定性的权衡)。组内滚动:df.groupby('code')['close'].rolling(20).mean()——输出会多一层组索引(需要reset或droplevel);更顺手的等价写法是transform+lambda或直接df.groupby('code')['x'].transform(lambda s: s.rolling(20).mean())。expanding:窗口从首个观测一直扩大到当前——"历史所有"而非"最近N"(历史分位数因子用它)。
为什么需要它
①"过去N天"是因子世界的第一大家族:动量/反转/波动/换手均值/量比——rolling一族全包;②含当日语义的自觉:你要「昨日的20日均」还是「含今的20日均」——差一个shift(1),回测含义完全不同(前者今日可用,后者含今日收盘只能明日用);③与groupby的组合是面板数据的日常——忘了分组会让股票A的尾部窗口吃进股票B的头部(跨组污染,q-312同款事故的窗口版)。
实际应用场景
因子速成五连:mom=close.pct_change(20);vol=ret.rolling(20).std()*sqrt(252);ma_ratio=close/rolling(20).mean();turn_avg=turnover.rolling(20).mean();vol_ratio=volume/rolling(20).mean()——每一行都是一个经典因子的种子。
与之前知识的联系
q-313的shift控制窗口的"时间终点";q-309的transform把rolling结果保形贴回;q-381-385(实战五题)全部建立在rolling之上。
⚠ 常见误解
  • rolling自动分组:它不知道股票边界——面板必须groupby后rolling,否则跨组污染
  • 含当日就是前视:rolling含当日=用到今天收盘——只要配的是明日收益(标签负shift)就干净;怕混就统一"shift(1)后rolling"再无歧义
  • NaN很烦就min_periods=1:半窗结果不稳定(3天的"20日波动")——min_periods至少设窗口的一半

🤖 AI导师

导师会先检查你的前置知识(shift、groupby transform),再用案例、公式和代码帮助理解。此功能需要先启用服务。