ローリング回帰

ローリングOLSは、固定された観測ウィンドウを使ってOLS回帰を適用し、その後ウィンドウをデータセット全体に渡ってスライド(移動)させます。重要なパラメータはwindowで、これは各OLS回帰で使用する観測値の数を決定します。デフォルトでは、RollingOLSはウィンドウ内の欠損値を除外し、利用可能なデータポイントを使用してモデルを推定します。

推定された値は、データポイント\(i+1, i+2, ... i+window\)を使用して推定されたモデルが\(i+window\)の位置に保存されるように整列されます。

このノートブックで使用するモジュールをインポートすることから始めます。

(翻訳者注: notebook実行時に警告メッセージが多発します(Statsmodelsの関数内で廃止予定のpandas-datareaderの機能が参照されている)。説明の見易さを優先し、警告メッセージを抑止するコードを冒頭に追加しました。

import warnings
warnings.simplefilter(action="ignore", category=FutureWarning)

[1]:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import pandas_datareader as pdr
import seaborn

import statsmodels.api as sm
from statsmodels.regression.rolling import RollingOLS
import warnings
warnings.simplefilter(action="ignore", category=FutureWarning)

seaborn.set_style("darkgrid")
pd.plotting.register_matplotlib_converters()
%matplotlib inline
pandas-datareaderは、ケン・フレンチのウェブサイトからデータをダウンロードするために使用されます。
ダウンロードされる2つのデータセットは、3つのファマ・フレンチ因子と10の業種ポートフォリオです。
データは1926年から利用可能です。

データは、因子または業種ポートフォリオの月次リターンです。

[2]:
factors = pdr.get_data_famafrench("F-F_Research_Data_Factors", start="1-1-1926")[0]
factors.head()
[2]:
Mkt-RF SMB HML RF
Date
1926-07 2.96 -2.56 -2.43 0.22
1926-08 2.64 -1.17 3.82 0.25
1926-09 0.36 -1.40 0.13 0.23
1926-10 -3.24 -0.09 0.70 0.32
1926-11 2.53 -0.10 -0.51 0.31
[3]:
industries = pdr.get_data_famafrench("10_Industry_Portfolios", start="1-1-1926")[0]
industries.head()
[3]:
NoDur Durbl Manuf Enrgy HiTec Telcm Shops Hlth Utils Other
Date
1926-07 1.45 15.55 4.69 -1.18 2.90 0.83 0.11 1.77 7.04 2.13
1926-08 3.97 3.68 2.81 3.47 2.66 2.17 -0.71 4.25 -1.69 4.35
1926-09 1.14 4.80 1.15 -3.39 -0.38 2.41 0.21 0.69 2.04 0.29
1926-10 -1.24 -8.23 -3.63 -0.78 -4.58 -0.11 -2.29 -0.57 -2.63 -2.84
1926-11 5.20 -0.19 4.10 0.01 4.71 1.63 6.43 5.42 3.71 2.11

最初に推定されたモデルは、テクノロジーセクター企業の超過リターンを市場の超過リターンに回帰させるローリングバージョンのCAPMです。

ウィンドウは60ヶ月で、したがって最初の60ヶ月(window)後に結果が利用可能になります。最初の59ヶ月(window - 1)の推定値はすべてnanで埋められています。

[4]:
endog = industries.HiTec - factors.RF.values
exog = sm.add_constant(factors["Mkt-RF"])
rols = RollingOLS(endog, exog, window=60)
rres = rols.fit()
params = rres.params.copy()
params.index = np.arange(1, params.shape[0] + 1)
params.head()
[4]:
const Mkt-RF
1 NaN NaN
2 NaN NaN
3 NaN NaN
4 NaN NaN
5 NaN NaN
[5]:
params.iloc[57:62]
[5]:
const Mkt-RF
58 NaN NaN
59 NaN NaN
60 0.876155 1.399240
61 0.879936 1.406578
62 0.953169 1.408826
[6]:
params.tail()
[6]:
const Mkt-RF
1175 0.552565 1.086061
1176 0.610923 1.090145
1177 0.517339 1.089693
1178 0.503159 1.088327
1179 0.521466 1.088530

次に、市場負荷を95%のポイントごとの信頼区間とともにプロットします。 alpha=False は、constant列が存在する場合、それを省略します。

[7]:
fig = rres.plot_recursive_coefficient(variables=["Mkt-RF"], figsize=(14, 6))
../../../_images/examples_notebooks_generated_rolling_ls_10_0.png

次に、モデルは、余剰市場、サイズ要因、価値要因の 3 つの要因すべてを含むように拡張されます。

[8]:
exog_vars = ["Mkt-RF", "SMB", "HML"]
exog = sm.add_constant(factors[exog_vars])
rols = RollingOLS(endog, exog, window=60)
rres = rols.fit()
fig = rres.plot_recursive_coefficient(variables=exog_vars, figsize=(14, 18))
../../../_images/examples_notebooks_generated_rolling_ls_12_0.png

RollingOLSRollingWLSは、どちらも式インターフェースを使用したモデル仕様をサポートしています。以下の例は、以前推定された3因子モデルと同等です。なお、1つの変数は有効なPythonの変数名を持つように名前が変更されています。

[9]:
joined = pd.concat([factors, industries], axis=1)
joined["Mkt_RF"] = joined["Mkt-RF"]
mod = RollingOLS.from_formula("HiTec ~ Mkt_RF + SMB + HML", data=joined, window=60)
rres = mod.fit()
rres.params.tail()
[9]:
Intercept Mkt_RF SMB HML
Date
2024-05 0.682975 1.114558 -0.091375 -0.351516
2024-06 0.719744 1.121549 -0.106960 -0.357406
2024-07 0.674874 1.122952 -0.115250 -0.361814
2024-08 0.691389 1.116355 -0.108634 -0.368916
2024-09 0.658586 1.115486 -0.105006 -0.375140

RollingWLS: ローリング加重最小二乗法

rollingモジュールは、オプションのweights入力を受け取ってローリング加重最小二乗法を実行するRollingWLSも提供します。これは、データのローリングウィンドウに適用すると、WLSと一致する結果を生成します。

フィットオプション

fitは共分散推定器を設定するための他のオプションキーワードを受け付けます。サポートされている推定器は2つだけです: 'nonrobust'(従来のOLS推定器)と、ホワイトの異方分散にロバストな推定器である'HC0'です。

params_only=Trueを設定することで、モデルパラメータのみを推定することができます。これは、推定を行うために必要な値の完全なセットを計算するよりも大幅に高速です。

最後に、resetパラメータを正の整数に設定することで、非常に長い標本における推定誤差を制御できます。RollingOLSは、標本をロールする際に、最も最近の観測値を追加し、削除された観測値を除去することによって、完全な行列積を回避します。resetを設定すると、reset期間ごとに完全な内積を使用します。ほとんどのアプリケーションでは、このパラメータは省略できます。

[10]:
%timeit rols.fit()
%timeit rols.fit(params_only=True)
397 ms ± 68.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
144 ms ± 35.3 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

標本の拡張

十分な観測値がフルウィンドウ長に対して利用可能になるまで、標本を拡張することができます。この例では、12 の観測値が利用可能になった時点から開始し、その後、標本を拡張して 60 の観測値が利用可能になるまで増加させます。最初の非nan値は12の観測値を使用して計算され、次は 13、そしてその後も順次増えていきます。それ以外のすべての推定値は 60 の観測値を使用して計算されます。

[11]:
res = RollingOLS(endog, exog, window=60, min_nobs=12, expanding=True).fit()
res.params.iloc[10:15]
[11]:
const Mkt-RF SMB HML
Date
1927-05 NaN NaN NaN NaN
1927-06 1.560283 0.999383 1.351219 -0.471879
1927-07 1.235899 1.294857 0.742924 -0.540048
1927-08 1.249999 1.297546 0.752327 -0.548306
1927-09 1.375626 1.286724 1.177758 -0.609331
[12]:
res.nobs[10:15]
[12]:
Date
1927-05     0
1927-06    12
1927-07    13
1927-08    14
1927-09    15
Freq: M, dtype: int64
[ ]:


最終更新日: 2025年01月28日