基于SVM算法的股票预测分析

1.数据集选取与描述

由于股票数据的混沌性、无序性,不适宜选取太多的数据作为模型训练的数据集。故本文选出的数据是“温氏股份”200个交易日的股票数据,数据集的原始变量有交易日期、开盘价、收盘价、最低价、最高价、成交量、价格变动、涨跌幅等。本文的数据来源是Python的一个第三方库TuShare-财经数据包。其中,date代表日期,open为当天开盘价,high为当天最高价,close为当天收盘价,low为当天的最低价,volume为当天的成交量, price_change为价格变动,p_change为涨跌幅,diff为收盘价与开盘价之差即close-open获得,up为1代表涨,up为-1代表为跌。

from cProfile import label
from cmath import sqrt
from csv import field_size_limit
from os import closerange
import tushare as ts
import numpy as np
import pandas as pd
from pandas import DataFrame as DF
from sklearn import svm
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.model_selection import train_test_split
from sklearn import preprocessing as pre
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
import seaborn as sns
from sklearn.metrics import accuracy_score
from sklearn.metrics import roc_curve, auc
#导入plot_roc_curve,roc_curve和roc_auc_score模块
from sklearn.metrics import plot_roc_curve,roc_curve,auc,roc_auc_score
from sklearn.metrics import mean_squared_error # 均方误差
from sklearn.metrics import mean_absolute_error # 平方绝对误差
from sklearn.metrics import r2_score

#中文标签、负号正常显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

#1数据采集
#温氏股份的股票代码为300498,数据采集并存到本地csv文件
data = ts.get_hist_data(code='300498',start = '2019-12-01',end='2022-05-04')
#取近90天的温氏股份股票的交易日期、开盘价、收盘价、最低价、最高价、成交量、价格变动以及涨跌幅数据
data = DF(data).iloc[0:200,0:7]
#diff列代表当天收盘价和开盘价之差
data['diff'] = data['close']-data['open']
data.fillna(0,inplace=True)
#up列为1代表当天上涨,-1代表当天下跌
data['up'] = data['diff']
data['up'][data['diff']>=0] = 1
data['up'][data['diff']<0] = -1
#将数据写入csv文件
data.to_csv('C:/Users/86188/Desktop/Python数据挖掘与数据分析/基于SVM算法的股票预测/data/data.csv')

在这里插入图片描述

图1 温氏股份200个交易日的数据

2.数据集预处理

对数据集进行检测缺失值,并没有发现缺失值。

由于股票的波动异常会有金融机构发声,数据产生的200个交易日内该股票没有报道相关异常指标,即默认没有异常值。

对数据中成交量进行最大-最小标准化。

#2数据的预处理
data = pd.read_csv('C:/Users/86188/Desktop/Python数据挖掘与数据分析/基于SVM算法的股票预测/data/data.csv')
#查看数据情况
data.describe()
#检测有无缺失值
noneIndex = data.loc[data.isnull().any(axis=1)].index
#输出空列表,说明没有缺失值
print("缺失值所在行号:",noneIndex)
#对volume成交量进行最大最小归一化处理
data['volume'] = (data['volume'] - min(data['volume'])) / (max(data['volume']) - min(data['volume']))
print(data)

在这里插入图片描述

图2 数据的初步处理结果

由于日期不是股票的相关变量,故排除在外。借助PCA主成分分析,对开盘价、收盘价、最低价、最高价、成交量、价格变动、涨跌幅和当日股价之差分析,我们可以从图3得出前五个变量所占的累计贡献率达到0.99973944,已经能代表数据的显著特征,即开盘价、收盘价、最低价、最高价、成交量。

#3模型的搭建
#x为变量,除去日期
x = data.iloc[:,1:9]
#y为涨跌值
y = data.iloc[:,9]
#3.1利用pca主成分分析,从开盘价、收盘价、最低价、最高价、成交量、价格变动、涨跌幅和当日股价之差选取特征5个变量
pca = PCA(n_components=None)
pca.fit(x)
pca.components_  # 成分矩阵
print("各变量的方差:",pca.explained_variance_)
print("各变量的贡献度:",pca.explained_variance_ratio_)
#根据累积贡献率,说明前五个变量的累计贡献率已经达到0.999,则取前五个作为特征变量
print("累积贡献率:",np.cumsum(pca.explained_variance_ratio_))
#提取特征变量
pca = PCA(n_components=5)
pca.fit(x)
nx = pca.fit_transform(x)
print("特征变量数据:",nx)

在这里插入图片描述

图3 各变量PCA主成分分析结果

将特征变量的数据赋值给变量nx,并对特征变量的数据进行规范化处理,并将代表涨跌情况的up数据赋予变量y,最后划分训练集和测试集,训练集占90%,测试集仅为20个数据,占10%。

3.SVM算法模型建立

​ 调用Python第三方库中的sklearn库的SVM模型,并调用线性核函数、多项式函数、sigmoid函数以及rbf函数分别构建SVM模型,目的在于分析核函数不同对于SVM模型股票预测的影响。

在这里插入图片描述

图4 Python代码搭建不同核函数的SVM模型

4.SVM算法模型的评估

从图5的ROC曲线对比来看,不同核函数SVM模型ROC曲线的拐点显然不同,linear线性核函数的SVM模型拐点最高,其他三个拐点高度一样。从这个ROC曲线来看,明显linear线性核函数的SVM模型处理的效果更好。

fig,ax = plt.subplots(figsize=(12,10))
lsvm_roc = plot_roc_curve(estimator=lsvm, X=x_test, 
                        y=y_test, ax=ax, linewidth=1,label='linear')
ssvm_roc = plot_roc_curve(estimator=ssvm, X=x_test, 
                        y=y_test, ax=ax, linewidth=1,label='sigmoid')
psvm_roc = plot_roc_curve(estimator=psvm, X=x_test,
                        y=y_test, ax=ax, linewidth=1,label='poly')
rsvm_roc = plot_roc_curve(estimator=rsvm, X=x_test,
                        y=y_test, ax=ax, linewidth=1,label='rbf')
ax.legend(fontsize=12)
plt.savefig(fname="C:/Users/86188/Desktop/Python数据挖掘与数据分析/基于SVM算法的股票预测/tmp/ROC.jpg")
plt.show()

在这里插入图片描述

图5 不同核函数SVM模型的ROC曲线图

从模型的评价得分来看,linear线性核函数的SVM模型最优,得分为0.95,其次到sigmoid核函数的SVM模型,最差是多项式核函数的SVM模型。

#mse、mae、rmse、r2计算
lsvm_mse = mean_squared_error(y_test,lyp)
lsvm_mae = mean_absolute_error(y_test,lyp)
lsvm_rmse = sqrt(lsvm_mse)
lsvm_r2 = r2_score(y_test,lyp)
print("核函数为linear的SVM模型:")
print("mse:",lsvm_mse)
print("mae:",lsvm_mae)
print("rmse:",lsvm_rmse)
print("r2:",lsvm_r2)

ssvm_mse = mean_squared_error(y_test,syp)
ssvm_mae = mean_absolute_error(y_test,syp)
ssvm_rmse = sqrt(ssvm_mse)
ssvm_r2 = r2_score(y_test,syp)
print("核函数为sigmoid的SVM模型:")
print("mse:",ssvm_mse)
print("mae:",ssvm_mae)
print("rmse:",ssvm_rmse)
print("r2:",ssvm_r2)

psvm_mse = mean_squared_error(y_test,pyp)
psvm_mae = mean_absolute_error(y_test,pyp)
psvm_rmse = sqrt(psvm_mse)
psvm_r2 = r2_score(y_test,pyp)
print("核函数为poly的SVM模型:")
print("mse:",psvm_mse)
print("mae:",psvm_mae)
print("rmse:",psvm_rmse)
print("r2:",psvm_r2)

rsvm_mse = mean_squared_error(y_test,ryp)
rsvm_mae = mean_absolute_error(y_test,ryp)
rsvm_rmse = sqrt(rsvm_mse)
rsvm_r2 = r2_score(y_test,ryp)
print("核函数为rbf的SVM模型:")
print("mse:",rsvm_mse)
print("mae:",rsvm_mae)
print("rmse:",rsvm_rmse)
print("r2:",rsvm_r2)

在这里插入图片描述

图6 各模型的得分

​ 从各个模型的MSE、MAE、RMSE、R2来看,显然linear线性核函数的SVM模型的MSE最小,R2最大,模型最优,最差的是多项式函数的SVM模型

在这里插入图片描述

图7 各模型的MSE、MAE、RMSE、R2情况

从混淆矩阵对比图来看,我们发现落在(0,0)和(1,1)区域最多的混淆矩阵是linear线性核函数的SVM模型,其次到sigmoid核函数的SVM模型,然后再到以rbf为核函数的SVM模型,最差是多项式核函数的SVM模型。

#画出混淆矩阵
figure = plt.subplots(figsize=(12,10))
plt.subplot(2,2,1)
plt.title("核函数为linear")
heatmap = sns.heatmap(lcm, annot=True, fmt='d')
heatmap.yaxis.set_ticklabels(heatmap.yaxis.get_ticklabels(), rotation=0, ha='right')
heatmap.xaxis.set_ticklabels(heatmap.xaxis.get_ticklabels(), rotation=45, ha='right')
plt.ylabel("true label")
plt.xlabel("predict label")

plt.subplot(2,2,2)
plt.title("核函数为sigmoid")
heatmap = sns.heatmap(scm, annot=True, fmt='d')
heatmap.yaxis.set_ticklabels(heatmap.yaxis.get_ticklabels(), rotation=0, ha='right')
heatmap.xaxis.set_ticklabels(heatmap.xaxis.get_ticklabels(), rotation=45, ha='right')
plt.ylabel("true label")
plt.xlabel("predict label")

plt.subplot(2,2,3)
plt.title("核函数为polynomial")
heatmap = sns.heatmap(pcm, annot=True, fmt='d')
heatmap.yaxis.set_ticklabels(heatmap.yaxis.get_ticklabels(), rotation=0, ha='right')
heatmap.xaxis.set_ticklabels(heatmap.xaxis.get_ticklabels(), rotation=45, ha='right')
plt.ylabel("true label")
plt.xlabel("predict label")

plt.subplot(2,2,4)
plt.title("核函数为rbf")
heatmap = sns.heatmap(rcm, annot=True, fmt='d')
heatmap.yaxis.set_ticklabels(heatmap.yaxis.get_ticklabels(), rotation=0, ha='right')
heatmap.xaxis.set_ticklabels(heatmap.xaxis.get_ticklabels(), rotation=45, ha='right')
plt.ylabel("true label")
plt.xlabel("predict label")
plt.savefig(fname="C:/Users/86188/Desktop/Python数据挖掘与数据分析/基于SVM算法的股票预测/tmp/confusion_matrix.jpg")
plt.show()

在这里插入图片描述

图8 各模型混淆矩阵

从各个模型的预测值与真实值重合曲线情况图来看,预测值和真实值都是一致程度最高的为以linear为核函数的SVM模型、其次到sigmoid核函数的SVM模型,然后再到以rbf为核函数的SVM模型,最差是多项式核函数的SVM模型。

#画出收盘价走势图以及真实值和预测值图
plt.subplot(3,1,1)
#收盘价走势图
plt.title("收盘价走势图")
plt.plot(data['date'].iloc[-20:],data['close'].iloc[-20:])
plt.xticks(rotation=30)
plt.subplot(3,1,3)
plt.title("预测-真实图")
plt.plot(data['date'].iloc[-20:],lyp,color='red',label='预测值')
plt.plot(data['date'].iloc[-20:],data['up'].iloc[-20:],color='blue',label='真实值')
plt.xticks(rotation=30)
plt.legend()
plt.savefig(fname="C:/Users/86188/Desktop/Python数据挖掘与数据分析/基于SVM算法的股票预测/tmp/lyp.jpg")
plt.show()

在这里插入图片描述

图9 核函数为linear的SVM模型
#画出收盘价走势图以及真实值和预测值图
plt.subplot(3,1,1)
#收盘价走势图
plt.title("收盘价走势图")
plt.plot(data['date'].iloc[-20:],data['close'].iloc[-20:])
plt.xticks(rotation=30)
plt.subplot(3,1,3)
plt.title("预测-真实图")
plt.plot(data['date'].iloc[-20:],syp,color='red',label='预测值')
plt.plot(data['date'].iloc[-20:],data['up'].iloc[-20:],color='blue',label='真实值')
plt.xticks(rotation=30)
plt.legend()
plt.savefig(fname="C:/Users/86188/Desktop/Python数据挖掘与数据分析/基于SVM算法的股票预测/tmp/syp.jpg")
plt.show()

在这里插入图片描述

图10 核函数切多项式的SVM模型
#画出sigmoid收盘价走势图以及真实值和预测值图
plt.subplot(3,1,1)
#收盘价走势图
plt.title("收盘价走势图")
plt.plot(data['date'].iloc[-20:],data['close'].iloc[-20:])
plt.xticks(rotation=30)
plt.subplot(3,1,3)
plt.title("预测-真实图")
plt.plot(data['date'].iloc[-20:],pyp,color='red',label='预测值')
plt.plot(data['date'].iloc[-20:],data['up'].iloc[-20:],color='blue',label='真实值')
plt.xticks(rotation=30)
plt.legend()
plt.savefig(fname="C:/Users/86188/Desktop/Python数据挖掘与数据分析/基于SVM算法的股票预测/tmp/pyp.jpg")
plt.show()

在这里插入图片描述

图11 核函数为sigmoid的SVM模型
#画出rbf收盘价走势图以及真实值和预测值图
plt.subplot(3,1,1)
#收盘价走势图
plt.title("收盘价走势图")
plt.plot(data['date'].iloc[-20:],data['close'].iloc[-20:])
plt.xticks(rotation=30)
plt.subplot(3,1,3)
plt.title("预测-真实图")
plt.plot(data['date'].iloc[-20:],ryp,color='red',label='预测值')
plt.plot(data['date'].iloc[-20:],data['up'].iloc[-20:],color='blue',label='真实值')
plt.xticks(rotation=30)
plt.legend()
plt.savefig(fname="C:/Users/86188/Desktop/Python数据挖掘与数据分析/基于SVM算法的股票预测/tmp/ryp.jpg")
plt.show()

在这里插入图片描述

图12 核函数为rbf的SVM模型

5.模型改进

​ 从模型评价来看,SVM算法的核函数对模型评分、精度来说很重要,不同的数据集适合不同的核函数。对于股票涨跌的情况预测,我们不难发现,一些评价标准是不能代表模型的好坏了,如虽然linear核函数的SVM模型是最好的,但是其真实值和预测值重合度还是有一定的差距,整体走势是一样的,但似乎存在预测时差,即涨跌拐点日期有出入。所以改进方法应该使用自编的核函数,基于径向基核函数的SVM算法用于股票价格预测,对股票未来十五天的走向进行预测,可以发现SVM算法预测的结果可靠性强、误差小,但也会耗费一定的时间,降低运算速度。

6.结论

处理股票函数需要先用PCA主成分分析尽可能降低维度,处理冗余函数,不同核函数的SVM算法对股票预测的情况不同。从上面的例子来看,显然linear核函数更适合“温氏股份”的股票预测分析,但从知网文章的角度来看,最好使用径向基核函数的SVM算法。

,一些评价标准是不能代表模型的好坏了,如虽然linear核函数的SVM模型是最好的,但是其真实值和预测值重合度还是有一定的差距,整体走势是一样的,但似乎存在预测时差,即涨跌拐点日期有出入。所以改进方法应该使用自编的核函数,基于径向基核函数的SVM算法用于股票价格预测,对股票未来十五天的走向进行预测,可以发现SVM算法预测的结果可靠性强、误差小,但也会耗费一定的时间,降低运算速度。

6.结论

处理股票函数需要先用PCA主成分分析尽可能降低维度,处理冗余函数,不同核函数的SVM算法对股票预测的情况不同。从上面的例子来看,显然linear核函数更适合“温氏股份”的股票预测分析,但从知网文章的角度来看,最好使用径向基核函数的SVM算法。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐