Markets & Python & ...

機関投資家の卵がPythonのコードと共に金融マーケットについて浅くつぶやきます

J-REITのキャピタルリターン、インカムリターン、リスクをPlotlyの3Dバブルチャートで比較

このコードは、http://www.japan-reit.com からスクレイピングして取得したデータと株価を元に、J-REIT全銘柄のキャピタルリターン、インカムリターン、リスク(ボラティリティ標準偏差)を比較できるインタラクティブな3Dバブルチャートを作成します。

完成したものは以下のリンクから見られます。

https://chart-studio.plotly.com/~hiroshimaeasyryo/255/#/

import pandas as pd
import numpy as np
from bs4 import BeautifulSoup
from pandas import Series, DataFrame
import requests
import urllib
import YahooFinanceSpider as y
import datetime
import plotly.offline as po
import plotly.graph_objs as go
import plotly.figure_factory as ff
import math
import codecs
import io
from datetime import timedelta
from plotly.offline import iplot
from plotly.graph_objs import Scatter, Figure, Layout, Histogram


urls = []
soups = []
base_url =  'http://www.japan-reit.com/meigara/'


# 銘柄コード
codes = [8951,8952,8953,8954,8955,8956,8957,8958,8960,
               8961,8963,8964,8966,8967,8968,8972,8975,8976,
               8977,8979,8984,8985,8986,8987,3226,3227,3234,
               3249,3269,3278,3279,3281,3282,3283,3287,3290,
               3292,3295,3296,3298,3451,3309,3453,3455,3459,
               3462,3463,3466,3468,3470,3471,3472,3473,3476,
               3478,3481,3487,3488,3492,3493,2971,2972,2979]

# 銘柄コードをurlに埋め込む
for i in codes:
   url = urllib.parse.urljoin(base_url, str(i) +"/")
   urls.append(url)
   
# beautifulsoupでparseする
for v in urls:
   res = requests.get(v)
   soup = BeautifulSoup(res.content, 'html.parser')
   soups.append(soup)   
   
# titleの取得
titles = []
for t in soups:
   brand = t.title.string[:-40]
   titles.append(brand)

# 分配金利回りの取得
div_int_rates = []
for d in soups:
   try:
       table_d = d.find_all("table", {"class":"meigara-table"})[0]
       div_int_rate = table_d.find_all("td", {"class":"r"})[2].string[:-9]
       div_int_rates.append(div_int_rate)
   except:
       div_int_rates.append('0')
   
# 時価総額の取得
capitals = []
for c in soups:
   try:
       table = c.find_all("table", {"class":"meigara-table"})[0]
       capital = table.find_all("td", {"class":"r"})[1].string[:-3]
       capitals.append(capital)
   except:
       capitals.append('0')

# 時価総額をint型に変換し、バブルサイズをいい感じにするために係数で割って調整
rmcs = []
for rmc in capitals:
   r = round(float(rmc.replace(',', ''))) / 25000
   rmcs.append(r)

# DataFrameに格納
df = pd.DataFrame([titles, codes, div_int_rates, capitals]).T.rename(
   columns={0: '銘柄名', 1: '銘柄コード', 2:'分配金利回り[%]', 3:'時価総額[百万円]'})

# j-reit.comから抽出したデータ
jrc_data = df.T

# 90日間のデータを使う
end_time = datetime.date.today()
start_time = end_time - timedelta(days = 90)

# クローラーを作る
c = y.Crawler()

# 終値の取得
prc = [[] for i in range(len(codes))]
for i in range(len(codes)):
   for yf in c.get_price(str(codes[i]), start_time, end_time, y.DAILY):
       prc[i].append(yf.close)
row_df = pd.DataFrame(prc).T

# 日付の取得
date = []
for yf in c.get_price(str(codes[0]), start_time, end_time, y.DAILY):
   date.append(yf.date)

# インデックスを日付に、カラムを銘柄名に
row_df.index = date
row_df.columns = titles

# 値をfloat型に
df = row_df.astype(float)

# キャピタルリターン算出の為変化率のdataframeを用意する
pct_df = df.iloc[::-1].pct_change().dropna()

# キャピタルリターンを'算術平均'にて算出
# 本来なら'幾何平均'を使うべき
annual_return = pct_df.mean() * 3650000 / len(df.index)
X = annual_return

# インカムリターンの算出(スクレイピングデータより)
inc_ret = pd.Series(jrc_data.iloc[2])
Y = inc_ret

# リスク(標準偏差)の算出
std = pct_df.std()
Z = std



# チャートの描画
from plotly.graph_objs import Scatter3d
from plotly.offline import init_notebook_mode, iplot
init_notebook_mode()    # <- Notebook出力にはこの1行が必要


scatter = Scatter3d(x=X, y=Y, z=Z, 
                   mode='markers',
                   text=X.index,
                   marker=dict(size=rmcs,                  # マーカーのサイズ
                               color=Z,                    # 色分けに使う数値(任意の数値を指定可)
                               colorscale='Magma',         # 色のパターン
                               showscale=True)             # カラーバーを表示
                  )

# レイアウトの指定
# バブルサイズの調整
start, end = 15000, 1200000
fig = go.Figure(scatter)
fig.update_layout(scene = dict(
                           xaxis_title = 'x:年間平均リターン[%]',
                           yaxis_title = 'y:配当利回り[%]',
                           zaxis_title = 'z:標準偏差'
                           ),
                           width=750,
                           height=650,
                           margin=dict(r=20, b=10, l=10, t=10)
               )
iplot(fig)    # <- Notebookに出力するにはiplot関数を使う<200b>

Plotly Chart Studioでオンライン上で表示

chart studioでオンライン上で表示する為にはchart studioの登録とapi keyの設定が必要になります。

import chart_studio.plotly as py


py.plot(fig, filename='JREIT bubble chart')

ぜひ自分の手で動かしてみて欲しい。

f:id:hiroshimaeasy:20200705015743g:plain
自分で動かしてみよう