2016-03-15 3 views
1

У меня есть простая, но сложная алгоритмическая проблема.Как определить конкретные последовательности (round-trip) в наборе данных pandas?

У меня есть набор данных на уровне трейдера - фондовый день, и я хочу идентифицировать круглые поездки в данных. Круглые поездки - это только определенные последовательности данных. То есть, если вы со временем накапливаете удерживающую позицию запасов для отдельного i, начинается круговое движение и заканчивается нулевой фиксированной позицией.

Пример:

pd.DataFrame({'trader' : ['a','a','a','a','a','a','a'], 
       'stock' : ['a','a','a','a','a','a','b'], 
       'day' :[0,1,2,4,5,10,1], 
       'delta':[10,-10,15,-10,-5,5,6], 
       'cumq' : [10,0,15,5,0,5,6] , 
       'tag': [1,1,2,2,2,0,0]}) 

выход

Out[15]: 
    cumq day delta stock tag trader 
0 10 0  10  a 1  a 
1  0 1 -10  a 1  a 
2 15 2  15  a 2  a 
3  5 4 -10  a 2  a 
4  0 5  -5  a 2  a 
5  5 10  5  a 0  a 
6  6 1  6  b 0  a 

Здесь вы можете увидеть, что трейдер a купил две акции (a и b). delta соответствует количеству, купленному или проданному в определенный день. Таким образом, вы можете увидеть, что у нас есть два полных раунда на stock a (-10 +10 = 0) и (+15 - 10 -5 = 0) и два незавершенных раунда (+5 на stock a и +6 на stock b).

Я хотел был бы иметь возможность создать переменную tag которая говорит мне это. То есть, переменная, которая равна 0 всякий раз, когда кругооборот не заканчивается, и который принимает значения 1, 2, 3 для первого, второго, третьего и т. Д., Которые указаны в данной комбинации биржевых торговцев.

Любая идея, как это сделать эффективным образом? Большое спасибо!

EDIT:

  • короткие продажи возможны. Например, продайте 10, купите 25, продайте 25 и купите 10, будет одна поездка туда и обратно.
  • В тот же день можно осуществить круговое путешествие: в этом случае дельта будет равна нулю (действительно, вы покупаете и продаете то же количество в тот день). Это означает, что несколько ежедневных рейсов могут следовать друг за другом в данных. Таким образом, границы 0 для круглых поездок включены. Пример: вы покупаете 10 и продаете 10 сегодня (delta = 0), затем вы покупаете 15 и продаете 15 завтра (delta = 0 снова). Они соответствуют двум различным последовательным спуско-

Предложенное решение - КАЖЕТСЯ ДЛЯ РАБОТЫ - ОЧЕНЬ МЕДЛЕННО

import pandas as pd 
import numpy as np 

df = pd.DataFrame({'trader' : ['a','a','a','a','a','a','a'],'stock' : ['a','a','a','a','a','a','b'], 'day' :[0,1,2,4,5,10,1],'delta':[10,-10,15,-10,-5,5,0] ,'out': [1,1,2,2,2,0,1]}) 

def proc_trader(_df): 
    _df['tag'] = np.nan 
    # make every ending of a roundtrip with its index 
    _df['tag'][df.cumq == 0] = range(1, (_df.cumq == 0).sum() + 1) 
    # backfill the roundtrip index until previous roundtrip; 
    # then fill the rest with 0s (roundtrip incomplete for most recent trades) 
    _df['tag'] = _df['tag'].fillna(method = 'bfill').fillna(0) 
    return _df 

df.sort_values(by=['trader', 'stock','day'], inplace=True) 
df['cumq']=df.groupby(['trader', 'stock']).delta.transform('cumsum') 
df = df.groupby(['trader', 'stock']).apply(proc_trader) 

Любые идеи? Большое спасибо !!!!

+1

Как вы относитесь к краткосрочным продажам? Если разрешено, каков будет результат трейдера, который купил 10 и продал 20 на следующий день? – Alexander

+0

короткие продажи начнутся с минуса. скажем, вы продаете 10, а затем вы покупаете 10. Это совершенно правильно –

+1

Но что, если пересек в тот же день? Вы вынуждаете нуль и повторяете дни или показываете чистое изменение дня? – Alexander

ответ

1

Я хотел бы сделать что-то вроде этого:

import pandas as pd 
import numpy as np 

df = pd.DataFrame({'trader' : ['a','a','a','a','a','a','a'],'stock' : ['a','a','a','a','a','a','b'], 'day' :[0,1,2,4,5,10,1],'delta':[10,-10,15,-10,-5,5,6], 'cumq' : [10,0,15,5,0,6,11] ,'tag': [1,1,2,2,2,0,0]}) 

def proc_trader(_df): 
    if _df.shape[0] == 1: 
     _df['tag'] = _df['delta'] == 0 
     return _df 

    _df['tag'] = np.nan 
    # make every ending of a roundtrip with its index 
    _df['tag'][df.cumq == 0] = range(1, (df.cumq == 0).sum() + 1) 
    # backfill the roundtrip index until previous roundtrip; 
    # then fill the rest with 0s (roundtrip incomplete for most recent trades) 
    _df['tag'] = _df['tag'].fillna(method = 'bfill').fillna(0) 
    return _df 

df = df.groupby(['trader', 'stock']).apply(proc_trader) 

Идея заключается в том, что запись каждого трейдера состоит из ряда туда и обратно, кроме возможно, в конце концов; это предполагает что-то о том, как рассчитывать периоды нулевой дельта. Мы обнаруживаем все концы периодов roundtrip, backprop индекс и заполняем остальные 0s.

+0

спасибо, но я получаю 'ValueError: длина замещения должна быть равна длине последовательности при запуске вашего кода' –

+1

Моя ошибка. Я проверил 'groupby ('trader')', но не 'groupby (['trader', 'stock'])'. Это изменение должно работать для приведенного выше примера. Ошибка была равна размеру группы 1 (трейдер выполняет одну транзакцию за определенную безопасность). –

+0

Привет, Яким, видимо, у меня все та же проблема. См. Мой отредактированный пост. –