Расчет совокупной доходности с помощью кадра данных pandas

У меня есть этот фрейм данных

Poloniex_DOGE_BTC   Poloniex_XMR_BTC    Daily_rets  perc_ret
172 0.006085    -0.000839   0.003309    0
173 0.006229    0.002111    0.005135    0
174 0.000000    -0.001651   0.004203    0
175 0.000000    0.007743    0.005313    0
176 0.000000    -0.001013   -0.003466   0
177 0.000000    -0.000550   0.000772    0
178 0.000000    -0.009864   0.001764    0

Я пытаюсь сделать текущую сумму daily_rets в perc_ret

однако мой код просто копирует значения из daily_rets

df['perc_ret'] = (  df['Daily_rets'] + df['perc_ret'].shift(1) )


Poloniex_DOGE_BTC   Poloniex_XMR_BTC    Daily_rets  perc_ret
172 0.006085    -0.000839   0.003309    NaN
173 0.006229    0.002111    0.005135    0.005135
174 0.000000    -0.001651   0.004203    0.004203
175 0.000000    0.007743    0.005313    0.005313
176 0.000000    -0.001013   -0.003466   -0.003466
177 0.000000    -0.000550   0.000772    0.000772
178 0.000000    -0.009864   0.001764    0.001764

person David Hancock    schedule 12.02.2016    source источник


Ответы (3)


Если важна производительность, используйте numpy.cumprod:

np.cumprod(1 + df['Daily_rets'].values) - 1

Время:

#7k rows
df = pd.concat([df] * 1000, ignore_index=True)

In [191]: %timeit np.cumprod(1 + df['Daily_rets'].values) - 1
41 µs ± 282 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [192]: %timeit (1 + df.Daily_rets).cumprod() - 1
554 µs ± 3.63 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
person jezrael    schedule 12.02.2016
comment
Этот ответ неверен. дробные доходы не могут быть просто сложены вместе, так как доход на завтра должен учитывать доход на сегодня. Смотрите ответ Александра ниже для правильного ответа. - person Valdemar; 24.03.2018
comment
@Valdemar - Согласен, поэтому изменил ответ. - person jezrael; 30.05.2019
comment
@EndreMoen - Можно ли опубликовать новый вопрос с примерами данных, ожидаемым результатом? Потому что я не знаю, что ты имеешь в виду - person jezrael; 18.12.2020

Если это ежедневные простые доходы, и вы хотите получить совокупный доход, конечно, вы должны хотеть ежедневное сложное число?

df['perc_ret'] = (1 + df.Daily_rets).cumprod() - 1  # Or df.Daily_rets.add(1).cumprod().sub(1)

>>> df
     Poloniex_DOGE_BTC  Poloniex_XMR_BTC  Daily_rets  perc_ret
172           0.006085         -0.000839    0.003309  0.003309
173           0.006229          0.002111    0.005135  0.008461
174           0.000000         -0.001651    0.004203  0.012700
175           0.000000          0.007743    0.005313  0.018080
176           0.000000         -0.001013   -0.003466  0.014551
177           0.000000         -0.000550    0.000772  0.015335
178           0.000000         -0.009864    0.001764  0.017126

Если они возвращаются из журнала, вы можете просто использовать cumsum.

person Alexander    schedule 12.02.2016

вы просто не можете просто добавить их все, используя cumsum

например, если у вас есть массив [1.1, 1.1], у вас должно быть 2.21, а не 2.2

import numpy as np

# daily return:
df['daily_return'] = df['close'].pct_change()

# calculate cumluative return
df['cumluative_return'] = np.exp(np.log1p(df['daily_return']).cumsum())
person Dong Yi    schedule 08.05.2017
comment
Нужно ли нам - 1 в конце для np.exp(np.log1p(df['daily_return']).cumsum()) ? - person Menglong Li; 10.04.2018
comment
да, правильная формула: np.exp(np.log1p(df['daily_return']).cumsum()) - 1 - person Ximix; 30.05.2018
comment
В качестве альтернативы используйте функцию np.expm1 напрямую. Точнее численно - person linello; 02.03.2021