我正在研究价格合理的数据框架。我发现返回计算的算术或日志与第一个价格值和最后一个值之间的实际回报不同。我认为它们应该是相同的或不同的小分数。
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
答案 0 :(得分:2)
我认为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位(相对于第一种方法为4%或绝对值为5.390295537921995e-05),但这种差异可能是由于存储时发生的精度问题浮动。
编辑:绘制复合权益
您在评论中说明了您想要绘制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()