我有一个简单但有挑战性的算法问题要解决。
我有一个交易者-股票-日水平的数据集,我想确定数据中的往返行程。往返只是数据中的特定序列。也就是说,如果你把个人i的股票s的持仓量累积起来,一个往返的开始和结束都是一个零的净持仓量。
例如:

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

在这里,您可以看到交易者购买了两支股票(aa)。b对应于在给定日期购买或出售的数量。因此,您可以看到我们有两个完整的往返delta(-10+10=0)和(+15-10-5=0)和两个未完成的往返(+5 onstock a,和+6 onstock a)。
我希望能够创建一个变量stock b来告诉我这一点。也就是说,一个变量,当一个往返没有终止时,它是0,并且在给定的股票交易者组合中,第一次、第二次、第三次等的往返中取1、2、3的值。
你知道如何有效地做到这一点吗?
非常感谢!
编辑:
卖空是可能的。例如,卖出10,买入25,卖出25,买入10将是一次往返。
往返可以在同一天执行:在这种情况下,delta将为零(实际上,您当天买卖的数量相同)。这意味着,在数据中,每天有几次往返可以互相跟踪。所以往返行程的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)

有什么想法吗?
非常感谢!!!!

最佳答案

我会这样做:

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填充其余部分。

08-07 13:26