AIとファイナンス

AIとファイナンスの架け橋、それがこのブログの目指すところです。兼業投資家向けに、Pythonを駆使して株やFXの分析を「自分で」行えるようになるための情報を提供します。ニューラルネットワークを活用した市場予測から、実証済みの金融理論まで、全てのコードを公開し、誰もが活用できるように!是非色々なコードで遊んでみてください!

【現代ポートフォリオ理論】全世界株式(オルカン)の資産配分は正しいのか?「最適ポートフォリオ」のパフォーマンス分析【Python】

皆さん、こんにちは!今回は、私たちの最適ポートフォリオを探す旅をさらに進め、全世界株式(俗に言うオルカン)が果たして最適な資産配分をしているのかを見てみましょう。MSCIのAll Country World Index(ACWI)など全世界の株式の指数に連動するETF投資信託を皆様もお持ちだったり、検討されたことがあるのではないでしょうか。

ACWIの場合は以下のように米国株式64%、日本株式5.6%にヨーロッパ各国、新興国の株が続きます。

MSCI ACWI 組み入れ比率

そこでみなさんも気になるのが「果たしてこの比率は本当に最適な配分なのでしょうか」?ということですよね!ここでもPythonと現代ポートフォリオ理論の力を借りてデータを分析してみました!コードへのリンクは最下部にあるので皆さまも是非試してください。また現代ポートフォリオ理論については詳しくこちらのエントリーで説明しています。

 

データの準備と分析
早速yfinanceライブラリを使い、VTI(米国株式)、VEA(先進国株式除く米国)、VWO(新興国株式)の3つのETFから成るポートフォリオの過去10年間のデータを分析しました。まずは、これらのETFの日次調整終値をダウンロードし、日次リターンを計算します。

import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 対象ETFのシンボルリスト
symbols = ['VTI', 'VEA', 'VWO']  # ここに好きな銘柄を足してみてくださいね!

# 過去10年分の日足データをダウンロード
data = {symbol: yf.download(symbol, period='10y', interval='1d')['Adj Close'] for symbol in symbols}

# 各ETF終値データをDataFrameに結合
close_prices = pd.DataFrame(data)

# 日次リターンを計算
daily_returns = close_prices.pct_change().dropna()

効率的フロンティアの視覚化
効率的フロンティアは、与えられたリスクレベルで最大のリターンを得られるポートフォリオの組み合わせを示します。この概念を視覚化するために、ランダムに生成した10,000のポートフォリオを分析し、それぞれのリターン、ボラティリティ、そしてシャープ比率を計算しました。

num_assets = len(symbols)
num_portfolios = 10000
all_weights = np.zeros*1
return_arr = np.zeros(num_portfolios)
volatility_arr = np.zeros(num_portfolios)
sharpe_arr = np.zeros(num_portfolios)

# 年間リスクフリーレートを仮定(例:2%)
risk_free_rate = 0.02
np.random.seed(100)

for i in range(num_portfolios):
    # ランダムな重みを生成
    weights = np.random.random(num_assets)
    weights /= np.sum(weights)
    all_weights[i, :] = weights
   
    # 期待リターン
    return_arr[i] = np.dot(weights, daily_returns.mean()) * 252
   
    volatility_arr[i] = np.sqrt(np.dot(weights.T, np.dot(daily_returns.cov() * 252, weights)))
   
    # シャープ比率
    sharpe_arr[i] = (return_arr[i] - risk_free_rate) / volatility_arr[i]

# 最大シャープ比率のポートフォリオを探す
max_sharpe_idx = sharpe_arr.argmax()
max_sharpe_return = return_arr[max_sharpe_idx]
max_sharpe_volatility = volatility_arr[max_sharpe_idx]

# 効率的フロンティアのプロット
plt.scatter(volatility_arr, return_arr, c=sharpe_arr, cmap='viridis')
plt.colorbar(label='Sharpe Ratio')
plt.xlabel('Volatility(Risk)')
plt.ylabel('Expected Return')

# 最大シャープ比率のポートフォリオをマーキング
plt.scatter(max_sharpe_volatility, max_sharpe_return, color='red', s=50, edgecolors='black')

plt.title('Efficient Frontier')
plt.show()

# 最適ポートフォリオの重み
print("最適ポートフォリオの重み:", all_weights[max_sharpe_idx, :])

3銘柄の効率的フロンティア

最適な配分[VTI, VEA, VWO]

やはり米国株が強く、安定しているため米国株にかなり偏ったポートフォリオを最適な配分として出してきますね。ではこのポートフォリオオルカンの対象指数として採用されることも多いMSCI ACWIのリターンを比べたらどうなるのでしょうか?

# ACWIのデータをダウンロード
acwi_data = yf.download('ACWI', period='10y', interval='1d')
acwi_close = acwi_data['Adj Close']

# ACWIのトータルリターンを計算
acwi_total_return = (acwi_close.iloc[-1] / acwi_close.iloc[0]) - 1
# 最適ポートフォリオの重み(先ほどの結果を使用)
optimal_weights = all_weights[max_sharpe_idx, :]

# 最適ポートフォリオのトータルリターン計算
optimal_portfolio_return = (daily_returns * optimal_weights).sum(axis=1) + 1
optimal_portfolio_total_return = optimal_portfolio_return.cumprod().iloc[-1] - 1

print(f"ACWIのトータルリターン: {acwi_total_return:.2%}")
print(f"最適ポートフォリオのトータルリターン: {optimal_portfolio_total_return:.2%}")

結果

過去いろいろな記事でオルカンとその他の比較を行ってきましたがまたもやオルカン以外に軍配が上がってしまいました。これは米国株に偏重したポートフォリオ配分になっているため当たり前ですよね。

ただ気をつけないければならないのは今回国は違えど同じ資産クラス(株式)でポートフォリオを組んでいますね?ということは相関係数もかなり1に近い(暴落するときは株式全部暴落する)ので本当の意味での分散投資にはなっていないんです。例えば逆相関になることが多いといわれる債権関係や不動産なども混ぜることで一つの資産クラスが暴落しても耐えることできる盤石な「最適ポートフォリオ」が完成します。

 

以下のリンクからもコードにアクセスできます。銘柄の追加もできるので皆様も是非遊んでみてくださいね!みんなも大好きな’SOXL’を追加してみると。。。

colab.research.google.com

 

過去の現代ポートフォリオ理論に関するエントリー

ai-and-finance.net

ai-and-finance.net

クリックお願いします!

参考サイト

https://www.msci.com/documents/10199/8d97d244-4685-4200-a24c-3e2942e3adeb

*1:num_portfolios, num_assets