iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 24
0
AI & Data

量化交易30天系列 第 24

量化交易30天 Day24 - 投資組合概念(四) 效率前緣

  • 分享至 

  • xImage
  •  

量化交易30天
本系列文章是紀錄一位量化交易新手的學習過程,除了基礎的Python語法不說明,其他金融相關的東西都會一步步地說明,希望讓更多想學習量化交易但是沒有學過相關金融知識的朋友們,透過這系列的文章,能夠對量化交易略知一二,也歡迎量化交易的高手們多多交流。

還記得上一篇使用SPY與TLT兩檔商品畫出的曲線嗎?

如果再加上第三檔商品去湊成一個投資組合,那這張圖會變成什麼樣呢?下面就來實驗看看:

加入GLD黃金指數型ETF

  • 爬資料 & 整理
# 爬蟲
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')
GLD = pdr.get_data_tiingo('GLD', api_key='your api key')
SPY.reset_index(inplace=True)
TLT.reset_index(inplace=True)
GLD.reset_index(inplace=True)

# 整理
import pandas as pd
Close = pd.concat([SPY.adjClose, TLT.adjClose, GLD.adjClose], axis = 1)
Close.index = SPY.date
Close.columns = ['SPY', 'TLT', 'GLD']
  • 計算統計數字
# 共變異數矩陣
import numpy as np
cov_matrix = Close.pct_change().apply(lambda x: np.log(1+x)).cov()
cov_matrix

# 平均報酬率
expected_return = Close.resample('Y').last()[:-1].pct_change().mean()
expected_return
SPY    0.150916
TLT    0.057185
GLD    0.091891
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.188367
TLT    0.137420
GLD    0.137545
dtype: float64
# 整理成表格
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 = 3
port_nums = 2000

for port in range(2000):
    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)
    
data = {'Returns': port_ret, 'Standard Dev.': port_dev}

for counter, symbol in enumerate(Close.columns.tolist()):
    data[symbol+' weight'] = [w[counter] for w in port_weights]
    
portfolios = pd.DataFrame(data)
portfolios.head()

  • 繪圖
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)

跟前一篇一樣,上面這張圖的每個點,都代表一個投資組合,都有不同的SPY/TLT/GLD比例,上一篇有提到過,越往左上方的點,報酬率越高而風險越低,所以這些點是最有投資效率的,因此它就稱之為效率前緣,是Markowitz提出的理論。

計算效率前緣

這邊就要用Python找出最左上角的點,稍微寫一下演算法:

  1. 將標準差(x軸)切成1000等份
  2. 針對每一個小等份找出最高報酬率的點
  3. 如果這個點的報酬率高於前一個等份的最高報酬率,就將這個點加入效率前緣組合
# 取效率前緣
std = []
ret = [portfolios[portfolios['Standard Dev.'] == portfolios['Standard Dev.'].min()]['Returns'].values[0]]
eff_front_set = pd.DataFrame(columns=['Returns', 'Standard Dev.', 'SPY weight', 'TLT weight', 'GLD weight'])
for i in range(800,1800,1):
    df = portfolios[(portfolios['Standard Dev.'] >= i/10000) & (portfolios['Standard Dev.'] <= (i+15)/10000)]
    try:
        # 上側
        max_ret = df[df['Returns'] == df['Returns'].max()]['Returns'].values[0]
        if max_ret >= max(ret):
            std.append(df[df['Returns'] == df['Returns'].max()]['Standard Dev.'].values[0])
            ret.append(df[df['Returns'] == df['Returns'].max()]['Returns'].values[0])
            eff_front_set = eff_front_set.append(df[df['Returns'] == df['Returns'].max()], ignore_index = True)
    except:
        pass

ret.pop(0)
eff_front_std = pd.Series(std)
eff_front_ret = pd.Series(ret)

上面這邊就已經取得效率前緣組合的報酬率與標準差。接下來就標出這些點,看看是不是有找對:

plt.figure(figsize=(15,10))
plt.scatter(x = portfolios['Standard Dev.'], y = portfolios['Returns'])
# 效率前緣點,用紅色標註
plt.scatter(x = eff_front_std, y = eff_front_ret, c = 'r')
plt.grid()
plt.xlabel("Standard Dev.", fontsize=20)
plt.ylabel("Expected Returns", fontsize=20)
plt.xticks(fontsize=15)
plt.yticks(fontsize=15)

上面這個圖看起來的確有找到偏左上的點,這些點的集合就是SPY/TLT/GLD三檔商品組成投組的效率前緣啦。

而這些點的投組比例如下表,共有759個投資組合。

eff_front_set

本篇總結
這篇就實際用三檔商品計算,來了解什麼是效率前緣,教科書在教可能會比較抽象一點,真正帶入數據計算之後,感覺更具體了一些,這些投組的比例只提供參考,實際投資還是有許多要考慮的因素,例如:總體經濟、市場趨勢...等等。

那效率前緣包含許多的投資組合,投資人該怎麼去分析這些投組的差異性呢?下一篇將引述相關的金融理論來說明,請繼續收看囉。

P.S.
如果大家對於量化交易有興趣的話,我自己有上過以下這門課,課程內容從串接股市資料API、儲存至資料庫、將自己的策略轉化成程式碼、自動下單,並且可以把整個流程自動化,每天早上執行一次,一整天就不用看盤了,覺得是蠻實戰的,可以參考看看。

筆者 Sean
奈米戶投資人 / Python愛用者
喜歡用Python玩轉金融數據,從個股基本面、技術面、籌碼面相關資料,一直到總體經濟數據,都是平常接觸到的素材;對於投資,除了研究歷史數據,也喜歡瞭解市場上大家在玩些什麼。


上一篇
量化交易30天 Day23 - 投資組合概念(三) 股債配比分析
下一篇
量化交易30天 Day25 - 投資組合概念(五) Sharpe ratio
系列文
量化交易30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言