iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 23
0
AI & Data

量化交易30天系列 第 23

量化交易30天 Day23 - 投資組合概念(三) 股債配比分析

  • 分享至 

  • xImage
  •  

量化交易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代表一個投資組合,四個欄位分別是投組的平均報酬率、標準差以及兩個商品的比重。

平均報酬率 v.s. 標準差

這邊就要來看,用真正的股價算出來的數字去畫圖,跟上一篇理論畫出來的圖會不會是相似的

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玩轉金融數據,從個股基本面、技術面、籌碼面相關資料,一直到總體經濟數據,都是平常接觸到的素材;對於投資,除了研究歷史數據,也喜歡瞭解市場上大家在玩些什麼。


上一篇
量化交易30天 Day22 - 投資組合概念(二) 相關係數
下一篇
量化交易30天 Day24 - 投資組合概念(四) 效率前緣
系列文
量化交易30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言