Python预测基金净值:LSTM模型有点香
搭建LSTM神经网络预测基金净值
上一篇《Python预测基金净值:keras神经网络》搭建了一个简单神经网络用来预测基金净值。
最后得出什么结论?
有点臭。
看看训练情况:
Epoch 1/100
156/156 [= = = = =] - 0s 3ms/step - loss: 0.0450 - val_loss: 0.1114
…
Epoch 100/100
156/156 [= = = = =] - 0s 2ms/step - loss: 0.0299 - val_loss: 0.1056
经过100次训练,训练集的loss已经从0.0450降到0.0299,但是验证集的val_loss几乎么有改善(说明训练集的“改善”只是过拟合)。这对于一个神经网络而言,相当于死刑判决:模型或参数有大问题。
事实上,对于股票/指数/基金净值这些“有序”数据而言,应该采用循环神经网络来搭建,本篇就此试一试。
初步结论是:有点香。
一、LSTM简述
循环神经网络(Recurrent Neural Network, RNN)是以序列数据为输入,在序列的演进方向进行循环递归的递归神经网络。RNN适用于处理时间顺序、逻辑顺序或其他序列特性顺序的数据。
RNN的单元结构如下图(左)所示,上一时刻输出ht-1与当前时刻输入Xt进行拼接,然后由神经网络(以tanh为激活函数)进行处理,得到输出ht。
后续研究发现RNN存在“长期依赖问题”(long-term dependencies problem),亦即在学习过程中,会出现梯度消失或梯度爆炸现象。
LSTM比较好地解决了这个问题,其单元结构如上图(中)所示,增加了一个t时刻的细胞状态Ct,并且增加了三个门(忘记门、输入门、输出门),即图中标注为σ(sigma)的3个以sigmoid作为激活函数的神经网络。如果去掉Ct和三个门,如上图(右)所示,则与上图(左)的RNN等效。
关于LSTM,可参见:理解 LSTM 网络 by 朱小虎
关于keras,可参见:keras中文文档
二、继续爬基金,生成训练集、验证集、测试集文件
import requests
import time
import execjs
fileTrain = './data/accTrain.csv'
jjTrain = ['004609', '004853', '005524', '005824', '007749']
fileTest = './data/accTest.csv'
jjTest = '007669'
def getUrl(fscode):
head = 'http://fund.eastmoney.com/pingzhongdata/'
tail = '.js?v='+ time.strftime("%Y%m%d%H%M%S",time.localtime())
return head+fscode+tail
# 根据基金代码获取净值
def getWorth(fscode):
content = requests.get(getUrl(fscode))
jsContent = execjs.compile(content.text)
#累计净值走势
ACWorthTrend = jsContent.eval('Data_ACWorthTrend')
ACWorth = []
for dayACWorth in ACWorthTrend:
ACWorth.append(dayACWorth[1])
return ACWorth
ACWorthFile = open(fileTrain, 'w')
for code in jjTrain:
try:
ACWorth = getWorth(code)
except:
continue
if len(ACWorth) > 0:
ACWorthFile.write(",".join(list(map(str, ACWorth))))
ACWorthFile.write("\n")
print('{} data downloaded'.format(code))
ACWorthFile.close()
ACWorthTestFile = open(fileTest, 'w')
ACWorth = getWorth(jjTest)
if len(ACWorth) > 0:
ACWorthTestFile.write(",".join(list(map(str, ACWorth))))
ACWorthTestFile.write("\n")
print('{} data downloaded'.format(jjTest))
ACWorthTestFile.close()
如上一篇所述,‘004609’, ‘004853’, ‘005524’, ‘005824’, '007749’是5只目前收益较稳定的偏债型混合基金。爬取每日净值数据,作为训练集和验证集(通过设置validation_split=0.25)的数据文件。'007669’也是一只同类型的基金,上一篇没选它,是因为它目前在支付宝基金里面暂停代购。这次用作测试集的数据文件。
注意,和上一篇相比,代码改动了一点:基金数据按日期正序保存。
三、建模,读入数据,训练,验证
import numpy as np
import pandas as pd
import csv
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from matplotlib import pyplot as plt
plt.rcParams['font.sans-serif']='SimHei'
plt.rcParams['axes.unicode_minus']=False
batch_size = 4
epochs = 50
time_step = 6 #用多少组天数进行预测
input_size = 6 #每组天数,亦即预测天数
look_back = time_step * input_size
showdays = 120 #最后画图观察的天数(测试天数)
X_train = []
y_train = []
X_validation =