python-3.x - pct_change 和 log 返回值与实际值不同

标签 python-3.x pandas dataframe financial

我正在处理带有价格的数据框。我发现算术或日志计算的返回与第一个价格值和最后一个价格之间的实际返回不同。在我看来,它们应该相同或有小部分不同。

dfset.head()
                       Open   Close    High     Low      Volume
Date_utc                                                       
2017-12-01 00:00:00  432.01  434.56  435.09  432.01  781.788110
2017-12-01 00:05:00  434.25  435.82  436.98  434.25  584.017105
2017-12-01 00:10:00  435.81  435.50  436.39  434.80  494.047392
2017-12-01 00:15:00  435.88  435.10  436.07  434.50  527.840340
2017-12-01 00:20:00  434.51  433.50  434.95  432.98  458.557971


dfset.tail()
                       Open   Close    High     Low       Volume
Date_utc                                                        
2017-12-21 23:40:00  781.41  781.01  783.46  778.12   792.433089
2017-12-21 23:45:00  779.60  784.76  784.90  778.20   657.316066
2017-12-21 23:50:00  784.83  783.42  784.90  782.22   473.108867
2017-12-21 23:55:00  783.40  786.98  787.00  782.62  1492.764405
2017-12-22 00:00:00  786.96  791.93  792.00  786.86  1745.559100

通过以下方式计算返回时:
dfset['Close'].pct_change().sum()
0.694478597676

或使用日志返回:
np.log(dfset['Close'] / dfset['Close'].shift(1)).sum()
0.60013897914

我认为正确的实际总体返回:
dfset['Close'].iloc[len(dfset) - 1] / dfset['Close'].iloc[0] - 1
0.822372054492

任何想法请为什么算术和日志返回关闭?
INSTALLED VERSIONS
------------------
commit: None
python: 3.6.3.final.0
python-bits: 64
OS: Darwin
OS-release: 16.7.0
machine: x86_64
processor: i386
byteorder: little
LC_ALL: None
LANG: None
LOCALE: None.None

pandas: 0.21.1
pytest: 3.2.1
pip: 9.0.1
setuptools: 36.5.0.post20170921
Cython: 0.26.1
numpy: 1.13.3
scipy: 0.19.1
pyarrow: None
xarray: None
IPython: 6.1.0
sphinx: 1.6.3
patsy: 0.4.1
dateutil: 2.6.1
pytz: 2017.2
blosc: None
bottleneck: 1.2.1
tables: 3.4.2
numexpr: 2.6.2
feather: None
matplotlib: 2.1.0
openpyxl: 2.4.8
xlrd: 1.1.0
xlwt: 1.2.0
xlsxwriter: 1.0.2
lxml: 4.1.0
bs4: 4.6.0
html5lib: 0.999999999
sqlalchemy: 1.1.13
pymysql: None
psycopg2: None
jinja2: 2.9.6
s3fs: None
fastparquet: None
pandas_gbq: None
pandas_datareader: 0.5.0
None

最佳答案

我认为这 3 个操作是完全不同的。我只会把尾部展示出来。

首先:

print( dfset['Close'].pct_change()) 

2017-12-21         NaN
2017-12-21    0.004801
2017-12-21   -0.001708
2017-12-21    0.004544
2017-12-22    0.006290
Name: Close, dtype: float64

相当于做:
print(dfset['Close'].diff()/dfset['Close'].shift(1))

2017-12-21         NaN
2017-12-21    0.004801
2017-12-21   -0.001708
2017-12-21    0.004544
2017-12-22    0.006290
Name: Close, dtype: float64

所以它们的总和是相等的:
print((dfset['Close'].diff()/dfset['Close'].shift(1)).sum())
0.013927992282837915

然后我看不到重点:
np.log(dfset['Close'] / dfset['Close'].shift(1))

等于 pct_change .
print(np.log(dfset['Close'] / dfset['Close'].shift(1)))

2017-12-21         NaN
2017-12-21    0.004790
2017-12-21   -0.001709
2017-12-21    0.004534
2017-12-22    0.006270
Name: Close, dtype: float64

结果是相似的,因为没有减 1 也没有指数。但这并不能使它在数学上正确。

通常,为了避免除法,我会取对数并减去它们,然后返回指数。无论如何,复制pct_change :
print(np.log((dfset['Close'] / dfset['Close'].shift(1))-1).apply(np.exp))
2017-12-21         NaN
2017-12-21    0.004801
2017-12-21         NaN
2017-12-21    0.004544
2017-12-22    0.006290
Name: Close, dtype: float64

print((np.log(dfset['Close'].diff()) -  np.log(dfset['Close'].shift(1))).apply(np.exp))

2017-12-21         NaN
2017-12-21    0.004801
2017-12-21         NaN
2017-12-21    0.004544
2017-12-22    0.006290
Name: Close, dtype: float64

在任何情况下,使用对数都会为负值返回 NaN。

所以元素的总和与使用pct_change不同:
print((np.log(dfset['Close'].diff()) -  np.log(dfset['Close'].shift(1))).apply(np.exp).sum())

0.015635520699169063

最后,最后一个匹配第一个(注意,不是使用 .iloc[len(dfset) - 1] 来查找最后一个元素,您可以执行 .iloc[- 1] ):
print(dfset['Close'].iloc[-1] / dfset['Close'].iloc[0] - 1)

0.013981895238217135

第一种方法和这个方法之间的第 5 位小数存在差异(相对于第一种或绝对值 5.390295537921995e-05 的 4%),但这种差异可能是由于存储浮点数时发生的精度问题。

编辑:绘制复利

您在评论中解释说要绘制 cumsum这就是与总变化 dfset['Close'].iloc[-1] / dfset['Close'].iloc[0] - 1 的不同之处。 .

背后的原因是日期范围内百分比变化的累积总和不等于区间 的第一个元素和最后一个元素之间的百分比变化.

为此,您必须使用 compound interest , 这是一个计算时间步之间连续变化时总增量的公式 .这样,使用 csv 根据您的评论,您将通过执行以下操作来匹配第一天和最后一天之间的变化:
print(((dfset['Close'].pct_change(axis=0)+1).cumprod()-1).iloc[-1])

0.8223720544918787

import matplotlib.pyplot as plt
((dfset['Close'].pct_change(axis=0)+1).cumprod()-1).plot()
plt.show()

enter image description here

关于python-3.x - pct_change 和 log 返回值与实际值不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49005742/

相关文章:

python - 刷新包含下载百分比的输出行

python-3.x - 当列数未知时,替换 Pandas Dataframe 中特定列中的值

python - 按跨年份的日历周分组

python - 将 float64 列转换为日期时间 Pandas

python - Pandas groupby 列并乘以聚合函数中的其他两列

python - 与 Pandas 合并后设置索引?

python-3.x - 在多个列表中查找经常出现的单词

python - 运算符//= 和::做什么?

python - 当需要计算数据帧列时使用 dask 进行并行计算

R:data.frame 中的 ne-name 因子值