【问题标题】:Calculating price change & cumulative percentage change in price based on conditions on another column根据另一列的条件计算价格变化和价格的累积百分比变化
【发布时间】:2020-07-03 17:54:56
【问题描述】:

问题的背景是我正在尝试对交易策略进行回测,并随着时间的推移评估我的投资组合表现。我正在使用 Pandas DataFrame 来操作数据。

我使用

生成了虚拟数据
data = {'position': [1, 0, 0, 0, -1, 0, 0, 1, 0, 0], 
        'close': [10,25,30,25,22,20,21,16,11,20], 
        'close_position' : [10,25,30,25,22,22,22,16,11,20]}

df = pd.DataFrame(data = data)

输出df是

+-------+----------+------------+----------------+
| index | position | close      | close_position |
+-------+----------+------------+----------------+
|     0 |        1 |         10 |             10 |
|     1 |        0 |         25 |             25 |
|     2 |        0 |         30 |             30 |
|     3 |        0 |         25 |             25 |
|     4 |       -1 |         22 |             22 |
|     5 |        0 |         20 |             22 |
|     6 |        0 |         21 |             22 |
|     7 |        1 |         16 |             16 |
|     8 |        0 |         11 |             11 |
|     9 |       -1 |         20 |             20 |
+-------+----------+------------+----------------+

position 列告诉您何时入职。 1 代表买入,-1 代表卖出。

我首先在指数 0 分配 100 美元,其中价格由 close 表示,即10,当价格为 22 时我在指数 4 处出售,所以我的投资组合增加了 120%,这使我的投资金额达到 @ 987654329@。在指数56 上,我没有持仓,因此我的投资组合变化为0%,我将维持220 美元。

在指数7 我再次买入,但这次我没有使用 100 美元,而是使用 220 美元以收盘价买入16 并以20 卖出,从而将我的投资组合增加了 25%。现在我会拥有220 + 55 = 275

我使用下面的代码生成了列change,它告诉索引0 的价格变化和pct_change 计算相对于基准价格的百分比变化。我想根据position 列动态更改下面代码第 3 行中的基本价格,即df.close.iloc[0]。在索引 7 处,我想将第 3 行中的 df.close.iloc[0] 更改为 df.close.iloc[7] 并且我希望将 alloc 更改为 220,因为现在我将投资 220 美元,因为我将获得一个新职位。

下面代码的第 2 行也计算了相对于指数 0 的收盘价差,这在指数 6 之前很好,但从指数 7 开始,我想计算相对于指数 7 的价格差。

alloc = 100 # allocation amount
df['change_cumsum'] = df.close_position.diff().cumsum()
df['pct_change_cumsum'] = alloc + ((df.change_cumsum / df.close.iloc[0]) * alloc)

电流输出:

+-------+----------+-------+----------------+---------------+-------------------+
| index | position | close | close_position | change        | pct_change        |
+-------+----------+-------+----------------+---------------+-------------------+
|     0 |        1 |    10 |             10 | NaN           | NaN               |
|     1 |        0 |    25 |             25 | 15            | 250               |
|     2 |        0 |    30 |             30 | 20            | 300               |
|     3 |        0 |    25 |             25 | 15            | 250               |
|     4 |       -1 |    22 |             22 | 12            | 220               |
|     5 |        0 |    20 |             22 | 12            | 220               |
|     6 |        0 |    21 |             22 | 12            | 220               |
|     7 |        1 |    16 |             16 | 6             | 160               |
|     8 |        0 |    11 |             11 | 1             | 110               |
|     9 |        0 |    20 |             20 | 10            | 200               |
+-------+----------+-------+----------------+---------------+-------------------+

期望的输出:

+-------+----------+-------+----------------+---------------+-------------------+
| index | position | close | close_position | change.       | pct_change        |
+-------+----------+-------+----------------+---------------+-------------------+
|     0 |        1 |    10 |             10 |             0 |                 0 |
|     1 |        0 |    25 |             25 |            15 |               250 |
|     2 |        0 |    30 |             30 |            20 |               300 |
|     3 |        0 |    25 |             25 |            15 |               250 |
|     4 |       -1 |    22 |             22 |            12 |               220 |
|     5 |        0 |    20 |             22 |            12 |               220 |
|     6 |        0 |    21 |             22 |            12 |               220 |
|     7 |        1 |    16 |             16 |             0 |                220|
|     8 |        0 |    11 |             11 |            -5 |            151.25 |
|     9 |        0 |    20 |             20 |             4 |               275 |
+-------+----------+-------+----------------+---------------+-------------------+

【问题讨论】:

  • 我想我注意到您想要的输出不一致:您的列pct_change 是您分配位置百分比的变化。我想知道您对索引 7 的想法:您以 0% 的变化开始一个位置,但在索引 8 处,我希望看到 -31 而不是 151.25。这个专栏到底是关于什么的?
  • 如果我在指数 7 分配 220 美元,我将建立一个新头寸,在指数 7 时我的投资组合百分比变化为 0%,因此指数 7 的价值应该是 220(这是我的错误,我已经进行了编辑)。但是,如果您从 220 美元减少 -31%,那么您应该在索引 8 处获得 151.25 美元,这是正确的。
  • 好吧,现在说得通了!如果我有办法找到pct_change 而不需要change,你还能接受吗?
  • 是的,可以接受。

标签: python pandas dataframe


【解决方案1】:

这是我对您问题的解决方案:

首先我添加一个net_position 列来考虑您的累积位置。考虑到该仓位仅在第二天有效(收市时买入),我将其移动了 1

df['net_position'] = df.position.cumsum().shift().fillna(0)

那么计算您的投资价值的方法是计算每次收盘之间的百分比变化。通过将其乘以累积位置,您只考虑位置不为空时的变化。最后,在这个变化百分比上加一,得到一个相对变化,再做一个累加乘积,得到你投资的变化百分比。

df['change'] = (df.close.pct_change() * df.net_position + 1).cumprod() * alloc

    position    close   close_position  net_position    change
0   1           10      10              0.0 
1   0           25      25              1.0             250
2   0           30      30              1.0             300
3   0           25      25              1.0             250
4   -1          22      22              1.0             220
5   0           20      22              0.0             220
6   0           21      22              0.0             220
7   1           16      16              0.0             220
8   0           11      11              1.0             151.25
9   0           20      20              1.0             275

【讨论】:

  • 此解决方案不考虑分配金额,仅在初始分配为 100 美元时才有效。我在我的问题中使用了分配作为变量,我希望它在解决方案中被视为变量。
  • 如果我错了,请告诉我,但只需将 df['change_%'] 乘以 alloc 就是您想要的。 cumprod 假设您将通过之前的销售获得的资金完全再投资。无论原始 alloc 多少(例如尝试 200),它都有效。我编辑了我的答案。
  • 是的,这将通过 df['change_%'] 乘以分配来完成任务。
  • 答案末尾已经提到过,但没关系,我进行了编辑以直接考虑alloc
猜你喜欢
  • 2023-02-20
  • 2021-09-01
  • 2020-08-20
  • 2021-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-27
相关资源
最近更新 更多