python 分段拟合 判别_利用Python检验你的策略参数是否过拟合(转)

2023-11-19

过拟合现象

一般来说,量化研究员在优化其交易策略参数时难免会面临这样一个问题:优化过后的策略在样本内表现一般来说均会超过其在样本外的表现,即参数过拟合。

对于参数优化来说,由于优化时存在噪音,过拟合是不可避免的现象。然而为了追求策略的稳定性,我们应当尽可能地使过拟合风险最小化。

为了检测在一个策略的参数优化过程中的过拟合风险,David H. Bailey等人在2015年发表了一篇名为《THE PROBABILITY OF BACKTEST OVERFITTING》的文章,

给出了一种估计参数过拟合概率的方法,本文将对此方法作较为详细的阐述。

主要思路

David H. Bailey等人的主要思路是这样的:对于一个策略的参数优化过程来说,我们能够获得一系列的样本内以及样本外的策略收益率序列,

并能够使用它们计算出策略的评价指标,如夏普比率,收益回撤比等等。是故,他们定义了这样一个概率空间(T,F,P) ,其中T为样本内指标与样本外指标的组合组成的集合,

如(样本内夏普比,相应的样本外夏普比)。在这样一个概率空间内,我们可以认为当我们选择最优的样本内参数时,我们得到的样本外策略表现劣于平均样本外策略表现的概率,即为参数过拟合的概率。

主要框架

为了计量过拟合的概率,David H. Bailey等人使用了一种类似交叉验证的方法来对一个经过参数优化的策略回报矩阵重采样。

第一步

我们在其参数空间上随机采样,得到N组不同的参数以及它们所对应的收益率序列,将其拼接成一个大矩阵M,其形状为TxN,T即是策略的回测时长。

第二步

我们将矩阵M以一定的步长L按行分割为S个不同的区块,如从第1行到第L行为第一个区块,第L+1行到第2L行为第二个区块等。

第三步

我们对这些不同的小矩阵随机分为两组,一组代表随机抽样产生的样本内组,另一组便是样本外组。我们将这些分块矩阵重新按照时间顺序拼接起来,得到了抽样的样本内收益率序列以及相应的抽样的样本外收益率序列。

第四步

我们计算重新抽样后N个不同参数的策略的样本内收益率序列评价指标(如夏普比率),以及相应的N个样本外收益率序列评价指标。计算完成后,我们需要观察样本内最优策略对应的样本外策略的表现。在这里,我们使用Rank以及Relative Rank = Rank / (N + 1)来评价样本外策略的表现。此外,我们还使用Logit = Log(Relative Rank / (1 - Relative Rank))作为样本外策略表现的评价指标,注意到它是关于Relative Rank的增函数,是故样本外策略表现越好,其评价值便越大。此外,我们也能够获得样本内的最优夏普比率以及样本外相应的夏普比率。

第五步

我们需要估计第四步中Logit统计量的分布,是故我们需要对第三步~第四步进行重复操作,操作的次数由我们自己决定,次数越多,其估计所得分布越稳健。

代码实现

本文使用Python3 + WinPython初步实现了该方法,其所用到的包主要为numpy。此外,对于结果的可视化展示以及进一步分析还使用了pandas,matplotlib,seaborn以及sklearn。

首先,实现该方法的代码如下:

#Overfitting Test

defPBOTest(rets,SampleTimes,block_len):'''Probability of Overfitting Test Based On Return Matrix and Sharpe Ratio Inputs:

rets: Return Matrix with shape of TxN indicating N backtesting result using different params

SampleTimes: Overfitting Indicator Sample

Size block_len: Bootstrap Block Length Outputs:

PBO: Probability of Overffiting

POS: Probability of Getting Loss OutOfSample

rd: Overfitting Indicator Logit

ratios: Sharpe Ratios of Optimal InSample and of respective OutOfSample'''

#Compute Through the Framework

N = rets.shape[1]

S= len(rets)//block_len

M= rets[:(block_len*S)]

Ms=M.reshape((S,block_len,N))

training_part_block= S//2 + S%2rd=np.zeros(SampleTimes)

ratios= np.zeros((SampleTimes,2))for i inrange(SampleTimes):

rnd_num=np.random.rand(S).argsort()

TPartOrder=np.sort(rnd_num[:training_part_block])

VPartOrder=np.sort(rnd_num[training_part_block:])

TJ= Ms[TPartOrder].reshape((training_part_block*block_len,N))

VJ= Ms[VPartOrder].reshape(((S-training_part_block)*block_len,N))

TSharpe= np.mean(TJ,axis = 0)/np.std(TJ,axis =0)

VSharpe= np.mean(VJ,axis = 0)/np.std(VJ,axis =0)

Vrelative_rank= (1 + VSharpe.argsort().argsort())/(N + 1)#Compute rd

T_n_best =np.argmax(TSharpe)

VT_n_best_rank=Vrelative_rank[T_n_best]

logit= np.log(VT_n_best_rank/(1-VT_n_best_rank))

rd[i]=logit#Compute Ratio

ratios[i,0] =TSharpe[T_n_best]

ratios[i,1] =VSharpe[T_n_best]

PBO= np.sum(rd<=0) /SampleTimes

POS= np.sum(ratios[:,1] <= 0) /SampleTimesreturn PBO,POS,rd,ratios

View Code

我们来进一步分析一下这段代码:

N = rets.shape[1]

S= len(rets)//block_len

M= rets[:(block_len*S)]

Ms=M.reshape((S,block_len,N))

training_part_block= S//2 + S%2rd=np.zeros(SampleTimes)

ratios= np.zeros((SampleTimes,2))

这一段代码定义了回测中我们从参数空间抽取参数进行回测的次数N,以及区块的长度block_len和区块的个数S,并且如果rets的行不能整除S,我们便舍去除不尽的部分,最后得到的矩阵为M。Ms为一个三维矩阵,是经过分块的矩阵的组合。training_part_block是我们在第三步中需要抽取的小矩阵的个数。rd,ratios分别是最终结果统计量Logit以及夏普比率的预分配空间。

rnd_num =np.random.rand(S).argsort()

TPartOrder=np.sort(rnd_num[:training_part_block])

VPartOrder=np.sort(rnd_num[training_part_block:])

TJ= Ms[TPartOrder].reshape((training_part_block*block_len,N))

VJ= Ms[VPartOrder].reshape(((S-training_part_block)*block_len,N))

这一段代码主要实现了框架中的第三步以及第四步,如重新采样等。首先我们生成一串长度为S的随机数,利用argsort函数得到其下标的排序rnd_num。其次,我们利用前training_part_block个下标作为组成样本内矩阵的下标TPartOrder,并且重新拼接形成TJ。VPartOrder以及VJ同理。

TSharpe = np.mean(TJ,axis = 0)/np.std(TJ,axis =0)

VSharpe= np.mean(VJ,axis = 0)/np.std(VJ,axis =0)

Vrelative_rank= (1 + VSharpe.argsort().argsort())/(N + 1)

然后,我们计算样本内所有策略的夏普比率TSharpe以及样本外所有策略的夏普比率VSharpe,并且计算得到代表样本外策略表现的Relative Rank的Vrelative_rank。

#Compute rd

T_n_best =np.argmax(TSharpe)

VT_n_best_rank=Vrelative_rank[T_n_best]

logit= np.log(VT_n_best_rank/(1-VT_n_best_rank))

rd[i]=logit#Compute Ratio

ratios[i,0] =TSharpe[T_n_best]

ratios[i,1] = VSharpe[T_n_best]

接下来,我们能够计算得到最优样本内策略对应的样本外Realative Rank以及Logit统计量,并且将其赋值给预先分配好的空间。

PBO = np.sum(rd<=0) /SampleTimes

POS= np.sum(ratios[:,1] <= 0) / SampleTimes

最后,我们计算出过拟合的概率PBO,即为Logit统计量小于0的概率。POS为样本外策略夏普比率为负的概率,即优化出亏损策略的概率。

框架测试

那最后让我们来尝试一下这一个框架吧。我们首先下载得到上证指数从2010年1月1日到2017年5月16日之间的日行情,利用pandas进行读入。我们使用简单的均线策略进行测试:如快线上穿慢线即做多,快线下穿慢线做空。其参数为快线的计算长度以及慢线的计算长度。暂时不设止损线。策略的代码如下:

def MA(close,num = 5):

res= [close[0]*1]for i in range(1,len(close)):if i >=num:

res.append((res[-1]*num - close[i-num] + close[i])/num)else:

res.append((res[-1]*i + close[i])/(i+1))

res=np.array(res)returnresdef backtest(data,params = [],num = 100,money = 1e6):

Fastlen,Slowlen,thdAB,stoploss=params

high= data['high'].values

low= data['low'].values

close= data['close'].values

hlen=len(close)

profit=np.zeros(hlen)

Ama=MA(close, Fastlen)

Bma=MA(close, Slowlen)

opened=False

long=False

opened_price=0for i inrange(hlen):if notopened:if Ama[i]/Bma[i] - 1 >thdAB:

opened=True

long=True

opened_price=close[i]

profit[i]= -close[i]*0.0002*numelif Ama[i]/Bma[i] - 1 < -thdAB:

opened=True

long=False

opened_price=close[i]

profit[i]= -close[i]*0.0012*numelse:iflong:

profit[i]= (close[i] - close[i-1])*numif Ama[i] < Bma[i] or low[i]/opened_price - 1 < -stoploss:

opened=False

profit[i]= profit[i] - close[i]*num*0.0012

else:

profit[i]= (close[i-1] - close[i])*numif Ama[i] > Bma[i] or high[i]/opened_price - 1 >stoploss:

opened=False

profit[i]= profit[i] - close[i]*num*0.0002rets= profit /money

equity= np.cumprod(1 +rets)return rets,equity

View Code

利用回测函数,我们能够得到相应的收益率序列以及净值曲线。

我们对该策略进行参数的重采样,有:

X = np.arange(5,120)

rets= np.array([backtest(data,[x,2*x,0,1],100)[0] for x in X]).T

便能够得到我们需要的收益率序列矩阵,对其进行策略参数过拟合测试:

np.random.seed(0)

PBO,POS,rd,ratios= PBOTest(rets,SampleTimes = 1000,block_len = 50)

我们得到了其过拟合的概率以及亏损的概率。在该例子中,他们分别为70.2%以及 56.3%。此外,我们可以对结果进行进一步的分析:

np.random.seed(0)

PBO,POS,rd,ratios= PBOTest(rets,SampleTimes = 1000,block_len = 50)#Histgram of Dist of logit

plt.figure(figsize = (10,6))

plt.title('Distribution of Logit')

plt.hist(rd,bins= 20)#Performance Degration

model =sl.LinearRegression()

model.fit(ratios[:,0].reshape((-1,1)),ratios[:,1])

plt.figure(figsize= (10,8))

plt.title('Performance Degration')

plt.plot(ratios[:,0],ratios[:,1],'.')

plt.plot(ratios[:,0],model.decision_function(ratios[:,0].reshape((-1,1))),'-')

plt.xlabel('IS Sharpe Ratio')

plt.ylabel('OOS Sharpe Ratio')

该图显示了Logit统计量的分布。

该图形象地显示出了随着样本内夏普比率的上升,样本外的夏普比率的变化趋势。

总结

本文实现了David H. Bailey等人的方法对策略过拟合的概率进行了测试。该方法有一个特点,那便是我们仅仅需要回测收益率序列便能够对其是否过拟合进行测试,其测试的本质实质上是看样本内以及样本外策略的盈利能力的延续性,以及优化过程中是否所有的时间段的策略表现都会随着参数的变化而同时被优化。利用该方法,我们通过估计过拟合的概率,能够在一定程度上评估策略的稳健性。

作者:时风_瞬

链接:http://www.jianshu.com/p/3bd86cca96bd

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python 分段拟合 判别_利用Python检验你的策略参数是否过拟合(转) 的相关文章

  • QT添加qss文件和资源文件

    先右键项目 选择 Add New 选择一个模板 选择 Qt 模板 再选择 Qt Resource Files 点击 Choose 填上资源文件的名称 默认添加项目路径下 后面的步骤默认即可 点击完成 新建完成了资源文件后 默认会进入 res
  • 运放稳定性连载21:电容性负载的稳定性——具有双通道反馈的RISO(2)

    现在 我们必须测量如图10 6所示的Zo 小信号AC开环输出阻抗 该Tina SPICE测试电路将测试空载OPA177的Zo R2和R1以及LT为低通滤波器函数提供了一条AC通道 这样 使得我们能将DC短路和AC开路一起并入反馈电路 DC工
  • ssh报错no key alg(关于低版本连接高版本ssh)

    高版本 8 4 低版本 4 3 按照网上的方法试过 通过ssh keygen命令重新生成ssh主机秘钥 可以不用重启sshd服务 ssh keygen t rsa f etc ssh ssh host rsa key ssh keygen
  • NoReverseMatch: Reverse for ‘data‘ not found . ‘data‘ is not a valid view function or pattern

    Django gt python manage py runserver时报错 NoReverseMatch Reverse for data not found data is not a valid view func tion or
  • 制作一辆“自动驾驶”平衡自行车需要用到哪些知识

    目录 先看下小车效果 小车电路设计 相关软件工具 keil C语言设计编码调试工具 主要 mcuisp 代码烧录工具 一般使用一种烧录工具就可以 STM32 STlink stlink烧录工具 STM32 Cube pro 烧录工具 ope
  • C++中的虚函数(表)实现机制以及用C语言对其进行的模拟实现

    本文是转载的 正版是https blog twofei com 496 欢迎去看正版 C 中的虚函数 表 实现机制以及用C语言对其进行的模拟实现 前言 大家都应该知道C 的精髓是虚函数吧 虚函数带来的好处就是 可以定义一个基类的指针 其指向
  • OceanBase使用范例

    http www mysqlops com 2011 08 31 oceanbase use html OceanBase的使用类似于关系型数据库 需要预先创建schema 关于schema的格式 请参见schema说明 假如我们有以下sc
  • c#Socket 异步通讯(客户端与服务端)

    c Socket 异步通讯 多个客户端与服务端 最近公司有个项目 涉及到的通讯对象有点多 就拿其中一个库的通讯来说就用到了3个PLC 这里就涉及了一个服务器与多个客户端之间的通讯了 同时上位机既需要做客户端 也需要做服务端 因为跟PLC之间
  • HTTP响应详解, HTTP请求构造及HTTPS详解

    HTTP响应详解 认识 状态码 status code 状态码表示访问一个页面的结果 是访问成功 还是失败 还是其他的一些情况 以下为常见的状态码 200 OK 这 是一个最常见的状态码 表示访问成功 抓包抓到的大部分结果都是 200 例如
  • numpy load npz文件

    一 问题 numpy version 1 23 0 优化项目的是时候发现索引一个dict的时候很慢 因此进行分析 速度很慢的问题代码如下 arr dict np load test npz npz 100MB for i in range
  • 神州网信远程、关闭屏幕时间、关闭神州网信密码

    一 远程查看电脑 按 windows r 输入gpedit msc 运行组策略 gpedit msc 进行下面的操作 1 计算机配置 管理模板 Windows组件 远程桌面服务 远程桌面会话主机 连接 允许用户通过使用远程桌面服务进行远程连
  • Qt creator4.8.0 以上使用SqLite数据库进行数据操作

    文章目录 前言 一 在 pro工程文件中添加sql模块 二 使用步骤 1 添加头文件 2 链接并打开数据库 3 创建用户信息表management info 4 插入数据操作 5 修改数据库操作 6 查询数据库 总结 前言 Qt creat
  • 基于MATLAB的filter的使用,低通、带通和高通滤波器设计

    1 目的 学习MATLAB的filter函数的使用 通过设计低通 带通和高通滤波器对其进行仿真 2 用到的主要函数和工具 MATLAB FDATOOL filter fft 3 设计 信号的产生 Parameter Interface Fr
  • java高级开发面试题总结

    面试题总结 JAVA高级工程师 近期考虑换工作的问题 于是投简历面试 面试5家公司的高级Java工程师 有4家给了我offer 想着总结一下面试经验 方便最近正在寻求机会的你们 一 无笔试题 不知道是不是职位原因还是没遇到 面试时 都不需要
  • 阿里云轻量应用服务器使用指南适用于所有人

    最近一直在捣鼓阿里云服务器 想着把自己写好的一些项目部署到服务器上供其他人访问 一路上踩了不少坑 也查了不少资料 最后解决了 写个博客记录下来 也为其他想要建站的同学提供一个指引 购买轻量应用服务器 传送门 阿里云 如果是在校学生 可以直接
  • SpringCloud之Hystrix

    1 服务熔断与降级 在微服务架构中多层服务之间会相互调用 如果其中有一层服务故障了 可能会导致一层服务或者多层服务 故障 从而导致整个系统故障 这种现象被称为服务雪崩效应 SpringCloud 中的 Hystrix 组件就可以解决此类问题
  • 有时间再看decode详解

    Oracle 中 decode 函数用法 含义解释 decode 条件 值1 返回值1 值2 返回值2 值n 返回值n 缺省值 该函数的含义如下 IF 条件 值1 THEN RETURN 翻译值1 ELSIF 条件 值2 THEN RETU
  • 冲刺春招-精选笔面试 66 题大通关 day6

    day6题目 33 搜索旋转排序数组 54 螺旋矩阵 bytedance 006 夏季特惠 学习计划链接 冲刺春招 精选笔面试 66 题大通关 今日知识点 二分 模拟 01背包 难度为中等 中等 字节 简单 33 搜索旋转排序数组 整数数组
  • ARouter(二)源码解析

    前言 这一篇我们来具体看一下ARouter的实现原理 如果你之前没有接触过ARouter 可以先阅读上一篇 Android 从零开始打造自己的深度链接库 一 ARouter简介 废话不多 我们赶紧分析源码 正文 首先我们从github下载最

随机推荐

  • 中文信息处理实验8——基于逻辑斯蒂回归模型的文本分类

    目录 实验目的 实验要求 实验内容及原理 参考代码 实验结果 实验目的 加深对汉语文本信息处理基础理论及方法的认识和了解 锻炼和提高分析问题 解决问题的能力 通过对具体项目的任务分析 数据准备 算法设计和编码实现以及测试评价几个环节的练习
  • win10系统C盘出现感叹号及加密图标解除

    近期遇到Win10系统C盘图标加密情况 经过搜索查找最终解决 并对操作进行简单记录 1 以管理员身份打开命令行窗口 2 输入 manage bde off c 3 相关指令 加密指令 manage bde on c 查看状态指令 manag
  • 使用定时框架Quartz.net时,发布到服务器后无法正常执行定时任务

    问题描述 使用Quartz net每天定时执行某个任务时 未能正常执行 每次在本地测试时 设置了短的时间间隔 都能正常执行任务 但是挂到服务器后 设置定时执行时间为几个小时 却不能正常执行我们要执行的操作 原 因 IIS的程序池有一个闲置超
  • _Linux网络数据包的揭秘以及常见的调优方式总结

    作为业务 SRE 我们所运维的业务 常常以 Linux TCP UDP daemon 的形式对外提供服务 SRE 需要对服务器数据包的接收和发送路径有全面的了解 以方便在服务异常时能快速定位问题 以 tcp 协议为例 本文将对 Linux
  • 自己封装一个类express路由框架

    今天用了Node封装一个简单的类似express框架的路由 首先先看看 没封装 之前的server路由代码 const http require http const url require url const ejs require ej
  • Java变量与常量书写方式与规范

    变量 变量是什么 变量是可以变化的量 Java是一种强类型语言 每个变量都必须声明其类型 Java变量是程序中最基本的存储单元 其要素包括变量名 变量类型和作用域 type varName value varName value 数据类型
  • 链表指定区间反转

    题目 反转从位置 m 到 n 的链表 请使用一趟扫描完成反转 说明 1 m n 链表长度 输入 1 gt 2 gt 3 gt 4 gt 5 gt NULL m 2 n 4 输出 1 gt 4 gt 3 gt 2 gt 5 gt NULL 头
  • java公钥签名,ping++ java验签(签名,公钥,charge)怎么获取

    packageexample importjava io FileInputStream importjava security InvalidKeyException importjava security KeyFactory impo
  • Halcon模板匹配

    Halcon模板匹配 Halcon模板匹配的方法 模板匹配的流程 基于形状的模板匹配的思路 原理 Halcon模板匹配的方法 模板匹配的流程 基于形状的模板匹配的思路 读取图像 转灰度图 dev close window dev open
  • vue项目打包部署到linux tomcat服务器,解决一刷新就报错404问题

    1 部署到服务器前 更改webpack配置 修改index js中以下配置 2 运行npm run build 或者cnpm run build命令 打包完成后 在项目的根目录dist文件下生成了如下文件 3 tomcat的webapps创
  • 问题解决——使用串口调试助手发送控制字符 协议指令 <ESC>!?

    问题解决 使用串口调试助手发送控制字符 协议指令 参考文章 1 问题解决 使用串口调试助手发送控制字符 协议指令 2 https www cnblogs com wlsandwho p 4202094 html 备忘一下
  • 丁鹏:多角度回顾因果推断的模型方法

    来源 集智俱乐部 本文约23000字 建议阅读20 分钟 本文整理自丁鹏老师的8篇短文 从多角度回顾了因果推断的各种模型方法 导读 推断因果关系 是人类思想史与科学史上的重要主题 现代因果推断的研究 始于约尔 辛普森悖论 经由鲁宾因果模型
  • 云服务器是什么? 云服务器有哪些选择?

    欢迎前往我的个人博客云服务器查看更多关于云服务器和建站等相关文章 随着互联网技术的发展和云计算技术的应用 越来越多的企业倾向于使用云服务器来满足其不断增长的计算需求 云服务器是一种基于云计算技术的虚拟服务器 它能够为企业提供高性能 可靠 灵
  • 【算法竞赛】Python快速入门指南

    该指南由GPT4编写 用于快速入门蓝桥杯Python组 当然 仅限入门而已 本指南由GPT 4生成 我只是负责引导 并对内容进行整理和补充 一直以来我都是使用C 作为算法竞赛语言 但是奈何C 组太卷 自己又太菜 于是另谋他路 Prompt模
  • 【AD20】快速且只选中部分自己想要的同类型的元件

    在project属性框里面 可以选择所有如下图所示内容 这个是一个过滤器 里面有多种小选项 比如 Components 元件 Pads 焊盘 Texts 文本 选择哪个就只能选择对应的部分 比如 只选择文本 在画图区域 框选 发现只有文本才
  • 数位拆分

    4 数位拆分v1 0 现有一个4位数的正整数n 4321 即n是一个已知的数 固定为4321 编写程序将其拆分为两个2位数的正整数43和21 计算并输出拆分后的两个数的加 减 乘 除和求余的结果 例如n 4321 设拆分后的两个整数为a b
  • 【目标检测】OneNet: Towards End-to-End One-Stage Object Detection

    label assignment是指 在训练过程中如何将某个prediction指定给某个GT 用于计算损失 训练网络 对于上一篇文章 他们首先用one to one label assignment替换了one to many label
  • 生信学习——Linux必做20题(附详细答案解读)

    题目列表 1 在任意文件夹下面创建形如 1 2 3 4 5 6 7 8 9 格式的文件夹系列 2 在创建好的文件夹 home qiime2 Desktop test 1 2 3 4 5 6 7 8 9 下创建文本文件 me txt 3 在文
  • C#中unsafe的使用

    1 unsafe在C 程序中的使用场合 实时应用 采用指针来提高性能 引用非 net DLL提供的如C 编写的外部函数 需要指针来传递该函数 调试 用以检测程序在运行过程中的内存使用状况 2 使用unsafe的利弊 好处是 性能和灵活性提高
  • python 分段拟合 判别_利用Python检验你的策略参数是否过拟合(转)

    过拟合现象 一般来说 量化研究员在优化其交易策略参数时难免会面临这样一个问题 优化过后的策略在样本内表现一般来说均会超过其在样本外的表现 即参数过拟合 对于参数优化来说 由于优化时存在噪音 过拟合是不可避免的现象 然而为了追求策略的稳定性