機器人理財 — 投資組合再平衡效益分析
這裡有完整的機器人理財分析報告,有關於再平衡分析的結果,說明為甚麼進行再平衡能夠優化投資組合,以及多久進行一次再平衡能夠有最高的sharpe ratio。
.1. 投資組合再平衡的頻率(每月、每季、每半年、每年) 如何影響投資績效? 最佳的再平衡頻率為何?
以60%股票/40%債券的投資組合為例,股票標的包含:VTI、IVV、IWM、QQQ、EFA、IWB、SPYG、SPYV、IOO,債券ETF標的包含:TLT、IEF、AGG、LQD,投資期間為10年,請隨機抽取40組起始日,然後比較未再平衡的投資組合與不同再平衡頻率的投資組合間,年化報酬率、年化標準差、夏普值、最大下跌幅度的差異。
在我的做法中,首先我使用yahoo finance下載相關的股票和債券的標的,從2005年1月1日到2024年5月14號的資料,同時我們設定可以選擇的起始時間點是2005/1/1到2014/5/13,投資期間為十年。 同時,我們將所有開盤日期存在days裡面,並且先處理好無風險利率以及beta值(用SPY)為主的內容。同時,為了方便起見,我沒有計算買賣股票的手續費。
import yfinance as yf
import numpy as np
import pandas as pd
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
from scipy import stats
import random
from tqdm import tqdm
stock_list = ["VTI", "IVV", "IWM", "QQQ", "EFA", "IWB", "SPYG", "SPYV", "IOO","IYR", "TLT", "IEF", "AGG", "LQD", "GLD", "TIP","ICF","^TNX","SPY"]
for stock in stock_list:
stock_name = yf.Ticker(stock)
stock_hist = stock_name.history(start="2005-01-01", end="2024-05-14")
stock_hist.to_csv(f"{stock}.csv")
#將每日收盤價資料存進一個dictionary之中
price_data = dict()
for i in stock_list:
df = pd.read_csv(i+'.csv')
price_data[i] = df['Close'].tolist()
print(len(price_data[i]))
# 紀錄所有的datetime資料
from datetime import datetime, timedelta
days = df['Date'].tolist()
for a, j in enumerate(days):
days[a] = datetime.strptime(j, '%Y-%m-%d %H:%M:%S%z').date()
# 紀錄rf的資料
from datetime import datetime, timedelta
tnx = pd.read_csv("TNX.csv")
rf = list()
for i, d in tnx.iterrows():
if datetime.strptime(d["Date"], '%Y-%m-%d %H:%M:%S%z').date() in days:
rf.append(d["Close"])
rf = [x for x in rf if x == x]
rf_mean = (sum(rf) / len(rf))/100
# 準備不同期限的年齡資料的result
none_result = []
monthly_result = []
quarterly_result = []
semiannually_result = []
annually_result = []
collect_result()函數是用來計算所有相關數值,輸入的內容包含interval(半年、一年、一個月、一季、無…),price_his(包含每一個交易日他持有的金額,扣掉本金100萬之後可以算出各式報酬率等),以及index(他從第幾個交易日開始計算,到index+2520個交易日,我們假設每個人都投資十年,也就是2520個交易日)。print_result則是將我所儲存的資料的統計資料印出。
除了年化收益率、年化標準差、最大回測以及sharpe ratio、最後該用戶所持有的本金之外,我也額外計算該投資組合的beta與alpha(用SPY來當作rm),以及特雷諾比率與卡馬比率。
# 只要有每一天的本金,就可以計算所有數值
from datetime import datetime, timedelta
def collect_result(interval, price_his, index):
data_collected = []
final_principal = BGN_PRINCIPAL*price_his[-1]/price_his[0]
close_series = pd.Series(price_his)
sp500_close_series = pd.Series(price_data["SPY"])
# 期末本金
data_collected.append(final_principal)
# 計算每日收益率
daily_return = close_series.pct_change()
# 計算年化收益率
annual_return = daily_return.mean() * 252
data_collected.append(annual_return)
# 計算年化標準差
annual_std = daily_return.std() * np.sqrt(252)
data_collected.append(annual_std)
# 計算每個時間點之前的最高價格
high_water_mark = close_series.expanding().max()
# 計算每個時間點的回撤,並尋找最大的drawdown
drawdown = (close_series - high_water_mark) / high_water_mark
max_drawdown = drawdown.min()
data_collected.append(max_drawdown)
# sharpe ratio計算
sharpe_ratio = (annual_return - rf_mean) / annual_std
data_collected.append(sharpe_ratio)
# 計算 sp500 從起始日到最後一天的每日收益率
sp500_daily_return = sp500_close_series[index:index+2520].pct_change()
sp500_annual_return = sp500_daily_return.mean() * 252
# 計算 sp500 的年化標準差
sp500_annual_std = sp500_daily_return.std() * np.sqrt(252)
sp500_sharpe_ratio = (sp500_annual_return - rf_mean) / sp500_annual_std
data_collected.append(sp500_sharpe_ratio)
beta, _ = stats.linregress(sp500_daily_return.dropna(), daily_return.dropna())[:2]
data_collected.append(beta)
alpha = annual_return - rf_mean - beta * (sp500_annual_return - rf_mean)
data_collected.append(alpha)
treynor_ratio = (annual_return - rf_mean) / beta
data_collected.append(treynor_ratio)
calmar_ratio = annual_return / abs(max_drawdown)
data_collected.append(calmar_ratio)
if interval == "none":
none_result.append(data_collected)
if interval == "monthly":
monthly_result.append(data_collected)
if interval == "quarterly":
quarterly_result.append(data_collected)
if interval == "semiannually":
semiannually_result.append(data_collected)
if interval == "annually":
annually_result.append(data_collected)
def print_result(interval, name):
data_collected = []
if interval == "none":
data_collected = none_result
if interval == "monthly":
data_collected = monthly_result
if interval == "quarterly":
data_collected = quarterly_result
if interval == "semiannually":
data_collected = semiannually_result
if interval == "annually":
data_collected = annually_result
print("==================================================")
print(f"============= {name} result =============")
final_principal = sum(i[0]/len(data_collected) for i in data_collected)
print("期末本金:{:6.9}元".format(final_principal))
# 計算年化收益率
annual_return = sum(i[1]/len(data_collected) for i in data_collected)
print("年化報酬率:{:1.5%}".format(annual_return))
# 計算年化標準差
annual_std = sum(i[2]/len(data_collected) for i in data_collected)
print("年化標準差:{:.2%}".format(annual_std))
# max_drawdown
max_drawdown = sum(i[3]/len(data_collected) for i in data_collected)
print("ETF 的最大回撤為: {:.2%}".format(max_drawdown))
# sharpe ratio計算
sharpe_ratio = sum(i[4]/len(data_collected) for i in data_collected)
print("Sharpe比率: {:.5f}".format(sharpe_ratio))
# sp500
sp500_sharpe_ratio = sum(i[5]/len(data_collected) for i in data_collected)
print("該期SP500的Sharpe比率: {:.5f}".format(sp500_sharpe_ratio))
beta = sum(i[6]/len(data_collected) for i in data_collected)
print("Beta值: {:.5f}".format(beta))
alpha = sum(i[7]/len(data_collected) for i in data_collected)
print("Alpha值: {:.5f}".format(alpha))
treynor_ratio = sum(i[8]/len(data_collected) for i in data_collected)
print("特雷諾比率: {:.5f}".format(treynor_ratio))
calmar_ratio = sum(i[9]/len(data_collected) for i in data_collected)
print("卡瑪比率: {:.5f}".format(calmar_ratio))
print("==================================================")
# Function to rebalance portfolio
def rebalance_portfolio(portfolio_value, numbers_of_each_ETF, current_index):
new_numbers_of_each_ETF = []
for asset, weight in weights.items():
target_value = portfolio_value * weight
current_value = numbers_of_each_ETF[list(weights.keys()).index(asset)] * price_data[asset][current_index]
new_amount = target_value / price_data[asset][current_index]
new_numbers_of_each_ETF.append(new_amount)
return new_numbers_of_each_ETF
def calculate_portfolio_value(index):
new_portfolio_value = 0
cnt = 0
for asset, weight in weights.items():
new_portfolio_value += numbers_of_each_ETF[cnt]*price_data[asset][index]
cnt += 1
price_his.append(new_portfolio_value)
return new_portfolio_value
在第一題中,我們假設stock_etf裡面所有的股票ETF所佔據的比重維持60/9% = 6.6667%,而bond_etf裡面的債券ETF則時40/4% = 10%,我們每次再平衡的時候,都要維持這個比例。同時我們定義時間間隔:我們一律抓2520天當作某人的投資週期(10年),定義時間間隔一年252天、半年126天、三個月63天、一個月21天。
calculate_portfolio_value代表在某天時,該投資者的本金是多少,而rebalance_portfolio則是在特定需要再平衡的日子被呼叫,透過賣出漲幅較高的股票,買進報酬率較低的股票,來讓stock etf的比率回到6.667%,bond etf的比率回到10%。
# question 1
import datetime
weights = dict()
stock_etf = ['VTI','IVV','IWM','QQQ','EFA','IWB','SPYG','SPYV','IOO']
bond_etf = ['TLT', 'IEF', 'AGG', 'LQD']
for i in stock_etf:
weights[i] = 0.6/len(stock_etf)
for i in bond_etf:
weights[i] = 0.4/len(bond_etf)
import datetime
BGN_PRINCIPAL = 1000000
num_simulations = 40
rebalancing_frequencies = ['monthly', 'quarterly','semiannually', 'annually', 'none']
filtered_dates = [date for date in days if date < datetime.date(2014, 5, 14)]
for i in tqdm(range(num_simulations)):
# Select a random starting date within the investment period
random_index = random.randint(0, 2354)
for freq in rebalancing_frequencies:
portfolio_value = BGN_PRINCIPAL
current_index = random_index
inner_count = 0
numbers_of_each_ETF = []
price_his = []
for asset, weight in weights.items(): #weight應該不變
value_distributed = portfolio_value*weight
amount_of_ETF_bought = value_distributed/price_data[asset][current_index]
numbers_of_each_ETF.append(amount_of_ETF_bought)
while True:
inner_count += 1
portfolio_value = calculate_portfolio_value(current_index)
if freq == 'monthly' and inner_count % 21 == 0:
numbers_of_each_ETF = rebalance_portfolio(portfolio_value, numbers_of_each_ETF, current_index)
elif freq == 'quarterly' and inner_count % 63 == 0:
numbers_of_each_ETF = rebalance_portfolio(portfolio_value, numbers_of_each_ETF, current_index)
elif freq == 'semiannually' and inner_count % 126 == 0:
numbers_of_each_ETF = rebalance_portfolio(portfolio_value, numbers_of_each_ETF, current_index)
elif freq == 'annually' and inner_count % 252 == 0:
numbers_of_each_ETF = rebalance_portfolio(portfolio_value, numbers_of_each_ETF, current_index)
current_index += 1
if inner_count == 2520:
break
collect_result(freq, price_his, random_index)
for freq in rebalancing_frequencies:
print_result(freq, freq)
我的策略是每天都要計算投資人在該時間擁有的總資產,同時在需要在平衡的時間點進行在平衡,確保股票ETF的比例是6.67%,債券ETF的比例是10%,最後的結果如下:
============= monthly result =============
期末本金:2275620.4元
年化報酬率:8.71657%
年化標準差:10.80%
ETF 的最大回撤為: -27.93%
Sharpe比率: 0.61091
該期SP500的Sharpe比率: 0.52141
Beta值: 0.54750
Alpha值: 0.01225
特雷諾比率: 0.11703
卡瑪比率: 0.36628
============= quarterly result =============
期末本金:2278855.72元
年化報酬率:8.71595%
年化標準差:10.65%
ETF 的最大回撤為: -27.51%
Sharpe比率: 0.61868
該期SP500的Sharpe比率: 0.52141
Beta值: 0.53807
Alpha值: 0.01308
特雷諾比率: 0.11901
卡瑪比率: 0.36984
============= semiannually result =============
期末本金:2284789.87元
年化報酬率:8.73418%
年化標準差:10.51%
ETF 的最大回撤為: -27.04%
Sharpe比率: 0.62656
該期SP500的Sharpe比率: 0.52141
Beta值: 0.52984
Alpha值: 0.01392
特雷諾比率: 0.12106
卡瑪比率: 0.37267
============= annually result =============
期末本金:2277996.22元
年化報酬率:8.69090%
年化標準差:10.42%
ETF 的最大回撤為: -26.52%
Sharpe比率: 0.62593
該期SP500的Sharpe比率: 0.52141
Beta值: 0.52469
Alpha值: 0.01382
特雷諾比率: 0.12123
卡瑪比率: 0.37526
============= none result =============
期末本金:2315145.25元
年化報酬率:8.80914%
年化標準差:10.83%
ETF 的最大回撤為: -27.69%
Sharpe比率: 0.59808
該期SP500的Sharpe比率: 0.52141
Beta值: 0.55294
Alpha值: 0.01070
特雷諾比率: 0.11548
卡瑪比率: 0.34635
我們分開檢視這些資料,可以得到以下的觀點:
a. 有關於年化報酬率的部分,最後的結果是不調整>半年>一個月>一季>一年,但是後三者的年畫報酬率相差不大,會因為參考時間的不同而有所變動,但是整體來說,不調整的報酬率會是最高的,半年第二,所以如果要追求報酬率的化,應該要以半年調整一次為主。
b. 關於年化標準差的部分,結果是不調整>一個月>一季>半年>一年,可以觀察到如果有進行再平衡的化,一年調整一次的標準差最小。
c. 綜合以上的資料,我們可以透過sharpe ratio來觀察哪個的sharpe ratio比較高,最後的結果是半年(0.62656)>一年(0.62593)>一季(0.61868)>一個月(0.61091)>不調整(0.59808),如果以sharpe ratio來當作選擇基礎的化,會跟年化報酬率的結果類似,半年調整一次的結果會是最好的,一年調整一次的結果也相當類似,而過短時間就平衡一次或不平衡的結果都不夠好。
d. 關於max drawdown的部分,這也是風險的一個指標,可以觀察到是一年>半年>三個月>不調整>一個月,蠻有趣的是不調整的max drawdown會比一個月調整一次還要來的好,本來以為不調整的化會面齡最大的drop down風險,但是結果論來說是一個月調整一次沒有顯著的優勢。
e. 觀察到beta值和alpha值的部分,alpha值的比率比較是半年調整一次(0.01392)>一年(0.01382)>一季(0.01308)>一個月(0.01225)>不調整(0.01070),這也顯示出半年調整一次是最好的選擇,因為可以得到最高比例的超額報酬。而beta在這分調查的意義不大,多數都是比只投資SPYU還要保守,在0.52到0.55之間。
配合我沒有提到的其他比率,以及sharpe跟alpha值等等,皆顯示出半年調整一次是最好的時間間隔。
2. 資產間的相關係數如何影響投資組合再平衡的效益?
請以50%A資產/50%B資產的投資組合為例,AB資產包含VTI、IVV、IWM、QQQ、EFA、IWB、SPYG、SPYV、IYR、TLT、IEF、AGG、LQD、GLD、TIP,投資期間為10年,每季再平衡一次,請隨機抽取40組起始日和AB資產。計算投資期間(10年)AB資產的相關係數,請比較未再平衡的投資組合與再平衡的投資組合間,年化報酬率、年化標準差、夏普值、最大下跌幅度的差異和相關係數的關係。 例如相關係數越小,未再平衡的投資組合與再平衡的投資組合間年化報酬率和年化標準差的差異越大。
在這一題中,我會從15個資產裡面隨機抽取兩個,將50%的定義為資產的50%投入到A股票,另一半投入到B股票,如果起始資金為100萬,則代表AB兩資產各投入50萬。因為當我隨機抽取兩檔股票時,兩檔股票之間的關聯可以算出一個相關係數的數值,我們再針對相關係數的高低,在有再平衡以及沒有在平衡的情況下,對年化報酬率、年化標準差、夏普值、最大下跌幅度的差異和相關係數的關係。我也會額外探討alpha與beta的關聯。
經過隨機抽取40組投資組合,並且將該兩檔股票的相關係數,以及利用該兩檔股票所建立的投資組合所算出的各式指標,再計算一次兩者的相關係數,就可以看到當相關係數變動一單位時,標準差、報酬和最大下跌幅度等的變動。為了討論方便,我將max_drawdown的值加上了一個負號,這樣比較好討論。
import datetime
BGN_PRINCIPAL = 1000000
num_simulations = 40
filtered_dates = [date for date in days if date < datetime.date(2014, 5, 14)]
stock_selected_list = []
correlation_list = []
quarterly_result = []
none_result = []
rebalancing_frequencies = [ 'quarterly','none']
stock_list = ["VTI", "IVV", "IWM", "QQQ", "EFA", "IWB", "SPYG", "SPYV", "IOO","IYR", "TLT", "IEF", "AGG", "LQD", "GLD", "TIP","ICF"]
for i in range(num_simulations):
random_values = random.sample(stock_list, 2)
stock1 = random_values[0]
stock2 = random_values[1]
weights = dict()
weights[stock1] = 0.5
weights[stock2] = 0.5
random_index = random.randint(0, 2354)
print(random_values)
print(random_index)
# 轉換成numpy陣列
arr1 = np.array(price_data[stock1][random_index:random_index+2520])
arr2 = np.array(price_data[stock2][random_index:random_index+2520])
# 計算相關矩陣
corr_matrix = np.corrcoef(arr1, arr2)
# 取得相關係數
corr_coef = corr_matrix[0, 1]
print("相關係數:", corr_coef)
stock_selected_list.append(random_values)
correlation_list.append(corr_coef)
for freq in rebalancing_frequencies:
portfolio_value = BGN_PRINCIPAL
current_index = random_index
inner_count = 0
numbers_of_each_ETF = []
price_his = []
for asset, weight in weights.items():
value_distributed = portfolio_value*weight
amount_of_ETF_bought = value_distributed/price_data[asset][current_index]
numbers_of_each_ETF.append(amount_of_ETF_bought)
while True:
inner_count += 1
portfolio_value = calculate_portfolio_value(current_index)
if inner_count % 63 == 0 and freq == 'quarterly':
numbers_of_each_ETF = rebalance_portfolio(portfolio_value, numbers_of_each_ETF, current_index)
current_index += 1
if inner_count == 2520:
break
collect_result(freq, price_his, random_index)
print_result("quarterly", str(random_values))
print_result("none", str(random_values))
correlation_list = np.array(correlation_list)
annually_result = np.array([sublist[1] for sublist in quarterly_result])
annually_std = np.array([sublist[2] for sublist in quarterly_result])
max_drawdown = np.array([sublist[3] for sublist in quarterly_result])
sharpe = np.array([sublist[4] for sublist in quarterly_result])
beta = np.array([sublist[6] for sublist in quarterly_result])
alpha = np.array([sublist[7] for sublist in quarterly_result])
data = dict()
data["annually_result"] = annually_result
data["annually_std"] = annually_std
data["max_drawdown"] = -max_drawdown
data["sharpe"] = sharpe
data["beta"] = beta
data["alpha"] = alpha
# 轉換成numpy陣列
corr_quarter = []
for name in data:
corr_matrix = np.corrcoef(correlation_list, data[name])
corr_coef = corr_matrix[0, 1]
print(f"兩資產相關係數和做再平衡的{name}的相關係數:", corr_coef)
corr_quarter.append(corr_coef)
correlation_list2 = np.array(correlation_list)
annually_result2 = np.array([sublist[1] for sublist in none_result])
annually_std2 = np.array([sublist[2] for sublist in none_result])
max_drawdown2 = np.array([sublist[3] for sublist in none_result])
sharpe2 = np.array([sublist[4] for sublist in none_result])
beta2 = np.array([sublist[6] for sublist in none_result])
alpha2 = np.array([sublist[7] for sublist in none_result])
data2 = dict()
data2["annually_result"] = annually_result2
data2["annually_std"] = annually_std2
data2["max_drawdown"] = -max_drawdown2
data2["sharpe"] = sharpe2
data2["beta"] = beta2
data2["alpha"] = alpha2
corr_none = []
# 轉換成numpy陣列
for name in data2:
corr_matrix = np.corrcoef(correlation_list, data2[name])
corr_coef = corr_matrix[0, 1]
print(f"兩資產相關係數和沒有進行再平衡的{name}的相關係數:", corr_coef)
corr_none.append(corr_coef)
i=0
for name in data:
print(f"有再平衡減去沒有再平衡的{name}差距:", corr_quarter[i] - corr_none[i])
i+=1
兩資產相關係數和做再平衡的annually_result的相關係數: 0.36695602316864107
兩資產相關係數和做再平衡的annually_std的相關係數: 0.16375954216932642
兩資產相關係數和做再平衡的max_drawdown的相關係數: 0.10533196051651555
兩資產相關係數和做再平衡的sharpe的相關係數: 0.2524361346515781
兩資產相關係數和做再平衡的beta的相關係數: 0.2902573583335202
兩資產相關係數和做再平衡的alpha的相關係數: -0.19624989756129588
兩資產相關係數和沒有進行再平衡的annually_result的相關係數: 0.39109163595385454
兩資產相關係數和沒有進行再平衡的annually_std的相關係數: 0.1750170061038735
兩資產相關係數和沒有進行再平衡的max_drawdown的相關係數: 0.13009143972849868
兩資產相關係數和沒有進行再平衡的sharpe的相關係數: 0.29188344217771495
兩資產相關係數和沒有進行再平衡的beta的相關係數: 0.3432245352103515
兩資產相關係數和沒有進行再平衡的alpha的相關係數: -0.2082718309141809
有再平衡減去沒有再平衡的annually_result差距: -0.02413561278521348
有再平衡減去沒有再平衡的annually_std差距: -0.011257463934547074
有再平衡減去沒有再平衡的max_drawdown差距: -0.024759479211983126
有再平衡減去沒有再平衡的sharpe差距: -0.03944730752613684
有再平衡減去沒有再平衡的beta差距: -0.052967176876831334
有再平衡減去沒有再平衡的alpha差距: 0.012021933352885011
透過有再平衡的資料扣去沒有再平衡的資料,我們可以觀察到以下現象:
當相關係數變動一單位,則(再平衡減去沒有再平衡)所帶來的報酬率和標準差都是負值,代表在這樣的情境下,報酬率和標準差都是「沒有進行再平衡」的表現會比「有再平衡」的表現還要來的高,在sharpe的情況下,當相關係數增加,有進行再平衡的係數為0.25243,沒有進行再平衡的係數是0.29188,代表當相關係數增加時,沒有進行再平衡的投資組合所變動的量會比較大,差距為0.03。
另外提到max_drawdown,當有進行再平衡時,當相關係數增加,最大幅度的下降的變動量為0.10533,而沒有進行在平衡時,相關係數增加時最大幅度下降的變動亮則為0.13,可以觀察到大致上來說,在固定資產組合並且進行測試時,當相關係數增加,沒有再平衡的投資組合受到的影響程度較大。唯一沒有明顯關係的是alpha值,但是也趨近於0。
3. 資產的數量如何影響投資組合再平衡的效益?
請比較2到5個資產類別的投資組合再平衡的效益差異,投資期間為10年,每季再平衡一次,請隨機抽取40組起始日和資產,請分析未再平衡的投資組合與再平衡的投資組合間,年化報酬率、年化標準差、夏普值、最大下跌幅度的差異,是否隨著資產的數量增加 而有所差異。
I: VTI、IVV、IOO
II: IEF、TLT
III: LQD
IV: IYR、ICF
V: TIP、GLD
這一題中,除了股票資產的選擇之外,其他的表現方式和第一題相當類似,我們在以上五組資產中,分別選取兩組、三組、四組以及五組資產,接者在這一些被選擇的組別中,隨機選一個資產,這樣就會分別有兩個、三個、四個以及五個資產的組合,並且進行計算。以下是模擬的結果。
import datetime
BGN_PRINCIPAL = 1000000
num_simulations = 40
filtered_dates = [date for date in days if date < datetime.date(2014, 5, 14)]
stock_list = [['VTI','IVV','IOO'],['IEF','TLT'],['LQD'],['IYR','ICF'],['TIP','GLD']]
for nums_of_type in range(2,6):
quarterly_result = []
for i in range(40):
random_values = []
selected_stock = []
random_types = random.sample(stock_list, nums_of_type)
for stock in random_types:
selected_stock.append(random.sample(stock, 1)[0])
weights = dict()
for stk in selected_stock:
weights[stk] = 1/len(selected_stock)
random_index = random.randint(0, 2354)
for freq in rebalancing_frequencies:
portfolio_value = BGN_PRINCIPAL
current_index = random_index
inner_count = 0
numbers_of_each_ETF = []
price_his = []
for asset, weight in weights.items():
value_distributed = portfolio_value*weight
amount_of_ETF_bought = value_distributed/price_data[asset][current_index]
numbers_of_each_ETF.append(amount_of_ETF_bought)
while True:
inner_count += 1
portfolio_value = calculate_portfolio_value(current_index)
if inner_count % 63 == 0 and freq == 'quarterly':
numbers_of_each_ETF = rebalance_portfolio(portfolio_value, numbers_of_each_ETF, current_index)
current_index += 1
if inner_count == 2520:
break
collect_result(freq, price_his, random_index)
print_result("quarterly", "有再平衡"+str(nums_of_type)+"類型股票結合")
print_result("none", "無再平衡"+str(nums_of_type)+"類型股票結合")
==================================================
============= 有再平衡2類型股票結合 result =============
期末本金:1895675.56元
年化報酬率:7.05582%
年化標準差:12.00%
ETF 的最大回撤為: -27.07%
Sharpe比率: 0.40096
該期SP500的Sharpe比率: 0.53000
Beta值: 0.34958
Alpha值: 0.01541
特雷諾比率: -3.02915
卡瑪比率: 0.30188
==================================================
==================================================
============= 無再平衡2類型股票結合 result =============
期末本金:1884804.37元
年化報酬率:6.93474%
年化標準差:11.98%
ETF 的最大回撤為: -27.39%
Sharpe比率: 0.38360
該期SP500的Sharpe比率: 0.53000
Beta值: 0.35414
Alpha值: 0.01243
特雷諾比率: 0.13710
卡瑪比率: 0.28713
==================================================
==================================================
============= 有再平衡3類型股票結合 result =============
期末本金:1898079.73元
年化報酬率:6.89987%
年化標準差:10.61%
ETF 的最大回撤為: -24.96%
Sharpe比率: 0.45253
該期SP500的Sharpe比率: 0.53184
Beta值: 0.39393
Alpha值: 0.00982
特雷諾比率: 0.08821
卡瑪比率: 0.33249
==================================================
==================================================
============= 無再平衡3類型股票結合 result =============
期末本金:1876094.99元
年化報酬率:6.80101%
年化標準差:11.16%
ETF 的最大回撤為: -25.79%
Sharpe比率: 0.40833
該期SP500的Sharpe比率: 0.53092
Beta值: 0.36908
Alpha值: 0.00966
特雷諾比率: 0.11555
卡瑪比率: 0.30565
==================================================
==================================================
============= 有再平衡4類型股票結合 result =============
期末本金:1962857.72元
年化報酬率:7.11832%
年化標準差:9.67%
ETF 的最大回撤為: -23.04%
Sharpe比率: 0.51073
該期SP500的Sharpe比率: 0.58219
Beta值: 0.37192
Alpha值: 0.01107
特雷諾比率: 0.15130
卡瑪比率: 0.36752
==================================================
==================================================
============= 無再平衡4類型股票結合 result =============
期末本金:1901018.21元
年化報酬率:6.87557%
年化標準差:10.70%
ETF 的最大回撤為: -24.95%
Sharpe比率: 0.43472
該期SP500的Sharpe比率: 0.54801
Beta值: 0.37744
Alpha值: 0.00846
特雷諾比率: 0.12185
卡瑪比率: 0.31939
==================================================
==================================================
============= 有再平衡5類型股票結合 result =============
期末本金:2000689.29元
年化報酬率:7.26648%
年化標準差:9.09%
ETF 的最大回撤為: -20.99%
Sharpe比率: 0.56496
該期SP500的Sharpe比率: 0.58383
Beta值: 0.35810
Alpha值: 0.01377
特雷諾比率: 0.14194
卡瑪比率: 0.44077
==================================================
==================================================
============= 無再平衡5類型股票結合 result =============
期末本金:1926015.36元
年化報酬率:6.95890%
年化標準差:10.31%
ETF 的最大回撤為: -23.82%
Sharpe比率: 0.46044
該期SP500的Sharpe比率: 0.55696
Beta值: 0.37588
Alpha值: 0.00863
特雷諾比率: 0.12477
卡瑪比率: 0.34688
==================================================
我們先來專心研究有再平衡的情況下,兩種類型到五種類型的結果。年化報酬率從兩檔到五檔分別是7.05582% -> 6.89987% -> 7.11832% -> 7.26648%,雖然看起來是買五檔的結果會最好,但是我每次跑資料,這樣的比例都不盡相同,可能代表所雖然資產組合越多,報酬率會較好,但是由於隨機模擬的原因,這樣的關係不夠顯著。
標準差也發生同樣的狀況 10.61% -> 11.16% -> 9.67% -> 9.09%,看起來也是買五檔的情況下,年化標準差最低,代表最安全,但是這樣的關係也有一定的波動。 但是兩者結合起來時,當我們研究sharpe比率時,買五檔股票的sharpe ratio是最高的:
0.40096 -> 0.45253 -> 0.51073 -> 0.56496,可以看到當買越多檔股票時,可以提升sharpe ratio,可以推測的是這五種類型的股票所關注的範圍都不太一樣,導致買五檔股票可以有很大程度的分散掉風險,導致sharpe ratio隨者資產數量增加而變大。另外在最大回撤的部分,結果是-27.07% -> -24.96% -> -23.04% -> -20.99%,可以觀察到當風險分散程度越大,所面臨到的最大下跌幅度可以減少。
接者,我們研究沒有再平衡的情況下,兩種類型到五種類型的結果。年化報酬率從兩檔到五檔分別是6.93474%-> 6.80101% -> 6.87557% -> 6.95890%,四者的報酬率大小都比有進行再平衡的投資組合的報酬率(7.05582% -> 6.89987% -> 7.11832% -> 7.26648%)來的低,變動程度也比較小,可以看到沒有進行再平衡的話,整體會獲得比較低的報酬。
標準差也發生類似的狀況,在沒有進行再平衡的情況下,通常標準差會比有進行再平衡的情況來的大,從兩檔到五檔的比率分別為11.98%-> 11.16%-> 10.70%-> 10.31% 12.00%->10.61% -> -> 9.67% -> 9.09%,看起來也是買五檔的情況下,年化標準差最低,代表最安全,在購買兩檔股票的情況下,標準差相當相似(12% vs 11.98%),但是隨者購買資產的數量增加,有進行再平衡的投資組合所帶來的標準差,是比沒有進行再平衡的投資組合的標準差來的低,在購買五檔ETF的情況下,標準差的差距來到了1.22%(10.31% vs 9.09%),顯示出有進行在平衡會降低購買時的風險,尤其是在購買大量不同的ETF的時候。
最重要的,我們研究sharpe比率時,從兩檔到五檔,沒有進行再平衡的sharpe ratio為0.38360 -> 0.40833 -> 0.43472 -> 0.46044 ,雖然說買五檔股票的sharpe ratio也是最高的,但是表現卻遠低於有進行再平衡的sharpe ratio:0.40096 -> 0.45253 -> 0.51073 -> 0.56496,有進行和無進行再平衡的差距為( 0.01736 -> 0.04420 -> 0.07601 -> 0.10452),可以看到雖然當買越多檔股票時,可以提升sharpe ratio,但是當購買的股票數量越多,有沒有再平衡所帶來的影響越明顯。這樣的跡象非常明顯的解釋再平衡的影響,有再平衡會對sharpe ratio產生正面的影響,尤其是資產數量越多時,這樣的情況就會越明顯。
另外在最大回撤的部分,結果是-27.39% -> -25.79% -> -24.95% -> -23.82%,相對於有進行再平衡的數據(-27.07% -> -24.96% -> -23.04% -> -20.99%)來說,可以觀察到如果沒有進行再平衡的話,最大下降的幅度會比有進行再平衡的情況來的大,所以可以顯示出進行再平衡可以降低風險,同時購買越多的資產也可以降低風險,兩者都具有顯著的影響力。