Допустим, у меня есть 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 возвратов вперёд, вполне подходящие после беглого взгляда.Сюжет выглядел так:
Учитывая, что эти акции с высоким риском, на которые я смотрю, были убиты в последние несколько месяцев, возможность даже вернуть 0% на самом деле является чем-то вроде победителя, поэтому я пришел к выводу, что стоит посмотретьпри совершении сделки.
В любом случае, надеюсь, это поможет кому-нибудь однажды.