7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Python】S&P500の中で最適ポートフォリオを見つけ出す

Last updated at Posted at 2021-04-29

S&P500(米国優良企業約500社)の組合せの中から,最適なポートフォリオを探索します.

この記事ではソースコードの大まかな流れだけを説明し,全ソースコードの説明および最適化結果は本記事の最後にあるリンク先で説明します.

#やりたいこと

S&P500(米国優良企業約500社)の組合せの中から,最適ポートフォリオを見つけたいです.

今回見つける最適ポートフォリオは,

・リスク(ボラティリティ)が最小になるポートフォリオ
・シャープレシオが最大になるポートフォリオ

とします.シャープレシオとは,期待リターンをボラティリティで割った量です.

#ポートフォリオ最適化の概要
以下のような流れで行います.

1.S&P500の株価時系列データを取得する
2.株価データを元に各銘柄の期待リターンとリスク(ボラティリティ,共分散の平方根)を求める
3.色々な割合のポートフォリオでその期待リターンとリスクを計算する.つまり,効率的フロンティアを作成する
4.リスクが最小,シャープレシオが最大になるポートフォリオを各々探す
(5.セクターごとのポートフォリオに直す)

#S&P500の株価時系列データを取得する
まずは,S&P500銘柄の質(期待リターン,リスク)を計算するために,銘柄の株価を取得する必要があります.

S&P500の銘柄取得については,以下のURLにあるCSVから取得することにします.

S&P500銘柄の取得は,以下でできます.

import pandas as pd
url = "https://raw.githubusercontent.com/datasets/s-and-p-500-companies/master/data/constituents.csv"
sp500 = pd.read_csv(url, encoding="SHIFT_JIS")

sp500 = sp500['Symbol'] #sp500ティッカーコードのデータフレーム
sp500_tickers = sp500.values.tolist() #データフレームをリストに変換

そして,取得した銘柄の株価を取得するには,pandas-datareaderなどを用います.

import datetime
import pandas_datareader.data as web
start = datetime.date(2014,1,1)
end = datetime.date.today()

data = web.DataReader(sp500_tickers, 'yahoo', start, end)["Adj Close"] #sp500の株価データを取得

ただし,開始日(start)以前に上場していない銘柄については,株価は取得されないことに注意して下さい.
また,何度も株価を取得すると時間もかかり,APIのサーバーにも良くないようなのでCSVファイルに保存しておくことをおすすめします.

data.to_csv('sp500_stocks_data.csv')

詳しくは,以下の記事をご覧ください.

#2.株価データを元に各銘柄の期待リターンとリスクを求める

コード全文は記事の最後に貼ってあるリンク先で説明しますが,簡単に説明すると,ポートフォリオ全体の期待リターンとリスク(ボラティリティ)の計算に必要な各銘柄のリターンおよび共分散行列を以下で計算します.

# calculate daily and annual returns of the stocks
returns_daily = data.pct_change()
returns_annual = returns_daily.mean() * 250

# get daily and covariance of returns of the stock
cov_daily = returns_daily.cov()
cov_annual = cov_daily * 250

各銘柄のリターンと銘柄の割合ベクトルの内積をとることでポートフォリオの期待リターンを求めます.
また,各銘柄間の共分散行列を割合ベクトルで挟み,平方根を取ることでリスク(ボラティリティ)を求めます.

#3.効率的フロンティアを作成する

縦軸に期待リターン,横軸にボラティリティを取り,各プロット点がポートフォリオを意味する図を作ります.以下は実際に生成した効率的フロンティアです.

optSP500_effi.png

点が緑色であるほどシャープレシオが大きく,赤色であるほど小さいです.

#4.ボラティリティが最小,シャープレシオが最大になるポートフォリオを各々探す

先ほど作成した効率的フロンティアの図から,ボラティリティが最小のポートフォリオと,シャープレシオが最大になるポートフォリオをピックアップします.

効率的フロンティアの図では,青色の位置のポートフォリオがボラティリティ最小,赤色の位置のポートフォリオがシャープレシオ最大となっています.

これらを円グラフにすると,以下のようになります.

optSP500.png

ひとつひとつの銘柄が描かれているのですが,細かすぎて何が何だか分かりませんよね.そこで,セクター別にまとめて円グラフを表示してみます(また,記事最後のリンク先では表で銘柄別の結果を示しています).

#5.セクターごとのポートフォリオに直す

これについては,以下のリンク先で説明します.

#全ソースコードと実行結果
##全ソースコード
S&P500の中で最適ポートフォリオを見つけ出し,セクター別でも表示するコード全文は以下です.コードの説明もしています.

##実行結果
以下の記事では,実行結果の詳細のみを書いています.

実行結果には,以下が含まれます.
・最適ポートフォリオ(リスク最小,シャープレシオ最大)の銘柄構成割合
・上記の最適ポートフォリオをセクター別構成にまとめたもの

7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?