我们要做股票的预测,针对于历史数据来预测股价的走势。在这里,我们要解决的具体问题为:给定历史数据来预测5天之后的股价。 这个问题是经典的回归问题,所以可以使用线性回归模型来解决。
在这个项目中,需要做如下的几件事情:
- 读取某一只股票行情数据,并试着理解每一个字段的含义
- 对于读取之后的数据,做一些必要的预处理(如排序,去掉NAN,把字符串转换成日期等)
- 提取特征值和预测值,分别保存为X, y两个变量中
- 把数据分为训练和测试数据
- 在训练数据中训练模型,在测试数据中测试模型的效果
- 做简单的可视化展示
- 分析特征的重要性,这部分可以从学出来的权重获得。
1. 数据的读取和数据预处理
# 导入必要的库
import numpy as np # 数学计算
import pandas as pd # 数据处理, 读取 CSV 文件 (e.g. pd.read_csv)
import matplotlib.pyplot as plt # 可视化工具
from datetime import datetime as dt # 时间的工具
from sklearn import preprocessing # 归一化时用到
# 对于股票数据,你可以使用如下的方法下载某一个公司的股票交易历史
# 000001 为平安银行
# 如果你还没有安装, 可以使用 pip install tushare 安装tushare python包
# import tushare as ts
# df = ts.get_hist_data('000001')
# print(df)
# df.to_csv('000001.csv')
# 读取股票代码为000001的行情数据
df = pd.read_csv('000001.csv')
print(np.shape(df))
print(df.head())

股票数据的特征
- date:日期
- open:开盘价
- high:最高价
- close:收盘价
- low:最低价
- volume:成交量
- price_change:价格变动
- p_change:涨跌幅
- ma5:5日均价
- ma10:10日均价
- ma20:20日均价
- v_ma5:5日均量
- v_ma10:10日均量
- v_ma20:20日均量
# 将每一个数据的键值的类型从字符串转为日期,并把date字段设置为index
df['date'] = pd.to_datetime(df['date'])
df = df.set_index('date')
# 按照时间升序排列数据, 使用df中的sort_values函数
df = df.sort_values(by=['date'])
print(df.head())

# 检测是否有缺失数据 NaNs
df.dropna(axis=0 , inplace=True)
print(df.isna().sum())

2. 构建特征向量X和预测值y
# 创建新的一列(预测值)。预测值为5天之后的收盘价,使用shift函数来实现。
num = 5 # 预测5天后的情况
df['label'] = df['close'].shift(-num)
print(df.tail(10))

# 由于数据往前移了5位,所以最后5个样本的label值为"NA",在这里去掉包含”NA"的样本。
df.dropna(inplace=True)
print(df.tail(10))

# 构建特征向量X,也就是数据中的X。由于我们要预测df['label']值,需要先去掉,不然就失去预测意义了。 另外,
# 在本次预测任务中先不考虑"price_change"和"p_change"两个字段。
X = df.drop(['price_change', 'label', 'p_change'],axis=1)
X = X.values
# 使用z-score normalization做归一化,参考preprocessing模块里的scale函数的使用
X = preprocessing.scale(X)
# 提取预测值
y = df.label.values
print(np.shape(X), np.shape(y))
# 把数据分为训练和测试数据。我们把一开始的550个样本作为训练数据,之后的样本作为测试数据
X_train, y_train = X[0:550, :], y[0:550]
X_test, y_test = X[550:606,:], y[550:606]
print(X_train.shape)
print(y_train.shape)
print(X_test.shape)
print(y_test.shape)
3. 训练模型
# 训练线性回归模型
# 导入相应的线性回归库
from sklearn import linear_model
# 在训练数据上训练线性回归模型
lr = linear_model.LinearRegression()
lr.fit(X_train,y_train)
# 使用绝对系数 R^2 评估模型
print(lr.score(X_test, y_test))
4. 可视化结果(预测值 vs 真实值)
# 输出针对最后五个样本的预测,以及真实值
x_predict = X[-100:] # 选取最新的100个样本
forcast = lr.predict(x_predict) # 预测
plt.plot(y[-100:], color='r' , label="actual value")
plt.plot(forcast, color='b', label="predicted value")
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0.)
plt.show()

5. 观察模型的权重
在线性回归中,权重(绝对值)越大,就意味着跟预测值之间的关系就越大
for idx, col_name in enumerate(['open', 'high', 'close', 'low', 'volume', 'ma5', 'ma10', 'ma20', 'v_ma5', 'v_ma10', 'v_ma20']):
print("The coefficient for {} is {}".format(col_name, lr.coef_[idx]))
