拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Python复现衍生品对股价波动性实证:GARCH、OLS与代码链路

简介这份面向金融工程与量化分析学习者的论文复现文档以Python为工具完整还原上市公司衍生品使用对股价波动性影响的实证研究流程。内容覆盖数据预处理、股价波动率与贝塔系数计算、双向固定效应面板回归建模并延伸至内生性工具变量处理、规模异质性分析、中介路径剖析及多种稳健性检验最终通过预测与敏感性测试验证模型鲁棒性。资源包仅含1个docx文件大小28KB虽轻量却集中呈现了从变量定义到结论验证的完整代码与逐段解释适合对照论文理解每一步操作逻辑。目前已有220人学习下载对希望掌握面板数据建模、时间序列波动率测算与金融因果推断的读者而言可作为一份可落地的复现代码笔记与排错参考。1. 用Python复现衍生品波动性实证先说清楚这个题目在做什么拿到“金融领域使用Python分析衍生品对股价波动性的实证研究论文复现含详细代码及解释”这个标题的读者多半已经在别处看过几篇研报复现帖发现代码能跑但结论对不上。这篇笔记是我个人对这个题目的完整拆解从行情数据下载、波动率估计到回归检验每一步用什么Python库、参数怎么设、为什么这么设、失败时看哪里全部摊开讲。适合正在做量化研究、写毕业论文、或者刚进入金融数据分析岗位想独立验证一篇论文结论的从业者。核心就一句话衍生品活跃度到底是在给标的股价波动率“加噪声”还是“加信息”这个问题靠Python把数据处理、估计、检验串成一条可复现的链路才真正有答案。2. 数据准备从yfinance取行情到衍生品活跃度指标2.1 数据源选择用yfinance拿股票与期权链快照的边界复现这类论文首先要面对的是数据从哪来。常见做法是用yfinance库直接拿股票日线数据它免费、无需注册、接口简单适合快速搭原型。但这里有个边界衍生品的历史日频数据比如每日期权成交量、每日未平仓量yfinance并不提供完整历史序列它只能给你“当前”的期权链快照。所以完整复现时衍生品活跃度需要用替代指标来构造常见的有期权链快照成交总量、正股成交量比值OIR或者干脆用隐含波动率指数作为衍生品市场情绪的代理。import numpy as np import pandas as pd import yfinance as yf # 下载苹果公司日线数据auto_adjustTrue 让价格自动复权避免除权跳空污染收益率 stock yf.download(AAPL, start2015-01-01, end2023-12-31, auto_adjustTrue) close stock[Close] log_ret np.log(close / close.shift(1)).dropna() # 抓当前期权链快照用于构造衍生品活跃度截面指标 tk yf.Ticker(AAPL) option_dates tk.options[:6] # 取最近6个到期日 snapshots [] for d in option_dates: chain tk.option_chain(d) calls chain.calls puts chain.puts snapshots.append({ date: d, call_volume: calls[volume].sum(), put_volume: puts[volume].sum(), call_oi: calls[openInterest].sum(), put_oi: puts[openInterest].sum(), }) snapshot_df pd.DataFrame(snapshots)逻辑说明第一个代码块中auto_adjustTrue会调整历史价格以反映拆股和分红这避免了收益率序列里出现假跳变。注意shift(1)这一步它把价格序列整体下移一行close / close.shift(1)就是“今天除以昨天”取对数后就是连续复利收益率。参数说明start和end决定了样本区间论文复现时一般要覆盖至少一个完整牛熊周期五年起步tk.options[:6]取前六个到期日是因为近月合约流动性最好、交易最活跃更能反映衍生品交易热度。这里必须坦白期权链快照只有当天数据没法重构历史序列。所以后续建模时如果坚持用期权成交量就只能做截面回归验证“某一天期权交易活跃的股票其当天波动率是否更高”。如果想做时间序列面板回归更现实的衍生品活跃度替代指标是隐含波动率指数或者用新闻热度、搜索量这类外部数据。论文读到的“衍生品交易量显著影响标的波动率”结论背后用了什么样的数据频率直接影响你复现时能复现到什么程度——这一步想清楚了后面才不会被数据缺口卡死。2.2 收益率与滚动波动率对数收益率和年化口径怎么算实证研究里波动率很少直接用价格计算而是带在收益率上。最简单的波动率估计是历史滚动标准差——把过去N天的收益率当成一个样本窗口计算标准差后年化。这里有两个参数要定窗口长度N和年化因子。窗口选5天得到周度波动率选22天得到月度波动率选252天得到年度波动率。金融论文里最常见的组合是22天窗口和sqrt(252)年化这样日度波动率就被换算成年化百分比可以直接和期权隐含波动率对比。# 22个交易日约等于一个月年化因子 sqrt(252) 把日波动率换成年度口径 monthly_vol log_ret.rolling(22).std() * np.sqrt(252) weekly_vol log_ret.rolling(5).std() * np.sqrt(252)逻辑说明rolling(22).std()做的事情是从第一个数据点开始每次取连续22个收益率算一个标准差然后窗口向后滑动一天。这样得到的波动率序列天然带有“随时间变化”的特征能反映波动率聚集现象——大波动后面跟着大波动。参数说明年化因子的数学依据是独立同分布假设。如果收益率是独立同分布的n天的累计方差等于单日方差的n倍所以标准差乘sqrt(n)。一年大约252个交易日所以日波动率乘sqrt(252)。但注意如果你的数据是周度频率年化因子要换成sqrt(52)是月度就换sqrt(12)。很多复现时数字差好几倍就是年化因子用错了。用对数收益率而不用普通收益率是因为对数收益率可加性更好两天的连续复利收益率可以直接相加得到累计收益率而且它近似服从正态分布符合GARCH族模型的分布假设。普通收益率只能做乘积数学处理上麻烦得多。这个选择不是偏好问题是后面接GARCH模型时能否顺利收敛的前提。2.3 衍生品活跃度指标OIR与期权未平仓量怎么落到面板上有了波动率序列还需要一个代表衍生品活跃度的解释变量。我一般用OIR也就是期权总成交量与正股成交量的比值。逻辑很直观股票本身成交清淡但期权成交活跃说明衍生品市场在价格发现中扮演了更重要的角色这种信息结构差异会反映到股价波动上。OIR的数据构造如下。# 假设stock_df包含正股成交量列 Volume stock_volume stock[Volume] # 用前面抓到的期权链快照把看涨看跌的成交量合并 total_option_volume snapshot_df[call_volume].sum() snapshot_df[put_volume].sum() # 构造当日OIR截面单日 oir_today total_option_volume / stock_volume.iloc[-1] # 如果要做面板把每天的期权链快照汇总后拼进DataFrame panel pd.DataFrame(indexlog_ret.index) panel[vol_22d] monthly_vol panel[ret] log_ret panel[stock_volume] stock_volume逻辑说明OIR大于某个阈值比如1时说明期权市场成交量已经超过正股市场衍生品交易者主导了信息传递。这个比值做截面比较时要注意流动性差异——小盘股的期权成交天然不活跃OIR普遍偏低归回时要控制市值因子否则结论会有偏。参数说明如果拿不到历史期权成交量退而求其次的方案是用未平仓量OI的变化量。OI增加代表新开仓减少代表平仓只有新开仓才对波动率的边际影响最大。snapshot_df[call_oi].sum()是没用的要差分后再用。不过同样受限于yfinance不提供历史快照这一步只能验证当日截面关系。真正做完整面板时我建议直接换数据源或者换隐含波动率指数不要在一个拿不到的数据维度上硬耗——这是复现论文时最容易钻进死胡同的地方。3. 波动率估计GARCH(1,1)与EWMA的参数设置和Python实现3.1 波动率代理指标的三个层次与选择原则滚动波动率虽然直观但它有个致命弱点窗口内所有天数的权重相等过去22天前的那天和昨天对今天波动率的贡献一样大。这不符合金融市场的直觉——昨天的冲击对今天的影响应该远大于一个月前。所以论文里更常用的是EWMA指数加权移动平均和GARCH广义自回归条件异方差模型。选哪个当波动率代理指标直接影响后续回归的显著性EWMA波动率更平滑GARCH波动率能捕捉波动率聚集滚动波动率则会引入大量序列自相关干扰回归标准误。我的一般原则是主回归用GARCH条件波动率稳健性检验用EWMA滚动波动率只做交叉验证。3.2 用arch包在Python里拟合GARCH(1,1)命令与参数Python里拟合GARCH模型最顺手的库是arch。GARCH(1,1)的数学形式是当前条件方差等于一个常数项、上一期收益率平方项和上一期条件方差项的线性组合。它意味着今天的波动率不仅受昨天实际收益冲击影响还受昨天波动率水平影响这就是波动率聚集能被建模的原因。from arch import arch_model # 用对数收益率拟合带常数均值的GARCH(1,1) model arch_model(log_ret, meanConstant, volGARCH, p1, q1, distnormal) result model.fit(dispoff) print(result.summary()) # 提取条件波动率序列作为后续回归的因变量 conditional_vol result.conditional_volatility逻辑说明meanConstant表示均值方程只估计一个常数不在均值里引入AR项。复现论文时这个设置够用但如果收益率序列有显著的一阶自相关就改成meanAR。p1, q1是GARCH族最经典的配置绝大多数金融时间序列用这一个组合就够描述波动率特征加高阶容易过拟合。参数说明distnormal假设标准化残差服从正态分布这是基准设置。很多论文会说收益率有厚尾这时把dist换成t让模型自己估计自由度往往能明显改善拟合优度。dispoff关掉了迭代过程输出跑批量循环时不会刷屏。拟合完要看两个数alpha[1]是上一期收益冲击的系数beta[1]是上一期条件方差的系数两者之和越接近1说明波动率的持续性越强。我见过不少复现里alpha估计出来是负的或者不显著一旦出现这种情况先检查收益率序列里有没有极端异常值再看要不要换成Student-t分布这两个原因解决了大半问题。3.3 EWMA和历史波动率的Python实现参数怎么定EWMA波动率不需要估计参数公式固定今天的方差等于lambda乘昨天的方差加1减lambda乘昨天的收益率平方。最关键的是lambda取值。RiskMetrics给出的经典值是0.94意思是昨天的权重是0.94新冲击只占0.06。这个值在日度数据上表现稳定想更灵敏就把lambda降到0.90但代价是波动率序列会变得很毛糙回归时噪声变大。def ewma_vol(returns, lam0.94): var np.zeros_like(returns, dtypefloat) var[0] returns.iloc[0] ** 2 for i in range(1, len(returns)): var[i] lam * var[i - 1] (1 - lam) * returns.iloc[i - 1] ** 2 return pd.Series(np.sqrt(var * 252), indexreturns.index) ewma_vol_series ewma_vol(log_ret)逻辑说明这个迭代式体现的核心思想是指数衰减——越久远的数据对今天的影响按指数速度衰减。var[i-1]前乘0.94昨天的收益率平方前乘0.06合起来权重之和等于1保证方差序列是无偏的。参数说明lam0.94是日度数据的经验值如果用周度数据要降到0.97左右因为低频数据的自相关更强。这个参数不建议自由发挥除非你有明确理由。EWMA的优势是不需要优化算法几行代码就能跑出来适合当GARCH的对照——如果两个波动率序列在回归里得出的结论方向不一致那说明结论对波动率度量方式太敏感论文的稳健性存疑。这里也提醒一个新手常踩的坑GARCH和EWMA给出的都是日度条件波动率要用np.sqrt(252)年化后才能和滚动波动率对比。忘记年化会导致回归系数量级差几十倍而且不同波动率代理之间数值不可比。把三个序列画在一张图里检查量级是否一致是正式回归前必做的一步我的习惯是先画图再跑模型不做这一步就回归等于闭眼开车。4. 实证回归设计衍生品活跃度对波动性的检验步骤4.1 基准OLS回归与解释变量分层波动率序列有了衍生品活跃度指标也有了接下来就是实证回归。第一步不能上来就堆变量而是先跑一个最简模型波动率对衍生品活跃度指标回归控制条件放最少。这样能看出去掉所有干扰后衍生品活跃度和股价波动性之间有没有最朴素的相关关系。这看起来简单但意义很大后续每加一个控制变量这个系数的变化轨迹就是在告诉你结论的稳健性边界在哪。import statsmodels.api as sm # 组装面板数据 df pd.DataFrame({ vol: conditional_vol, # GARCH年化条件波动率 ret: log_ret, # 当日收益率 stock_volume: stock_volume, # 正股成交量 oir: oir_series, # 衍生品活跃度指标 }) # 基准模型只放OIR X1 sm.add_constant(df[[oir]]) y df[vol] model1 sm.OLS(y, X1).fit() print(model1.summary()) # 扩展模型加入收益率和正股成交量作为控制 X2 sm.add_constant(df[[oir, ret, stock_volume]]) model2 sm.OLS(y, X2).fit() print(model2.summary())逻辑说明sm.add_constant会给解释变量矩阵加一列全1对应截距项。model1里如果oir的系数显著为正说明衍生品活跃日标的波动率更高为负则说明衍生品交易平抑了波动。但model1的问题很明显——它没控制正股自身的成交活跃度而股票的成交量和波动率本来就有强相关不控制就会把“股票交易活跃导致的波动”误记到衍生品头上。参数说明基准模型里ret作为控制变量是为了剔除收益率方向对波动率的不对称影响stock_volume取原始值即可但如果你发现系数量级奇怪可以取对数因为成交量的分布右偏严重对数变换能让它更接近正态。这一层模型的系数要是和model1方向相反多半是OIR构造有问题比如分母用了未复权的成交量。检验基准模型输出时重点看oir的t值和p值。p值大于0.05说明统计上不显著但别急着下结论——先看样本量。如果只有几百个交易日不显著可能只是功效不足扩样本后再看才是正路。4.2 加入市场因子后的稳健性回归单只股票的波动率里有相当一部分是市场系统性波动不是个股特有信息。所以严谨的做法是把市场波动率或市场收益率放进去当控制变量。常见的做法是引入SPY标普500ETF的收益率和波动率把市场层面的冲击从个股波动率里剥离出来。这个步骤如果省略复现出来的系数很可能被系统性风险污染——2020年这种年份所有股票的波动率都在涨你会错误地归因于衍生品交易。# 下载SPY作为市场代理 spy yf.download(SPY, start2015-01-01, end2023-12-31, auto_adjustTrue) spy_ret np.log(spy[Close] / spy[Close].shift(1)).dropna() df[spy_ret] spy_ret.reindex(df.index) df[oil_volume] df[stock_volume] / df[stock_volume].rolling(22).mean() # 标准化成交量 X3 sm.add_constant(df[[oir, ret, stock_volume, spy_ret]]) model3 sm.OLS(y, X3).fit() print(model3.summary())逻辑说明spy_ret在这里扮演两个角色一是剔除系统性收益冲击对个股收益率的同步影响二是间接控制市场波动状态。reindex(df.index)确保SPY的收益率严格对齐到个股交易日索引上这一步经常因为交易日不齐而出NaN后面踩坑章节会详细说。参数说明标准化成交量stock_volume / rolling(22).mean()是为了去除成交量的长期趋势——股票成交量随市值增长年年变大不标准化的话这个变量在多年样本里会带时间趋势造成伪回归。标准化后它代表的是“相对过去一个月今天的成交量放大了还是缩水了”这才是控制变量的正确口味。加了spy_ret之后重点观察oir系数有没有大幅变小。如果变小说明原始基准模型里有一部分效应其实是市场波动贡献的衍生品活跃度本身的边际解释力没那么强。这不是坏事恰恰是复现论文时最有价值的发现——论文结论在你这个样本上到底站不站得住答案就在这里。4.3 子样本期回归不同市场状态下的结论差异衍生品和波动率的关系不是铁板一块。低波动率环境下期权交易者少衍生品对股价的影响弱高波动率环境下比如2020年疫情冲击对冲需求暴增衍生品交易量飙升这时OIR与波动率的正相关会更显著。如果全样本回归出一个不温不火的系数拆开看子样本期往往能看到完全不同的图景。pre_mask df.index 2020-01-01 post_mask df.index 2020-01-01 for name, mask in [(2015-2019, pre_mask), (2020-2023, post_mask)]: sub df[mask].copy() X_sub sm.add_constant(sub[[oir, ret, stock_volume, spy_ret]]) model_sub sm.OLS(sub[vol], X_sub).fit() print(f {name} ) print(model_sub.summary())逻辑说明布尔索引df.index 2020-01-01直接切出样本区间sub是原DataFrame的一份拷贝避免切片赋值时的SettingWithCopyWarning。逐段跑回归并对比系数是论文里“分样本稳健性”的常规操作。参数说明切分点选2020年不是随意的——疫情导致全球市场波动率结构突变以这个点为界两段样本的波动率特征差异足够大。你也可以参考VIX指数的走势图来选结构突变点而不是机械地按年份切。这个步骤最有价值的地方在于它告诉你论文结论的成立条件。如果前一段不显著、后一段显著那说明衍生品对波动率的影响不是线性的、稳定的而是依赖于市场状态的。写结论时不能写“衍生品提升波动率”要写“高波动时期衍生品活跃度与波动率正相关”。这种措辞上的差别正是一篇有说服力的实证研究和一篇看似严谨实则在过度解读的复现之间的分界线。拆子样本是论文复现里成本最低、信息量最大的稳健性检验没有之一。5. 论文复现避坑5个让结果对不上的常见问题与排查5.1 日期索引错位导致merge后全是NaN现象跑回归时发现样本量从2000多掉到几百解释变量那一列为空。原因yfinance返回的DataFrame索引带时区信息而自己构造的Panel里日期是纯日期两者类型不一致时reindex或merge会把所有日期匹配失败返回NaN。另一个常见原因是股票和SPY的交易日历不完全一致美国市场有节假日个股和ETF的停牌日也可能不同。解决统一先reset_index()把日期变成普通列用pd.to_datetime统一格式再用howinner做merge丢弃不匹配的日期。merge之后用dropna()清一遍确保没有残余空值进入回归。5.2 GARCH拟合报奇异矩阵或收敛失败现象model.fit()报错提示Singular matrix或者迭代几百次后结果里alpha为负。原因收益率序列里有极端异常值比如某天涨跌超过20%正态分布假设被厚尾破坏方差方程的迭代矩阵接近奇异。另一个常见原因是收益率序列未清理停牌日连续多个0收益率会把波动率瞬间压到零附近。解决先对收益率做winsorize处理把上下0.5%分位的极端值截断到分位数边界再把distnormal换成distt厚尾分布对异常值容忍度高很多。如果还不行检查数据里是否有连续重复的0值有就把这些日期删掉。这一步不处理后面所有波动率序列都是错的。5.3 回归结果换个样本期就翻车现象用2015-2019年数据回归OIR系数显著为正换成2020-2023就变成不显著甚至符号反转。原因衍生品活跃度与波动率的关系存在状态依赖性。2020年之后波动率整体抬升所有股票的波动率都在涨OIR的边际解释力被市场因子吸收而在低波动期衍生品交易量的边际信息含量更突出。还有一个可能是两个时期里你用的期权快照流动性差异很大。解决先跑子样本回归确认方向差异然后不要试图用全样本调和出“唯一正确答案”。论文复现的价值就该体现在这里——同一个模型在不同市场状态下结论不同这是发现而不是错误。报告两段结果并说明原因比强行删数据改出显著性好得多。5.4 期权历史数据拿不到别在结构缺口上硬拼现象想在日度面板里放期权成交量作为连续解释变量发现yfinance只能给当前快照历史序列完全缺失。自己动手天天跑脚本抓数据抓了几个月发现存下来的数据结构混乱无法使用。原因yfinance的期权接口设计就是获取当前市场状态不是历史数据接口。这是工具的结构性限制不是代码能绕过的。硬抓数据只会浪费大量时间在数据清洗上。解决换思路。用隐含波动率指数比如VIX对SPY或者个股的已实现波动率与历史波动率之差作为衍生品市场情绪的代理指标从公开数据源直接下载。或者重新设计研究问题改成截面回归在某一天比较不同股票的OIR与其当日波动率的关系。这样既能用上期权快照又不与数据结构缺口硬碰。5.5 Windows系统跑代码报msvcp140.dll找不到现象刚配好的VSCode环境里import pandas或arch时直接报错由于找不到msvcp140.dll无法继续执行代码代码完全跑不起来。原因arch和statsmodels这类科学计算库在Windows上依赖微软Visual C运行库。新装的系统或精简版系统缺这个运行库pip安装时又不自动附带。解决安装Microsoft Visual C Redistributable2015-2022 x64版本装完重启终端即可。如果你用的是VSCode装完运行库后记得在设置里确认Python解释器指向你创建虚拟环境的那一个因为VSCode左侧选择解释器和终端里实际生效的解释器可能不一致这又是个隐性坑。这个坑本身和金融模型无关但它能卡住你半天时间属于典型的环境血泪经验。6. 用模拟数据先验证整条代码链路一个省时间的进阶技巧6.1 构造带波动率聚集的模拟价格序列真实数据里就算结果显著你也无法确定是代码写对了还是数据碰巧撞出了个显著。我的习惯是先用模拟数据把“数据下载-波动率估计-回归检验”整条链路跑通确认每个环节输出正常之后再换真实数据。模拟数据的优势是生成参数完全已知比如设定alpha0.08、beta0.90跑完GARCH之后如果估计出来的参数和设定值偏差不大说明估计代码没有问题。np.random.seed(42) n 3000 omega_true, alpha_true, beta_true 0.05, 0.08, 0.90 sigma2 np.zeros(n) eps np.zeros(n) for t in range(1, n): sigma2[t] omega_true alpha_true * eps[t-1] ** 2 beta_true * sigma2[t-1] eps[t] np.sqrt(sigma2[t]) * np.random.standard_t(5) sim_ret pd.Series(eps * 0.01, indexpd.date_range(2015-01-01, periodsn, freqD))逻辑说明这个循环严格按照GARCH(1,1)定义生成数据先算今天的条件方差用昨天的收益率平方和昨天的方差再从t分布里抽一个随机数作为标准化残差乘上标准差得到今天的收益率。用t分布而不是正态分布是为了模拟真实收益率的厚尾特征。参数说明np.random.seed(42)固定随机种子保证模拟数据可复现。eps * 0.01把收益率倍数调整到实际量级避免方差数值过大影响GARCH估计数值稳定性。自由度设5的t分布尾部比正态更厚更接近真实行情。6.2 用模拟数据跑通指标构建-估计-回归三段代码生成模拟数据之后不要直接丢进GARCH就完事。要把真实数据流程完整走一遍先算22日滚动波动率再拟GARCH提取条件波动率然后构造一个假的OIR序列比如直接用某个正态随机数加正股模拟成交量跑一次完整回归。重点不是回归系数而是确认每一段代码在数据形态真实时都不会报错、不会出现莫名NaN。# 模拟正股成交量与OIR sim_volume pd.Series(np.random.lognormal(mean15, sigma0.5, sizen), indexsim_ret.index) sim_oir pd.Series(np.random.uniform(0.3, 1.5, sizen), indexsim_ret.index) # 重复第3章的GARCH估计和第4章的回归流程 sim_model arch_model(sim_ret, meanConstant, volGARCH, p1, q1, distt) sim_res sim_model.fit(dispoff) print(sim_res.params[[alpha[1], beta[1]]]) sim_df pd.DataFrame({ vol: sim_res.conditional_volatility, ret: sim_ret, stock_volume: sim_volume, oir: sim_oir, }) X sm.add_constant(sim_df[[oir, ret, stock_volume]]) sim_ols sm.OLS(sim_df[vol], X).fit() print(sim_ols.summary())逻辑说明用t分布拟合模拟数据时如果估计出的alpha和beta接近0.08和0.90就说明GARCH估计在厚尾数据上工作正常。回归部分OIR系数理论上应该不显著因为模拟数据里OIR完全独立于波动率生成——如果它显著了说明回归代码里有bug或变量构造时混入了未来信息。参数说明lognormal先生成正股成交量是为了模拟真实成交量的右偏分布uniform(0.3, 1.5)生成OIR这个范围参考了美股常见个股的实际OIR区间。模拟回归里OIR不显著是预期结果这恰好验证了回归代码不会“无中生有”地造出显著性。这一步做完你对代码链路的信心会强很多。真实数据复现时再出问题就可以把注意力集中在数据质量上而不是怀疑是估计函数用错了。6.3 模拟数据与真实数据的差距在哪里模拟数据能验证链路但永远验证不了经济结论。三组gap必须清楚。第一模拟数据没有跳跃与断点真实数据里有财报暴雷、熔断、突发事件这些极端事件会扭曲GARCH参数估计第二模拟数据没有杠杆效应即收益率为负时波动率上升更快真实数据里这一效应普遍存在需要用EGARCH或GJR-GARCH才能捕捉第三模拟数据没有时变参数真实世界里alpha和beta本身也在缓慢漂移十年样本里用固定参数的GARCH(1,1)本身就是近似。模拟数据是工程层面的保险丝不是经济结论层面的论证。跑完模拟验证后回到真实数据时要做好心理准备系数可能不显著、方向可能反转、子样本结论可能分裂。这些不是代码bug而是真实世界的复杂度。模拟链路帮我排除掉七成以上的低级错误剩下的变量和模型选择问题才是论文复现真正要花心思的地方。6.4 完整复现后如何判断论文结论是否仍然成立链路全通之后最终判断分三步走第一系数符号与原论文一致吗如果符号都反了先假设自己的数据或指标构造有误回头查日志再查代码但不要直接认定论文是错的——更可能是样本期不同导致的真实差异。第二显著性水平在子样本里稳定吗如果只在某一时期显著结论要降级为“特定市场状态下成立”。第三换波动率代理指标后结论是否一致GARCH和EWMA结果方向一致说明结论对度量方式不敏感不一致说明结论的依赖条件要明确写出来。三年的实际数据复现经验告诉我论文复现最大的收获不是验证别人对错而是被迫把数据、估计、检验每个环节的决策都暴露在阳光下。我现在的习惯是拿到一篇论文先花半天做模拟数据验证自己的代码链路再花两天下载和清洗真实数据最后半天跑回归。第一天晚上看到显著结果不要高兴第二天早上换个样本期跑一遍再下结论。希望帮到你。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门