python實現灰色預測模型(GM11)——以預測股票收盤價為例


程序簡介

利用灰色預測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')


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM