当前位置:   article > 正文

深入浅出Python量化交易实战--第3章-机器学习在交易中的简单应用(上)_python股票量化交易 使用机器学习算法预测股票涨跌

python股票量化交易 使用机器学习算法预测股票涨跌

在第2章中,我们和小瓦一起用简单的回测来对交易策略进行了 评估,并且学习了两种基于市场动量的经典交易策略。现在小瓦提出 一个新的问题:如果我们掌握了足够多的数据,不就可以用机器学习 技术来预测股价的涨跌和涨幅了吗?事实上,这是一个非常好的主 意。机器学习技术就是使用样本数据训练模型,并且让模型对新样本 做出预测的技术。本章我们就和小瓦一起来探索一下机器学习在交易 中的基本应用。本章的主要内容如下。

  1. 机器学习的基本概念。
  2. 机器学习工具的基本使用方法。
  3. 基于机器学习的简单交易策略。

 

3.1 机器学习的基本概念

近年来,随着人工智能(Artificial Intelligence,AI)的蓬勃发展, 机器学习在各行各业都有着非常广泛的应用。不过,作为一个非计算机 专业出身的学生,机器学习对于小瓦来说是一个完全陌生的领域。然 而,小瓦坚信世上无难事,只怕有心人。更何况要理解机器学习的基本 概念,其实并不困难。当然,对机器学习的基本概念已经有一定了解的 读者,可以跳过这一部分,直接阅读后面的内容

3.1.1 有监督学习和无监督学习

在机器学习领域,有监督学习(supervised learning)和无监督学习 (unsupervised learning)是常见的两种方法。为了帮助小瓦理解这两种 方法的不同,我们可以用一个小例子来阐述。

例如,我们给小瓦一堆化妆品,相信小瓦与其他女生一样,可以很轻松地叫出每样化妆品 的名字。这是因为在小瓦的认知当中,每种物品已经有了一个标签 (label),如口红、眉笔、粉扑。这些标签对应着不同的特征 (feature),例如,“红色”“用来涂在嘴唇上”的,对应的就是“口红”这 个标签。符合这个特征的化妆品,就会被小瓦归入“口红”这个类 别。对于模型来说,这种有已知标签的任务就是有监督学习的一种。

我们再给小瓦一些不同的物品:计算机主板。

 

这时我们再来要求小瓦说出计算机主板上零件的名 字,就有些难为她了。毕竟小瓦没有接触过这个领域的知识,也就是 说,在小瓦的脑子里,没有这些零件所对应的标签。即便如此,小瓦还 是可以通过观察这些东西的特征,将它们归到不同的类别中,例如,有 些是“黑色凹槽”,有些是“白色凹槽”,有些是“黑色圆柱”——虽然不知 道它们具体是什么东西,但还是能够看出它们的作用肯定是不同的。这 种没有已知标签,但是让模型通过观察特征将它们放入不同类别的过 程,就是无监督学习的一种。

 

3.1.2 分类和回归

在有监督学习当中,常见的两种任务就是分类(classification)和 回归(regression)。其中,分类任务指的是,给定样本的分类标签,训 练模型使其可以将新的样本归入正确的分类中——这时模型的目标是离 散的;而回归任务指给定样本的目标值,训练模型使其可以预测出新样 本对应的数值——这时模型的目标是连续的。

用小瓦可以更容易理解的语言来说,假如要预测某只股票在未来 会“涨”还是会“跌”,这时模型所做的就是分类的工作,但如果要预测某 只股票未来会涨1元,还是8角8分,还是–5角,这时模型所做的就是回 归的工作。

3.1.3 模型性能的评估

如果使用算法来进行交易的话,小瓦最关心的就是模型是否可以准 确地预测出股票的涨跌或者涨幅。实际上,模型是不可能做到百分之百 准确的,这就需要我们对模型的性能进行评估,以便找到最可用的模 型。要达到这个目的,我们就需要将掌握的数据集(dataset)拆分为训 练集(trainset)和验证集(testset),使用训练集训练模型,并使用验 证集来评估模型是否可用。

举一个例子,假如小瓦有某只股票100天的价格数据,就可以将前 80天的数据作为训练集,将后20天的数据作为验证集,同时评估模型分 别在训练集与验证集中的准确率。如果模型在训练集中的得分很高,而 在验证集中的得分很低,就说明模型出现了过拟合(over-fitting)的问 题;而如果模型在训练集和验证集中的得分都很低,就说明模型出现了 欠拟合(under-fitting)的问题。

要解决这些问题,小瓦就需要调整模型的参数、补充数据,或者进 行更细致的特征工程。随着小瓦工作的继续深入,我们会一起来探索详 细的解决方案。

3.2 机器学习工具的基本使用方法

对于小瓦这种初学者来说,有一个特别好的消息,即在Python中实 现各种不同的机器学习算法是非常容易的,有各种各样的第三方库可以 直接调用,如久负盛名的scikit-learn、深度学习框架TensorFlow、 Pytorch及很容易上手的Keras等。

在本节中,我们就帮助小瓦来熟悉一下scikit-learn的基本使用方法。

3.2.1 KNN算法的基本原理

在诸多机器学习算法中,KNN(K-Nearest Neighbor,K最近邻)算 得上是较简单且易于理解的算法之一了。不过,简单不意味着KNN能做 的事情比较少,它既可以用于分类任务,也可以用于回归任务。 KNN算法的原理十分容易理解:它识别k个最近的数据点(基于欧 几里得距离)来进行预测,它分别预测邻域中最频繁的分类或是回归情 况下的平均结果。用通俗的话讲,已知大部分皮肤比较白的人是欧洲 人,大部分皮肤比较黑的人是非洲人。现在给你介绍一位朋友,让你判 断他来自哪个国家。通过目测,你发现这位朋友与3位非洲朋友的肤色 比较接近,与1位欧洲朋友的肤色比较接近,这时,你大概率会把这位 新朋友归到非洲人的分类当中。

对于回归任务来说,KNN的工作机理也是相似的。例如,你打算去 买一套房子,在同一个小区当中发现有3套户型和面积都十分接近的房 屋。第一套的售价是500万元,第二套的售价是520万元,而第三套的售 价未知。鉴于第三套的情况与前面两套十分接近,你可以大致估算出它 的售价会是510万元左右,即前两套房子售价的均值。

下面我们来逐一演示一下KNN在分类和回归当中的应用。

3.2.2 KNN算法用于分类

1). 载入数据集并查看

scikit-learn内置了一些供大家学习的玩具数据集(toy dataset),其 中有些是分类任务的数据,有些是回归任务的数据。首先我们使用一个 最简单的数据集来给小瓦演示KNN算法在分类中的应用。输入代码如 下:

  1. #首先导入鸢尾花数据载入工具
  2. from sklearn.datasets import load_iris
  3. #导入KNN分类模型
  4. from sklearn.neighbors import KNeighborsClassifier
  5. #为了方便可视化,我们再导入matplotlib和seaborn
  6. import matplotlib.pyplot as plt
  7. import seaborn as sns

 

运行代码,如果程序没有报错,就说明所有的库都已 经成功载入。接下来我们就用数据集载入工具加载数据。输入代码如 下:

  1. #加载鸢尾花数据集,赋值给iris变量
  2. iris = load_iris()
  3. #查看数据集的键名
  4. iris.keys()

 

【结果分析】如果读者朋友们也得到了同样的结果,就说明代码运 行成功。我们看到,该数据集存储了若干个键(key),这里我们重点 关注一下其中的target和feature_names,因为这两个键对应的分别是样本 的分类标签和特征名称。 首先我们看下数据集存储了样本的哪些特征,输入代码如下:

  1. #查看数据集的特征名称
  2. iris.feature_names

 

 

【结果分析】从上述代码结果中可以看出,数据集中的样本共有4 个特征,分别是sepal length(萼片长度)、sepal width(萼片宽度)、 petal length(花瓣长度)和petal width(花瓣宽度)。

下面再来看一下这些样本被分为几类,输入代码如下:

  1. #查看数据集中的样本分类
  2. iris.target

 

【结果分析】观察代码的运行结果,我们可以发现系统返回了一个 数组,数组中的数字有0、1和2。这说明数据集中的样本分为3类,分别 用0、1、2这3个数字来表示。 到这里,相信小瓦也已经明白,这个数据集的目的是:根据样本鸢 尾花萼片和花瓣的长度及宽度,结合分类标签来训练模型,以便让模型 可以预测出某一种鸢尾花属于哪个分类。

2). 拆分数据集

下面,我们就来把数据集拆分为训练集和验证集,以便验证模型的 准确率。先输入如下代码:

  1. #将样本的特征和标签分别赋值给X和y
  2. X, y = iris.data, iris.target
  3. #查看是否成功
  4. X.shape

 

 

【结果分析】从上面的代码运行结果可以看出,我们将数据集的特 征赋值给了X,而将分类标签赋值给了y。通过查看X的形态,可知样本 数量共有150个,每个样本有4个特征。

下面来对数据集进行拆分,输入代码如下:

  1. #导入数据集拆分工具
  2. from sklearn.model_selection import train_test_split
  3. #将X和y拆分为训练集和验证集
  4. X_train, X_test, y_train, y_test =\
  5. train_test_split(X, y)
  6. #查看拆分情况
  7. X_train.shape

 

 

结果分析】从上面的代码运行结果可以看到,通过拆分,训练集 中的样本数量为112个,其余的38个样本则进入了验证集。

3). 训练模型并评估准确率

下面训练一个最简单的KNN模型,输入代码如下:

  1. #创建KNN分类器,参数保持默认设置
  2. knn_clf = KNeighborsClassifier()
  3. #使用训练集拟合模型
  4. knn_clf.fit(X_train, y_train)
  5. #查看模型在训练集和验证集中的准确率
  6. print'训练集准确率:%.2f'%knn_clf.score(X_train, y_train))
  7. print'验证集准确率:%.2f'%knn_clf.score(X_test, y_test))

 

 

【结果分析】从上面的代码运行结果可以看到,使用KNN算法训 练的分类模型,在训练集中的准确率达到了100%,在验证集中的准确率 达到了0.95%。这是一个非常不错的成绩。 需要说明的是,在scikit-learn中,KNN可以通过调节n_neighbors参 数来改进模型的性能。在不手动指定的情况下,KNN默认的近邻参数 n_neighbors为5。那么这个参数是最优的吗?我们可以使用网格搜索法 来寻找到模型的最优参数。输入代码如下:

  1. # 导入网格搜索
  2. from sklearn.model_selection import GridSearchCV
  3. # 定义一个从1到10的n_neighbors
  4. n_neighbors = tuple(range(1,11,1))
  5. # 创建网格搜索实例,estimator用KNN分类器
  6. # 把刚刚定义的n_neighbors传入给param_grid参数
  7. # 参数指交叉验证次数为5
  8. cv = GridSearchCV(estimator=KNeighborsClassifier(),
  9. param_grid = {'n_neighbors':n_neighbors},
  10. cv=5)
  11. # 使用网格搜索拟合数据集
  12. cv.fit(X,y)
  13. # 查看最优参数
  14. cv.best_params_

 

 

【结果分析】从上面的代码运行结果可以看到,程序将网格搜索找 到的最优参数进行了返回——KNN分类器的最优n_neighbors参数是6。 也就是说,当n_neighbors参数为6时,模型的准确率是最高的。 下面我们就来看一下当把n_neighbors设置为6时,模型的准确率。

输入代码如下:

  1. #创建KNN分类器,n_neighbors设置为6
  2. knn_clf = KNeighborsClassifier(n_neighbors=6
  3. #使用训练集拟合模型
  4. knn_clf.fit(X_train, y_train)
  5. #查看模型在训练集和验证集中的准确率
  6. print'训练集准确率:%.2f'%knn_clf.score(X_train, y_train))
  7. print'验证集准确率:%.2f'%knn_clf.score(X_test, y_test))

 

 

【结果分析】从上面的代码运行结果可以看到,当把n_neighbors参 数设置为6时,模型在训练集中的准确率100%,可以说这是非 常不错的成绩了;而在验证集中的准确率依旧保持在92%左右,没有提升。

3.2.3 KNN算法用于回归

下面我们就来给小瓦展示KNN算法在回归任务中的应用。

1). 载入数据集并查看

这里依旧使用scikit-learn内置的数据集来给小瓦进行讲解。说到回 归任务,我们自然会想到波士顿房价数据集。该数据集中有506个样 本,每个样本有13个特征,以及对应的价格(target)。下面我们载入 数据集并对其进行初步的了解。

  1. #载入波士顿房价数据集导入工具
  2. from sklearn.datasets import load_boston
  3. #将数据导入
  4. boston = load_boston()
  5. #查看数据集的键名
  6. boston.keys()

 

 

【结果分析】从代码运行结果可以看出,数据集中存储了5个键, 这里我们重点关注target(房屋的售价)及feature_names(房屋的特 征)。也就是说,我们需要训练模型,让它学习房屋特征和售价的关 系,并且可以自动预测出新房屋的售价。 下面来看一下数据中存储的特征都有哪些,输入代码如下:

  1. #查看样本的特征名称
  2. boston.feature_names

 

 

【结果分析】从代码运行结果可以看到,程序返回了样本全部的特 征名称,包括房间数量RM、房龄AGE等共计13个。因为这里只是进行 回归分析的演示,所以我们不展开讲解这些特征具体代表什么。感兴趣 的读者可以自行查看scikit-learn官方文件进行深入了解。 如果读者朋友希望继续了解房屋的价格是什么样子,可以使用下面 这行代码来查看一下:

  1. #选取前十套房屋,查看售价
  2. boston.target[:10]

 

接下来重复进行类似分类任务的步骤,将数据集拆分为训练集和验 证集。

2). 拆分数据集并训练模型

与分类任务一样,在回归任务中,我们也要使用训练集来训练模 型,并使用验证集来验证模型的性能。

下面来进行数据集的拆分,输入代码如下。

  1. #将样本特征和售价赋值给X,y
  2. X, y = boston.data, boston.target
  3. #使用train_test_split拆分为训练集和验证集
  4. X_train, X_test, y_train, y_test =\
  5. train_test_split(X, y)
  6. #查看拆分的结果
  7. X_train.shape

 

【结果分析】如果读者朋友也得到了这个结果,就说明你的数据集 拆分成功。训练集中有379个样本,其余127个样本进入了验证集。 下面开始模型的训练,输入代码如下:

  1. #导入KNN回归算法
  2. from sklearn.neighbors import KNeighborsRegressor
  3. #创建一个实例,参数保持默认设置
  4. knn_reg = KNeighborsRegressor()
  5. #拟合训练集数据
  6. knn_reg.fit(X_train, y_train)
  7. #查看模型在训练集和验证集的性能表现
  8. print'训练集准确率:%.2f'%knn_reg.score(X_train, y_train))
  9. print'验证集准确率:%.2f'%knn_reg.score(X_test, y_test))

 

 

【结果分析】从上面的代码运行结果可以看到,缺省参数的KNN 回归模型在该数据集中的性能表现差强人意,在训练集中的准确率只有 67%,而在验证集中则更加糟糕,只有58%。这说明模型出现了欠拟合 的问题,我们需要对数据集进行处理,或者对模型进行调优。

到这里,相信读者朋友们和小瓦一样,发现了这样一个事情:不论 是在分类模型中,还是回归模型中,我们都使用了.score( )方法来评 估模型的性能。然而,在两种模型中,.score( )方法所进行的计算是 不一样的。在分类模型中,.score( )返回的是模型预测的准确率 (accuracy),其计算公式为:

在上面这个公式中,TP(True Positive)表示模型预测正确的正样 本数量;TN(True Negative)表示模型预测正确的负样本数量; FP(False Positive)表示原本是负样本,却被模型预测为正样本的数 量,也就是我们平时说的“假阳性”;FN(False Negative)表示原本是正 样本,却被模型预测为负样本的数量,也就是“假阴性”。TP、FP、 TN、FN的和就是所有的样本数量。也就是说,分类模型的准确率是模 型预测正确的样本数量,除以全部参与预测的样本数量。当然,除了准 确率之外,我们还可以用Precision、Recall、F1 score等方法来对分类模 型进行性能评估,这里暂时不展开讲解。

在回归任务中,.score( )方法返回的是模型的R2。对于小瓦来 说,这个概念有些陌生。R2是描述模型预测数值与真实值差距的指标, 它的计算公式为

在这个公式中, y^代表模型对样本的估计值,y可代表的是样本真 实值的均值。也就是说,R^2样本真实值减模型估计值,再进行平方并 求和,除以样本真实值减样本平均值的平方和,最后用1减去这个结 果。因此R^2值为0~1,并且越接近1,说明模型的性能越好。 除了R^2外,回归模型还可以用均方误差(Mean Squared Error, MSE)、绝对中位差(Median Absolute Error,MAE)等指标来进行评 估。如果有需要,我们也会在后面做进一步的讲解。 前面说了,缺省参数的KNN模型在波士顿房价预测这个任务中的表 现并不理想。下面我们尝试对KNN回归的参数进行调整,看是否可以改 进模型的性能。与分类模型一样,我们先使用网格搜索来寻找模型的最 优参数。输入代码如下:

  1. # 这次让n_neighbors参数从120遍历
  2. n_neighbors = tuple(range(1,21,1))
  3. # 创建KNN回归的网格搜索实例
  4. cv_reg = GridSearchCV(estimator = KNeighborsRegressor(),
  5. param_grid = {'n_neighbors':n_neighbors},
  6. cv = 5)
  7. # 用网格搜索拟合数据集
  8. cv_reg.fit(X, y)
  9. cv_reg.best_params_

 

【结果分析】从上面的代码运行结果可以看到,KNN回归模型的 最佳n_neighbors参数是10,也就是说,当n_neighbors取10时,模型的R2 最高。 现在来看一下当n_neighbors取10时,模型的R^2是多少。输入代码如 下:

  1. #查看最佳参数对应的最佳模型R^2
  2. cv.best_score_

 

 【结果分析】从代码运行结果可以看到,当我们设置KNN回归模 型的n_neighbors参数为10时,模型的R^2提高到了0.98,可以说在性能方 面有了显著的提升。 注意:在使用网格搜索时,我们没有手动将数据集拆分为训练集 和验证集。这是因为网格搜索内置了交叉验证(cross validation)法。 在网格搜索中,我们设置cv参数为5,也就是说,交叉验证会将数据分 成5份,第一份作为验证集,其余作为训练集,而后再把第二份作为验 证集,其余部分作为训练集……以此类推,直到全部验证完毕,因此 省去了拆分数据集的步骤。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/129645?site
推荐阅读
相关标签
  

闽ICP备14008679号