2016-03-15 32 views
1

我有一個簡單而又有挑戰性的算法問題需要解決。如何識別熊貓數據集中的特定序列(往返)?

我在交易員 - 股票 - 日級別有一個數據集,我想確定數據中的往返行程。往返只是數據中的特定序列。也就是說,如果您隨着時間的推移累計個人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買了兩隻股票(ab)。 delta對應於某一天購買或出售的數量。所以你可以看到我們在stock a(-10 +10 = 0)和(+15 - 10 -5 = 0)和兩次未完成的往返(+ stock a和+6在stock b上)。

我希望能夠創建一個變量tag告訴我這一點。也就是說,只要往返行程沒有終止,變量爲0,並且在給定的證券交易者組合中識別的第一,第二,第三等往返行程的值爲1,2,3。

任何想法如何以有效的方式做到這一點? 非常感謝!

編輯:

  • 賣空是可能的。例如賣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) 

的想法是每個商人的紀錄由一系列中端除了可以往返的;這假定了一些關於如何計算零增量週期的內容。我們檢測往返時間段的所有末端,反向索引並用0填充其餘部分。

+0

謝謝,但我得到'ValueError:當我運行你的代碼時,替換長度必須等於系列長度' –

+1

我的錯誤。我檢查了'groupby('trader')''但不是'groupby(['trader','stock'])''。這個編輯應該適用於上面的例子。該錯誤來自組大小爲1(交易者每個給定的安全性執行單個事務)。 –

+0

嗨Yakym,顯然我仍然有同樣的問題。請看我編輯的帖子。 –