微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在熊猫中更改多头/空头头寸的更有效方法

如何解决在熊猫中更改多头/空头头寸的更有效方法

是否有比我在下面提出的更有效的方法来改变熊猫的多头/空头头寸?

逻辑要点:

  • 持仓为 np.nan,直到出现买入 (+1) 或卖出 (-1) 信号。
  • 第一次出现买入/卖出 (+/-1) 信号时,将头寸设置为该数字。
  • 设置第一个位置后,继续前进。仅在相同符号的情况下添加到位置。否则,更改符号并设置符号乘以 1(即,如果当前头寸为 3,然后您收到卖出 (-1) 信号,则头寸从 3 变为 -1。反之亦然,如果头寸为 -3 且有买入信号,仓位从 -3 变为 1)。

我的代码

import numpy as np
import pandas as pd

df = pd.DataFrame({
    'buy_sell': [np.nan,1,np.nan,-1,-1],'position': np.nan
})

for i,r,in df.iterrows():
    buy_sell = r['buy_sell']

    # Check if first index
    if i != 0:
        last_position = df.loc[i-1,'position']

        if np.isnan(buy_sell):
            df.loc[i,'position'] = last_position
        else:
            if np.isnan(last_position) or last_position * buy_sell <= 0:
                df.loc[i,'position'] = buy_sell
            else:
                df.loc[i,'position'] = last_position + buy_sell
    else:
        df.loc[i,'position'] = buy_sell

预期的解决方

df_expected = pd.DataFrame({
    'buy_sell': [np.nan,'position': [np.nan,2,3,-2,})
    buy_sell  position
0        NaN       NaN
1        1.0       1.0
2        NaN       1.0
3        1.0       2.0
4        NaN       2.0
5        NaN       2.0
6        1.0       3.0
7       -1.0      -1.0
8        NaN      -1.0
9       -1.0      -2.0
10       NaN      -2.0
11       1.0       1.0
12       NaN       1.0
13      -1.0      -1.0

注意:我上面的代码生成了预期的数据框。我在问是否有更有效/更好的方法来做我上面所做的。

解决方法

你可以这样做:

df["position"] = df.buy_sell.groupby(\
                      df.buy_sell.bfill()\
                      .diff()\
                      .abs()\
                      .cumsum()\
                 ).cumsum().ffill()
                 

输出

df
     buy_sell   position
0         NaN        NaN
1      1.0000     1.0000
2         NaN     1.0000
3      1.0000     2.0000
4         NaN     2.0000
5         NaN     2.0000
6      1.0000     3.0000
7     -1.0000    -1.0000
8         NaN    -1.0000
9     -1.0000    -2.0000
10        NaN    -2.0000
11     1.0000     1.0000
12        NaN     1.0000
13    -1.0000    -1.0000

说明

基本上,您需要某种 cumsum by group 由列中的符号更改创建的组,然后,首先我们需要找到这些更改:

>>> df.buy_sell.bfill().diff().abs()
0           NaN
1        0.0000
2        0.0000
3        0.0000
4        0.0000
5        0.0000
6        0.0000
7        2.0000
8        0.0000
9        0.0000
10       2.0000
11       0.0000
12       2.0000
13       0.0000

如您所见,每个 2 都是符号变化。现在,使用 pandas.Series.cumsum 我们可以为每一行分配一个组

>>> df.buy_sell.bfill().diff().abs().cumsum()
0           NaN
1        0.0000
2        0.0000
3        0.0000
4        0.0000
5        0.0000
6        0.0000
7        2.0000
8        2.0000
9        2.0000
10       4.0000
11       4.0000
12       6.0000
13       6.0000

所以,0 的每一行都是一个组,2 的每一行都是一个组,依此类推。有了这个,我们可以直接将 pandas.Series.groupbypandas.core.groupby.GroupBy.cumsum 一起使用:

>>> df.buy_sell.groupby(df.buy_sell.bfill().diff().abs().cumsum()).cumsum()
0           NaN
1        1.0000
2           NaN
3        2.0000
4           NaN
5           NaN
6        3.0000
7       -1.0000
8           NaN
9       -2.0000
10          NaN
11       1.0000
12          NaN
13      -1.0000

我们现在所需要做的就是使用 pandas.Series.ffill 将最后一个有效观察向前传播到下一个有效观察:

>>> df.buy_sell.groupby(df.buy_sell.bfill().diff().abs().cumsum()).cumsum().ffill()
0           NaN
1        1.0000
2        1.0000
3        2.0000
4        2.0000
5        2.0000
6        3.0000
7       -1.0000
8       -1.0000
9       -2.0000
10      -2.0000
11       1.0000
12       1.0000
13      -1.0000

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。