Calculating price change & cumulative percentage change in price based on conditions on another column

守給你的承諾、 提交于 2021-01-29 17:00:34

问题


Background of the problem is I am trying to backtest a trading strategy and evaluate my portfolio performance over time. I am using Pandas DataFrame to manipulate the data.

I've generated dummy data using

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)

output df would be

+-------+----------+------------+----------------+
| 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 |
+-------+----------+------------+----------------+

Column position tells when to take a position. 1 represents buying & -1 represents selling.

I start by allocating say $100 at index 0 where price is represented by close i.e 10 & I sell at index 4 when price is 22 so my portfolio increases by 120% which takes my invested amount to 100 + 120 = 220. At index 5 & 6 I take no position therefore the change in my portfolio would be 0% and I would be maintaining $220.

At index 7 I buy again but this time instead of using $100 I use $220 to buy at close price 16 and sell at 20 thereby increasing my portfolio by 25%. Now I would have 220 + 55 = 275.

I've used the code below to generate column change which tells the change in price with respect to index 0 & pct_change calculates the percentage change from base price. I want to change the base price in line 3 of below code i.e. df.close.iloc[0] dynamically based on the column position. At index 7 I want to change df.close.iloc[0] in line 3 with df.close.iloc[7] & I want alloc to change to 220 since now I would be investing $220 as I would be taking a new position.

Line 2 of below code also takes difference in close price with respect to index 0, which is fine till index 6 but from index 7 onwards I want to compute difference in price with respect to index 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)

Current Output:

+-------+----------+-------+----------------+---------------+-------------------+
| 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               |
+-------+----------+-------+----------------+---------------+-------------------+

Desired Output:

+-------+----------+-------+----------------+---------------+-------------------+
| 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 |
+-------+----------+-------+----------------+---------------+-------------------+

回答1:


Here is my solution to your problem:

First I add a net_position column to consider your cumulative position. I shift it by 1 to take into account that the position is only effective the next day (bought when market is closed)

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

Then the way to calculate the value of your investment, is by computing the percentage change between each close. By multiplying this by the cumulative position, you only consider changes when the position is not null. Finally, you add one to this change percentage to obtain a relative change, and perform a cumulative product to get the percentage of change of your investment.

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


来源:https://stackoverflow.com/questions/62700953/calculating-price-change-cumulative-percentage-change-in-price-based-on-condit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!