主要采用支持向量机算法,参考两篇文章:
1.傅航聪,张伟.机器学习算法在股票走势预测中的应用.软件导刊,2017年10日第16卷第10期:31-34,46.
2.文成.基于机器学习方法的股票数据研究.重庆理工大学硕士学位论文(2011年).
主要参考第二篇。传统技术分析过多依靠主观判断。
文章使用了开盘价,收盘价,最高价,最低价,成交量,成交额这六个指标,先对数据进行归一化到[1,2]。
1 | # 准备数据 |
将收盘价上移一行作为目标值,即预测第二天的收盘价。
在对数据没有先验知识的情况下,选择高斯径向基核函数。
先用默认参数让模型跑起来。
用2018年的数据进行训练,80%的训练集,20%测试集。
模型评分: 0.9551444471554572
再用2019年的数据进行验证:
验证数据模型评分: 0.7667456601663809
还不错。
改进一下,用今天以前的五天的数据来预测今天的收盘价。
遇到一个问题是如何准备训练特征,直接用每五天的数据组成新的特征,用第六天的收盘价作为目标值,进行训练,结果sklearn报错,称只接受小于等于二维的数据。于是直接用reshape函数把特征数据拉成二维,再进行训练。
测试数据的评分为:-1.3774486958961827
验证数据的评分:0.6959191032444751
验证数据评分降了很多,测试数据的模型评分居然成了负值。有没有办法改进呢?更换核函数看看,试了一圈,线性核函数效果最好,测试集评分0.35,验证集评分0.91。画图看看。
看着还行。但是再来比较一下模型预测涨跌的准确率吧。
模型预测涨跌准确率:0.495798,跟瞎猜一样的……可能是将五天数据合并成一天有问题吧,我是直接合并成一个列表。应该组合成一个五行六列的矩阵作为一个特征值,但是sklearn的fit只接受n×m的二维矩阵。要不试试用5天的平均数来作为特征值。尝试结果,是完全一样的。再做个试验:用前五天收盘价的均值作为第六天的预测值,看看结果如何。
结果是预测准确率0.516807,一样的。
现在进行调参,主要是惩罚参数C(默认值1.0)和核函数参数ε(取值范围[0.0001, 0.1], 默认值0.1)两个。
调参方法有穷举法,网格搜索法,交叉验证法,粒子群算法,遗传算法等。
先用网格搜索法。最佳参数:{‘C’: 1000, ‘epsilon’: 0.1, ‘kernel’: ‘linear’}
模型预测涨跌准确率:0.520833
是比前面提升了一点,但是提升太少。尝试缩小搜索的间隔,结果……
模型参数: {‘C’: 11, ‘epsilon’: 0.0901, ‘kernel’: ‘linear’}
最佳模型准确率评分 -1.023333747321061
模型预测涨跌准确率:0.479167
更差了!
试试其它方法。
粒子群算法(Particle Swarm Optimization,PSO),先看基础知识
是受鸟群觅食规律启发想出来的。其优点是收敛速度快、参数少、算法简单易实现。其基本思想是粒子之间共享信息使群体找到最优解。粒子有位置和速度两个属性,速度表示粒子下一步迭代的移动方向和距离,位置是所求问题的一个解。算法的六个参数:粒子速度、位置、个体最优解、群体最优解、个体历史最优适应值(个体搜索到最优解时的优化目标的函数值)、群体历史最优适应值。
算法流程(我就直接搬运上文的图啦,图源见水印,致谢!)
迭代时粒子速度更新的公式有三项,分别是惯性部分(对之前运动状态的继承),认知部分(粒子自己的经验),社会部分(其它粒子共享的经验)。
算法的参数有:粒子群规模N(推荐[20, 1000]),粒子维度D(自变量个数),迭代次数K(推荐[50, 100]),惯性权重w(不宜固定,越大,全局寻优能力越强,局部寻优能力越弱,推荐[0.4,2]),学习因子c1c2(c1粒子自己经验所占比重,c2群体经验所占比重)。
大致了解了一下原理,接下来就实操吧。找到一篇现成的用粒子群算法进行SVR调参的文章
照搬就行了。
具体到我们的SVR模型调参的问题,粒子群规模为每个参数取值范围大小,粒子群维度为待寻优参数的个数,粒子群位置为参数的具体数值,粒子群方向为参数取值变化方向,适应度为粒子对应的模型评价指标。gbest为全局历史最优解,pbest为粒子个体历史最优解。
粒子速度更新公式:
vi =w×vi + c1×rand()×(pbesti − x i) + c2×rand()×(gbest − xi)
位置更新公式:
xi =xi + vi
下面看具体代码:
1 | # 粒子群算法进行SVR调参 |
运行结果
迭代次数: 500 最佳参数: [1.4696656179315561, 0.0001] 最佳适应度: 0.6041666666666666
最终参数: [1.4696656179315561, 0.0001] 验证数据模型评分: 0.7564837943259253 模型预测涨跌准确率: 0.495798
用预测涨跌的准确率作为适应度计算函数,最终结果还是等于瞎猜。
时间越长,预测结果与真实值相差越大。
改改粒子群算法参数看看。改变不大,准确率还是50%左右。
最后再试试遗传算法。它是借鉴了自然界的遗传,进化机制,通过遗传、交叉、变异、选择等,保留较优个体,淘汰较差个体,最终找到最优个体。选择、交叉、变异是遗传算法的基本操作。
还是找一篇现成的
尝试了半天,还是有bug没法顺利运行,于是再找找,果然有现成的库:scikit-opt。
用pip install scikit-opt安装。
文档地址
先测试一下。
1 | from sko.GA import GA |
然后就用遗传算法进行调参,具体代码太长,上github去看吧。运行了半天,最后结果:
准确率51.6%,回测年化收益率29.4%,好像不行……
可以看到开始还行,到后面误差越来越大。
看资产净值图也能看出来,到后半段直接就没交易了。
尝试失败,不过主要的收获在于学会了用粒子群算法和遗传算法来调参的方法,还有个体会:在python里很多常规的问题都有相应的库,别上来就自己造轮子。聚焦自己的主要问题吧。
本文代码
我发文章的三个地方,欢迎大家在朋友圈等地方分享,欢迎点“在看”。
我的个人博客地址:https://zwdnet.github.io
我的知乎文章地址: https://www.zhihu.com/people/zhao-you-min/posts
我的微信个人订阅号:赵瑜敏的口腔医学学习园地