6 株式データ分析入門

Published

2026/05/15

Modified

2026/04/26

1 この回で新たに学ぶ関数・演算子

今回は株式データを用いて,リターンの計算から統計的推論(\(t\)検定)までを実践する.新しく登場する関数・演算子を確認しておこう.

関数・演算子 パッケージ 役割
%in% base R 値が集合に含まれるかを判定する
prod() base R 要素の積を求める(リターンの累積に使用)
pull() dplyr データフレームから列をベクトルとして取り出す
length() base R ベクトルの要素数(標本サイズ)を求める
mean() base R 平均値を求める
var() base R 標本分散を求める
t.test() base R \(t\)検定を実行する
  • 前回までに学んだmutate()group_by()summarize()lag()filter()write_csv()なども引き続き使用する.
  • 迷ったらこの表に戻って「今どの関数を使っているのか」を確認しよう.

2 Rを利用した株式データ分析入門(教科書第5.1節)

2.1 株式データの読み込み

  • まずは,simulation_dataフォルダ内に格納している株式データch05_stock_data.csvを読み込もう.
Code
pacman::p_load(tidyverse) 

# 株式データの読み込み
stock_data <- read_csv("../simulation_data/ch05_stock_data.csv") 

2.2 stock_dataに格納されている各変数

Code
head(stock_data)
  • stock_price: 月末時点での終値
  • DPS: 一株当たり配当額 (Dividend Per Share; DPS)
  • shares_outstanding: 月末時点での発行済株式数
  • adjustment_coefficient: 調整係数
  • R_F: 月次無リスク金利

2.3 (余談)日本企業が採用する配当政策

  • 安定配当政策・・・日本企業の多くが採用していた伝統的な配当政策.業績に関わらず,毎期一定の配当を支払うことを目標にする考え方.
    • 代表例:井村屋(年一回1株当たり28円)
  • 配当性向 (payout ratio)政策・・・業績に応じて,配当額を変化させる考え方
    • 代表例:伊藤忠商事(配当性向目標30%)

Note\(t+1\)期の配当性向 (\(\text{配当性向}_{t+1}\))の計算方法

\[ \text{配当性向}_{t+1} = \frac{D_{t+1}}{X_{t+1}} \]

  • 例えば,東京エレクトロンは,両者を組合せて配当性向50%を目処とするとともに,安定的に還元するため,1株当たりの年間配当金は50円を下回らないようにしている.

2.4 近年では,DOEを意識する企業も

  • 株主資本配当率 (Dividend on Equity ratio; DOE)政策・・・1株当たりの株主資本に対して,一定の割合の配当を支払うことを目標にする考え方
    • 代表例:エーザイ(DOE目標15%)
Note\(t+1\)期のDOE (\(\text{DOE}_{t+1}\))の計算方法

\[ \text{DOE}_{t+1} = \frac{D_{t+1}}{Y_{t}} \]

  • 分母の1株当たり株主資本は,期首期末の平均 (\(=(Y_{t}+Y_{t+1})/2\))を採用したり,期末の\(Y_{t+1}\)を採用する場合などもある.
  • 一般的に,利益よりも株主資本の方が分散が少ないので,配当性向政策を採用する企業よりも,DOE政策を採用する企業の方が,安定的な配当が見込める.

2.5 配当支払いの例

Code
stock_data %>% 
  filter(firm_ID == 1 & month_ID %in% 27:30)
  • month_ID %in% 27:30month_ID27, 28, 29, 30を含んでいるという意味.
  • 6列目のDPSであるが,権利確定月,及び一株当たりの受け取り配当を記録するデータである.
  • 例えば,firm_ID1の企業について見てみると,2017年6月の月末時点の株主に対して,一株当たり43円の配当が支払われたことが分かる.

2.6 調整係数が1以外の値を取る例

Code
stock_data %>% 
  filter(firm_ID == 74 & month_ID %in% 29:32)

  • 8列目のadjustment_coefficientは,株式分割や併合などに伴う株式数の変化を調整するためのデータである.
  • 例えば,株式分割により旧1株が新しく2株になったとしよう.理論株価は半分になる一方で,元の株主はそれを相殺するように2倍の株式数を手にする.ここで単純に株価だけを用いてプライス・リターンを計算してしまうと,株主の資産の変化を誤って捉えてしまう.したがって,この場合は調整係数を2として,リターンを計算する際に調整する必要がある.
Tipプライス・リターンとは?
  • 株価の変化のみに着目したリターンであり,月次\(t\)の株価を\(P_{t}\)と表すと以下のように計算することができる. \[ \frac{P_{t} - P_{t-1}}{P_{t-1}} \]

2.7 時価総額の計算

  • データフレームstock_dataに時価総額ME列をmutate()関数を使って追加してみよう.
Code
stock_data <- stock_data %>% 
  mutate(ME = stock_price * shares_outstanding)

2.8 トータル・リターンの計算

  • ここで計算するリターンはトータル・リターンや配当込みリターンと言われ,株価の変化に加え配当収入も加味したリターンである.
  • 例えば,ある投資家が保有する銘柄が株式分割を行ったとしよう.定義より,月末時点でその投資家は元の保有株数の\({\rm adjustment\_coefficient}_t\)倍の株式を保有することになる.そして,ポートフォリオの時価評価は一株当たり\({\rm stock\_price}_t\)であり,更に\({\rm DPS}_t\)の配当を受け取る.したがって,この株式の\(t\)期のトータル・リターンは以下のように計算できる.
Noteトータル・リターンの計算式

\[ R_t = \frac{({\rm stock\_price}_t + {\rm DPS}_t) \times {\rm adjustment\_coefficient}_t - {\rm stock\_price}_{t-1}}{{\rm stock\_price}_{t-1}} \label{eq:definition_R} \tag{5.1} \]


2.9 月次リターンの計算を実現するコード例

  • 以下のコードでは,先に前月株価lagged_stock_priceを定義してから,(5.1)式に基づいて月次のトータル・リターンRをデータフレームstock_dataに追加している.
Code
# 月次リターンの追加
stock_data <- stock_data %>% 
  group_by(firm_ID) %>% 
  mutate(lagged_stock_price = lag(stock_price)) %>% # 前月株価をlagged_stock_priceと定義
  ungroup() %>% 
  mutate(R = ((stock_price + DPS) * adjustment_coefficient - lagged_stock_price) / lagged_stock_price) # (5.1)式に従って月次リターンを計算

2.10 様々なリターンの定義(教科書コラム2.1)

  • 例えば,昨日の株価が100円で,今日の株価が110円になった場合,ネット・リターンは10% (\(=\) 0.1)である.一方,元本分も含める場合はグロス・リターンと呼び,ネット・リターンに1を足して110% (\(=\) 1.1)となる.
  • 単純にリターンと言った場合にどちらを指すかは文脈によるが,本書では原則としてネット・リターンの意味で用いる.


2.11 無リスク金利に対する超過リターンの計算

  • ネット・リターンから無リスク金利を差し引いた値を,(無リスク金利に対する)超過リターンと呼ぶ. \[ \text{($t$期の超過リターン)~~~~~} R_{t}^e = R_{t}-R_{F,t}  \]

ここで,\(R_{F,t}\)は同期間に安全資産で運用した場合のネット・リターンを指し,\(R_{t}^e\)\(e\)は超過を意味するexcessの略である.

Code
# 月次超過リターンの追加も加える
stock_data <- stock_data %>% 
  group_by(firm_ID) %>% 
  mutate(lagged_stock_price = lag(stock_price)) %>% # 前月株価をlagged_stock_priceと定義
  ungroup() %>% 
  mutate(R = ((stock_price + DPS) * adjustment_coefficient - lagged_stock_price) / lagged_stock_price, # (5.1)式に従って月次リターンを計算
         Re = R - R_F) # 月次超過リターンを計算

3 リターンの累積(教科書第5.3節)

3.1 バイ・アンド・ホールド・リターンの考え方 - 1ヶ月間を例に

  • 例えば,ある銘柄に12月末に投資をして,1ヶ月保有し続けた場合の1ヶ月間のリターンを考えてみよう.この例のように,一度投資すれば,後は売買することなく保有し続けた場合のリターンのことを明示的に強調するために,バイ・アンド・ホールド・リターン (buy-and-hold return)と呼ぶ.
  • バイ・アンド・ホールド・リターンは元本を再投資し続けた場合のリターンと言い換えられるので,運用を継続することによる複利の効果を反映した値である.


3.2 バイ・アンド・ホールド・リターンの考え方 - 3ヶ月間を例に

  • 1ヶ月が3ヶ月に伸びたところで同じように考えることができる.すなわち,バイ・アンド・ホールドで3ヶ月間のリターンを累積するには,12月末から3月末にかけての投資家の資産額の変化率を計算すれば良い.ここでのポイントは,(得られた配当はすぐにその同銘柄に再投資すると考える限りにおいて)資産額のグロス変化率は,以下のように積の形で分解できる点である.

\[ \begin{align*} \underbrace{\left(\frac{W_{\text{3月}}}{W_{\text{12月}}}\right)}_{\textbf{グロスの3ヶ月間のリターン}} = \underbrace{\left(\frac{\cancel{W_{\text{1月}}}}{W_{\text{12月}}}\right)}_{1 + R_{\text{1月}}} \times \underbrace{\left(\frac{\cancel{W_{\text{2月}}}}{\cancel{W_{\text{1月}}}}\right)}_{1 + R_{\text{2月}}} \times \underbrace{\left(\frac{W_{\text{3月}}}{\cancel{W_{\text{2月}}}}\right)}_{1 + R_{\text{3月}}} \end{align*} \]


3.3 バイ・アンド・ホールド・リターンの計算 - 12ヶ月間を例に

  • 月次リターンを年次リターンに累積するには,上の計算例を3ヶ月から12ヶ月に伸ばすだけで良いことが分かるだろう.

\[ \begin{align*} \underbrace{\left(\frac{W_{\text{翌年12月末}}}{W_{\text{12月末}}}\right)}_{\textbf{グロスの年次リターン}} & = (1 + R_{\text{1月}})\times (1 + R_{\text{2月}})\times \cdots \times (1 + R_{\text{12月}}) \nonumber\\ & = \prod_{t = \text{1月}}^{\text{12月}}(1 + R_{t}) \end{align*} \]

Note目標
  • stock_dataを基に,新しくannual_stock_dataというデータフレームを作成し,各銘柄の年次リターン,及びそれに対応する年次超過リターンをネットで計算してみよう.annual_stock_dataは,firm_ID, year, R, Re, R_Fの五変数で構成されるようにすること.
  • こうして完成したデータフレームを次週の講義に備えて,simulation_dataフォルダにannual_stock_data.csvとして出力しておこう.

(ヒント1) ネットの年次リターンは,単純にグロスの年次リターンから1を差し引けば良い.

(ヒント2) 各要素の積は,prod()関数により求めることができる.


3.4 目標を実現するためのコード例

以下のコードでは,group_by()関数を用いてfirm_ID,及びyearの各ペアに関して,stock_dataをグループ化し,summarize()関数を用いて年次リターンR,及びそれに対応する年次無リスク金利R_Fを計算した後,年次超過リターンReを定義している.

Code
# 月次リターンを累積して年次リターンを計算
annual_stock_data <- stock_data %>%
  group_by(firm_ID, year) %>% # firm_IDとyearのペアでグループ化
  summarize(R = prod(1 + R) - 1, # バイ・アンド・ホールドの年次リターン
            R_F = prod(1 + R_F) - 1,
            .groups = "drop") %>% # グループ化を解除
  mutate(Re = R - R_F) %>% # 年次超過リターンの計算
  select(firm_ID, year, R, Re, R_F)

# head()関数により確認
head(annual_stock_data)
Code
# write_csv()関数を用いて出力
write_csv(annual_stock_data, "../simulation_data/annual_stock_data.csv")

4 統計的推論入門

4.1 リターン・データを用いた統計的推論

Note目標

firm_ID1の銘柄の月次超過リターン\(R_{1,t}^e\)は,期待値の意味でゼロより大きいだろうか?

  • すなわち,月次リターン\(R_{1,t}\)が期待値の意味で無リスク金利\(R_{F,t}\)より大きいかどうかを統計的に検定したい.
  • 中心極限定理に基づくと,真の期待値がゼロという仮定の下で,以下で定義される (\(t\)-value)は近似的に標準正規分布に従う(\(\stackrel{d}{\approx }\)は「分布が近似できる」の意味). \[ \begin{align} t=\frac{\bar{X}-\mu_0}{\sqrt{s^2/n}} \; \stackrel{d}{\approx } \; {\rm N}(0, 1) \label{eq:t-value} \tag{5.2} \end{align} \] ここで,\(\bar{X}\)は標本平均,\(s^2\)は標本分散,\(n\)は標本サイズである.また,\(\mu_0\)は帰無仮説(後述)の値で,ここでは真の期待値と等しくゼロとする.\(t\)値は超過リターンに限らず一般的に定義されるため,ここではあえて\(\bar{R}_1^e\)でなく,\(\bar{X}\)という記法を採用している.\(\mu_0=0\)を省略しなかったのも同様の理由である.

4.2 関数に頼らない\(t\)検定

  • 以下のコードでは,まずdrop_na()関数を利用して欠損値を除去した後の月次超過リターンのベクトルをRe_firm_ID_1として定義している.
  • その後,(5.2)式を定義通りに計算すると,この場合の\(t\)値は約2.12であることが分かる.
Code
# 月次超過リターンの期待値に関するt検定 (1)

Re_firm_ID_1 <- stock_data %>%
  filter(firm_ID == 1) %>% # firm_IDが1の企業のみ抽出
  drop_na(Re) %>% # 欠損値を削除
  pull(Re) # データフレームからベクトルとして取り出す

mu0 <- 0 # 帰無仮説を期待値0と設定
n <- length(Re_firm_ID_1) # 標本サイズ

t_value <- (mean(Re_firm_ID_1) - mu0) / sqrt(var(Re_firm_ID_1) / n) # 定義に従ってt値を計算

## [1] 2.121296

4.3 既成の関数を使うやり方

  • Rでは\(t\)検定を行うためにt.test()関数が用意されている.
  • この関数は第一引数に標本集合を取り,第二引数以降に検定の詳細を指定する.第二引数以降が省略された場合,自動的に帰無仮説は期待値ゼロに設定される.
Code
# 月次超過リターンの期待値に関するt検定 (2)
t.test(Re_firm_ID_1) # t.test()関数で第二引数以降を省略

5 自習課題

  • 以下の課題に取り組み,今回学んだ内容の理解度を自分で確認しよう.
  • 課題では,講義で作成したstock_dataおよびannual_stock_dataをそのまま使用する.

5.1 準備:自分だけの分析条件を生成する

  • 以下のコードをRコンソールで実行しよう.set.seed()関数の引数には,自分の学籍番号の末尾4桁の数字(末尾の英字を除く)を入力すること.
Code
# 全期間にわたって月次データが揃っている企業を対象に絞る
target_firms <- stock_data %>%
  count(firm_ID) %>%
  filter(n == max(n)) %>%
  pull(firm_ID)

# 自分の学籍番号の末尾4桁の数字を入力(例: 学籍番号が2001234Bの場合は1234)
set.seed(1234)

# 自分だけの分析条件を生成
my_firm  <- sample(intersect(1:500, target_firms), 1)  # 分析対象の企業ID
my_year  <- sample(2016:2020, 1)                       # 分析対象の年度(年次累積に最初の月のlagが必要なので2016年以降)
my_firms <- sort(sample(intersect(1:500, target_firms), 5))  # 比較対象の5企業
my_month <- sample(2:12, 1)                            # リターン確認用の月

cat("対象企業:", my_firm, "\n")
cat("対象年度:", my_year, "\n")
cat("比較企業:", my_firms, "\n")
cat("対象月:", my_month, "\n")

5.2 Q1: トータル・リターンの手計算による確認

Note問題
  • stock_dataから,my_firmの企業のmy_yearmy_month月(year == my_year & month == my_month)の行を抽出し,stock_priceDPSadjustment_coefficient,及び前月のlagged_stock_priceの値を確認せよ.
  • 確認した値を用いて,以下の(5.1)式に基づきトータル・リターンを手計算し,R列の値と一致することを確かめよ.\[R_t = \frac{(\text{stock\_price}_t + \text{DPS}_t) \times \text{adjustment\_coefficient}_t - \text{stock\_price}_{t-1}}{\text{stock\_price}_{t-1}}\]

5.3 Q2: prod() を使った年次リターンの累積

Note問題
  • stock_dataからmy_firmの企業のmy_year年度の月次リターンRを全て抽出し,prod()関数を用いてバイ・アンド・ホールドの年次リターン(ネット)を計算せよ.
  • 計算した値がannual_stock_dataの対応する行のRと一致することを確認し,その年次リターンの値を報告せよ.

(ヒント!)

  1. ネットの年次リターンはprod(1 + R) - 1で計算できる.prod()の中にグロス・リターン(\(= 1 + R\))を入れるのがポイントである.
  2. filter()で抽出した後,pull(R)でベクトルとして取り出してからprod()を適用しよう.

5.4 Q3: シャープレシオによるパフォーマンス評価

Note問題
  • 準備で生成したmy_firmsの5企業それぞれについて,stock_dataの月次超過リターンReの平均値(\(\bar{R}^e\)),標準偏差(\(\text{sd}(R^e)\)),及び以下の定義に従うシャープレシオ(\(\text{SR}\))を計算せよ.\[\text{SR} = \frac{\bar{R}^e}{\text{sd}(R^e)}\]
  • シャープレシオとは,超過リターンの平均をそのばらつき(標準偏差)で割った値であり,リスク1単位あたりに得られる超過リターンを表す指標である.値が大きいほど,リスクに対して効率よくリターンを得ていることを意味する.
  • 5企業の中で「平均超過リターンが最も高い企業」と「シャープレシオが最も高い企業」はそれぞれどのfirm_IDか報告せよ.両者が一致しない場合,なぜ異なるのかを一文で説明せよ.

(ヒント!)

  1. stock_datafilter(firm_ID %in% my_firms)で絞り込み,group_by(firm_ID)した上でsummarize()を使えば,5企業分を一度に計算できる.
  2. 標準偏差はsd()関数で求められる.var()の平方根と同じである.

5.5 Q4: t.test() による統計的推論

Note問題
  • stock_dataからmy_firmの企業の月次超過リターンRepull()で取り出し(欠損値はdrop_na()で除去すること),以下の手順で\(t\)検定を行え.
    1. まず,length()mean()var()を用いて(5.2)式の\(t\)値を手計算せよ(\(\mu_0 = 0\)とする).\[t = \frac{\bar{X} - \mu_0}{\sqrt{s^2 / n}}\]
    2. 次に,同じデータに対してt.test()関数を適用し,手計算の\(t\)値と一致することを確認せよ.
  • t.test()の出力に含まれる\(p\)値(p-value)が\(0.05\)未満かどうかを報告し,「この企業の月次超過リターンの期待値はゼロと異なるか」について一文で答えよ.