分享

利用机器学习模型,构建量化择时策略(附全流程代码)

 yliu277 2025-01-31

零. 机器学习,浅尝一下

人类发现规律一般采用的是归纳演绎法,对观察到的大量现象进行归纳,在心中形成规律,然后再遇到类似的情况,就可以迅速做出预测和判断,比如说“朝霞不出门,晚霞行千里”、“瑞雪兆丰年”、“狗打喷嚏天要晴”,这都是老祖先归纳演绎法的结晶,可能不是每回都灵验。

利用机器学习模型,构建量化择时策略(附全流程代码)

机器学习和人类的思考过程非常相似,把历史数据输入到模型当中,训练出一个能完成特定任务的数学模型,等到有新的数据出现时,就把新数据输入到训练好的模型当中,这就会输出一个预测的结果,特别地,机器学习在识别非线性规律方面,相较于人脑更有优势。

具体结合咱这次的目标进行说明,咱这次的任务就是利用机器学习模型,预测沪深300指数第二天的涨跌情况,输入的数据就是沪深300指数的开高低收行情数据,将这些数据输入到支持向量机(Support Vector Machine,SVM)当中进行模型训练,待SVM训练好之后,输入今天的行情数据,就能输出对第二天行情的预判。

为什么选择SVM呢?因为咱这次使用的数据集是沪深300指数的日线行情数据,它自2005年上市以来,拢共才四千多个交易日,换句话说,也才四千多个样本点,相对于几百万上千万的“大数据”来说,这充其量才算一个“小样本”,这无疑是一个非常适合SVM的应用场景。

因为在深度学习(一般需要大数据“投喂”)尚未全面兴起时,SVM由于其较高的小样本预测准确率,并且能够解决非线性分类问题,属于当时机器学习方法潮流圈中的扛把子。

SVM很能打,但本身并不是非常复杂,今儿个不抠数学细节,大白话讲讲SVM是什么有什么用,以免没开始就把大伙儿劝退了。

利用机器学习模型,构建量化择时策略(附全流程代码)

SVM最初的设计是用来解决二分类问题,后来扩展到多分类问题,“预测沪深300指数涨跌”就属于典型的二分类问题,“涨”是一个类别,“跌”就是另一个类别。

它通过寻找一个最大间隔超平面(上图黑斜线)将两类样本线性区分开来,并且保证两侧样本的最近边缘点到这个平面的距离是最大的,由于最大间隔超平面仅取决于两个类别的边缘点,例如上图中被红线和蓝线穿过的红点和蓝点,这些点就被称为支持向量,这就是“支持向量机”名称的由来。

但现实世界很奇妙,有线性可分的数据集,就有非线性可分的数据集,那遇到非线性可分的情况怎么办?

利用机器学习模型,构建量化择时策略(附全流程代码)

那也有办法,SVM引入了核函数,可以将低维不可分的数据映射到高维线性可分,如上图,二维不可分就映射到三维,常用的核函数有线性核、多项式核、高斯核(RBF核)和Sigmoid核。

利用机器学习模型,构建量化择时策略(附全流程代码)

但在现实当中,由于噪声和极端样本点的存在,数据集无论在低纬和高维都可能出现线性不可分的情况,于是乎,SVM当中引入了松弛变量的概念,允许了最大间隔超平面不用完美区分两个类别,允许错误分类的存在,SVM通过惩罚系数C控制这些错误分类的容忍程度,C值越高分类准确率越高,但数值过高容易导致过拟合,C值过低则会导致准确率受损。

SVM唠完了,咱来说说一般机器学习建模的流程,一般分为6步走,按照先后顺序分别是收集数据、准备数据、选择/建立模型、训练模型、测试模型和调节参数。量化,没有白走的路,每一步都算数,下文咱一步一步地走一遍~

利用机器学习模型,构建量化择时策略(附全流程代码)

一. 收集数据

巧妇难为无米之炊,第一步咱要获取到最原始的建模数据,对于指数的日线数据而言,有非常多的免费获取渠道,只要能获取到指数的日期(date)、开盘价(open)、最高价(high)、最低价(low)和收盘价(close)就可以了。

在此处以tushare为例,获取沪深300指数自2005年4月8日上市以来的全部行情数据,它是一个免费、开源的python财经数据接口包,网址是:http:///。

导入tushare包之后,使用它的get_k_data函数,就可以获得沪深300指数的历史K线数据,返回的数据格式是dataframe,咱只选取开高低收数据,并将日期(字符串格式)设置为索引。

import numpy as npimport pandas as pdimport talibimport warningswarnings.filterwarnings('ignore')import tushare as tsdata = ts.get_k_data(code='hs300', start='2005-04-08', end='2022-11-08', ktype='D')data = data.set_index('date')data = data[['open', 'high', 'low', 'close']]print('样本数目:%d' %data.shape[0])print(data.head(10))print(45*'-')print(data.tail(10))
利用机器学习模型,构建量化择时策略(附全流程代码)

二. 数据准备

有了原始数据之后,咱还要进一步进行加工和处理,主要工作是变量选择、确认标签和数据清洗。

变量选择在量化投资当中叫“因子选择”,就是用哪些因子(factor)进行选股择时那些,在机器学习领域一般叫“特征选择”,指定用哪些特征(feature)来作为算法模型的输入。

在这里咱用到因子分别是EMA值(ema)、价格波动率(stddev)、价格斜率(slope)、RSI值(rsi)和威廉指标值(wr),此处咱利用talib包丝滑地完成计算,它是一款量化圈驰名、彪悍强大的第三方技术分析指标计算包。

data['ema'] = talib.EMA(data['close'].values, timeperiod=20)data['stddev']= talib.STDDEV(data['close'].values, timeperiod=20, nbdev=1)data['slope'] = talib.LINEARREG_SLOPE(data['close'].values, timeperiod=5)data['rsi'] = talib.RSI(data['close'].values, timeperiod = 14)data['wr'] = talib.WILLR(data['high'].values, data['low'].values, data['close'].values, timeperiod=7)data.tail(10)
利用机器学习模型,构建量化择时策略(附全流程代码)

确认标签呢,就是给这个样本点打上类别标签,由于咱是预测指数第二天的涨跌情况,于是,咱先计算出每个样本第二天的涨幅(pct),如果第二天上涨,则设置标签(rise)为1,反之为0。

由于指数数据一般异常情况不是很多,如果有空值,咱把空值删除就好了。

data['pct'] = data['close'].shift(-1) / data['close'] - 1.0data['rise'] = data['pct'].apply(lambda x: 1 if x>0 else 0)#删除缺失值data = data.dropna()data.tail(10)
利用机器学习模型,构建量化择时策略(附全流程代码)

三. 选择/建立模型

选择/建立模型就是需要确定自己这次使用哪种机器学习模型,是支持向量机SVM呢,还是神经网络NN呢,亦或是随机森林RF呢,或者其他的模型。

在之前已经说过了,咱是用SVM模型,原因和原理不再赘述,为了方(tou)便(lan)实现和建立模型,咱可以直接从Scikit-learn(简称sklearn)中导入,它是非常流行的Python免费机器学习库 ,具有各种分类、回归和聚类算法,一般配合numpy数据格式使用。

四. 训练模型

在这里,咱需要把整个数据集分拆为训练集和测试集,因为除了训练模型之外,咱还要留出一部分数据来验证训练出来模型的优劣。

一般来说,将完整数据集80%的样本作为训练集,剩余20%的样本作为测试集,要注意的是,这里要将dataframe中的因子数据转换成numpy的ndarray数组格式,因为这种数据类型更适配sklearn。

# 划分训练集和测试集num_train = round(len(data)*0.8)data_train = data.iloc[:num_train, :]data_test = data.iloc[num_train:, :]# 训练集数据和标签X_train = data_train[['ema', 'stddev', 'slope', 'rsi', 'wr']].valuesy_train = data_train['rise']# 测试集数据和标签X_test = data_test[['ema', 'stddev', 'slope', 'rsi', 'wr']].valuesy_test = data_test['rise']print(X_train[:10])print(45*'-')print(X_test[:10])
利用机器学习模型,构建量化择时策略(附全流程代码)

在划分数据集之后,还有非常重要的一步,那就是对数据进行标准化处理,这是因为每个因子的数值量纲差别太大,例如指数EMA的均值是2919.6,而RSI的均值是52.7,这样会造成SVM对某些因子的“偏心”。

在此处,采用“(原始值 - 均值) / 标准差”的方法对数据进行标准化处理,处理过后,每个因子的均值都会变为0,标准差变为1.0。

from sklearn.preprocessing import StandardScalerprint('---标准化之前---')print('训练集的均值:')print(X_train.mean(axis=0))print('训练集的标准差:')print(X_train.std(axis=0))# 对数据进行标准化scaler = StandardScaler()X_train = scaler.fit_transform(X_train)X_test = scaler.transform(X_test)print('---标准化之后---')print('训练集的均值:')print(X_train.mean(axis=0))print('训练集的标准差:')print(X_train.std(axis=0))
利用机器学习模型,构建量化择时策略(附全流程代码)

数据标准化处理之后,就可以将训练集数据输入SVM当中,代码实现很简单,从sklearn的svm模块当中导入SVM分类器SVC,创建实例对象后,将训练集因子数据和对应标签塞进fit函数就行了,SVM模型的惩罚系数使用默认值1.0,核函数也用默认的RBF核函数,训练过程非常快,不用一个东的时间,就把SVM分类器训练好了。

from sklearn.svm import SVCclassifier = SVC(C=1.0, kernel='rbf')classifier.fit(X_train, y_train)print(classifier)
利用机器学习模型,构建量化择时策略(附全流程代码)

五. 测试模型

至此,SVM分类器已经训练好了,把因子数据塞进predict函数,就能输出每个样本的预测值,咱分别把训练集和测试集的预测标签插回到原来的数据集当中,用来计算预测的准确率。

y_train_pred = classifier.predict(X_train)y_test_pred = classifier.predict(X_test)data_train['pred'] = y_train_preddata_test['pred'] = y_test_predaccuracy_train = 100 * data_train[data_train.rise==data_train.pred].shape[0] / data_train.shape[0]accuracy_test = 100 * data_test[data_test.rise==data_test.pred].shape[0] / data_test.shape[0]print('训练集预测准确率:%.2f%%' %accuracy_train)print('测试集预测准确率:%.2f%%' %accuracy_test)

输出结果:

训练集预测准确率:57.52%测试集预测准确率:52.35%

从结果当中看出,训练集的预测准确率明显比测试集的高,这是因为整个模型都是在训练集数据上训练出来的,对测试集数据则还很“陌生”,这就相当于高考数学考卷都是你们学校的数学老师出的,整体来看,你们的平均分就非常可能比其他同级别的学校高。

光看准确率还不够直观,咱还要看一下如果纯粹按照这个择时模型的预测结果进行投资,能获得多少收益,此处只使用测试集进行模拟。

假设指数可以多空交易,如果模型预测为1(上涨),第二天策略的收益率就是指数的涨幅,如果模型预测为0(下跌),第二天策略的收益率就是指数的涨幅的相反数,有了每天的日收益率之后,通过dataframe自带的累乘函数cumprod,就可以得到择时策略和沪深300指数的净值曲线,为了方(tou)便(lan)起见,不考虑交易费率,以及按照收盘价成交。

import matplotlib.pyplot as plt#策略日收益率data_test['strategy_pct'] = data_test.apply(lambda x: x.pct if x.pred>0 else -x.pct, axis=1)#策略和沪深300的净值data_test['strategy'] = (1.0 data_test['strategy_pct']).cumprod()data_test['hs300'] = (1.0 data_test['pct']).cumprod()# 粗略计算年化收益率annual_return = 100 * (pow(data_test['strategy'].iloc[-1], 250/data_test.shape[0]) - 1.0)print('SVM 沪深300指数择时策略的年化收益率:%.2f%%' %annual_return)#将索引从字符串转换为日期格式,方便展示data_test.index = pd.to_datetime(data_test.index)ax = data_test[['strategy','hs300']].plot(figsize=(16,9), color=['SteelBlue','Red'], title='SVM 沪深300指数择时策略净值 by 量化君')plt.show()
利用机器学习模型,构建量化择时策略(附全流程代码)

六. 调节参数

从上一步的测试当中看出,训练集和测试集的预测准确率只有57%和52%,不算理想,说明还有很大的提升空间,还可以对模型进行优化改进。

比如说,现在使用的5个因子,还没有反应到价格波动的本质,还可以增改更多的因子。

还比如说,SVM模型当中的惩罚系数C过小,对错误样本的容忍度过高,RBF核函数不适合作为这个数据集的映射转换函数。

再比如说,甚至连SVM模型本身也是一个参数,也可以更改,比如说可以换成其他的机器学习分类模型。

也就是说到这调节参数这一步,如果训练好的模型结果不能让自己满意,就可以重新将前5步走一遍。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多