程序簡介
利用灰色預測GM11模型預測股票收盤價,由於灰色預測模型適合短期預測和小樣本,所以程序輸入數據為5個,輸出為1個,進行動態建模
程序輸入:原序列、需要往后預測的個數
程序輸出:預測值、模型結構(后驗差比、發展系數、灰色作用量)
灰色預測模型(GM11)即對原始數據作累加生成(或其它方法生成)得到近似的指數規律再進行建模的方法。灰色預測模型對於不同問題采用不同模型,模型主要解決生成序列是有指數變化規律,只能描述單調的變化過程。
程序/數據集下載

代碼分析
導入模塊、路徑
# -*- coding: utf-8 -*-
from Module.BuildModel import GM11
from sklearn.metrics import mean_absolute_error
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import os
#路徑目錄
baseDir = ''#當前目錄
staticDir = os.path.join(baseDir,'Static')#靜態文件目錄
resultDir = os.path.join(baseDir,'Result')#結果文件目錄
讀取上證指數數據分割訓練和測試集,本文只使用收盤價,查看內容
#讀取數據
data = pd.read_csv(staticDir+'/000001.csv',encoding='gbk')
train = data['收盤價'].values[-15:-10]#訓練數據
test = data['收盤價'].values[-10:]#測試數據
data.head()
| 日期 | 股票代碼 | 名稱 | 收盤價 | 最高價 | 最低價 | 開盤價 | 前收盤 | 漲跌額 | 漲跌幅 | 成交量 | 成交金額 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2020-02-18 | '000001 | 上證指數 | 2984.9716 | 2990.6003 | 2960.7751 | 2981.4097 | 2983.6224 | 1.3492 | 0.0452 | 311665913 | 3.74998562648e+11 |
| 1 | 2020-02-17 | '000001 | 上證指數 | 2983.6224 | 2983.6371 | 2924.9913 | 2924.9913 | 2917.0077 | 66.6147 | 2.2837 | 313198007 | 3.67014340129e+11 |
| 2 | 2020-02-14 | '000001 | 上證指數 | 2917.0077 | 2926.9427 | 2899.5739 | 2899.8659 | 2906.0735 | 10.9342 | 0.3763 | 250650627 | 3.08080368726e+11 |
| 3 | 2020-02-13 | '000001 | 上證指數 | 2906.0735 | 2935.4060 | 2901.2425 | 2927.1443 | 2926.8991 | -20.8256 | -0.7115 | 274804844 | 3.34526327364e+11 |
| 4 | 2020-02-12 | '000001 | 上證指數 | 2926.8991 | 2926.8991 | 2892.4240 | 2895.5561 | 2901.6744 | 25.2247 | 0.8693 | 248733429 | 2.97534420493e+11 |
使用GM11函數進行動態建模,打印結論,GM11函數位於項目文件夾的Module/BuildModel.py,下文會給出代碼
#GM11動態建模
yPre = []
for i in range(test.shape[0]):
#只預測1個數
result = GM11(train,1)
yPre.append(result['predict']['value'][0])
#更新訓練集
train = train.tolist()[:-1]
train.append(test[i])
train = np.array(train).reshape(-1)
#計算MAE
MAE = mean_absolute_error(test,yPre)
#打印模型
print(result['C']['desc'])
print(result['a']['desc'],np.round(result['a']['value'],2))
print(result['b']['desc'],np.round(result['b']['value'],2))
后驗差比<=0.65,模型精度等級為勉強
發展系數 0.07
灰色作用量 150.96
這是上文GM11的函數,該代碼可直接運行進行測試,函數輸入為原序列和預測個數,輸出為模型各參數和序列值
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
def GM11(x,n):
'''
灰色預測
x:序列,numpy對象
n:需要往后預測的個數
'''
x1 = x.cumsum()#一次累加
z1 = (x1[:len(x1) - 1] + x1[1:])/2.0#緊鄰均值
z1 = z1.reshape((len(z1),1))
B = np.append(-z1,np.ones_like(z1),axis=1)
Y = x[1:].reshape((len(x) - 1,1))
#a為發展系數 b為灰色作用量
[[a],[b]] = np.dot(np.dot(np.linalg.inv(np.dot(B.T, B)), B.T), Y)#計算參數
result = (x[0]-b/a)*np.exp(-a*(n-1))-(x[0]-b/a)*np.exp(-a*(n-2))
S1_2 = x.var()#原序列方差
e = list()#殘差序列
for index in range(1,x.shape[0]+1):
predict = (x[0]-b/a)*np.exp(-a*(index-1))-(x[0]-b/a)*np.exp(-a*(index-2))
e.append(x[index-1]-predict)
S2_2 = np.array(e).var()#殘差方差
C = S2_2/S1_2#后驗差比
if C<=0.35:
assess = '后驗差比<=0.35,模型精度等級為好'
elif C<=0.5:
assess = '后驗差比<=0.5,模型精度等級為合格'
elif C<=0.65:
assess = '后驗差比<=0.65,模型精度等級為勉強'
else:
assess = '后驗差比>0.65,模型精度等級為不合格'
#預測數據
predict = list()
for index in range(x.shape[0]+1,x.shape[0]+n+1):
predict.append((x[0]-b/a)*np.exp(-a*(index-1))-(x[0]-b/a)*np.exp(-a*(index-2)))
predict = np.array(predict)
return {
'a':{'value':a,'desc':'發展系數'},
'b':{'value':b,'desc':'灰色作用量'},
'predict':{'value':result,'desc':'第%d個預測值'%n},
'C':{'value':C,'desc':assess},
'predict':{'value':predict,'desc':'往后預測%d個的序列'%(n)},
}
if __name__ == "__main__":
data = np.array([1.2,2.2,3.1,4.5,5.6,6.7,7.1,8.2,9.6,10.6,11,12.4,13.5,14.7,15.2])
x = data[0:10]#輸入數據
y = data[10:]#需要預測的數據
result = GM11(x,len(y))
predict = result['predict']['value']
predict = np.round(predict,1)
print('真實值:',y)
print('預測值:',predict)
print(result)
進行觀測值預測值可視化
#用來正常顯示中文標簽
plt.rcParams['font.sans-serif']=['SimHei']
#用來正常顯示負號
plt.rcParams['axes.unicode_minus']=False
plt.plot(range(test.shape[0]),yPre,label="預測值")
plt.plot(range(test.shape[0]),test,label="觀測值")
plt.legend()
plt.title('GM11預測效果,MAE:%2f'%MAE)
plt.savefig(resultDir+'/GM11預測效果.png',dpi=100,bbox_inches='tight')

