Регулярная регрессия OLS и ValueError: длина значений не соответствует длине индекса - PullRequest
0 голосов
/ 07 мая 2019

Допустим, у меня есть df цены акций, которые выглядят примерно так:

Date                       Stock A
2019-05-06 07:59:59.999    0.028213
2019-05-06 08:59:59.999    0.028389
2019-05-06 09:59:59.999    0.028242
2019-05-06 10:59:59.999    0.028744
2019-05-06 11:59:59.999    0.028826
2019-05-06 12:59:59.999    0.028949
2019-05-06 13:59:59.999    0.028886
2019-05-06 14:59:59.999    0.028863
2019-05-06 15:59:59.999    0.029398
Name: Stock A, Length: 1000, dtype: float64

Что я пытаюсь сделать для каждой акции - это вычислить прогнозируемое значение, используя ols.PandasRollingOLS(y, X, window=n) из pyfinance, а затем рассчитайте, на сколько стандартных отклонений текущая цена отклоняется от прогнозируемого значения, и затем нанесите на график это с некоторыми форвардными доходами, т. Е. Насколько цена выросла или выросла, n количество дней вбудущее, в основном .shift(-n).Это звучит очень просто, но я как-то застреваю все больше и больше.

Код для запуска скользящей регрессии выглядит следующим образом и работает нормально, поэтому проблема не в этом:

X = df['Time']
y = df['Stock A']
model = ols.PandasRollingOLS(y, X, window=250)
prediction = model._predicted

Prediction затем возвращает 751 массив, причем конечное число в каждом массиве будет номером, который я хочу использовать.Так что для меня, чтобы вернуть список прогнозируемого значения для каждой точки данных, я должен сделать [i[-1] for i in prediction], который затем дает мне [...0.02862762374502103, 0.028612066422311653, 0.028596879968127514, 0.028582598374502034, 0.02856930540239047, 0.028553991394421267, 0.02854553854980154, 0.028536955824703027, 0.028531125290838216, 0.028522397768924877, 0.02851387212749102, 0.028514959521912523].

То, что я хочу сделать в первую очередь, это возможность создать новоестолбец скажет df['Diff'], который вычисляет разницу между текущей ценой и прогнозируемой ценой, а затем делится на скользящее стандартное отклонение 100.

Мой код будет выглядеть примерно так: df['Diff'] = (df['Stock A'] - [i[-1] for i in prediction]) / df['Stock A'].rolling(100).std()

Однако этовыдает TypeError: unsupported operand type(s) for /: 'generator' and 'float' как ошибку, и когда я просто пытаюсь минусить одно из другого без бита стандартного отклонения, я получаю ValueError: operands could not be broadcast together with shapes (1000,) (751,).

Я могу понять, почему я получаю ошибку как ценуданные имеют длину 1000 точек данных и есть только 751 прогноз.

В конце я хочу получить 2 столбца, один из которых рассчитывает разницу между текущей ценой и прогнозируемой ценой, деленной на скользящий стандарт, и второйколонка, вычисляющая процентные форвардные доходы, т.е. df['returns'] = df['Stock A'].diff(-100)/df['Stock A']:

Date                       Diff     Returns
2019-05-02 07:59:59.999    0.68213  -0.91
2019-05-02 08:59:59.999    0.68389  -0.91
2019-05-02 09:59:59.999    0.68452  -0.92
2019-05-02 10:59:59.999    0.69642  -0.92
2019-05-02 11:59:59.999    0.71459  -0.94
2019-05-02 12:59:59.999    0.73697  -0.96
2019-05-02 13:59:59.999    0.75624  -0.97
2019-05-02 14:59:59.999    0.78542  -0.98
2019-05-02 15:59:59.999    1.20543  -1.25

Как только я смогу получить это право на одну акцию, я просто сделаю цикл, чтобы сделать это дляостальные.Любая помощь действительно приветствуется, ура.

РЕДАКТИРОВАТЬ:

Итак, что я сделал, так как есть несоответствие по длине двух наборов данных, я написал, чтобы сократитьстолбец цены до размера.Теперь у меня есть следующее:

X = data['Time']
y = data['Stock A']
model = ols.PandasRollingOLS(y, X, window=250)
prediction = model._predicted
data['returns'] = (data['Stock A'].shift(-150)-data['Stock A'])/data['Stock A']
data['Stock A'] = data['Stock A'].iloc[-751:]
data['Stock A'].dropna(inplace=True)
data['diff'] = (data['Stock A'] - [i[-1] for i in prediction])/data['Stock A'].rolling(250).std()

Это, по сути, делает то, что я хочу, но теперь у меня проблема в том, что вместо данных, начинающихся в точке 250, они начинаются с 497, поэтому они обрезаются.немедленно вычеркните половину моих данных.

Если кто-то может быстро увидеть, что я делаю неправильно, тогда здорово, если не беспокоиться об этом, похоже, мне придется отказаться от этого.Приветствия

РЕДАКТИРОВАТЬ 2.0:

Извините, сбрасывание NA вызывало проблему, поэтому сейчас я указываю длину df в вычислениях, поэтому мой окончательный код таков, еще раз спасибо за помощь:

X = data['Time']
y = data['Stock A']
model = ols.PandasRollingOLS(y, X, window=250)
prediction = model._predicted
data['returns'] = (data['Stock A'].shift(-150)-data['Stock A'])/data['Stock A']
data['diff'] = (data['Stock A'].iloc[-751:] - [i[-1] for i in prediction])/data['Stock A'].rolling(250).std()

В ответ на комментарий Брэда:

Итак, для начала я на самом деле получаю данные о своих запасах (144 акции) из файла CSV, так что вам придется откуда-то получать данные,но как только вы это сделаете, это то, что я делал.

Я хотел построить диаграмму / график стандартизированной разницы между фактическими и прогнозируемыми значениями для каждой акции, так же, как вы рассчитываете z-показатель и наносите его на график форварда.возвращает, скажем, 100 точек данных в будущем, какова разница в процентах.Я хотел посмотреть, была ли цена далеко от ее прогноза, действительно ли она давала выигрыш со временем.

Итак, я рассчитал стандартизированную разницу и прямую доходность, скажем, через окно в 300 пунктов для регрессии,и окно 400 пунктов для возвратов, а затем для каждой акции я добавил эти данные в df, отсортировал их по разнице и отбросил все, кроме самых крайних точек данных с обеих сторон, так как я бы совершил сделку, только если что-то былохорошо вне линии.

    df = []
    data['Time'] = range(0, 0+ len(data))
    for stock in stocks:
        X = data['Time']
        y = data[stock]
        model = ols.PandasRollingOLS(y, X, window=300)
        prediction = model._predicted
        data['returns'] = (data[stock].shift(-400) - data[stock]) / data[stock]
        lngth = (1000-300)+1 # the length the data needs to be to match the prediction array, otherwise you encounter an annoying error
        data['diff'] = (data[stock].iloc[-lngth:] - [i[-1] for i in prediction]) / data[stock].rolling(300).std()
        df.append(data[['diff', 'returns']])
    df = pd.concat(df, axis=0)
    df.dropna(inplace=True)
    df.reset_index(inplace=True)
    df = df.drop(['Date'], axis=1)
    df.sort_values('diff', inplace=True)
    size = len(df) * 0.001
    size = size.__round__()
    df = df.drop(df.index[size:-size])
    if len(df) > 0:
        X = df['diff'].values.reshape(-1,1)
        y = df['returns'].values.reshape(-1,1)
        model = LinearRegression()
        model.fit(X,y)
        return model.score(X,y)

Вы можете поиграть с параметрами, но то, что я искал, было хорошо подходящей комбинацией, и окно 300 регрессий, 400 возвратов вперёд, вполне подходящие после беглого взгляда.Сюжет выглядел так:

enter image description here

Учитывая, что эти акции с высоким риском, на которые я смотрю, были убиты в последние несколько месяцев, возможность даже вернуть 0% на самом деле является чем-то вроде победителя, поэтому я пришел к выводу, что стоит посмотретьпри совершении сделки.

В любом случае, надеюсь, это поможет кому-нибудь однажды.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...