株式投資ポートフォリオを作って運用してみる

ゼミのグループで「東京オリンピックに向けて伸びて行く」14銘柄をピックアップしました。
ざっくり分けると三つあり
1. 建設業界
2. オリンピックナショナルチームのスポンサー企業
3. スポーツ用品メーカ
の三つを中グループとして14銘柄選びました。この選定にもRを使いましたが、それはまた次の機会に行いたいと思います。

library(dplyr)
library(tidyverse)
library(quantmod)
library(PerformanceAnalytics)
library(ggplot2)
library(fPortfolio)


パッケージは上記のものを使います。
quantmodパッケージで簡単に株価の取得ができるのでそちらを14銘柄分やりました。
こちらが株式のリストです。

> final_sl
   銘柄コード.優先市場名                                   株銘柄名 現在値..基準価格..前日比   株式投資.収益率3年..日経J1000
1         1414\n東証1部         ショーボンドホールディングス(株)        8,060\n+70\n14:32   +74.1%\n+34.7%\n+39.4ポイント
2         1720\n東証1部                             東急建設(株)         1,148\n-2\n14:34  +117.5%\n+34.7%\n+82.8ポイント
3         1766\n東証1部                 東建コーポレーション(株)       13,470\0\n14:30 +184.5%\n+34.7%\n+149.8ポイント
4         1801\n東証1部                             大成建設(株)        6,130\n-50\n14:30  +101.3%\n+34.7%\n+66.5ポイント
5         1811\n東証1部                               (株)錢高組        6,190\n-20\n14:24  +100.0%\n+34.7%\n+65.3ポイント
6         1884\n東証1部                             日本道路(株)        6,620\n-40\n14:29    +28.1%\n+34.7%\n-6.6ポイント
7         1944\n東証1部                             (株)きんでん         1,853\n-5\n14:33   +77.1%\n+34.7%\n+42.4ポイント
8         1950\n東証1部                         日本電設工業(株)        2,395\n-23\n14:32   +62.0%\n+34.7%\n+27.3ポイント
9         2269\n東証1部                 明治ホールディングス(株)      10,040\n+120\n14:30   +89.4%\n+34.7%\n+54.6ポイント
10    7177\nジャスダック GMOフィナンシャルホールディングス(株)           730\n-6\n14:33                              --
11        7936\n東証1部                           (株)アシックス         1,732\n+3\n14:34   -43.1%\n+34.7%\n-77.9ポイント
12        8022\n東証1部                               美津濃(株)         3,345\n+5\n14:34   +17.7%\n+34.7%\n-17.0ポイント
13        8114\n東証1部                             (株)デサント        1,905\n+29\n14:34   +51.7%\n+34.7%\n+17.0ポイント
14        9202\n東証1部               ANAホールディングス(株)        4,637\n+16\n14:34   +60.2%\n+34.7%\n+25.5ポイント

データ準備

ショーボンドホールディングスの例

SHOBONDO <- getSymbols("1414",src="yahooj",auto.assign=FALSE) 
#オブジェクトに四桁の証券番号を設定しyahoo financeからのxts型の時系列データ読み込ませます
shobondo <- SHOBONDO[,6] 
#始値とかたくさんデータがありますが、そこは特に今回は必要ないので6つ目の終値だけを残します。
colnames(shobondo) <- c("shobondo")
shobondo_month <- apply.monthly(shobondo, mean) 
#apply.monthly()関数で月次データに変換
shobondo_return <- Return.calculate(shobondo_month)
#Return.calculate()関数で前月比を計算
shobondo_return <- shobondo_return[-1,]
#最初のデータは比較する前データがないのでカットします

こんな感じで14銘柄分作成しました。

データ統合&加工

returns <- merge(
  mizuno_return, asics_return, descente_return, ana_return, gmo_return,
  token_return, meiji_return, shobondo_return, tokyu_return, taisei_return,
  zenitaka_return, nihon_return, kinden_return, densetsu_return, osjb_return)
write.zoo(returns, "returns.csv", sep=",")
returns_csv <- read.csv("returns.csv")

統合したデータを最後に便宜上csvデータに変換しました。

> head(returns_csv)
       Index      mizuno       asics      descente          ana gmo        token meiji shobondo       tokyu       taisei     zenitaka       nihon      kinden      densetsu
1 2007-02-28  0.02269582 -0.03484882 -0.0484186212  0.076488953  NA -0.033838675    NA       NA -0.01797078  0.091042781  0.085226206  0.06675875  0.02640605  0.0439884538
2 2007-03-30 -0.01388298 -0.07138884  0.0103498406 -0.004004993  NA -0.167240466    NA       NA -0.03101938  0.001878855  0.001169677 -0.04779374 -0.03908642 -0.0598894604
3 2007-04-27 -0.01420324  0.14684786  0.0127790319  0.002441990  NA -0.073338369    NA       NA -0.08641176  0.020255616 -0.035188370 -0.03784089  0.20024723 -0.0005958235
4 2007-05-31 -0.03389126 -0.01104726  0.0005076834 -0.010724646  NA  0.007727567    NA       NA -0.06779375 -0.065514829  0.021403458 -0.02012808 -0.07512478 -0.0277078377
5 2007-06-29 -0.04191109  0.02466441  0.0306105611  0.003780525  NA  0.048220613    NA       NA -0.02881200  0.028783658  0.039181472  0.03610265 -0.01516242  0.0373258721
6 2007-07-31 -0.01054494  0.07857166  0.0818989673 -0.013538274  NA  0.171369782    NA       NA -0.02289352  0.010491877 -0.003052969  0.04701931  0.04586779  0.0596269727
         osjb
1 -0.07245125
2 -0.07814213
3 -0.09096905
4  0.03872594
5 -0.01742739
6 -0.06967905

ちなみにこんな感じになりました。
indexには日付が入ってます。さらに、企業には2007年時点では上場していないところもあることもわかります。
これを踏まえてさらに加工します

stock_return <- 
  gather(returns_csv, key = stock, value = price_return,
         mizuno, asics, descente, ana, gmo,token, meiji, shobondo,
         tokyu, taisei, zenitaka, nihon, kinden, densetsu, osjb)
mon_stock_return <- stock_return %>% 
  separate(Index, c("year", "month", "day"), sep="-") %>% 
  unite(Index, c("year", "month"), sep="-") %>% select(-day) 

統合したデータを整然データへと変換。日付データが見づらいので分解していらないところを除いてまた結合しました。

> head(mon_stock_return)
    Index  stock price_return
1 2007-02 mizuno   0.02269582
2 2007-03 mizuno  -0.01388298
3 2007-04 mizuno  -0.01420324
4 2007-05 mizuno  -0.03389126
5 2007-06 mizuno  -0.04191109
6 2007-07 mizuno  -0.01054494

結構見やすくなってます。

データ分析

returns_ts <- as.timeSeries(returns_csv)
returns_ts <- replace(returns_ts, which(is.na(returns_ts)), 0)

ts型のデータへと変換し、欠損値を0へと置き換えました。

nsl_effFrontier <- portfolioFrontier(returns_ts, constraints = "LongOnly")
plot(nsl_effFrontier,c(1,2,3,4))

f:id:kokiando:20171215154007p:plain

便利な世の中ですね。portfolioFrontier()関数で一気に効率的フロンティアを算出できます。
ここで効率的フロンティアの可視化ができたので、次はそのポイントでの資産の配分などを求めていきます。

stock_list <- c("mizuno", "asics", "descente", "ana", "gmo","token", "meiji", "shobondo",
                "tokyu", "taisei", "zenitaka", "nihon", "kinden", "densetsu", "osjb")
nsl_frontierWeights <- getWeights(nsl_effFrontier)
colnames(nsl_frontierWeights) <- stock_list
nsl_risk_return <- frontierPoints(nsl_effFrontier)

getWeights()で資産配分のデータを取得します。

nsl_mvp <- minvariancePortfolio(returns_ts, spec=portfolioSpec(), constraints="LongOnly")
nsl_tangencyPort <- tangencyPortfolio(returns_ts, spec=portfolioSpec(), constraints="LongOnly")
nsl_mvpweights <- getWeights(nsl_mvp)
nsl_tangencyweights <- getWeights(nsl_tangencyPort)
nsl_weight_df <- data.frame(nsl_mvpweights)
nsl_stocklist_weight <- cbind(stock_list, nsl_weight_df)

ここからggplot2で可視化をして来ます。

ggplot(nsl_stocklist_weight, 
       aes(x=stock_list, y=nsl_weight_df)) + 
  geom_bar(stat="identity", aes(fill=stock_list)) + 
  labs(x="Assets", y="Weight") + 
  ggtitle("Minimum Variance Portfolio Optimal Weights") + 
  geom_text(aes(label=nsl_weight_df),position=position_dodge(width=0.9), size=3.5)

f:id:kokiando:20171215154539p:plain

見づらいですけど、こんな感じです。

> nsl_dft <- data.frame(nsl_tangencyweights)
> nsl_dft
         nsl_tangencyweights
mizuno           0.000000000
asics            0.000000000
descente         0.069959609
ana              0.000000000
gmo              0.000000000
token            0.000000000
meiji            0.496777936
shobondo         0.388033784
tokyu            0.000000000
taisei           0.000000000
zenitaka         0.041828674
nihon            0.000000000
kinden           0.000000000
densetsu         0.003399996
osjb             0.000000000

次のポストでは実際にそれぞれの株価データの可視化とか、運用成績などを報告できたら良いなと思います。