2026/05/22
今回は株式データを用いて,リターンの計算から統計的推論(\(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()なども引き続き使用する.simulation_dataフォルダ内に格納している株式データch05_stock_data.csvを読み込もう.stock_dataに格納されている各変数stock_price: 月末時点での終値DPS: 一株当たり配当額 (Dividend Per Share; DPS)shares_outstanding: 月末時点での発行済株式数adjustment_coefficient: 調整係数R_F: 月次無リスク金利\(t+1\)期の配当性向 (\(\text{配当性向}_{t+1}\))の計算方法
\[ \text{配当性向}_{t+1} = \frac{D_{t+1}}{X_{t+1}} \]
\(t+1\)期のDOE (\(\text{DOE}_{t+1}\))の計算方法
\[ \text{DOE}_{t+1} = \frac{D_{t+1}}{Y_{t}} \]
month_ID %in% 27:30はmonth_IDが27, 28, 29, 30を含んでいるという意味.DPSであるが,権利確定月,及び一株当たりの受け取り配当を記録するデータである.firm_IDが1の企業について見てみると,2017年6月の月末時点の株主に対して,一株当たり43円の配当が支払われたことが分かる.1以外の値を取る例adjustment_coefficientは,株式分割や併合などに伴う株式数の変化を調整するためのデータである.2として,リターンを計算する際に調整する必要がある.プライス・リターンとは?
stock_dataに時価総額ME列をmutate()関数を使って追加してみよう.トータル・リターンの計算式
\[ 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} \]
lagged_stock_priceを定義してから,(5.1)式に基づいて月次のトータル・リターンRをデータフレームstock_dataに追加している.ここで,\(R_{F,t}\)は同期間に安全資産で運用した場合のネット・リターンを指し,\(R_{t}^e\)の\(e\)は超過を意味するexcessの略である.
# 月次超過リターンの追加も加える
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) # 月次超過リターンを計算\[ \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*} \]
\[ \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*} \]
目標
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()関数により求めることができる.
以下のコードでは,group_by()関数を用いてfirm_ID,及びyearの各ペアに関して,stock_dataをグループ化し,summarize()関数を用いて年次リターンR,及びそれに対応する年次無リスク金利R_Fを計算した後,年次超過リターンReを定義している.
# 月次リターンを累積して年次リターンを計算
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)目標
firm_IDが1の銘柄の月次超過リターン\(R_{1,t}^e\)は,期待値の意味でゼロより大きいだろうか?
drop_na()関数を利用して欠損値を除去した後の月次超過リターンのベクトルをRe_firm_ID_1として定義している.# 月次超過リターンの期待値に関する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.121296t.test()関数が用意されている.stock_dataおよびannual_stock_dataをそのまま使用する.set.seed()関数の引数には,自分の学籍番号の下4桁を入力すること.# 自分の学籍番号の下4桁を入力(例: 学籍番号が26A1234の場合は1234)
set.seed(1234)
# 自分だけの分析条件を生成
my_firm <- sample(1:500, 1) # 分析対象の企業ID
my_year <- sample(2015:2018, 1) # 分析対象の年度
my_firms <- sort(sample(1:500, 5)) # 比較対象の5企業
my_month <- sample(2:12, 1) # リターン確認用の月
cat("対象企業:", my_firm, "\n")
cat("対象年度:", my_year, "\n")
cat("比較企業:", my_firms, "\n")
cat("対象月:", my_month, "\n")問題
stock_dataから,my_firmの企業のmy_year年my_month月(year == my_year & month == my_month)の行を抽出し,stock_price,DPS,adjustment_coefficient,及び前月のlagged_stock_priceの値を確認せよ.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}}\]prod() を使った年次リターンの累積問題
stock_dataからmy_firmの企業のmy_year年度の月次リターンRを全て抽出し,prod()関数を用いてバイ・アンド・ホールドの年次リターン(ネット)を計算せよ.annual_stock_dataの対応する行のRと一致することを確認し,その年次リターンの値を報告せよ.(ヒント!)
prod(1 + R) - 1で計算できる.prod()の中にグロス・リターン(\(= 1 + R\))を入れるのがポイントである.filter()で抽出した後,pull(R)でベクトルとして取り出してからprod()を適用しよう.問題
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)}\]firm_IDか報告せよ.両者が一致しない場合,なぜ異なるのかを一文で説明せよ.(ヒント!)
stock_dataをfilter(firm_ID %in% my_firms)で絞り込み,group_by(firm_ID)した上でsummarize()を使えば,5企業分を一度に計算できる.sd()関数で求められる.var()の平方根と同じである.t.test() による統計的推論問題
stock_dataからmy_firmの企業の月次超過リターンReをpull()で取り出し(欠損値はdrop_na()で除去すること),以下の手順で\(t\)検定を行え.
length(),mean(),var()を用いて(5.2)式の\(t\)値を手計算せよ(\(\mu_0 = 0\)とする).\[t = \frac{\bar{X} - \mu_0}{\sqrt{s^2 / n}}\]t.test()関数を適用し,手計算の\(t\)値と一致することを確認せよ.t.test()の出力に含まれる\(p\)値(p-value)が\(0.05\)未満かどうかを報告し,「この企業の月次超過リターンの期待値はゼロと異なるか」について一文で答えよ.2025 経営データ分析(会計)