量化交易30天
本系列文章是紀錄一位量化交易新手的學習過程,除了基礎的Python語法不說明,其他金融相關的東西都會一步步地說明,希望讓更多想學習量化交易但是沒有學過相關金融知識的朋友們,透過這系列的文章,能夠對量化交易略知一二,也歡迎量化交易的高手們多多交流。
這一篇要來討論股債配比的議題,到底80/20、60/40有什麼差別呢?就拿數據來跑跑看吧,這次採用的投資組合是SPY跟TLT這兩檔指數型ETF,是蠻常被討論到的被動投資的標的,就拿它們來做實驗吧!
這邊就用Day1寫的tiingo api來爬一下,沒看過的可以跳過去看看喔。
import os
import pandas_datareader as pdr
SPY = pdr.get_data_tiingo('SPY', api_key='YOUR API KEY')
TLT = pdr.get_data_tiingo('TLT', api_key='YOUR API KEY')
SPY.reset_index(inplace=True)
TLT.reset_index(inplace=True)
這次的資料區間是從2015/10/01到2020/09/28
import pandas as pd
Close = pd.concat([SPY.adjClose, TLT.adjClose], axis = 1)
Close.index = SPY.date
Close.columns = ['SPY', 'TLT']
Close
相關係數是用在計算兩個變數的相關程度,可以用一個corr函數運算,相當方便,從下表可以看出來,在這個資料區間,SPY與TLT的相關係數大概是-0.413,表示兩者在這個區間是負相關的。
import numpy as np
corr = Close.pct_change().apply(lambda x: np.log(1+x)).corr()
corr_matrix
這邊會使用2015到2019的年報酬率,然後再做一個平均,計算這個時間區間的簡單平均年報酬率。
expected_return = Close.resample('Y').last()[:-1].pct_change().mean()
expected_return
SPY 0.150916
TLT 0.057185
dtype: float64
計算兩者的股價標準差
standard_dev = Close.pct_change().apply(lambda x: np.log(1+x)).std().apply(lambda x: x*np.sqrt(250))
standard_dev
SPY 0.188457
TLT 0.137443
dtype: float64
從下表可以看出來,SPY的平均報酬率較高,但標準差也較大;TLT的平均報酬率較低,標準差也低一些。
return_dev_matrix = pd.concat([expected_return, standard_dev], axis = 1)
return_dev_matrix.columns = ['Exp Returns', 'Standard Dev.']
return_dev_matrix
為了畫出預期報酬率與標準差的那條曲線圖,這邊要先用許多的不同投資比例去組合,算出平均報酬率跟標準差,所以每個投組在圖上都會是一個點,如果點夠多的話,這些點連起來應該會像上一篇最後的那張圖一樣,是一條曲線。
# 投組報酬率
port_ret = []
# 投組標準差
port_dev = []
# 投組比例
port_weights = []
# 投組商品數
assets_nums = 2
# 不同投組的數量,點越多代表組合越多種,圖畫出來就越密
port_nums = 2000
# 計算共變異數
cov_matrix = Close.pct_change().apply(lambda x: np.log(1+x)).cov()
# random兩千個不同比例的投組,算出報酬率跟標準差
for port in range(2000):
# random比例
weights = np.random.random(assets_nums)
weights = weights/np.sum(weights)
port_weights.append(weights)
# 計算平均報酬
returns = np.dot(weights, expected_return)
port_ret.append(returns)
# 計算標準差
var = cov_matrix.mul(weights, axis=0).mul(weights, axis=1).sum().sum()
sd = np.sqrt(var)
ann_sd = sd*np.sqrt(250)
port_dev.append(ann_sd)
# 將資料整合成一個dataframe
data = {'Returns': port_ret, 'Standard Dev.': port_dev}
# 標註每個row使用的投組比例是多少
for counter, symbol in enumerate(Close.columns.tolist()):
data[symbol+' weight'] = [w[counter] for w in port_weights]
# 整理資料成表格
portfolios = pd.DataFrame(data)
portfolios.head()
上面這個表格中,每個row代表一個投資組合,四個欄位分別是投組的平均報酬率、標準差以及兩個商品的比重。
這邊就要來看,用真正的股價算出來的數字去畫圖,跟上一篇理論畫出來的圖會不會是相似的
import matplotlib.pyplot as plt
plt.figure(figsize=(15,10))
plt.scatter(x = portfolios['Standard Dev.'], y = portfolios['Returns'])
plt.grid()
plt.xlabel("Standard Dev.", fontsize=20)
plt.ylabel("Expected Returns", fontsize=20)
plt.xticks(fontsize=15)
plt.yticks(fontsize=15)
仍然是一條漂亮的曲線,也符合相關係數小於0的投資組合該有的長相。
本篇總結
這篇主要都是在做計算的部份,下一篇會分析這張圖,並藉由這張圖學習一下效率前緣理論,請繼續收看。
P.S.
如果大家對於量化交易有興趣的話,我自己有上過以下這門課,課程內容從串接股市資料API、儲存至資料庫、將自己的策略轉化成程式碼、自動下單,並且可以把整個流程自動化,每天早上執行一次,一整天就不用看盤了,覺得是蠻實戰的,可以參考看看。
筆者 Sean
奈米戶投資人 / Python愛用者
喜歡用Python玩轉金融數據,從個股基本面、技術面、籌碼面相關資料,一直到總體經濟數據,都是平常接觸到的素材;對於投資,除了研究歷史數據,也喜歡瞭解市場上大家在玩些什麼。