FinMarketPy / 事件研究与季节性
事件研究与季节性:把「某类事件发生时市场怎么走」做成可核对的统计
官方 README 只用两句短语提到这块能力(“Investigate seasonality of trading strategies”“Conduct market event studies around data events”),但 economics/ 里的实现比这两句具体得多:EventStudy 负责事件日期与事件窗口,Seasonality 负责日历规律,VolStats 负责波动率统计。这一页把它们的方法结构、方法清单与最容易被做错的口径讲清楚,并给出中国大陆用户接中国宏观数据的两条可行路径。
economics/eventstudy.py 的方法结构与 README 中的事件研究示例);示意非官方流程图,事件口径需按你的研究设计确定。事件研究这一层有哪些方法可用
下表由 economics/eventstudy.py 源码实读(0.11.19)。这一层有两个类:EventStudy 与继承它的 EventsFactory,另有 HistEconDataFactory 负责历史经济数据。
| 方法 | 作用 | 典型用途 | 注意点 |
|---|---|---|---|
load_economic_events() | 载入经济事件清单 | 把非农、CPI、央行决议这类事件灌进来 | 事件清单要自己维护或有来源,库只负责读取与组织 |
harvest_category(category_name) | 按类别批量抓取事件 | 一次取某一类事件的全部日期 | 类别名要与你的数据源分类一致 |
get_economic_events() / get_all_economic_events() | 读取事件集合 | 核对事件表是否符合预期 | 做研究前先打印一遍事件数量与首尾日期 |
get_economic_event_date_time(name, event=None, csv=None) | 取单个事件的日期时间 | 把某个事件对齐到行情时间轴 | 事件时间戳的时区与行情时区必须一致,这是事件研究最常见的错位来源 |
get_economic_event_date_time_dataframe(...) | 批量取成 DataFrame | 把多个事件整理成可对齐的表 | 返回结构要与行情索引对齐后再运算 |
get_economic_event_date_time_fields(fields, name, event=None) | 取事件的指定字段 | 需要事件的预期值/实际值等附加信息时 | 字段可用性取决于数据源是否提供 |
create_event_descriptor_field(name, event, field) | 生成事件描述字段 | 给事件打标签,用于分组统计 | 标签体系决定你后面能切出哪些对比组 |
get_economic_event_vol_over_event_day(vol_in, name, event, start, end, realised=False) | 算事件日附近的波动率 | 回答「事件是否放大波动」 | realised 切换已实现/隐含口径;两者含义不同 |
get_daily_moves_over_event() | 事件期间的单日波动 | 看事件日的跳空与振幅 | 要明确「事件期间」的窗口定义 |
dump_economic_events_csv(path) | 把事件清单落成 CSV | 存档、复盘、别人复现 | 落盘是「可复现」的必要动作,别只在内存里跑 |
事件研究怎么做:四步与三处易错
事件研究看起来简单,但结论对口径极其敏感。四步里每一步都对应一个可核对的动作。
定事件清单:什么算一次「事件」
用
load_economic_events()/harvest_category()取事件表,或用dump_economic_events_csv(path)载入自建清单。易错点一:事件定义本身。同一个「非农」在不同来源下可能是发布日期、也可能是实际数据发布时间,两者差几个小时,跨时区后可能差一天。对齐时间轴:事件时间 vs 行情时间
用
get_economic_event_date_time(name, event)取到的时间戳要与行情表索引对齐(findatapy 提供时区工具)。易错点二:时区。美国数据按美东时间发布、行情按交易所时区,不统一就会出现「提前知道」的假象——这和未来函数是同一类问题。建窗口:事件日前后各取多少期
窗口长度(例如 [-5, +5] 交易日)必须显式写出来并保持一致。易错点三:窗口内有多个事件重叠时怎么处理——是要去重、还是要按事件数加权,官方不替你决定,但结论会不同。
做统计与画图
走势类用
get_daily_moves_over_event();波动类用get_economic_event_vol_over_event_day(...);分组对照用create_event_descriptor_field()先打标签。出图走 chartpy,把窗口内的平均路径与离散度一起画出来,比只画一条平均线更能说明问题。
季节性:日历规律怎么算、输出怎么看
官方这一层的方法比事件研究更少,但更容易被误用。
| 能/方法 | 签名与作用 | 典型输出 | 适用场景 | 注意点 |
|---|---|---|---|---|
Seasonality | time_of_day_seasonality(data_frame, years=False, seconds=False):按日内时段统计规律 | 按时段聚合的收益分布 | 日内交易时段效应、开盘/收盘效应 | 需要日内或更高频数据;years/seconds 控制更细的分组粒度 |
VolStats | adjust_implied_ON_fri_vol(data_frame):按周五/隔夜口径调整隐含波动率 | 调整后的波动率序列 | 跨周末的波动率研究 | 周末效应在周度数据上更明显,比较不同星期几时要先调整 |
| 官方示例方向 | gallery 里有黄金季节性与外汇波动率季节性两类图 | 月度/年度分布图 | 商品与外汇的日历效应 | 官方示例只覆盖这两个方向,没有 A 股示例 |
| 与回测的结合 | 季节性结论通常作为信号输入或过滤器 | 按月份/时段的策略表现分解 | 验证「某策略的收益是否集中在特定月份」 | 用 TradeAnalysis.run_day_of_month_analysis(resample_freq='B') 可以直接分解策略收益 |
| 季节性 ≠ 因果 | — | — | — | 样本期太短时,季节性极易被少数极端年份主导;务必做分年对照与样本外 |
PLANNED_FEATURES.md 把「更完整的季节性分析(例如分解出季节项与趋势项)」列为待办,说明当前实现更偏向分组统计而不是成熟的时序分解。如果你的研究需要严格的季节分解,要自己补这一步——官方声明以该文件为准。中国大陆用户怎么做中国宏观事件研究:两条路
官方示例是美元与商品方向,没有中国宏观事件的示例。下面两条路径都如实说明各自缺口。
| 路径 | 数据来源 | 怎么接进 finmarketpy | 缺口 / 注意点 |
|---|---|---|---|
| 路径一:自建事件清单 | 自己整理重要发布事件的日期时间(利率决议、CPI、PMI、GDP 等) | 整理成 CSV,经 dump_economic_events_csv() / get_economic_event_date_time(csv=…) 载入 | 要自己保证时间戳的时区与准确性;发布时刻与实际数据口径都可能调整,需标注采集时间 |
| 路径二:用免部署技能取宏观数据 | 免部署路线里的 akshare-finance 技能(文档列出 GDP/CPI/PMI/M2 等宏观接口) | 取到数据后整理成 DataFrame,再按路径一的方式做事件对齐与统计 | 技能侧是取数与一次性结论,不会替你搭事件研究框架;两者无已证实集成 |
| 行情侧(事件前后的价格) | findatapy 的免费源覆盖外汇与部分全球指数;A 股行情不在其 vendor 清单内 | 用 findatapy 取外汇/全球资产做事件研究最顺;A 股需另接数据 | 想研究「中国数据 → A 股反应」需要自己补齐 A 股行情(EAA 类技能或自建数据) |
| 时区处理 | 中国数据按北京时间发布、A 股按北京时间交易;但美元资产按美东时间 | 用 findatapy 的时区工具统一口径后再对齐 | 跨市场事件研究(中国数据 → 美元资产)最容易出错,务必显式记录时区 |
| 交易日历 | 中国节假日与欧美不同 | findatapy 提供日历工具,但需自己配置中国日历 | 用错日历会把「休市日」当成事件窗口的一部分 |
| 合规与口径 | 宏观数据的发布时间与修订机制由发布机构决定 | — | 历史数据会被修订,回测里用的是「当时公布值」还是「修订后值」必须写清——这是宏观研究最容易踩的坑 |
拿到窗口统计之后:怎么读、怎么避免过度解读
这一节是方法论,不是官方标准;但每一条都能对应到上面提到的实现细节。
| 你看到的 | 可能是真的 | 也可能是 | 下一步怎么查 |
|---|---|---|---|
| 事件窗口内平均收益为正 | 该类事件确实伴随某种方向性反应 | 少数几个极端年份主导了平均;或窗口有重叠事件重复计数 | 分年画对比、做中位数与分位数;检查窗口内事件重叠 |
| 事件日波动明显放大 | 事件确实抬高了短期波动 | 只是采样频率问题(事件日刚好有更多数据点) | 用 get_economic_event_vol_over_event_day(..., realised=…) 两种口径各跑一次对比 |
| 某月份表现特别好 | 存在日历效应 | 样本期太短,或该月份恰好赶上一次趋势行情 | 用 run_day_of_month_analysis() 做分月分解并看分年稳健性 |
| 某策略在特定时段有效 | 时段效应 | 参数过拟合到了那一段历史 | 做样本外切分(见回测体检第三层) |
| 叠加了成本之后效果消失 | 该效应太弱,扛不住摩擦 | 成本假设本身偏高 | 做成本敏感性:把 spot_tc_bp 从小到大扫一遍看结论是否翻转 |
事件研究与季节性常见问题
方法名与行为以 0.11.19 源码与官方示例为准;本站未实机运行。
事件数据要自己准备吗?
方向上是:库提供的是读取、组织、对齐与统计的框架(load_economic_events / harvest_category / get_economic_event_date_time),事件清单本身要么来自你的数据源,要么用 dump_economic_events_csv() 落成 CSV 自己维护。官方示例里的事件研究用的是经济数据源(FRED/ALFRED 一类)。个人建议:先把一份「小而准」的事件表维护好,再谈统计——事件表错了,后面全是错的。
为什么说时区是事件研究里最容易踩的坑?
因为事件时间与行情时间来自两套体系:美国数据按美东时间发布,外汇行情按交易中心时区连续交易,中国数据按北京时间。如果没统一口径就对齐,事件日可能整体错一期——结果是「策略提前知道了数据」,看起来效果很好,其实不成立。这和回测里的未来函数是同一类问题,处置方法也一样:显式统一时区并写进研究记录。
季节性分析最少要多少年数据?
本站不给具体年数(那会变成伪精确)。但可以给一个判断标准:如果某个「季节性」结论去掉收益最高的一两年就消失,那它大概率是样本期产物。实操上建议:分年画对比、看中位数而不只看均值、并把这个效应放到样本外区间验证。官方也把「更完整的季节性分解」列在待办里,说明当前实现不含严格的季节-趋势分解。
中国宏观数据怎么接?有没有现成的自动下载?
finmarketpy 与 findatapy 的官方资料里没有中国宏观数据的现成下载链路(示例是美元/黄金方向)。两条可行路径:一是自建事件清单 CSV(用 dump_economic_events_csv / csv= 参数载入);二是用免部署路线里 akshare-finance 技能取到 GDP/CPI/PMI/M2 等数据,再自己整理成表喂进来。第二条路线只解决取数,不替你搭事件研究框架,两者也无已证实集成。
宏观数据会不会被修订?对研究有影响吗?
会,而且影响很大。宏观数据普遍存在修订与口径调整,你今天取到的历史值不一定是当年发布时市场看到的那一版。如果事件研究用的是修订后数据,就相当于用了当时不存在的精确信息。处置:记录数据版本与取数时间;有条件时用「首次公布值」做事件研究,并用修订值做对照。
这一块有没有 本机技能能替代?
没有直接对应的技能。本机技能里能做的是取数(akshare-finance 的宏观接口、tushare-finance、mx-data 等)与技术面分析,没有事件研究框架或季节性分析技能。所以这里两条路线是「数据可互补、方法不重叠」,对比页也照此如实标注。