本期作者:Bernard Brenyah
本期翻譯:Barry
未經授權,嚴禁轉載
哈里馬科維茨對金融和經濟學的世界的貢獻是怎麼強調都不過分的。憑藉其於 1952年發表的開創性論文“資產組合選擇”,他被廣泛的視作現代資產組合理論(MPT)的開拓者。最終在1990年,基於對這一領域的巨大貢獻,他獲得了諾貝爾經濟學獎。
如今,幾乎全世界的任何一門商科、金融課程都會教授MPT理論。本文將通過真實的股票數據用python來介紹這一理論的基礎和有效前沿的構建。
那麼什麼是MPT,爲什麼你要理解它,又怎麼用python來實現它呢?
與大多數理論一樣,MPT也是建立在對真實世界一些假設之上。對MPT的的解釋將從闡述它的基本假設開始:
MPT的假設:
- 投資者是理性的並且風險厭惡
- 投資者追求收益最大化
- 所有投資者都想最大化期望收益
- 不考慮佣金和稅費
- 所有投資者都可以接觸到同樣的信息源和與投資決策相關的全部必要信息
- 投資者可以以無風險利率不受限制的借入和貸出資金
現代資產組合理論是關於在特定風險水平下投資者(風險厭惡)如何構建組合來最大化期望收益的理論。MPT的突破性在於提出不需將衆多投資的風險和收益特徵孤立分析,而是去研究這些投資如何對組合的表現產生影響。因此,MPT的假設強調投資者只有在可能得到更高期望收益時會有額外風險出現---也就是高風險,高收益。
這一理論最基本的原則是投資者可以構建投資組合的有效集合,即有效前沿。有效前沿可以在特定風險水平下使期望收益最大化。投資者對風險的容忍度將決定他所選擇的有效前沿。低容忍度的投資者會選在最低風險下可以提供最大收益的組合,高容忍度的會選擇高風險下的可以提供最大收益的組合。可以從下圖大致理解有效前沿的概念:
不同的股票組合將產生不同的期望收益。在馬科維茨證明了有效前沿之後人們最重要的一個發現是分散化投資的力量。因爲組合中資產的相關性和權重可以極大地影響組合收益,所以投資者可以在他們的風險偏好下通過用不同的證券簡單地構建組合來實現期望收益最大化。
那麼我們該怎麼通過python用真實股價數據來建立有效前沿組合呢?
數據獲取
import quandl import pandas as pd import numpy as np import matplotlib.pyplot as plt quandl.ApiConfig.api_key = 'PASTE YOUR API KEY HERE' selected = ['CNP', 'F', 'WMT', 'GE', 'TSLA'] data = quandl.get_table('WIKI/PRICES', ticker = selected, qopts = { 'columns': ['date', 'ticker', 'adj_close'] }, date = { 'gte': '2014-1-1', 'lte': '2016-12-31' }, paginate=True) data.head()
date ticker adj_close None 0 2014-01-02 CNP 19.290792 1 2014-01-03 CNP 19.282339 2 2014-01-06 CNP 19.307699 3 2014-01-07 CNP 19.510582 4 2014-01-08 CNP 19.307699
接下來是數據處理步驟,我們根據tickers來給調整後的收盤價排序:
clean = data.set_index('date') table = clean.pivot(columns='ticker') table.head()
adj_close ticker CNP F GE TSLA WMT date 2014-01-02 19.290792 12.884511 24.266002 150.10 71.343743 2014-01-03 19.282339 12.942926 24.248354 149.56 71.108673 2014-01-06 19.307699 13.001340 24.054226 147.00 70.710863 2014-01-07 19.510582 12.834442 24.080698 149.36 70.927850 2014-01-08 19.307699 12.967960 24.010106 151.28 70.367299
爲了得到有效前沿,我們需要模擬很多的投資組合(50000個)。
port_returns = [] port_volatility = [] stock_weights = [] num_assets = len(selected) num_portfolios = 50000 for single_portfolio in range(num_portfolios): weights = np.random.random(num_assets) weights /= np.sum(weights) returns = np.dot(weights, returns_annual) volatility = np.sqrt(np.dot(weights.T, np.dot(cov_annual, weights))) port_returns.append(returns) port_volatility.append(volatility) stock_weights.append(weights) portfolio = {'Returns': port_returns, 'Volatility': port_volatility} and weight in the portfolio for counter,symbol in enumerate(selected): portfolio[symbol+' weight'] = [weight[counter] for weight in stock_weights] df = pd.DataFrame(portfolio) column_order = ['Returns', 'Volatility'] + [stock+' weight' for stock in selected] df = df[column_order] df.head()
Returns Volatility CNP weight F weight WMT weight GE weight TSLA weight 0 0.051471 0.139810 0.193275 0.144265 0.286315 0.037991 0.338155 1 0.098057 0.205745 0.001220 0.192939 0.271552 0.359363 0.174927 2 0.042783 0.160203 0.281532 0.442986 0.164275 0.022419 0.088788 3 0.090758 0.199514 0.113044 0.344052 0.238166 0.293816 0.010922 4 0.053179 0.159999 0.212643 0.283324 0.015256 0.168772 0.320006
棒極了!繁瑣的步驟現在都已經完成了!我們來看一下有效前沿長什麼樣:
希望現在你對MPT有了基本的瞭解!
前面我們瞭解了資產組合理論(MPT)的基本內容並通過Monte Carlo模擬產生了有效前沿組合。下面我們專注於組合優化的概念。
50000個不同權重的投資組合產生了不同的期望收益和期望波動率。線上的每個點代表了股票的一個最優組合(CenterPoint Energy,Facebook,Walmart,General Electric,Tesla),最優組合在特定的風險水平下最大化了期望收益率。如果有效前沿曲線上的所有點都是最優組合,那麼在這些組合中的最優投資組合是什麼呢?優中最優組合的選取標準又是什麼呢?
另一個諾貝爾獎得主William F. Sharpe 拓展了Markowitz的工作,開發了資本資產定價模型(CAPM)。本文不會設計CAPM,但是我們會用到他的一個成果(Sharpe Ratio)最爲選擇最優的準則。
夏普比率可以用來衡量特定風險下投資收益的表現。這個比率調整了投資的收益,使我們可以在一定規模風險的情況下比較不同的投資表現。沒有規模風險的限制,我們無法比較不同證券組合的收益與風險表現。注:出於簡化,本文無風險收益率設爲0%。
我們將對上面的代碼做一些小改變。我們已經有了模擬出的組合的期望收益率和風險。接下來,我們將計算這些組合的風險調整收益率(藉助夏普比率),並且以夏普比率爲值畫出色標圖:
import quandl import pandas as pd import numpy as np import matplotlib.pyplot as plt quandl.ApiConfig.api_key = 'INSERT YOUR API KEY HERE' selected = ['CNP', 'F', 'WMT', 'GE', 'TSLA'] data = quandl.get_table('WIKI/PRICES', ticker = selected, qopts = { 'columns': ['date', 'ticker', 'adj_close'] }, date = { 'gte': '2014-1-1', 'lte': '2016-12-31' }, paginate=True) clean = data.set_index('date') table = clean.pivot(columns='ticker') returns_daily = table.pct_change() returns_annual = returns_daily.mean() * 250 cov_daily = returns_daily.cov() cov_annual = cov_daily * 250 port_returns = [] port_volatility = [] sharpe_ratio = [] stock_weights = [] num_assets = len(selected) num_portfolios = 50000 np.random.seed(101) for single_portfolio in range(num_portfolios): weights = np.random.random(num_assets) weights /= np.sum(weights) returns = np.dot(weights, returns_annual) volatility = np.sqrt(np.dot(weights.T, np.dot(cov_annual, weights))) sharpe = returns / volatility sharpe_ratio.append(sharpe) port_returns.append(returns) port_volatility.append(volatility) stock_weights.append(weights) portfolio = {'Returns': port_returns, 'Volatility': port_volatility, 'Sharpe Ratio': sharpe_ratio} for counter,symbol in enumerate(selected): portfolio[symbol+' Weight'] = [Weight[counter] for Weight in stock_weights] df = pd.DataFrame(portfolio) column_order = ['Returns', 'Volatility', 'Sharpe Ratio'] + [stock+' Weight' for stock in selected] df = df[column_order] plt.style.use('seaborn-dark') df.plot.scatter(x='Volatility', y='Returns', c='Sharpe Ratio', cmap='RdYlGn', edgecolors='black', figsize=(10, 8), grid=True) plt.xlabel('Volatility (Std. Deviation)') plt.ylabel('Expected Returns') plt.title('Efficient Frontier') plt.show()
通過上述代碼,我們得到了下圖:
接着,試着找出最優組合和有着最低波動率的組合(也就是風險厭惡最嚴重的投資者的偏好組合):
min_volatility = df['Volatility'].min() max_sharpe = df['Sharpe Ratio'].max() sharpe_portfolio = df.loc[df['Sharpe Ratio'] == max_sharpe] min_variance_port = df.loc[df['Volatility'] == min_volatility] plt.style.use('seaborn-dark') df.plot.scatter(x='Volatility', y='Returns', c='Sharpe Ratio', cmap='RdYlGn', edgecolors='black', figsize=(10, 8), grid=True) plt.scatter(x=sharpe_portfolio['Volatility'], y=sharpe_portfolio['Returns'], c='red', marker='D', s=200) plt.scatter(x=min_variance_port['Volatility'], y=min_variance_port['Returns'], c='blue', marker='D', s=200 ) plt.xlabel('Volatility (Std. Deviation)') plt.ylabel('Expected Returns') plt.title('Efficient Frontier') plt.show()
接下來輸出這兩個特殊組合的具體信息:
print(min_variance_port.T) print(sharpe_portfolio.T) 17879 Returns 0.045828 Volatility 0.138552 Sharpe Ratio 0.330761 CNP Weight 0.240327 F Weight 0.104659 WMT Weight 0.257760 GE Weight 0.001487 TSLA Weight 0.395767 31209 Returns 0.116145 Volatility 0.175045 Sharpe Ratio 0.663514 CNP Weight 0.372890 F Weight 0.008482 WMT Weight 0.404987 GE Weight 0.211450 TSLA Weight 0.002190
風險厭惡最嚴重的投資者將會選擇最小方差組合,它的期望收益率是4.58%,期望波動率是13.86%。追求最大風險調整收益率的投資者將會構建有着最大夏普比率的投資組合,它的期望收益率是11.61%,期望波動率是17.50%。
通過一些優化的數學技巧也可以得到相同的結論,但這裏,用了Monte Carlo模擬來解釋有效前沿和最有投資組合的概念。