[本文內容僅就一般性之證券投資公開資訊進行統計程式教學之範例,作者並不針對特定有價證券買賣提供建議]
統計上常用的管制圖(control chart)是透過標準差的計算來檢視資料的健康性;在上篇文章中,我們已經可以利用 pyTorch 以及 yfinance 這兩個 python 的工具透過股票資料來建立類神經網路模型,找到資料的趨勢;並且加上兩倍標準差及三倍標準差的計算,觀察資料的分佈,以得到有效的圖形作為資料健康判斷的依據;這樣的作法跟管制圖的使用,其實相當地接近。
為了可以更方便地使用上次發展出來的三層式類神經網路模型,可以先將程式作一些整理:
- 引入類別庫
在這個程式分別使用了「pyTorch」用來建立類神經網路以及作為 GPU 平行運算使用;「yfinance」作為擷取股票資料使用;「tqdm」用來顯示類神經網路訓練時疊代計算的進度。
import torch
from torch import nn
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
import matplotlib.font_manager as fontManger
from tqdm import tqdm
- 定義類神經網路
依照上篇文章的作法,定義一個三層式的類神經網路。
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)
- 定義呼叫函式
整理上一篇文章中發展出來的程式,依序分成「擷取資料及資料前處理」「建立並訓練類神經網路」「取得模型預測值」「繪製管制圖」幾個部份;這個函式可以單獨依照輸入的股票代號及名稱,完整完成一支股票或指標以一年為區間的管制圖。
def stockModel(idName, idLabel):
#------------- read stock data
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)
#-------------- normalized
train_x=(x-np.mean(x))/(np.max(x)-np.min(x))
train_y=(y-np.mean(y))/(np.max(y)-np.min(y))
#-------------- transfer to GPU data
X_train=torch.tensor(train_x.astype('float32')).unsqueeze(dim=1).to(device)
Y_train=torch.tensor(train_y.astype('float32')).to(device)
#------------- setup neural network training model
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
#------------- training neural network model
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()
#------------- predict from trained model
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)))
#------------- plot control chart
offset=np.std(y_pred-y)
upperBound1=y_pred+offset
lowerBound1=y_pred-offset
upperBound2=y_pred+offset*2
lowerBound2=y_pred-offset*2
#--------------
zhfont=fontManger.FontProperties(fname='NotoSansTC-VariableFont_wght.ttf')
labelX=dataYahoo.index.strftime('%Y/%m/%d')
showTick=np.arange(0,nData,20)
plt.plot(x,y,'b.',label=idLabel+'收盤資料')
plt.plot(x,upperBound1,'g--')
plt.plot(x,lowerBound1,'g--')
plt.plot(x,upperBound2,'r--')
plt.plot(x,lowerBound2,'r--')
plt.grid()
plt.legend(fontsize=12,prop=zhfont)
plt.ylabel(idLabel,fontproperties=zhfont)
plt.xlabel('日期',fontproperties=zhfont)
plt.xticks(ticks=showTick,labels=labelX[showTick],
fontsize=8,rotation=45)
plt.show()
- 撰寫主程式
最後我們定義程式所執行的 GPU 以及要繪製出來的股票或加權指標的圖形;可以提供綜合的判斷依據。
device=torch.device('cpu')
if torch.cuda.is_available():
device=torch.device('cuda')
elif torch.backends.mps.is_available():
device=torch.device('mps')
stock=[]
stock.append({'id':'^SOX','name':'費城半導體指數'})
stock.append({'id':'^TWII','name':'台灣加權指數'})
stock.append({'id':'2330.TW','name':'台積電'})
stock.append({'id':'2303.TW','name':'聯電'})
stock.append({'id':'0050.TW','name':'元大台灣五十(0050)'})
stock.append({'id':'0056.TW','name':'元大高股息(0056)'})
#-----------
for i in range(len(stock)):
stockModel(stock[i]['id'],stock[i]['name'])
- 輸出結果
其實本來一直以來就有很多各式各樣的圖表提供股票或財經的分析及判斷;類神經網路的好處是在於不限定於一個固定公式,而能從資料面找到接近的模型;透過這樣型的建立,再加上統計計算,建立一個可以使用般常管制圖的使用方法的圖形,作為資料判斷的依據。當然,在建立模型的過程當中,會有一些參數的設定都會影響到輸出的結果;這就有賴股票財經方面知識的累積來取得最佳參數的設定。





