[本文內容僅就一般性之證券投資公開資訊進行統計程式教學之範例,作者並不針對特定有價證券買賣提供建議]
一般我們會使用類神經網路來建立系統模型的原因,通常是因為無法用固定的方程式來描述系統,另一則是希望能夠透過建立的模型來更瞭解系統的變化。股票市場的變化,其實就是一個很典型的例子。
- 建立類神經網路類別
我們可以先利用「pyTorch」來建立一個類神經網路,作為股票資料的模型;模型的輸入為時間,而輸出則為股價。在這裏使用簡單的三層式反饋式類神經網路。
import torch
from torch import nn
#--------
# 取得 GPU device
#--------
device=torch.device('cpu')
if torch.cuda.is_available():
device=torch.device('cuda')
elif torch.backends.mps.is_available():
device=torch.device('mps')
#-----------
class classNeural(nn.Module):
def __init__(self,n_input,n_hidden,n_output):
super().__init__()
self.n_input=n_input
self.n_hidden=n_hidden
self.n_output=n_output
#--------
self.layer1=nn.Linear(n_input,n_hidden)
self.layer2=nn.Linear(n_hidden,n_output)
self.active=nn.Sigmoid()
#--------
def forward(self,x):
x=self.active(self.layer1(x))
return self.layer2(x)
- 取得線上股市資料庫
再來,依照之前文章的例子,我們可以透過「yfinance」 提供的股市資料庫來取得台北股市的資料;
import yfinance as yf
from datetime import date
from datetime import timedelta
from dateutil.relativedelta import relativedelta
import numpy as np
import matplotlib.pyplot as plt
# Google Chinese Font
# https://fonts.google.com/noto/specimen/Noto+Sans+TC?subset=chinese-traditional&script=Hant
import matplotlib.font_manager as fontManger
zhfont=fontManger.FontProperties(fname='NotoSansTC-VariableFont_wght.ttf')
#--------
# read Stock values
idName='^TWII'
# idName='^DJI'
endDate=date.today()
beginDate=endDate-relativedelta(months=12)
dataYahoo=yf.download(idName,start=beginDate,end=endDate,auto_adjust=True)
#---------------
- 訓練資料處理
取得資料之後,利用收盤價為模式學習的目標;不過要注意的是,股價或指數的數字必須要經過「正規化」的步驟,才能交給類神經綱路作訓練。
#---------------
y=dataYahoo['Close'].values
nData=len(y)
x=np.arange(0,nData,1.0)
#--------------
train_x=(x-np.mean(x))/(np.max(x)-np.min(x))
train_y=(y-np.mean(y))/(np.max(y)-np.min(y))
- GPU 資料轉換
同時,由於我們是在使用「pyTorch」透過 GPU 來進行訓練,所以資料要轉換成「pyTorch」要求的「Tensor」的型態來進行運算。
#--------------
X_train=torch.tensor(train_x.astype('float32')).unsqueeze(dim=1).to(device)
Y_train=torch.tensor(train_y.astype('float32')).to(device)
#-------------
- 類神經網路模型訓練
接下來,就是進行類神經網路的訓練,我們以 2000 次的疊代訓練為例。不過,訓練過程可能會花費一些時間;所以可以利用「tqdm」這個函數來輸出訓練的過程,可以看到實際訓練的進度。
from tqdm import tqdm
torch.manual_seed(13)
stockModel=classNeural(1,10,1).to(device)
loss_fn=nn.MSELoss() # MSE
optimizer=torch.optim.AdamW(stockModel.parameters(),lr=0.01)
stockModel.train()
n_epoche=2000
for epoche in tqdm(range(n_epoche)):
Y_pred=stockModel(X_train)
loss=loss_fn(Y_pred,Y_train)
optimizer.zero_grad()
loss.backward()
optimizer.step()
#------------

- 類神經網路模型預測
訓練結束之後,就會有一個可以使用的模型。接下來,使用原來的時間資料透過建立好的模型,就可以到正規化的預測結果。
stockModel.eval()
with torch.inference_mode():
Y_pred=stockModel(X_train)
y_cpu=Y_pred.to("cpu").numpy()
y_pred=np.mean(y)+y_cpu*((np.max(y)-np.min(y)))
#-----------
- 初步模型結果
有了預測結果,我們可以將模型以及原始資料繪製出來作為比較。
labelX=dataYahoo.index.strftime('%Y/%m/%d')
showTick=np.arange(0,nData,20)
#-----------
plt.plot(x,y,'b.',label='原始資料')
plt.plot(x,y_pred,'r-',label='模型')
plt.grid()
plt.legend(fontsize=12,prop=zhfont)
plt.ylabel('台灣加權指數',fontproperties=zhfont)
plt.xlabel('日期',fontproperties=zhfont)
plt.xticks(ticks=showTick,labels=labelX[showTick],
fontsize=8,rotation=45)
plt.show()

- 統計模型結果
在這裏我們可以看得出來,類神經網路確實有將股市資料的趨勢具體建立成一個模型。不過,由於股市資料本身就是不斷變動的資料,所以一般會再使用資料的變動指標,例如「兩倍標準差95%區間」來描述股票的行為;同時可以提供資料與趨勢模型偏移量的判斷依據;例如:
# variation evaluation
offset=np.std(y_pred-y)*2
upperBound=y_pred+offset
lowerBound=y_pred-offset
plt.plot(x,y,'b.',label='原始資料')
plt.plot(x,upperBound,'r--',label='95% 邊限')
plt.plot(x,lowerBound,'r--')
plt.grid()
plt.legend(fontsize=12,prop=zhfont)
plt.ylabel('台灣加權指數',fontproperties=zhfont)
plt.xlabel('日期',fontproperties=zhfont)
plt.xticks(ticks=showTick,labels=labelX[showTick],fontsize=8,rotation=45)
plt.show()
