使用ARIMA算法进行时间序列预测。
本文以行健宏扬中国为例,提取数据,使用ARIMA算法进行时间序列预测。
爬取数据
# 抓取行健宏扬中国基金 from bs4 import BeautifulSoup import requests headers = {'Accept':'text/javascript, application/javascript, */*; q=0.01', 'Accept-Encoding':'gzip, deflate', 'Accept-Language':'zh-CN,zh;q=0.8', 'Connection':'keep-alive', 'Cookie':'vjuids=148cf0186.15e03abf2ac.0.c311af0ddaa6c; ADVS=358187b0bd1a65; ASL=17431,000pn,7010519170105191; jrj_uid=15060593555978DJcIwmvnb; jrj_z3_newsid=723; ADVC=35686f6caeedf3; WT_FPC=id=2ef30c6a0af7eaf3a501506059355507:lv=1506063782501:ss=1506063782501; channelCode=3763BEXX; ylbcode=24S2AZ96; vjlast=1503300154.1506059356.23; Hm_lvt_a07bde197b7bf109a325eebaee445939=1506059356; Hm_lpvt_a07bde197b7bf109a325eebaee445939=1506063783', 'Host':'fund.jrj.com.cn', 'Referer':'http://fund.jrj.com.cn/archives,968006,jjjz.shtml', 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36', 'X-Requested-With':'XMLHttpRequest'} params = {'fundCode':'968006', 'obj':'obj', 'date':2017} r = requests.get('http://fund.jrj.com.cn/json/archives/history/netvalue?',params=params,headers=headers) r.encoding ='utf-8' mydata = r.text |
存储数据
# 从字符串中提取标准json格式数据 table = mydata[8:] # 将字符串转为json,不用手动解析 myJson = json.loads(table) # 提取净值数据 myJson['fundHistoryNetValue'] |
from pymongo import MongoClient db = MongoClient('localhost',27017)['fund'] collect = db.get_collection('hjhy') collect.insert(myJson['fundHistoryNetValue']) print('done') |
提取&处理数据
from pymongo import MongoClient import pandas as pd import time,datetime db = MongoClient('localhost',27017)['fund'] data = dict() for item in db.get_collection('hjhy').find(): data[datetime.datetime.fromtimestamp(time.mktime(time.strptime(item['enddate'],'%Y-%m-%d')))] = item['accum_net'] |
使用ARIMA模型预测
1.构建时间序列
# 构建时间序列 my_series = pd.Series(data, data.keys()) # 处理数据类型,将Str转换为float my_series = my_series.apply(lambda x: float(x)) # 按日期生序排序 my_series = my_series.sort_index() |
2.查看趋势图
自此基金成立至今,价格增长趋势变化。
%pylab # plot(my_series) my_series.plot() |
直接使用plot(my_series)会多画出来一条首尾相连接的直线。还是使用my_series.plot()调用对象自身的plot方法吧。
3.进行差分操作
from matplotlib import pyplot as plt # 一阶差分 fig = plt.figure() diff1 = my_series.diff(1) diff1.plot() # 二阶差分 fig = plt.figure() diff2 = my_series.diff(2) diff2.plot() |
4.一阶差分
5.二阶差分
6.查看描述性统计
# 一阶差分描述性统计 diff1.dropna(inplace=True) diff1.describe() |
每一次做差分,都会产生一个NA,所以要记得剔除NA。下面的结果是diff1的描述性统计:
# 二阶差分描述性统计 diff2.dropna(inplace=True) diff2.describe() |
下面的结果是diff2的描述性统计:
所以做一次差分就够了。
7.确定p, q参数值
import statsmodels.api as sm fig = plt.figure() ax0 = fig.add_subplot(211) fig = sm.graphics.tsa.plot_acf(diff1, lags=30, ax=ax0) ax1 = fig.add_subplot(212) fig = sm.graphics.tsa.plot_pacf(diff1, lags=30, ax=ax1) |
这是一阶差分的自相关与偏相关的趋势图,虽然一阶差分的平稳度要比二阶差分略好,但p>0,MR(q)截尾;q>0,AR(p)截尾。
选择使用二阶差分,二阶差分的自相关与偏相关趋势图如下所示:
5.预测
from statsmodels.tsa.arima_model import ARIMA
model = ARIMA(history_price, (12, 2, 1)).fit()
model.forecast(10)[0]
实际值
预测值
array([ 1.41013409, 1.4134152 , 1.41570651, 1.41638723, 1.42131414, 1.42299673, 1.42647455, 1.42795939, 1.43099336, 1.43316138])
欢迎大家围观,长按识别二维码,关注“数据分析手记”~