Option rolling window obsolète dans OLS from Pandas to Statsmodels
comme le titre l'indique, où l'option fonction de roulement de la commande ols dans Pandas a-t-elle migré dans les modèles de statistiques? Je n'arrive pas à le trouver. Pandas me dit que la ruine est en cours:
FutureWarning: The pandas.stats.ols module is deprecated and will be removed in a future version. We refer to external packages like statsmodels, see some examples here: http://statsmodels.sourceforge.net/stable/regression.html
model = pd.ols(y=series_1, x=mmmm, window=50)
en fait, si vous faites quelque chose comme:
import statsmodels.api as sm
model = sm.OLS(series_1, mmmm, window=50).fit()
print(model.summary())
vous obtenez des résultats (la fenêtre n'altère pas le fonctionnement du code) mais vous obtenez seulement les paramètres de l'exécution de régression sur l'ensemble de la période, pas la série de paramètres pour chacun des la période de roulement sur laquelle il devrait être censé travailler.
3 réponses
j'ai créé un ols
module conçu pour imiter pandas' déprécié MovingOLS
; il est ici .
elle comporte trois classes principales:
-
OLS
: statique (guichet unique) ordinaire de la régression des moindres carrés. La sortie sont des tableaux NumPy -
RollingOLS
: régression des moindres carrés ordinaires par laminage (fenêtres multiples). La sortie sont des tableaux NumPy de dimension supérieure. -
PandasRollingOLS
: enveloppe les résultats deRollingOLS
dans la série pandas & DataFrames. Conçu pour imiter l'apparence du module pandas déprécié.
notez que le module fait partie d'un package (que je suis en train de télécharger vers PyPi) et qu'il nécessite une importation inter-package.
les deux premières classes ci-dessus sont entièrement implémentées dans NumPy et utilisent principalement la matrice algèbre. RollingOLS
tire aussi largement parti de la radiodiffusion. Les attributs imitent largement les OLS de stats-modèles RegressionResultsWrapper
.
un exemple:
# Pull some data from fred.stlouisfed.org
from pandas_datareader.data import DataReader
syms = {'TWEXBMTH' : 'usd',
'T10Y2YM' : 'term_spread',
'PCOPPUSDM' : 'copper'
}
data = (DataReader(syms.keys(), 'fred', start='2000-01-01')
.pct_change()
.dropna())
data = data.rename(columns=syms)
print(data.head())
# usd term_spread copper
# DATE
# 2000-02-01 0.01260 -1.40909 -0.01997
# 2000-03-01 -0.00012 2.00000 -0.03720
# 2000-04-01 0.00564 0.51852 -0.03328
# 2000-05-01 0.02204 -0.09756 0.06135
# 2000-06-01 -0.01012 0.02703 -0.01850
# Rolling regressions
from pyfinance.ols import PandasRollingOLS
y = data.usd
x = data.drop('usd', axis=1)
window = 12 # months
model = PandasRollingOLS(y=y, x=x, window=window)
print(model.beta.head()) # Coefficients excluding the intercept
# term_spread copper
# DATE
# 2001-01-01 0.00010 0.05568
# 2001-02-01 0.00047 0.06271
# 2001-03-01 0.00147 0.03576
# 2001-04-01 0.00161 0.02956
# 2001-05-01 0.00158 -0.04497
print(model.fstat.head())
# DATE
# 2001-01-01 0.28121
# 2001-02-01 0.42602
# 2001-03-01 0.38802
# 2001-04-01 0.39230
# 2001-05-01 0.41706
# Freq: MS, Name: fstat, dtype: float64
print(model.rsq.head()) # R-squared
# DATE
# 2001-01-01 0.05882
# 2001-02-01 0.08648
# 2001-03-01 0.07938
# 2001-04-01 0.08019
# 2001-05-01 0.08482
# Freq: MS, Name: rsq, dtype: float64
le déploiement de la bêta, avec sklearn
import pandas as pd
from sklearn import linear_model
def rolling_beta(X, y, idx, window=255):
assert len(X)==len(y)
out_dates = []
out_beta = []
model_ols = linear_model.LinearRegression()
for iStart in range(0, len(X)-window):
iEnd = iStart+window
model_ols.fit(X[iStart:iEnd], y[iStart:iEnd])
#store output
out_dates.append(idx[iEnd])
out_beta.append(model_ols.coef_[0][0])
return pd.DataFrame({'beta':out_beta}, index=out_dates)
df_beta = rolling_beta(df_rtn_stocks['NDX'].values.reshape(-1, 1), df_rtn_stocks['CRM'].values.reshape(-1, 1), df_rtn_stocks.index.values, 255)
ajout pour complétude d'une solution numpy
-seulement rapide qui limite les calculs seulement aux coefficients de régression et à l'estimation finale
Numpy roulant fonction de régression
import numpy as np
def rolling_regression(y, x, window=60):
"""
y and x must be pandas.Series
"""
# === Clean-up ============================================================
x = x.dropna()
y = y.dropna()
# === Trim acc to shortest ================================================
if x.index.size > y.index.size:
x = x[y.index]
else:
y = y[x.index]
# === Verify enough space =================================================
if x.index.size < window:
return None
else:
# === Add a constant if needed ========================================
X = x.to_frame()
X['c'] = 1
# === Loop... this can be improved ====================================
estimate_data = []
for i in range(window, x.index.size+1):
X_slice = X.values[i-window:i,:] # always index in np as opposed to pandas, much faster
y_slice = y.values[i-window:i]
coeff = np.dot(np.dot(np.linalg.inv(np.dot(X_slice.T, X_slice)), X_slice.T), y_slice)
estimate_data.append(coeff[0] * x.values[window-1] + coeff[1])
# === Assemble ========================================================
estimate = pandas.Series(data=estimate_data, index=x.index[window-1:])
return estimate
Notes
dans certaines utilisations spécifiques, qui ne nécessitent que l'estimation finale de la régression, x.rolling(window=60).apply(my_ols)
semble être assez lent
pour rappel, les coefficients pour une régression peuvent être calculés comme un produit de matrice, comme vous pouvez le lire sur page des moindres carrés de wikipedia . Cette approche via la multiplication matricielle de numpy
peut accélérer quelque peu le processus vs En utilisant les ols dans statsmodels
. Ce produit est exprimé dans la ligne commençant par coeff = ...