Логарифмический возврат в pandas dataframe

Python pandas имеет функцию pct_change, которую я использую для расчета возвратов цен на акции в фрейме данных:

ndf['Return']= ndf['TypicalPrice'].pct_change()

Я использую следующий код для получения логарифмических возвратов, но он дает те же самые значения, что и функция pct.change():

ndf['retlog']=np.log(ndf['TypicalPrice'].astype('float64')/ndf['TypicalPrice'].astype('float64').shift(1))
#np is for numpy

Ответ 1

Вот один из способов расчета возврата журнала с помощью .shift(). И результат аналогичен, но не такой, как валовой доход, рассчитанный pct_change(). Можете ли вы загрузить копию ваших образцов данных (ссылку на общий доступ к Dropbox), чтобы воспроизвести несогласованность, которую вы видели?

import pandas as pd
import numpy as np

np.random.seed(0)
df = pd.DataFrame(100 + np.random.randn(100).cumsum(), columns=['price'])
df['pct_change'] = df.price.pct_change()
df['log_ret'] = np.log(df.price) - np.log(df.price.shift(1))

Out[56]: 
       price  pct_change  log_ret
0   101.7641         NaN      NaN
1   102.1642      0.0039   0.0039
2   103.1429      0.0096   0.0095
3   105.3838      0.0217   0.0215
4   107.2514      0.0177   0.0176
5   106.2741     -0.0091  -0.0092
6   107.2242      0.0089   0.0089
7   107.0729     -0.0014  -0.0014
..       ...         ...      ...
92  101.6160      0.0021   0.0021
93  102.5926      0.0096   0.0096
94  102.9490      0.0035   0.0035
95  103.6555      0.0069   0.0068
96  103.6660      0.0001   0.0001
97  105.4519      0.0172   0.0171
98  105.5788      0.0012   0.0012
99  105.9808      0.0038   0.0038

[100 rows x 3 columns]

Ответ 2

Возвраты журнала - это просто естественный логарифм 1 плюс арифметический возврат. Итак, как насчет этого?

df['pct_change'] = df.price.pct_change()
df['log_return'] = np.log(1 + df.pct_change)

Ответ 3

Одиночная строка и только вычисление журналов один раз. Сначала преобразуйте в лог-пространство, затем возьмите 1-периодный diff.

np.log(df.price).diff()

Ответ 4

Результаты могут показаться похожими, но это происходит только из-за расширения Тейлора для логарифма. Так как log (1 + x) ~ x, результаты могут быть похожими.

Однако

Я использую следующий код для получения логарифмических возвратов, но он дает те же самые значения, что и функция pct.change().

не совсем корректно.

import pandas as pd

df = pd.DataFrame({'p': range(10)})

df['pct_change'] = df.pct_change()
df['log_stuff'] = \
    np.log(df['p'].astype('float64')/df['p'].astype('float64').shift(1))
df[['pct_change', 'log_stuff']].plot();

enter image description here

Ответ 5

@poulter7: Я не могу комментировать другие ответы, поэтому я отправляю его как новый ответ: будьте осторожны с

np.log(df.price).diff() 

так как это приведет к сбою для индексов, которые могут стать отрицательными, а также факторы риска, например. отрицательные процентные ставки. В этих случаях

np.log(df.price/df.price.shift(1)).dropna()

является предпочтительным и на основе моего опыта, как правило, более безопасного подхода. Он также оценивает логарифм только один раз.

Если вы используете +1 или -1, это зависит от порядка ваших временных рядов. Используйте -1 для нисходящего и +1 для восходящих дат - в обоих случаях сдвиг предоставляет предыдущее значение даты.