有監(jiān)督的機器學習從數(shù)學角度看就是在擬合一個從特征空間到目標空間的映射,機器學習過程就是尋找或逼近這個映射。下面用循環(huán)神經網路來擬合上證指數(shù),看一下循環(huán)神經網絡的學習能力。
我們要擬合的映射關系是前n天的交易數(shù)據(jù)對應之后第m天后的收盤價,其中交易數(shù)據(jù)包括:收盤價 最高價、 最低價、 開盤價、 前收盤、 漲跌額、 漲跌幅、 成交量、 成交金額。n天的記錄組成一個(n,9)的時間序列。
上證指數(shù)交易數(shù)據(jù)從網易下載,包含從第一天(1990-12-19)到2018-12-27的數(shù)據(jù),下載后文件名為000001.csv。其中有些記錄中包含None,需要刪除掉這樣的記錄,然后按時間順序排列。處理方式如下:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import keras
from keras.models import Sequential
from keras.layers import Dense,Dropout,LSTM
data = pd.read_csv('d:/downloads/000001.csv',encoding='gbk')
data = data[(data['漲跌額']!='None') & (data['成交金額']!='None')]
data.sort_values(by='日期',ascending=True,inplace=True)
data.head()
輸出為
日期 股票代碼 名稱 收盤價 最高價 最低價 開盤價 前收盤 漲跌額 漲跌幅 成交量 成交金額
6853 1990-12-20 '000001 上證指數(shù) 104.39 104.39 99.98 104.30 99.98 4.41 4.4109 197 84000.0
6852 1990-12-21 '000001 上證指數(shù) 109.13 109.13 103.73 109.07 104.39 4.74 4.5407 28 16000.0
6851 1990-12-24 '000001 上證指數(shù) 114.55 114.55 109.13 113.57 109.13 5.42 4.9666 32 31000.0
6850 1990-12-25 '000001 上證指數(shù) 120.25 120.25 114.55 120.09 114.55 5.7 4.976 15 6000.0
6849 1990-12-26 '000001 上證指數(shù) 125.27 125.27 120.25 125.27 120.25 5.02 4.1746 100 53000.0
注意,日期前的數(shù)字為索引,因為重新排序了,索引從大到小顯示。特征只取從收盤價到成交金額的9個字段,并將類型設為float32
x = data.values[:,3:]
x = x.astype('float32')
把收盤價用曲線顯示一下
plt.plot(x[:,0])
plt.show()

設置訓練集大小為6500,并用訓練集的均值和標準差對全部數(shù)據(jù)進行標準化處理。
train_size = 6500
tr_mean = np.mean(x[0:train_size],axis=0)
tr_std = np.std(x[0:train_size],axis=0)
x-=tr_mean
x/=tr_std
定義一個函數(shù)來生成前l(fā)ookback天的交易記錄和第delay天后的收盤價的映射關系。
def generate_timestep_data(x,lookback=10,delay=3,step=1):
seq_ls = []
target_ls = []
for i in range(0,x.shape[0]-lookback-delay+1,step):
seq_ls.append(x[i:i+lookback])
target_ls.append(x[i+lookback+delay-1,0])
x_seq = np.asarray(seq_ls)
y = np.asarray(target_ls)
return x_seq,y
step是兩個時間序列之間的隔天數(shù),這里取1。
在訓練集和測試集上調用這個函數(shù),生成循環(huán)神經網絡需要的數(shù)據(jù)映射關系。這里生成的映射是前10天交易記錄對應之后第3天的收盤價。
x_train,y_train = generate_timestep_data(x[0:train_size],10,3,1)
x_test,y_test = generate_timestep_data(x[train_size:],10,3,1)
用keras的LSTM建立一個學習模型,并在訓練集上進行訓練,驗證集取訓練集的10%。
model = Sequential()
model.add(LSTM(128,input_shape=(x_train.shape[1:]),activation='tanh',kernel_regularizer='l2'))
#model.add(Dropout(0.5))
model.add(Dense(1))
model.summary()
model.compile(loss='mse',optimizer='adam',metrics=['mae'])
history=model.fit(x_train,y_train,validation_split=0.1,epochs=10,batch_size=64)
plt.plot(history.history['loss'],label='loss')
plt.plot(history.history['val_loss'],label='val_loss')
plt.legend()
損失函數(shù)隨訓練次數(shù)的變化如下:

用訓練好的模型在測試集上進行預測,并與真實值進行比較。
y_pred = model.predict(x_test)
y_pred = y_pred*tr_std[0]+tr_mean[0] #恢復到原有尺度數(shù)據(jù)
y_true = y_test*tr_std[0]+tr_mean[0] #恢復到原有尺度數(shù)據(jù)
plt.plot(y_true[:],label='true')
plt.plot(y_pred[:],label='pred')
plt.legend()

從對比情況可以看出,循環(huán)神經網絡模型能夠學到事先定義的映射關系,并且具有較好的泛化能力。
但這不表示可以用這個模型來預測上證指數(shù)走勢,因為決定其走勢的不是前幾天的交易數(shù)據(jù)。這里只是說明循環(huán)神經網絡模型對于時間序列具有的擬合能力。