赞
踩
时间是阻止所有事情同时发生的力量。——雷•卡明斯
本节使用的是以CSV文件形式在本地存储的金融数据集形式为本地存储的CSV文件。从技术上讲,CSV文件是包含数据行结构的文本文件,其特征是以逗号分隔单个值。在导入数据之前,导入一些软件包并进行定制:
In [1]: import numpy as np import pandas as pd from pylab import mpl, plt plt.style.use('seaborn') mpl.rcParams['font.family'] = 'serif' %matplotlib inline
pandas提供不同的函数和DataFrame方法,以导入不同存储格式(CSV、SQL、Excel等)的数据,并将数据导出为不同格式(详见第9章)。下面的代码通过pd.read_csv()函数导入CSV[1]文件中的时间序列数据:
In [2]: filename = '../../source/tr_eikon_eod_data.csv' ❶ In [3]: f = open(filename, 'r') ❷ f.readlines()[:5] ❷ Out[3]: ['Date,AAPL.O,MSFT.O,INTC.O,AMZN.O,GS.N,SPY,.SPX,.VIX,EUR=,XAU=,GDX, ,GLD\n', '2010-01-01,,,,,,,,,1.4323,1096.35,,\n', '2010-01-04,30.57282657,30.95,20.88,133.9,173.08,113.33,1132.99,20.04, ,1.4411,1120.0,47.71,109.8\n', '2010-01-05,30.625683660000004,30.96,20.87,134.69,176.14,113.63,1136.52, ,19.35,1.4368,1118.65,48.17,109.7\n', '2010-01-06,30.138541290000003,30.77,20.8,132.25,174.26,113.71,1137.14, ,19.16,1.4412,1138.5,49.34,111.51\n'] In [4]: data = pd.read_csv(filename, ❸ index_col=0, ❹ parse_dates=True) ❺ In [5]: data.info() ❻ <class 'pandas.core.frame.DataFrame'> DatetimeIndex: 2216 entries, 2010-01-01 to 2018-06-29 Data columns (total 12 columns): AAPL.O 2138 non-null float64 MSFT.O 2138 non-null float64 INTC.O 2138 non-null float64 AMZN.O 2138 non-null float64 GS.N 2138 non-null float64 SPY 2138 non-null float64 .SPX 2138 non-null float64 .VIX 2138 non-null float64 EUR= 2216 non-null float64 XAU= 2211 non-null float64 GDX 2138 non-null float64 GLD 2138 non-null float64 dtypes: float64(12) memory usage: 225.1 KB
❶ 指定路径和文件名。
❷ 显示原始数据(Linux/Mac)的前5行。
❸ 传递给pd.read_scv()函数的文件名。
❹ 指定第一列作为索引处理。
❺ 指定索引值为datetime类型。
❻ 结果为DataFrame对象。
在这一阶段,金融分析师可能首先观察数据,对其进行检查或者可视化(见图8-1):
In [6]: data.head() ❶ Out[6]: AAPL.O MSFT.O INTC.O AMZN.O GS.N SPY .SPX .VIX \ Date 2010-01-01 NaN NaN NaN NaN NaN NaN NaN NaN 2010-01-04 30.572827 30.950 20.88 133.90 173.08 113.33 1132.99 20.04 2010-01-05 30.625684 30.960 20.87 134.69 176.14 113.63 1136.52 19.35 2010-01-06 30.138541 30.770 20.80 132.25 174.26 113.71 1137.14 19.16 2010-01-07 30.082827 30.452 20.60 130.00 177.67 114.19 1141.69 19.06 EUR= XAU= GDX GLD Date 2010-01-01 1.4323 1096.35 NaN NaN 2010-01-04 1.4411 1120.00 47.71 109.80 2010-01-05 1.4368 1118.65 48.17 109.70 2010-01-06 1.4412 1138.50 49.34 111.51 2010-01-07 1.4318 1131.90 49.10 110.82 In [7]: data.tail() ❷ Out[7]: AAPL.O MSFT.O INTC.O AMZN.O GS.N SPY .SPX.VIX \ Date 2018-06-25 182.17 98.39 50.71 1663.15 221.54 271.00 2717.07 17.33 2018-06-26 184.43 99.08 49.67 1691.09 221.58 271.60 2723.06 15.92 2018-06-27 184.16 97.54 48.76 1660.51 220.18 269.35 2699.63 17.91 2018-06-28 185.50 98.63 49.25 1701.45 223.42 270.89 2716.31 16.85 2018-06-29 185.11 98.61 49.71 1699.80 220.57 271.28 2718.37 16.09 EUR= XAU= GDX GLD Date 2018-06-25 1.1702 1265.00 22.01 119.89 2018-06-26 1.1645 1258.64 21.95 119.26 2018-06-27 1.1552 1251.62 21.81 118.58 2018-06-28 1.1567 1247.88 21.93 118.22 2018-06-29 1.1683 1252.25 22.31 118.65 In [8]: data.plot(figsize=(10, 12), subplots=True); ❸
图8-1 以线图表示的金融时间序列数据
❶ 前5行。
❷最后5行显示。
❸ 这个语句通过多个子图来可视化整个数据集。
这里使用的数据来自Thomson Reuters (TR) Eikon Data API。TR金融工具代码称作路透金融工具代码(RIC)。RIC表示的金融工具为:
In [9]: instruments = ['Apple Stock', 'Microsoft Stock', 'Intel Stock', 'Amazon Stock', 'Goldman Sachs Stock', 'SPDR S&P 500 ETF Trust', 'S&P 500 Index', 'VIX Volatility Index', 'EUR/USD Exchange Rate', 'Gold Price', 'VanEck Vectors Gold Miners ETF', 'SPDR Gold Trust'] In [10]: for ric, name in zip(data.columns, instruments): print('{:8s} | {}'.format(ric, name)) AAPL.O | Apple Stock MSFT.O | Microsoft Stock INTC.O | Intel Stock AMZN.O | Amazon Stock GS.N | Goldman Sachs Stock SPY | SPDR S&P 500 ETF Trust .SPX | S&P 500 Index .VIX | VIX Volatility Index EUR= | EUR/USD Exchange Rate XAU= | Gold Price GDX | VanEck Vectors Gold Miners ETF GLD | SPDR Gold Trust
金融分析师采取的下一个步骤是观察不同的数据集汇总统计,从而对其有个总体的“感觉”:
In [11]: data.info() ❶ <class 'pandas.core.frame.DataFrame'> DatetimeIndex: 2216 entries, 2010-01-01 to 2018-06-29 Data columns (total 12 columns): AAPL.O 2138 non-null float64 MSFT.O 2138 non-null float64 INTC.O 2138 non-null float64 AMZN.O 2138 non-null float64 GS.N 2138 non-null float64 SPY 2138 non-null float64 .SPX 2138 non-null float64 .VIX 2138 non-null float64 EUR= 2216 non-null float64 XAU= 2211 non-null float64 GDX 2138 non-null float64 GLD 2138 non-null float64 dtypes: float64(12) memory usage: 225.1 KB In [12]: data.describe().round(2) ❷ Out[12]: AAPL.O MSFT.O INTC.O AMZN.O GS.N SPY .SPX .VIX \ Count 2138.00 2138.00 2138.00 2138.00 2138.00 2138.00 2138.00 2138.00 mean 93.46 44.56 29.36 480.46 170.22 180.32 1802.71 17.03 std 40.55 19.53 8.17 372.31 42.48 48.19 483.34 5.88 min 27.44 23.01 17.66 108.61 87.70 102.20 1022.58 9.14 25% 60.29 28.57 22.51 213.60 146.61 133.99 1338.57 13.07 50% 90.55 39.66 27.33 322.06 164.43 186.32 1863.08 15.58 75% 117.24 54.37 34.71 698.85 192.13 210.99 2108.94 19.07 max 193.98 102.49 57.08 1750.08 273.38 286.58 2872.87 48.00 EUR= XAU= GDX GLD count 2216.00 2211.00 2138.00 2138.00 mean 1.25 1349.01 33.57 130.09 std 0.11 188.75 15.17 18.78 min 1.04 1051.36 12.47 100.50 25% 1.13 1221.53 22.14 117.40 50% 1.27 1292.61 25.62 124.00 75% 1.35 1428.24 48.34 139.00 max 1.48 1898.99 66.63 184.59
❶ info()给出DataFrame对象的相关元信息。
❷ describe()提供每列的实用标准统计量。
敏锐的洞察力
pandas提供了许多方法如info和describe(),可以获得新导入的金融时间序列数据集的简单概况。它们还能快捷地检查导入程序是否按照要求进行(例如,DataFrame对象是否真正包含DatetimeIndex类型的索引)。
当然,pandas也提供自定义统计类型及显示方式的选项:
In [13]: data.mean() ❶ Out[13]: AAPL.O 93.455973 MSFT.O 44.561115 INTC.O 29.364192 AMZN.O 480.461251 GS.N 170.216221 SPY 180.323029 .SPX 1802.713106 .VIX 17.027133 EUR= 1.248587 XAU= 1349.014130 GDX 33.566525 GLD 130.086590 dtype: float64 In [14]: data.aggregate([min, ❷ np.mean, ❸ np.std, ❹ np.median, ❺ max] ❻ ).round(2) Out[14]: AAPL.O MSFT.O INTC.O AMZN.O GS.N SPY .SPX.VIX EUR= \ min 27.44 23.01 17.66 108.61 87.70 102.20 1022.58 9.14 1.04 mean 93.46 44.56 29.36 480.46 170.22 180.32 1802.71 17.03 1.25 std 40.55 19.53 8.17 372.31 42.48 48.19 483.34 5.88 0.11 median 90.55 39.66 27.33 322.06 164.43 186.32 1863.08 15.58 1.27 max 193.98 102.49 57.08 1750.08 273.38 286.58 2872.87 48.00 1.48 XAU= GDX GLD min 1051.36 12.47 100.50 mean 1349.01 33.57 130.09 std 188.75 15.17 18.78 median 1292.61 25.62 124.00 max 1898.99 66.63 184.59
❶ 每列均值。
❷ 每列最小值。
❸ 每列均值。
❹ 每列标准差。
❺ 每列中位数。
❻ 每列最大值。
使用aggregate方法还可以传递自定义函数。
统计分析方法往往基于随时间推移的变化,而不是绝对值。计算时间序列中的随时变化有多种选择,包括绝对偏差、变化率和对数回报率。
首先介绍绝对偏差,pandas为此提供了一个特殊的方法:
In [15]: data.diff().head() ❶ Out[15]: AAPL.O MSFT.O INTC.O AMZN.O GS.N SPY .SPX .VIX EUR= \ Date 2010-01-01 NaN NaN NaN NaN NaN NaN NaN NaN NaN 2010-01-04 NaN NaN NaN NaN NaN NaN NaN NaN 0.0088 2010-01-05 0.052857 0.010 -0.01 0.79 3.06 0.30 3.53 -0.69 -0.0043 2010-01-06 -0.487142 -0.190 -0.07 -2.44 -1.88 0.08 0.62 -0.19 0.0044 2010-01-07 -0.055714 -0.318 -0.20 -2.25 3.41 0.48 4.55 -0.10 -0.0094 XAU= GDX GLD Date 2010-01-01 NaN NaN NaN 2010-01-04 23.65 NaN NaN 2010-01-05 -1.35 0.46 -0.10 2010-01-06 19.85 1.17 1.81 2010-01-07 -6.60 -0.24 -0.69 In [16]: data.diff().mean() ❷ Out[16]: AAPL.O 0.064737 MSFT.O 0.031246 INTC.O 0.013540 AMZN.O 0.706608 GS.N 0.028224 SPY 0.072103 .SPX 0.732659 .VIX -0.019583 EUR= -0.000119 XAU= 0.041887 GDX -0.015071 GLD -0.003455 dtype: float64
❶ diff提供两个索引值之间的绝对变化。
❷ 当然,还可以应用聚合运算。
从统计学角度讲,绝对变化不是最优的,因为它们与时间序列数据本身的比例相关。因此,我们通常更偏重变化率。下面的代码可以计算金融环境里的变动率或者回报率(也称为简单回报率),并对其每列的平均值进行可视化(参见图8-2):
In [17]: data.pct_change().round(3).head() ❶ Out[17]: AAPL.O MSFT.O INTC.O AMZN.O GS.N SPY .SPX .VIX EUR= \ Date 2010-01-01 NaN NaN NaN NaN NaN NaN NaN NaN NaN 2010-01-04 NaN NaN NaN NaN NaN NaN NaN NaN 0.006 2010-01-05 0.002 0.000 -0.000 0.006 0.018 0.003 0.003 -0.034 -0.003 2010-01-06 -0.016 -0.006 -0.003 -0.018 -0.011 0.001 0.001 -0.010 0.003 2010-01-07 -0.002 -0.010 -0.010 -0.017 0.020 0.004 0.004 -0.005 -0.007 XAU= GDX GLD Date 2010-01-01 NaN NaN NaN 2010-01-04 0.022 NaN NaN 2010-01-05 -0.001 0.010 -0.001 2010-01-06 0.018 0.024 0.016 2010-01-07 -0.006 -0.005 -0.006 In [18]: data.pct_change().mean().plot(kind='bar', figsize=(10, 6)); ❷
❶ pct_change()计算两个索引值之间的变化率。
❷ 将结果的均值可视化为一个柱状图。
图8-2 变化率均值柱状图
对数回报率可作为回报率的替代品。在某些情况下,它们更容易处理,因此在金融环境中往往优先使用对数回报率。[2]
图8-3展示了单个金融时间序列的累计对数回报率。这种类型的图表导致了某种形式的规范化:
图8-3 一段时间的累计对数回报率
In [19]: rets = np.log(data / data.shift(1))❶ In [20]: rets.head().round(3) ❷ Out[20]: AAPL.O MSFT.O INTC.O AMZN.O GS.N SPY .SPX .VIX EUR= \ Date 2010-01-01 NaN NaN NaN NaN NaN NaN NaN NaN NaN 2010-01-04 NaN NaN NaN NaN NaN NaN NaN NaN 0.006 2010-01-05 0.002 0.000 -0.000 0.006 0.018 0.003 0.003 -0.035 -0.003 2010-01-06 -0.016 -0.006 -0.003 -0.018 -0.011 0.001 0.001 -0.010 0.003 2010-01-07 -0.002 -0.010 -0.010 -0.017 0.019 0.004 0.004 -0.005 -0.007 XAU= GDX GLD Date 2010-01-01 NaN NaN NaN 2010-01-04 0.021 NaN NaN 2010-01-05 -0.001 0.010 -0.001 2010-01-06 0.018 0.024 0.016 2010-01-07 -0.006 -0.005 -0.006 In [21]: rets.cumsum().apply(np.exp).plot(figsize=(10, 6)); ❸
❶ 以向量的方式计算对数回报率。
❷ 结果的一个子集。
❸ 绘制一段时间的累计对数回报率图表;首先调用cumsum()方法,然后对结果应用np.exp()。
重新采样是金融时间序列数据的重要操作之一,通常采用向下采样的形式,例如,分笔交易数据序列重新采样的时间间隔为一分钟,也可以将每日观察数据的时间序列重新采样为每周或者每月观察数据(如图8-4所示):
In [22]: data.resample('1w', label='right').last().head() ❶ Out[22]: AAPL.O MSFT.O INTC.O AMZN.O GS.N SPY .SPX .VIX \ Date 2010-01-03 NaN NaN NaN NaN NaN NaN NaN NaN 2010-01-10 30.282827 30.66 20.83 133.52 174.31 114.57 1144.98 18.13 2010-01-17 29.418542 30.86 20.80 127.14 165.21 113.64 1136.03 17.91 2010-01-24 28.249972 28.96 19.91 121.43 154.12 109.21 1091.76 27.31 2010-01-31 27.437544 28.18 19.40 125.41 148.72 107.39 1073.87 24.62 EUR= XAU= GDX GLD Date 2010-01-03 1.4323 1096.35 NaN NaN 2010-01-10 1.4412 1136.10 49.84 111.37 2010-01-17 1.4382 1129.90 47.42 110.86 2010-01-24 1.4137 1092.60 43.79 107.17 2010-01-31 1.3862 1081.05 40.72 105.96 In [23]: data.resample('1m', label='right').last().head() ❷ Out[23]: AAPL.O MSFT.O INTC.O AMZN.O GS.N SPY .SPX \ Date 2010-01-31 27.437544 28.1800 19.40 125.41 148.72 107.3900 1073.87 2010-02-28 29.231399 28.6700 20.53 118.40 156.35 110.7400 1104.49 2010-03-31 33.571395 29.2875 22.29 135.77 170.63 117.0000 1169.43 2010-04-30 37.298534 30.5350 22.84 137.10 145.20 118.8125 1186.69 2010-05-31 36.697106 25.8000 21.42 125.46 144.26 109.3690 1089.41 .VIX EUR= XAU= GDX GLD Date 2010-01-31 24.62 1.3862 1081.05 40.72 105.960 2010-02-28 19.50 1.3625 1116.10 43.89 109.430 2010-03-31 17.59 1.3510 1112.80 44.41 108.950 2010-04-30 22.05 1.3295 1178.25 50.51 115.360 2010-05-31 32.07 1.2305 1215.71 49.86 118.881 In [24]: rets.cumsum().apply(np.exp). resample('1m', label='right').last( ).plot(figsize=(10, 6)); ❸
❶ 日终数据以一周为时间间隔重新采样。
❷ 以一月为时间间隔重新采样。
❸ 这就绘制了随时间变化的累计对数回报率图表:首先调用cumsun(),然后对结果应用np.exp,最后进行重新采样。
图8-4 重采样的累计对数回报率图表(每月)
避免预见偏差
在很多情况下,pandas在重新采样时默认使用区间的左侧标签(或者索引值)。为了在金融业务中保持一致,请确保使用右标签(索引值)——一般是区间内最后一个可用数据点。否则,金融分析中可能潜藏着预见偏差。
本文摘自《Python金融大数据分析 第2版》
《Python金融大数据分析 第2版》分为5部分,共21章。第1部分介绍了Python在金融学中的应用,其内容涵盖了Python用于金融行业的原因、Python的基础架构和工具,以及Python在计量金融学中的一些具体入门实例;第2部分介绍了Python的基础知识以及Python中非常有名的库NumPy和pandas工具集,还介绍了面向对象编程;第3部分介绍金融数据科学的相关基本技术和方法,包括数据可视化、输入/输出操作和数学中与金融相关的知识等;第4部分介绍Python在算法交易上的应用,重点介绍常见算法,包括机器学习、深度神经网络等人工智能相关算法;第5部分讲解基于蒙特卡洛模拟开发期权及衍生品定价的应用,其内容涵盖了估值框架的介绍、金融模型的模拟、衍生品的估值、投资组合的估值等知识。
《Python金融大数据分析 第2版》本书适合对使用Python进行大数据分析、处理感兴趣的金融行业开发人员阅读。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。