Устаревшая опция rolling window В OLS от Pandas до Statsmodels

как следует из названия, где опция функции rolling в команде ols в Pandas перенесена в в statsmodels? Я не могу его найти. Панды говорят мне, что doom в работах:

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)

в самом деле, если вы делаете что-то вроде:

import statsmodels.api as sm

model = sm.OLS(series_1, mmmm, window=50).fit()

print(model.summary())

вы получаете результаты (окно не ухудшает работу кода), но вы получаете только параметры регрессии, запущенной на весь период, а не ряд параметров для каждого из скользящего периода, который должен быть должен работать дальше.

3 ответов


Я создал ols модуль, предназначенный для имитации устаревших панд MovingOLS; это здесь.

она имеет три основных класса:

  • OLS : статическая (одно окно) обычная регрессия наименьших квадратов. Выходные данные-массивы NumPy
  • RollingOLS: rolling (multi-window) обычная регрессия наименьших квадратов. Выход выше-размерность массивов numpy.
  • PandasRollingOLS : обертывания результаты RollingOLS в панд Серия & Таблиц Данных. Предназначен для имитации внешнего вида устаревшего модуля pandas.

обратите внимание, что модуль является частью пакета (который я в настоящее время загружаю в PyPi), и для этого требуется один импорт между пакетами.

первые два класса выше полностью реализованы в NumPy и в первую очередь используют матричную алгебру. RollingOLS пользуется широкой вещания. Атрибуты в значительной степени имитируют OLS statsmodels RegressionResultsWrapper.

пример:

# 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

Роллинг бета с 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)

добавление для полноты скорости numpy - единственное решение, которое ограничивает вычисления только коэффициентами регрессии и окончательной оценкой

функция регрессии качения Numpy

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             

Примечания

в некоторых конкретных случаях применения, которые требуют только окончательной оценки регрессии, x.rolling(window=60).apply(my_ols) Кажется несколько медленным

напомним, что коэффициенты регрессии могут быть рассчитывается как матричное произведение, как вы можете прочитать на страница наименьших квадратов Википедии. Этот подход через numpyматричное умножение может несколько ускорить процесс против использования ols в statsmodels. Этот продукт выражается в строке, начинающейся как coeff = ...