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

歌神演唱会人脸识别抓逃犯,阿尔法狗战胜人类围棋手,AI绘图《太空歌剧院》惊艳艺术博览会,ChatGPT一问解千愁~~~这些震撼成果的背后,都是人工智能在蓬勃发力。

图片

既然人工智能/机器学习这么厉害,在其他领域都取得了丰硕的成果和巨大的成功,那么是不是可以让计算机帮咱预测市场大盘、选择和买卖股票/期货/外汇/大饼,解放双手,丰衣足食,岂不美哉?

已经有非常多的机构开展这方面的研究和实践了,今儿个咱也来探索一下,机器学习在量化投资当中的应用,从零开始走通基于机器学习的量化指数择时模型的开发全流程。

目录

零. 机器学习,浅尝一下

一. 收集数据

二. 数据准备

三. 选择/建立模型

四. 训练模型

五. 测试模型

六. 调节参数


零. 机器学习,浅尝一下

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

图片

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

具体结合咱这次的目标进行说明,咱这次的任务就是利用机器学习模型,预测沪深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.org/。

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

import numpy as np
import pandas as pd
import talib
import warnings
warnings.filterwarnings('ignore')
import tushare as ts

data = 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.0
data['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']].values
y_train = data_train['rise']
# 测试集数据和标签
X_test = data_test[['ema', 'stddev', 'slope', 'rsi', 'wr']].values
y_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 StandardScaler

print('---标准化之前---')
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 SVC

classifier = 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_pred
data_test['pred'] = y_test_pred
accuracy_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步走一遍。

咱终于吭哧吭哧走完了,利用机器学习构建量化择时策略的全流程,相信大伙儿对机器学习相关概念和建模流程也有了初步的了解,基于这个建模框架流程,将来的你可以玩得更花,可以采用更高频的数据、更鲁棒的模型、更多的交易标的、更有效的因子、更有趣的预测任务,以及~~~遇见更好的自己。

参考资料

周志华,2016年1月,书籍《机器学习》

华泰金工,2017年8月,研报《人工智能选股之支持向量机模型》

阿泽,2020年6月,知乎《【机器学习】支持向量机 SVM(非常详细)》

### 机器学习量化投资中的应用 #### 回测方法与实现 在量化投资领域,机器学习的应用日益广泛,特别是在资产配置、Alpha因子创建以及交易策略的设计方面。为了验证这些基于机器学习的投资策略的有效性和稳定性,回测成为了不可或缺的一环。 #### 构建多因子量化模型 通过机器学习方法对各类因子进行加权处理,并结合优化算法来动态调整持仓比例,可以显著提升投资组合的表现。具体而言,在构建此类模型时,通常会纳入多种类型的因子,如NLP情绪因子和LSTM时间序列因子,前者有助于捕捉市场的短期非理性波动,后者则擅长于预测价格的长期趋势[^3]。 #### 实现回测流程 以下是利用Python及其相关库完成一次简单的量化投资回测的具体步骤: 1. **准备数据** 首先获取所需的历史行情数据和其他辅助信息作为训练集的一部分。对于A股市场来说,可以选择沪深300指数成分股的数据来进行分析。 2. **预处理数据** 对原始数据进行清洗、标准化等操作,确保后续使用的特征变量质量可靠。这部分工作可能涉及到缺失值填补、异常点检测等内容。 3. **定义评价函数** 明确设定衡量投资绩效的关键指标,比如累计收益率、年化收益率等。这一步骤至关重要,因为它直接影响到最后的结果解释。 4. **编写回测逻辑** 使用循环结构模拟实际交易过程,按照既定规则买入卖出证券,并记录每次变动后的账户状态变化情况。下面给出一段简化版代码示例用于说明如何计算净值并绘制净值曲线: ```python import pandas as pd import matplotlib.pyplot as plt # 假设df是一个包含历史收盘价的时间序列DataFrame对象 df_worth = df / df.iloc[0] plt.figure(figsize=(15,6)) plt.plot(df_worth.index, df_worth.values) plt.title('股价净值走势') plt.xlabel('日期') plt.ylabel('相对净值') plt.grid(True) plt.show() ``` 这段脚本展示了如何读取给定时间段内的每日收盘价,并将其转换成相对于起始日的价格水平;接着借助Matplotlib绘图工具包生成一张清晰直观的趋势图表供进一步观察分析。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值