首页 / 资讯中心 / 文章详情

【Python量化策略评估体系 #05】极端行情扛得住吗?2008/2015/2020 三场景压力测试

【Python量化策略评估体系 #05】极端行情扛得住吗?2008/2015/2020 三场景压力测试 ★ FEATURED ARTICLE
回测曲线一路向东北夏普 1.8你很满意。但放进 2008 年会怎样2015 年连续跌停呢2020 年疫情那种 V 型急跌呢不在极端行情里测过的策略上线就是裸奔。压力测试不是看历史最大回撤那么简单。本文教你用蒙特卡洛 三场景冲击量化组合在极端行情下的尾部风险。一、本文你将得到什么三种典型极端场景的冲击设计2008 金融危机、2015 股灾、2020 疫情。蒙特卡洛模拟 1000 条路径输出中位数、5% 分位、最大回撤、VaR、ES。一段可直接运行的 Python 脚本输入你的策略收益率就能跑压力测试。二、为什么做压力测试历史回测只告诉你「过去发生过什么」压力测试告诉你「如果再次发生会怎样」2008系统性暴跌 流动性枯竭资产相关性趋近于 1。2015杠杆断裂 连续跌停波动率和左尾同时放大。2020突发黑天鹅 政策救市急跌后快速反弹V 型走势。一个策略如果在三种场景下都死不掉才有资格谈稳健。三、压力测试设计思路我们用历史日收益率分布作为「基础分布」然后叠加三类冲击均值下挪整体收益环境变差。波动放大标准差乘 2~3 倍。结构冲击2008随机加入 -5% 跳空左尾。2015前 5 日连续 -7%。2020前 1/3 急跌、中 1/3 震荡、后 1/3 反弹。每个场景模拟 1000 条路径观察组合净值分布。四、代码实战importjsonimportrandomimportnumpyasnpfrommairuiimportClient DEMO_LICENCELICENCE-66D8-9F96-0C7F0FBCD073# 演示证书请换成你自己的正式证书CODE600519INIT_NAV100000.0# 初始组合净值POSITION_RATIO0.6# 股票仓位 60%defperturb_ohlc(bars,seed2026091305):rngrandom.Random(seed)out[]forbinbars:k1.0(rng.random()-0.5)*0.10nbdict(b)forfin(o,c,h,l):iffinnbandnb[f]isnotNone:nb[f]round(float(nb[f])*k,2)out.append(nb)returnoutdefmax_drawdown(nav_path):peaknp.maximum.accumulate(nav_path)dd(nav_path-peak)/peakreturnfloat(dd.min())defvar_es(returns,alpha0.05):sorted_rnp.sort(returns)idxint(alpha*len(sorted_r))varsorted_r[idx]essorted_r[:idx].mean()returnfloat(var),float(es)defscenario_paths(base_returns,scenario,n_path1000):rbase_returns.copy()nlen(r)paths[]ifscenariocrisis_2008:mu_shift-0.003vol_mult3.0for_inrange(n_path):shocksnp.random.normal(mu_shift,r.std()*vol_mult,n)jumpsnp.random.rand(n)0.05shocks[jumps]-0.05navINIT_NAV*np.cumprod(1shocks*POSITION_RATIO)paths.append(nav)elifscenariocrash_2015:for_inrange(n_path):shocksnp.random.normal(-0.002,r.std()*2.5,n)ifn5:shocks[:5]-0.07navINIT_NAV*np.cumprod(1shocks*POSITION_RATIO)paths.append(nav)elifscenariopandemic_2020:for_inrange(n_path):shocksnp.random.normal(0,r.std()*2.0,n)t1,t2n//3,2*n//3shocks[:t1]np.linspace(-0.04,-0.01,t1)shocks[t1:t2]np.random.normal(0,0.015,t2-t1)shocks[t2:]np.linspace(0.01,0.04,n-t2)navINIT_NAV*np.cumprod(1shocks*POSITION_RATIO)paths.append(nav)returnnp.array(paths)defsummarize(paths):final_navpaths[:,-1]total_returns(final_nav-INIT_NAV)/INIT_NAV mdds[max_drawdown(p)forpinpaths]daily_returnsnp.diff(paths,axis1).flatten()/paths[:,:-1].flatten()var,esvar_es(daily_returns,0.05)return{期末净值中位数:round(float(np.median(final_nav)),2),期末净值 5% 分位:round(float(np.percentile(final_nav,5)),2),总收益率中位数:f{float(np.median(total_returns))*100:.2f}%,总收益率 5% 分位:f{float(np.percentile(total_returns,5))*100:.2f}%,最大回撤中位数:f{float(np.median(mdds))*100:.2f}%,最大回撤 95% 分位:f{float(np.percentile(mdds,95))*100:.2f}%,日收益 VaR(5%):f{var*100:.2f}%,日收益 ES(5%):f{es*100:.2f}%,}np.random.seed(20260913)clientClient(DEMO_LICENCE)barsperturb_ohlc(client.stock_history(codeCODE,periodd,dividendf))closesnp.array([float(b[c])forbinbars])base_returnsnp.diff(closes)/closes[:-1]scenarios{2008 金融危机系统性暴跌 左尾跳空:crisis_2008,2015 股灾连续跌停 高波动:crash_2015,2020 疫情V 型急跌反弹:pandemic_2020,}result{基础日收益统计:{样本数:int(len(base_returns)),均值:f{float(base_returns.mean())*100:.4f}%,标准差:f{float(base_returns.std())*100:.4f}%,},压力测试结果:{},}forname,keyinscenarios.items():pathsscenario_paths(base_returns,key,n_path1000)result[压力测试结果][name]summarize(paths)print(json.dumps(result,ensure_asciiFalse,indent2))五、运行结果演示环境{基础日收益统计:{样本数:49,均值:0.0936%,标准差:3.8243%},压力测试结果:{2008 金融危机系统性暴跌 左尾跳空:{期末净值中位数:75266.25,期末净值 5% 分位:34923.93,总收益率中位数:-24.73%,总收益率 5% 分位:-65.08%,最大回撤中位数:-46.00%,最大回撤 95% 分位:-22.86%,日收益 VaR(5%):-11.75%,日收益 ES(5%):-14.64%},2015 股灾连续跌停 高波动:{期末净值中位数:72580.76,期末净值 5% 分位:38035.42,总收益率中位数:-27.42%,总收益率 5% 分位:-61.96%,最大回撤中位数:-38.51%,最大回撤 95% 分位:-20.64%,日收益 VaR(5%):-9.27%,日收益 ES(5%):-11.69%},2020 疫情V 型急跌反弹:{期末净值中位数:98450.61,期末净值 5% 分位:58464.43,总收益率中位数:-1.55%,总收益率 5% 分位:-41.54%,最大回撤中位数:-32.82%,最大回撤 95% 分位:-16.00%,日收益 VaR(5%):-7.72%,日收益 ES(5%):-9.69%}}}关键结论2008 / 2015组合大概率腰斩5% 分位下亏损超过 60%说明单一高仓位策略在极端行情下非常脆弱。2020中位数接近回本但 5% 分位仍亏损 41%说明 V 型反弹对大多数人只是「幸存者偏差」尾部风险不可忽视。六、常见坑与注意不要把历史最大回撤当压力测试。历史最大回撤只是过去发生过的最坏情况不代表未来。仓位是核心变量。示例里股票仓位 60%如果你仓位 90%所有损失数字会再放大 1.5 倍。不要只跑一个场景。三种场景分别测试系统性暴跌、流动性危机、黑天鹅 V 型漏掉任何一种都可能踩雷。演示证数据窗口有限。正式环境换自己的 licence 后可用更长的历史窗口做 bootstrapping模拟结果会更稳定。七、小结压力测试的价值不是预测未来而是让你知道「如果 2008 重来我会亏多少」。让你在上线前决定是否降仓位、加对冲、或重写策略。让你在客户问起时有数字而不是有信仰。下篇预告【Python量化策略评估体系 #06】策略上线前 8 项必查一份可落地的评估 checklist。了解更多代码与文档https://github.com/MaiRuiApi免责声明本文仅为技术方法演示不构成投资建议。历史表现不代表未来收益投资有风险入市需谨慎。
阅读完成 · 觉得有帮助?
咨询建站