Python 金融交易实用指南(二)(3)https://developer.aliyun.com/article/1523758
写入 CSV 文件
使用 pandas.DataFrame.to_csv(...)
方法可以轻松将 pandas DataFrame 写入 CSV 文件。header=
参数控制是否将标题写入文件顶部,而 index=
参数控制是否将索引轴值写入文件:
df.to_csv('df.csv', sep=',', header=True, index=True)
我们可以使用以下 Linux 命令检查写入磁盘的文件。!
字符指示笔记本运行一个 shell 命令:
!head -n 4 df.csv
文件包含以下行:
,A,B,C,D,E 4,-0.6329164608486778,0.3733235944037599,0.8225354680198685,-0.5171618315489593,0.5492241692404063 17,0.7664860447792711,0.8427366352142621,0.9621402130525599,-0.41134468872009666,-0.9704305306626816 24,-0.22976016405853183,0.38081314413811984,-1.526376189972014,0.07229102135441286,-0.3297356221604555
读取 CSV 文件
使用 pandas.read_csv(...)
方法可以读取 CSV 文件并构建一个 pandas DataFrame。在这里,我们将指定字符(虽然这是 read_csv
的默认值),index_col=
参数来指定哪一列作为 DataFrame 的索引,以及 nrows=
参数来指定要读取的行数:
pd.read_csv('df.csv', sep=',', index_col=0, nrows=5)
这构建了以下 DataFrame,该 DataFrame 与写入磁盘的相同:
A B C D E 4 -0.632916 0.373324 0.822535 -0.517162 0.549224 17 0.766486 0.842737 0.962140 -0.411345 -0.970431 24 -0.229760 0.380813 -1.526376 0.072291 -0.329736 33 0.662259 -1.457732 -2.268573 0.332456 0.496143 33 0.335710 0.452842 -0.977736 0.677470 1.164602
我们还可以指定 chunksize=
参数,该参数一次读取指定数量的行,这在探索非常大的文件中包含的非常大的数据集时会有所帮助:
pd.read_csv('df.csv', sep=',', index_col=0, chunksize=2)
这将返回一个 pandas TextFileReader
生成器,我们可以根据需要迭代它,而不是一次加载整个文件:
<pandas.io.parsers.TextFileReader at 0x7fb4e9933a90>
我们可以通过将生成器包装在列表中来强制生成器完成评估,并观察按两行一组加载的整个 DataFrame:
list(pd.read_csv('df.csv', sep=',', index_col=0, chunksize=2))
这给我们带来了以下两行块的列表:
[ A B C D E 4 -0.632916 0.373324 0.822535 -0.517162 0.549224 17 0.766486 0.842737 0.962140 -0.411345 -0.970431, A B C D E 24 -0.229760 0.380813 -1.526376 0.072291 -0.329736 33 0.662259 -1.457732 -2.268573 0.332456 0.496143, ...
现在我们将看看如何探索 JSON 文件中的文件操作。
JSON 文件
JSON 文件基于与 Python 字典相同的数据结构。这使得 JSON 文件非常方便,可用于许多目的,包括表示 DataFrames 和表示配置文件。
pandas.DataFrame.to_json(...)
方法方便地将 DataFrame 写入磁盘上的 JSON 文件。在这里,我们只写入了前四行:
df.iloc[:4].to_json('df.json')
让我们来看看写入磁盘的 JSON 文件:
!cat df.json
这样我们就得到了以下写入磁盘的字典样式 JSON 文件:
{"A":{"4":-0.6329164608,"17":0.7664860448,"24":-0.2297601641,"33":0.6622594878},"B":{"4":0.3733235944,"17":0.8427366352,"24":0.3808131441,"33":-1.4577321521},"C":{"4":0.822535468,"17":0.9621402131,"24":-1.52637619,"33":-2.2685732447},"D":{"4":-0.5171618315,"17":-0.4113446887 ,"24":0.0722910214,"33":0.3324557226},"E":{"4":0.5492241692 ,"17":-0.9704305307,"24":-0.3297356222,"33":0.4961425281}}
使用pandas.read_json(...)
方法将 JSON 文件读回到 Pandas DataFrames 中同样很容易:
pd.read_json('df.json')
这样我们就能得到原始的写入磁盘的四行 DataFrame:
A B C D E 4 -0.632916 0.373324 0.822535 -0.517162 0.549224 17 0.766486 0.842737 0.962140 -0.411345 -0.970431 24 -0.229760 0.380813 -1.526376 0.072291 -0.329736 33 0.662259 -1.457732 -2.268573 0.332456 0.496143
恭喜成功完成本课程!
总结
本章介绍了 pandas 库,几乎所有 Python 中的时间序列操作都是基于它完成的。我们已经学会了如何创建 DataFrame,如何修改它以及如何持久化它。
Pandas DataFrames 主要用于高性能的大规模数据操作、选择和重塑数据。它们是 Python 版本的 Excel 工作表。
在下一章中,我们将使用 Matplotlib 在 Python 中进行可视化探索。
第五章:使用 Matplotlib 进行数据可视化
数据可视化比阅读纯数字表格更容易理解数值数据。即时获取数据洞察力和识别模式、趋势和异常值是绘图库的主要用途。
在决定哪些股票可能适合哪些算法交易策略时,创建股票价格图是第一步——某些策略仅适用于趋势股票,某些策略适用于均值回归股票等等。虽然数值统计数据至关重要,但设计良好的图表是无法替代的。
本章向我们介绍了 Matplotlib,这是一个静态、动画和交互式的 Python 可视化库,扩展了 NumPy 的功能。pandas
库允许直接使用 Matplotlib 绘制 DataFrame 图表。
本章涵盖了以下主要主题:
- 创建图和子图
- 使用颜色、标记和线型丰富图表
- 通过刻度、标签和图例丰富坐标轴
- 使用注释丰富数据点
- 将图保存到文件中
- 使用 Matplotlib 绘制
pandas
DataFrame
技术要求
本章中使用的 Python 代码可在该书代码库中的 Chapter05/matplotlib.ipynb
笔记本中找到。
创建图和子图
Matplotlib 支持在单个图中绘制多个图表(子图),这是 Matplotlib 对绘图画布的术语。
定义图的子图
要创建一个 matplotlib.pyplot.figure
对象,请使用以下方法:
import matplotlib.pyplot as plt fig = plt.figure(figsize=(12, 6), dpi=200)
这会生成一个空的图形对象(0 Axes
):
<Figure size 2400x1200 with 0 Axes>
在我们在这个图上绘制任何东西之前,我们需要添加子图以为它们创建空间。matplotlib.pyplot.figure.add_subplot(...)
方法让我们通过指定子图的大小和位置来做到这一点。
下面的代码块在左侧添加了一个大小为 1x2 的子图,然后在右上方添加了一个 2x2 的子图,最后在右下方添加了一个 2x2 的子图:
ax1 = fig.add_subplot(1, 2, 1) ax2 = fig.add_subplot(2, 2, 2) ax3 = fig.add_subplot(2, 2, 4) fig
结果是以下图形对象,其中包含我们刚刚添加的子图:
图 5.1 – 包含三个空子图的图
现在,一旦我们创建了图表的空间("plots"
/"subplots"
),我们就可以用可视化数据填充它们。在所有报告中,页面上的物理空间都非常昂贵,因此创建像前面的图表是最佳实践。
在子图中绘图
让我们使用 numpy.linspace(...)
在 x 轴上生成均匀间隔的值,然后使用 numpy.square(...)
、numpy.sin(...)
和 numpy.cos(...)
方法在 y 轴上生成相应的值。
我们将使用从添加子图中获得的 ax1
、ax2
和 ax3
轴变量来绘制这些函数:
import numpy as np x = np.linspace(0, 1, num=20) y1 = np.square(x) ax1.plot(x, y1, color='black', linestyle='--') y2 = np.sin(x) ax2.plot(x, y2, color='black', linestyle=':') y3 = np.cos(x) ax3.plot(x, y3, color='black', linestyle='-.') fig
现在,以下图包含了我们刚刚绘制的值:
图 5.2 - 包含三个子图绘制平方、正弦和余弦函数的图
创建子图时,可以传递sharex=
参数,以指定所有子图应共享相同的x轴。
让我们演示这个功能并绘制平方,然后使用numpy.power(...)
方法将x
提高到 10 次方,并使用相同的x轴绘制它们:
fig, (ax1, ax2) = plt.subplots(2, figsize=(12, 6), sharex=True) ax1.plot(x, y1, color='black', linestyle='--') y2 = np.power(x, 10) ax2.plot(x, y2, color='black', linestyle='-.')
结果是以下带有共享x轴和不同函数绘制在每个图表上的图:
图 5.3 - 共享 x 轴的子图,包含平方和取 10 次方函数
我们生成的图表还不够自解释 - 尚不清楚x轴和y轴上的单位是什么,以及每个图表代表什么。为了改进图表,我们需要用颜色、标记和线型来丰富它们,用刻度、图例和标签来丰富轴,并提供选定数据点的注释。
用颜色、标记和线型丰富图表
颜色、标记和线型使图表更易于理解。
接下来的代码块绘制了四个不同的函数,并使用以下参数修改外观:
color=
参数用于分配颜色。linewidth=
参数用于更改线的宽度/粗细。marker=
参数分配不同形状来标记数据点。markersize=
参数改变了这些标记的大小。alpha=
参数用于修改透明度。drawstyle=
参数将默认线连接方式更改为一种绘制之间的阶梯连接方式。
代码如下:
fig, (ax1, ax2, ax3, ax4) = plt.subplots(4, figsize=(12, 12), sharex=True) x = np.linspace(0, 10, num=20) y1 = np.exp(x) y2 = x ** 3 y3 = np.sin(y2) y4 = np.random.randn(20) ax1.plot(x, y1, color='black', linestyle='--', linewidth=5, marker='x', markersize=15) ax2.plot(x, y2, color='green', linestyle='-.', linewidth=2, marker='^', markersize=10, alpha=0.9) ax3.plot(x, y3, color='red', linestyle=':', marker='*', markersize=15, drawstyle='steps') ax4.plot(x, y4, color='green', linestyle='-', marker='s', markersize=15)
输出显示了四个具有不同属性的函数:
图 5.4 - 演示不同颜色、线型、标记样式、透明度和大小选项的图
使用不同的颜色、线型、标记样式、透明度和大小选项,可以生成具有易于识别的多个时间序列的丰富图表。选择颜色时要明智,因为它们在某些笔记本电脑屏幕上或在打印时可能不会很好地呈现。
丰富轴是制作出色图表的下一步。
用刻度、标签和图例丰富轴
通过自定义轴来进一步改进图表,通过刻度、限制和标签:
matplotlib.pyplot.xlim(...)
方法设置x轴上的值的范围。
matplotlib.pyplot.xticks(...)
方法指定x轴上刻度显示的位置:
plt.xlim([8, 10.5]) plt.xticks([8, 8.42, 8.94, 9.47, 10, 10.5]) plt.plot(x, y1, color='black', linestyle='--', marker='o')
这将修改x轴以在指定的限制内,并在明确指定的值处显示刻度:
图 5.5 – 具有显式 x 轴限制和刻度的图表
我们还可以使用 matplotlib.Axes.set_yscale(...)
方法将其中一个轴的比例改变为非线性。
matplotlib.Axes.set_xticklabels(...)
方法更改x轴上的标签:
fig, ax = plt.subplots(1, figsize=(12, 6)) ax.set_yscale('log') ax.set_xticks(x) ax.set_xticklabels(list('ABCDEFGHIJKLMNOPQRSTUV')) ax.plot(x, y1, color='black', linestyle='--', marker='o', label='y=exp(x)')
那个代码块的输出显示了y轴比例尺的差异,现在是对数,以及x轴刻度具有特定的刻度标签:
图 5.6 – 具有对数 y 轴比例尺和自定义 x 轴刻度标签的图表
图表中的对数比例尺在数据集涵盖大范围的值和/或我们想要传达百分比变化或乘法因子时非常有用。
matplotlib.Axes.set_title(...)
方法用于向绘图添加标题,matplotlib.Axes.set_xlabel(...)
和 matplotlib.Axes.set_ylabel(...)
方法用于设置x和y轴的标签。
matplotlib.Axes.legend(...)
方法添加图例,使图表更易于解释。loc=
参数指定图例在图表上的位置,loc='best'
表示 Matplotlib 自动选择最佳位置:
ax.set_title('xtickslabel example') ax.set_xlabel('x labels') ax.set_ylabel('log scale y values') ax.legend(loc='best') fig
以下图表显示了标题、x 和 y 轴标签以及图例:
图 5.7 – 展示了标题、x 轴和 y 轴标签以及图例的图表
每个时间序列的不同渲染图表以及解释单位和轴标签足以理解图表。然而,总会有一些特殊的数据点,值得指出。
用注释丰富数据点
matplotlib.Axes.text(...)
方法向我们的图表添加文本框:
ax.text(1, 10000, 'Generated using numpy and matplotlib') fig
输出如下:
图 5.8 – 显示 Matplotlib 文本注释的图表
matplotlib.Axes.annotate(...)
方法提供了对注释的更多控制。
接下来的代码块使用以下参数控制注释:
xy=
参数指定数据点的位置。xytext=
参数指定文本框的位置。arrowprops=
参数接受一个字典,用于指定控制从文本框到数据点的箭头的参数。facecolor=
参数指定颜色,shrink=
参数指定箭头的大小。horizontalalignment=
和verticalalignment=
参数指定文本框相对于数据点的方向。
代码如下:
for i in [5, 10, 15]: s = '(x=' + str(x[i]) + ',y=' + str(y1[i]) + ')' ax.annotate(s, xy=(x[i], y1[i]), xytext=(x[i]+1, y1[i]-5), arrowprops=dict(facecolor='black', shrink=0.05), horizontalalignment='left', verticalalignment='top') fig
结果如下:
图 5.9 – 具有数据点的文本和箭头注释的图表
引导读者注意关键数据点有助于读者专注于图表的信息。
可以使用 matplotlib.Axes.add_patch(...)
方法添加不同形状的注释。
接下来的代码块添加了一个 matplotlib.pyplot.Circle
对象,它接受以下内容:
- 使用
xy=
参数来指定位置 - 使用
radius=
参数来指定圆的半径 - 使用
color=
参数来指定圆的颜色
代码如下:
fig, ax = plt.subplots(1, figsize=(12, 6)) ax.plot(x, x, linestyle='--', color='black', marker='*', markersize=15) for val in x: ax.add_patch(plt.Circle(xy=(val, val), radius=0.3, color='darkgray'))
这生成了以下图表,其中数据点周围有圆圈:
图 5.10 – 包含围绕数据点添加补丁生成的圆形注释的图表
现在我们已经生成了漂亮、专业的图表,需要学习如何分享这些图片。
将图表保存到文件
matplotlib.pyplot.figure
对象使我们能够以不同的文件格式保存图表到磁盘,具有许多尺寸和分辨率说明符,例如 dpi=
参数:
fig.savefig('fig.png', dpi=200)
这将以下图表写入 fig.png
文件:
图 5.11 – 写入磁盘上的 Matplotlib 图表并在外部查看器中打开
导出的交易策略表现图像经常用于 HTML 或电子邮件报告。对于打印,请选择打印机的 DPI 作为图表的 DPI。
使用 Matplotlib 绘制 pandas DataFrame 图表
pandas
库提供了使用 Matplotlib 对 Series 和 DataFrame 对象进行绘图的功能。
让我们创建一个包含连续值的 Cont
值的 pandas
DataFrame,模拟价格,以及模拟价格变化的 Delta1
和 Delta2
值。 Cat
值包含五种可能的分类数据:
import pandas as pd df = pd.DataFrame(index=range(1000), columns=['Cont value', 'Delta1 value', 'Delta2 value', 'Cat value']) df['Cont value'] = np.random.randn(1000).cumsum() df['Delta1 value'] = np.random.randn(1000) df['Delta2 value'] = np.random.randn(1000) df['Cat value'] = np.random.permutation(['Very high', 'High', 'Medium', 'Low', 'Very Low']*200) df['Delta1 discrete'] = pd.cut(df['Delta1 value'], labels=[-2, -1, 0, 1, 2], bins=5).astype(np.int64) df['Delta2 discrete'] = pd.cut(df['Delta2 value'], labels=[-2, -1, 0, 1, 2], bins=5).astype(np.int64) df
这生成了以下 DataFrame:
Cont value Delta1 val Delta2 val Cat value Delta1 discrete Delta2 discrete 0 -1.429618 0.595897 -0.552871 Very high 1 0 1 -0.710593 1.626343 1.123142 Medium 1 1 ... ... ... ... ... ... ... 998 -4.928133 -0.426593 -0.141742 Very high 0 0 999 -5.947680 -0.183414 -0.358367 Medium 0 0 1000 rows × 6 columns
让我们探索不同的方式,展现这个 DataFrame。
创建 DataFrame 列的线图
我们可以使用 pandas.DataFrame.plot(...)
方法的 kind=
参数在线图中绘制 'Cont value'
:
df.plot(y='Cont value', kind='line', color='black', linestyle='-', figsize=(12, 6))
此命令生成以下图表:
图 5.12 – 使用 pandas.DataFrame.plot(…) 方法生成的线图
线图通常用于显示时间序列。
Python 金融交易实用指南(二)(5)https://developer.aliyun.com/article/1523760