7.5 时间序列处理
课前导读
本节目标
你将学会:把 A 股行情看成按时间排队的记录,理解日期索引、排序、交易日、重采样和数据对齐。
适合基础:已经会创建 DataFrame、读取保存 CSV,知道时间序列是第 6 章量化数据里的核心概念。
预计用时:约 36 分钟。
本节边界:只讲 pandas 时间序列的基础处理,不展开完整回测系统、因子检验或实盘调度。
知识正文
1. 把时间序列想成“按日期排队的体检记录”
一只股票每天都有行情记录。
如果把这些记录随便打乱,就像把体检报告按随机顺序装订。
你看到 1 月 8 日在前,1 月 5 日在后,就很难判断变化过程。
时间序列的关键不是“有很多数字”。
关键是这些数字有先后顺序。
在 A 股量化研究中,顺序尤其重要。
今天的收盘价只能和之前已经发生的价格比较。
今天的公告只能在披露后影响研究判断。
如果你让程序不小心“看到未来”,结果会看起来很漂亮,却无法在真实交易中复现。
所以 pandas 处理时间序列的第一课,就是把日期处理清楚。
2. 日期列和日期索引有什么区别
DataFrame 里可以有一列叫“日期”。
这时日期只是普通字段。
你也可以把日期设为索引。
这时日期就变成每一行的时间标签。
类比一下。
普通日期列像表格里写着“体检日期”的一列。
日期索引像档案柜抽屉外面的日期标签。
当日期成为索引后,pandas 可以更自然地按时间切片、排序、重采样。
下面先创建一张顺序有点乱的小行情表。
import pandas as pd
data = {
"日期": ["2026-01-07", "2026-01-05", "2026-01-08", "2026-01-06"],
"股票代码": ["600000", "600000", "600000", "600000"],
"开盘价": [10.10, 10.00, 10.45, 10.20],
"最高价": [10.50, 10.25, 10.60, 10.28],
"最低价": [10.05, 9.95, 10.25, 10.00],
"收盘价": [10.45, 10.20, 10.30, 10.10],
"成交量": [1500000, 1200000, 1100000, 980000],
}
df = pd.DataFrame(data)
print(df)这张表的数据是手写的。
它故意把 2026-01-07 放在第一行。
如果直接计算收益率,就会拿错误的上一行做比较。
3. 转成日期类型,再设为索引
日期如果只是字符串,pandas 不一定知道它是时间。
所以第一步是转换日期类型。
第二步是把日期设为索引。
第三步是按日期排序。
df["日期"] = pd.to_datetime(df["日期"])
df = df.set_index("日期")
df = df.sort_index()
print(df)pd.to_datetime() 的作用是把文本日期转换成真正的日期类型。
set_index("日期") 把日期列放到索引位置。
sort_index() 按索引从早到晚排序。
这三步是 A 股日线数据处理的基本动作。
关键心得
只要涉及“上一天”“过去 N 天”“从左往右验证”,就必须先确认日期已经正确排序。
4. 交易日不是自然日
A 股不是每天都交易。
周末不开市。
法定节假日不开市。
有些股票还可能因为重大事项临时停牌。
所以你不能简单地把“下一天”理解为日历上的明天。
在量化数据里,“下一行”通常代表下一个已有记录的交易日。
比如 1 月 9 日是周五,下一条记录可能是 1 月 12 日周一。
如果中间遇到春节假期,间隔会更长。
这会影响收益率、滚动计算和数据对齐。
新手阶段先记住:不要强行补出每一个自然日,然后假装每天都交易。
5. 计算日收益率前先检查排序
排序完成后,再计算日收益率才更合理。
df["日收益率"] = df["收盘价"].pct_change()
print(df[["股票代码", "收盘价", "日收益率"]])pct_change() 使用上一行作为对比。
如果日期没排序,上一行就不是前一个交易日。
这类错误很隐蔽。
程序不会主动提醒你“顺序错了”。
它会认真地把错误顺序算完。
这也是量化开发需要严谨的原因。
6. 用日期切片观察一段时间
把日期设为索引后,可以按时间范围取数据。
window = df.loc["2026-01-06":"2026-01-08"]
print(window[["收盘价", "成交量"]])loc 可以按索引标签选择。
这里的意思是:取 2026-01-06 到 2026-01-08 之间的记录。
如果其中某一天不是交易日,结果里不会凭空出现那一天。
这和 A 股研究很贴近。
我们研究的是实际可交易记录,而不是日历上每一天。
7. 重采样:把日线装进周线篮子
重采样可以理解为“换一个时间篮子重新汇总”。
日线是一天天记录。
周线是把一周内的多个交易日合成一条记录。
例如开盘价用这一周第一条记录。
最高价用这一周最高值。
最低价用这一周最低值。
收盘价用这一周最后一条记录。
成交量用这一周合计。
weekly = df.resample("W-FRI").agg(
{
"开盘价": "first",
"最高价": "max",
"最低价": "min",
"收盘价": "last",
"成交量": "sum",
}
)
print(weekly)W-FRI 表示以周五作为一周结束的标签。
它不代表每周一定有周五交易。
如果周五是节假日,这一周的 last 会使用这一周内最后一个已有交易日。
如果整周没有交易记录,就可能出现空值。
常见误区
重采样不是随便平均价格。A 股 K 线汇总通常要分别处理开、高、低、收和成交量。
8. 停牌和节假日会怎样影响重采样
如果一只股票某几天停牌,日线表可能没有这些日期的交易记录。
也可能保留日期但价格为空或成交量为 0。
不同数据源处理方式不一样。
如果你不先理解数据来源,就直接重采样,周线结果可能被误读。
例如一周只有两天交易。
成交量合计自然会比五天交易的周少。
这不一定代表市场兴趣突然下降。
它可能只是交易日减少。
又比如停牌复牌后出现跳空。
这个价格变化不是普通连续交易造成的。
如果后续要研究收益,需要在记录中保留停牌和复牌信息。
本节不展开停牌规则细节,只强调:时间序列不是机械日期表,它承载了交易制度。
9. 数据对齐:让不同表站在同一天说话
量化研究常常不止一张表。
一张是价格表。
一张是公告表。
一张可能是财务披露表。
数据对齐就是让这些表按同一个时间标准合在一起。
例如我们做一个极简公告示例。
events = pd.DataFrame(
{
"日期": ["2026-01-06", "2026-01-08"],
"事件": ["业绩预告披露", "临时停牌提示"],
}
)
events["日期"] = pd.to_datetime(events["日期"])
events = events.set_index("日期")
aligned = df.join(events, how="left")
print(aligned[["收盘价", "事件"]])join(..., how="left") 的意思是以价格表的日期为主,把同日期的事件贴上去。
没有事件的日期就留空。
这只是最小示例。
真实研究还要关心事件是什么时候披露、投资者当时是否可见。
第 6 章提过“可得性”,在这里仍然重要。
10. 不能把未来信息提前对齐
假设公司在 1 月 8 日晚间披露业绩预告。
那这条信息通常不能用于 1 月 8 日盘中的决策。
如果你把它简单贴到 1 月 8 日整天,并用来解释当天收盘前的操作,就可能“偷看未来”。
时间对齐不是只看日期相同。
还要看信息在当时是否已经可见。
新手阶段可以先用一个保守原则。
如果不确定公告是在盘前、盘中还是盘后可见,就不要把它用于当天买卖判断。
宁可把它放到下一交易日观察。
这个原则虽然简单,但能帮助你远离很多纸面研究陷阱。
11. 时间序列处理流程
graph TD
A["拿到行情 DataFrame"] --> B["确认日期字段"]
B --> C["转换为日期类型"]
C --> D["设为日期索引"]
D --> E["按日期排序"]
E --> F["检查交易日缺口"]
F --> G["计算收益率或重采样"]
G --> H["与事件或财务数据对齐"]
H --> I["记录可得性假设"]这条流程不复杂。
但每一步都关系到研究是否可信。
A 股有节假日、停牌、涨跌停、公告披露时点。
这些制度因素会进入数据表。
所以时间序列处理不是纯技术小技巧,而是投资事实的整理方式。
交互实验室
练习 1:观察排序前后的差异
运行本节最开始的乱序 DataFrame。
先不要 sort_index(),直接计算一次 pct_change()。
再执行 sort_index() 后重新计算。
请比较两次结果。
你会看到同样的收盘价,只要顺序不同,日收益率就会不同。
练习 2:找出一段时间窗口
请用 loc 取出 2026-01-06 到 2026-01-08 的数据。
然后只显示收盘价和成交量。
思考:如果 2026-01-07 是停牌日而数据中没有这一行,你的窗口结果会怎样变化?
练习 3:手动新增一个停牌样例
把数据改成少一行 2026-01-07。
再次执行重采样。
观察周线的开盘价、最高价、最低价、收盘价和成交量。
请写一句话:交易日减少会怎样影响周成交量?
练习 4:给公告做保守对齐
假设 2026-01-08 晚间披露公告。
请在笔记里写下你的处理规则。
可以采用:“如果公告披露时点不清楚,就从下一交易日开始观察影响”。
这不是最精细的方法,但适合新手避免提前使用未来信息。
核心复盘
知识清单:
- [ ] 时间序列的核心是顺序,日期错位会让收益率和观察结论失真。
- [ ]
pd.to_datetime()、set_index()、sort_index()是处理日期数据的基础三步。 - [ ] A 股交易日不同于自然日,节假日和停牌会影响数据间隔。
- [ ]
resample()可以把日线汇总成周线,但开高低收和成交量要分别处理。 - [ ] 数据对齐不仅是日期相同,还要考虑信息当时是否可见。
- [ ] 不确定披露时点时,保守地从下一交易日观察更安全。
金句总结
时间序列不是一串数字,而是一条按交易制度发生的投资时间线。
风险提醒
排序错误、自然日与交易日混淆、停牌缺口和未来信息提前对齐,都会让量化研究结果看起来合理却无法真实复现。