【量化分析】股價路徑預測
以蒙地卡羅模擬法操作
本文重點概要
- 文章難度:★★★☆☆
- 以蒙地卡羅法模擬投資組合未來走勢
- 閱讀建議:本文首先簡述蒙地卡羅的方法原理,接著便會進行資料挑選、模擬過程以及結果呈現,讓讀者了解蒙地卡羅模擬過程的執行,文中不會提及任何數學公式,便於讀者閱讀。
前言
蒙地卡羅模擬法的用途是估計不確定事件的可能結果,其運作方式則是透過假設機率分佈,使不確定性事件的變數建立模型。 並且,每個預測期都會用一組隨機數字來不斷重新計算結果,藉此產生大量的可能結果。
而在財務金融領域中,此方法被廣泛用來衡量資產組合的報酬及風險,較注重預測末尾的極端走勢。因此,本文最後也將透過視覺化結果,說明資產組合的風險報酬表現。
編輯環境及模組需求
本文使用 MacOS 並以 Jupyter Notebook 作為編輯器
#基本套件
import numpy as np
import pandas as pd#繪圖套件
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
sns.set()#TEJAPI
import tejapi
tejapi.ApiConfig.api_key = 'Your Key'
tejapi.ApiConfig.ignoretz = True
資料庫使用
- 證券交易資料表: 資料庫代碼為 ‘TWN/EWPRCD’,提供證券日交易行情資訊,以及還原股價資訊。
- 報酬率資訊表: 資料庫代碼為 ‘TWN/EWPRCD2’,包含證券與指數之報日、週、月、年酬率資料。
資料處理
Step 1. 報酬率資料撈取
ticker = ['1476', '2330', '2603', '2882']
# 儒鴻, 台積電, 國泰金, 長榮ret = tejapi.get('TWN/EWPRCD2', # 公司交易資料-已調整股價(收盤價)
coid = ticker,
mdate = {'gte':'20200101'},
opts = {'columns': ['coid', 'mdate', 'roia']},
chinese_column_name = True,
paginate = True)
ret = ret.set_index('年月日')
# 資料轉置
RetData = {}for i in ticker:
r = ret[ret['證券代碼'] == i]
r = r['日報酬率 %']
RetData.setdefault(i, r)RetData = pd.concat(RetData, axis = 1)
RetData = RetData * 0.01
此處轉換資料表格式,便於後續計算各標的平均報酬與標的間共變異數。
Step 2. 平均報酬、共變異數、本金計算
# 平均報酬
Mean = pd.DataFrame(
list(np.mean(RetData[i]) for i in RetData.columns), index=RetData.columns, columns = ['平均值'])# 共變異數矩陣
covMatrix = RetData.cov()
price = tejapi.get('TWN/EWPRCD', # 公司交易資料-未調整股價
coid = ticker,
mdate = {'gte':'20220525', 'lte':'20220525'},
opts = {'columns': ['coid', 'mdate', 'close_d']},
chinese_column_name = True,
paginate = True)price = price.set_index('年月日')
principal = (price.loc['2020-05-25']['收盤價(元)'].sum()) * 1000
透過加總四支標的於2020年5月25日的收盤價,並假設至少持有一張股票(1000股),則初始本金為1,193,900元。
模擬條件設定
權重設定、模擬期間與模擬次數
# 權重設定
weights = list()for i in range(4):
weights.append(list(price['收盤價(元)'])[i]/price['收盤價(元)'].sum())# 模擬次數
number_of_trial = 100# 模擬期間
sim_period = 30
在權重設定的部分,讀者可以根據自身標的持有情形而做改變,此處直接使用股價權重比例僅為示範而已。
儒鴻:40%、台積電:44%、長榮:12%、國泰金:4%。
模擬計算流程
sim_mean = np.full(shape = (sim_period, 4), fill_value = Mean.T.loc['平均報酬'])
sim_mean = sim_mean.T
首先,定義儲存表格sim_mean並填入各標的之平均報酬,再將其轉置,將個別標的獨立出來。
sim_portfolio = np.full(shape = (sim_period, number_of_trial), fill_value = 0)
接著,定義儲存表格sim_portfolio為投資組合的預測欄位,並先行將每個欄位填入0,後續再通過計算填入該預測路徑該期間之預測值。
for i in range(0, number_of_trial):
multi_normal = np.random.normal(size = (sim_period, 4))
cholesky = np.linalg.cholesky(covMatrix)
sim_return = sim_mean + np.inner(cholesky, multi_normal)
sim_portfolio[:,i] =
np.cumprod(np.inner(weights, sim_return.T)+1) * principal
multi_normal:
從上圖中可以發現,除了長榮(2603)有較嚴重的厚尾問題,各項標的報酬分配大致上接近常態分配,因此本文此處也套用常態分配在各標的上。
cholesky:
在處理多資產投資組合時,透過cholesky分解出共變異數矩陣的下三角矩陣,處理標的間相關性問題。
接著,將上述兩矩陣內積,得到模擬之各項標的報酬走勢;最後乘上個標的權重比例(同樣是內積)以及初始本金,即完成投資組合路徑模擬計算。
視覺化模擬結果
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS'] # 輸入中文plt.figure(figsize=(15,8)) #框定圖表尺寸plt.plot(sim_portfolio)
plt.ylabel('投資組合累積價值變動', fontsize = 15)
plt.xlabel('模擬期間', fontsize = 15)
plt.title('模擬路徑', fontsize = 20)
plt.show()
透過這一次的模擬結果,可以藉由圖表中最下面的路徑推論,接下來一個月該投資組合走勢下檔風險最多不會超過 -16%;而上漲報酬最大可能為25%。因此該投資組合有較低下檔風險以及較高的漲勢機率。
結論
透過上述的過程,相信讀者可以明白蒙地卡羅方法的執行流程,並且可以知道其背後具有統計理論的支撐;然而,也因為蒙地卡羅方法是透過隨機機率為基礎進行大量計算,以模擬將來的可能走勢,所以不能代表市場會全然地與預測結果相同,若市場中有大幅度的波動導致極端值產生,則蒙地卡羅方法的參考性就有所降低。因此,想要在市場中保有領先地位,不僅僅要有邏輯清晰且數據支持的分析結果,也必須時刻掌握資訊的流通,而TEJ也歡迎讀者選購 TEJ E Shop中的方案,相信讀者具有完整的資料庫後,就能輕易地完成自身資產配置的走勢模擬,並掌握市場整體的脈動。
完整程式碼
延伸閱讀
相關連結
- TEJ API 資料庫首頁
- TEJ E-Shop 完整資料庫購買
給我們鼓勵
之後會持續分享更多財金資料庫的應用
如果你的覺得今天的文章不錯,可以幫我們在下面的 掌聲 icon 點 1下
如果覺得超讚,可以按住 掌聲 icon 不放直到 50 下
有任何想法歡迎點選 留言 icon和我們討論