全文共 13068 字,60 幅图,
预计阅读时间 66 分钟。
0
引言
看 PyEcharts 名字就猜得到
PyEcharts = Python + Echarts
Echarts 是一个由百度开源的数据可视化工具,凭借着良好的交互性,精巧的图表设计,得到了众多开发者的认可,而 Python 就不用多说了。
当 Python 遇到了 Echarts,就变成了 PyEcharts。
本帖需要的其他库如下:
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.patches as patches
%matplotlib inline
from datetime import datetime
Matplotlib 需要的画图颜色设置如下,这也是 PyEcharts 默认的调色。
r_hex = '#dc2624' # red, RGB = 220,38,36
dt_hex = '#2b4750' # dark teal, RGB = 43,71,80
tl_hex = '#45a0a2' # teal, RGB = 69,160,162
r1_hex = '#e87a59' # red, RGB = 232,122,89
tl1_hex = '#7dcaa9' # teal, RGB = 125,202,169
g_hex = '#649E7D' # green, RGB = 100,158,125
o_hex = '#dc8018' # orange, RGB = 220,128,24
tn_hex = '#C89F91' # tan, RGB = 200,159,145
g50_hex = '#6c6d6c' # grey-50, RGB = 108,109,108
bg_hex = '#4f6268' # blue grey, RGB = 79,98,104
g25_hex = '#c7cccf' # grey-25, RGB = 199,204,207
画图有了 Matplotlib 和 Seaborn 为什么还要学 PyEcharts,看完下面它们的对比图就知道了。
下面两图画出 USDCNY 从 2016-01-01 到 2019-05-13 的 K 线图。
知识点:K 线图
K 线又称蜡烛图,阴阳线。原来是日本米商用于记录米市中的行情波动的,后因其表示价格趋势的方法直观,真实,逐渐成为使用最广泛的技术图形。图像如下:
颜色不是最重要的,看 A 股的 K 线记住是「红涨绿跌」,看美股的 K 线记住是「绿涨红跌」。
重要的是 K 线是由很多「蜡烛」状的单元责成,每个单位包含四个数据:即开盘价、最高价、最低价、收盘价。所有的 K 线都是围绕这四个数据展开,反映大势的状况和价格信息。
先看用 Matplotlib 画的 K 线图,密密麻麻啥都看不清楚,根本区分不了开盘价、最高价、最低价、收盘价。
再看用 PyEcharts 画的 K 线图 (gif),也是密密麻麻的,但是注意到下方可伸缩的时间轴没?通过滑动鼠标我们可以锁定想看到的数据,比如那根大蓝柱 (数据来源是 yahoofinancial,但我查了查在 2016-12-07,USDCNY 日内最高价没有到过 7.49,估计数据源有错)。
除了操作滑动轴以外,上图 (左上方图例) 还可以任意显示或隐藏 K 线 (K-Line), 最高价 (high) 和最低价 (low)。
这种交互式 (interactive) 操作在我看来给图标增加了额外的维度,再反观 Matplotlib 绘制出来的 K 线图 (包含长时间历史数据图) 就像死水一潭。
你更喜欢哪个?选 Matplotlib 的可以轻轻点右上角,选 PyEcharts 的一起继续前行。
注:在公众号对话框输入 data 可下载数据和所有美如画的动态图。
本文思路也很简单,第一章来 PK 两者,PyEcharts 很自然地把 Matplotlib 比下去;第二章就看看胜者 PyEcharts 如何画多图。
本帖并不是 PyEcharts 的工具书,把里面所有类型的图都讲一遍,那些官方例子都有了。本帖还是结合金融数据,介绍几个最简单的交易策略,并用 PyEcharts 画图。
首先下载计算技术指标 (technical indicator) 的包 talib,和 PyEcharts 包 pyecharts。在 Anaconda 命令框里两句话搞定。
conda install -c masdeseiscaracteres ta-lib
pip install pyecharts
引入 talib 并起个别名 ta。
import talib as ta
本帖画图需要 pyecharts 里的几个原件:
从 pyecharts 中引用它们
from pyecharts import Line, Kline, Pie,
Grid, Overlap, Timeline,
WordCloud
本帖目录如下:
目录
第一章 - Matplotlib Vs PyEcharts
1.1 K 线图
1.2 移动均线图
1.3 布林带图
1.4 相对强弱指标图
第二章 - PyEcharts 多图
2.1 网格图
2.2 时间线轮播图
总结
1
Matplotlib Vs PyEcharts
1.1
K 线图
注:本节和 1.2, 1.3 都用以下方式来下载和处理数据。
数据
首先用 YahooFinancials API 来下载若干外汇和加密货币的三年半历史数据,安装该 API 用一行代码:
pip install yahoofinancials
数据的描述如下
其中
下面代码就是从 API 获取数据:
该 API 返回结果 FX_daily 和 CFX_daily 是「字典」格式,样子非常丑陋,感受一下。
数据样子虽丑,但还满齐全,画 K 线需要的开盘价 (open)、最高价 (high)、最低价 (low)、收盘价 (close) 都有。将上面的「原始数据」转换成 DataFrame,代码如下:
第 3 行完全是为了 YahooFinancial 里面的输入格式准备的。如果 Asset 是加密货币,直接用其股票代码;如果 Asset 是汇率,一般参数写成 EURUSD 或 USDJPY
第 6 行定义好开盘价、收盘价、最低价和最高价的标签。
第 7 行获取出一个「字典」格式的数据。
第 8, 9 行用列表解析式 (list comprehension) 将日期和价格获取出来。
第 11 到 13 行定义一个 DataFrame
处理过后的数据格式美如画,看看 USDCNY。
curr = 'USDCNY'
data = data_converter( FX_daily, curr, 'FX' )
data.head(3).append(data.tail(3))
数据整理好后,来看看 Matplotlib 和 PyEcharts 的 PK 吧。
Matplotlib 图
Matplotlib 里面没有直接画 K 线的方法,我们用里面的块 (patch) 对象,对其填充上色,空心红色代表阳线,实心深青色代表阴线,画出来的效果图如下。
实现上图的代码 (横屏看) 如下:
第 3-6 行设置了图的大小、dpi、坐标系、标题和 x 轴范围。
第 8-17 行是核心
第 8-9 行:对每一个数据,获取出开盘价 (open)、收盘价 (close)、最高价 (high)、最低价 (low)。
第 11-14 行:如果收盘价 > 开盘价 (阳线)
第 15-17 行:如果收盘价 < 开盘价 (阴线)
第 19-20 行设置了 x 轴刻度以及标签,并把日期标签旋转 90 度,以免标签相互重叠。
mpl_Kline( curr, data );
看到这图第一印象是什么?
一样对吗?三年半的数据密密麻麻画出的 K 线看不出任何 K 线应带的信息。如果能在横轴上任意拉伸就好了,这样就可以看清楚细节了。
Matplotlib 是无能为力了,PyEcharts 闪亮登场。
PyEcharts 图
PyEcharts 里画 K 线用到 Kline 对象,除此之外我们添加最高价和最低价两条线 Line 对象,再用 Overlap 对象来「叠加」它们。
第 1-2 行获取日期和汇率。
第 4 行创建 K 线对象 Kline,设置好标题 "xxx Chart" 和位置 center。第 5-6 行在 Kline 上添加属性
第 8 行创建折线对象 Line。第 9-13 行在 Line 上添加两条折线,一条是最高价,一条是最低价。
第 14 行创建叠加对象 Overlap。第 15-16 行在 Overlap 上分别添加之前的 Kline 和 Line,这样就把所有对象整合在一起了。
第 17 行如果被运行,该动态图被生成到 USDCNY Chart.html 网页文件里;如果没被运行,该动态图将显示在 Jupyter Notebook 中。
本例用到了 pyecharts 中的三个原件:Kline,Line 和 Overlap。它们的用法都是先创建 (可以带些必要属性,比如标题和尺寸),再用 add 方法添加额外属性。将其流程通用化得到
object = Object( 必要属性 )
object.add( 额外属性 )
如果你看懂了以上内容,你可以学会了 PyEcharts。接下来的所有例子都万变不离其宗。在后三节中,我准备用 PyEcharts 画出三个最常见的交易策略要看的指标图,分别是
MA, BBand 和 RSI 是量化交易常用的技术指标,通常我们用 talib 包里的函数直接计算。
1.2
移动均线图
知识点:移动均线
移动均线 (Moving Average, MA) 是将一段时间 (也叫窗口) 内资产收盘价的平均价格连成曲线,用以显示价格趋势的一种技术指标。
平均有不同定义,最常见的是简单移动平均 (Simple Moving Average, SMA),平均值是算术平均值,有时我们也用 MA 代表 SMA。其他常见的还有
还有一些少见的 TRIMA, KAMA 和 MAMA。公式就不写了,知道它们是一种计算均值的方法就行。
窗口可以自行选择,常见的有 5日、10日、20日、30日、60日等。
移动指的是窗口不停移动,假如一年有 252 个交易日,那么第 1 个 MA60 值需要第 1 到 60 个汇率,第 2 个 MA60 值需要第 2 到 61 个汇率,第 193 个 MA60 值需要第 193 到 252 个汇率。最终只有 193 个 MA60。同理可得到只有 223 个 MA20。
利用均值指标,最常见的交易策略就是「双均线策略」。
双均线策略:MA60 和 MA20 必有交点,若 20 天平均线「上穿越」60 天均线,则为买入点;反之为卖出点。该策略基于不同天数均线的交叉点抓住价格的强势和弱势时刻进行交易。
下面我们来看看两种类型的移动平均图:
不同窗口的 MA
我们以比特币 (代码 BTC-USD) 举例来绘图。
label = 'BTC-USD'
data = data_converter( CFX_daily, label, 'CFX' )
data.head(3).append(data.tail(3))
数据整理好后,来看看 Matplotlib 和 PyEcharts 的 PK 吧。
Matplotlib 图
第 1 行定义函数,label 和 data 是「位置参数」,window_periods 是「可变参数」。忘了这些参数类型的可回顾〖Python 入门篇 (下)〗。
第 3-6 行设置了图的大小、dpi、坐标系、标题和 x 轴范围。
第 8-10 行画出收盘价的折线图。
第 12-14 行遍历 window_periods 里所有值,用 talib 里的 ta.MA 函数计算不同窗口的 MA 值,再画出其折线图。
第 15 行把图例放在图的最佳位置 (loc=0)。
画出窗口为 30日、60日和 100日的简单移动平均线 (SMA) 看看。
mpl_MA( label, data, 30, 60, 100 );
只要历史数据一多就是 Matplotlib 的死穴,只能大概看得出价格走势,但却丢失很多细节。
PyEcharts 图
PyEcharts 里用 n 条线 Line 对象画移动平均图,并用 Overlap 对象来「叠加」它们。PyEcharts 里的代码比 Matplotlib 里的简洁多了。
第 1-2 行获取日期和比特币价格。
第 4 行创建折线对象 Line,起名为 line。设置好标题 "xxx Chart" 和位置 center。第 5-6 行在 Line 上添加属性
第 8 行创建另一个折线对象 Line,起名叫 line2。
第 11-13 行在 line2 上添加 n 条折线,即不同窗口的移动平均线。
第 15 行创建叠加对象 Overlap。第 16-17 行在 Overlap 上分别添加之前的「收盘价折线」和「n 条移动平均线」,这样就把所有对象整合在一起了。
第 18 行如果被运行,该动态图被生成到 BTCUSD Chart.html 网页文件里;如果没被运行,该动态图将显示在 Jupyter Notebook 中。
在动态图中,你可以一次性画出很多窗口下的 MA 线,在点击图例看你感兴趣的做双均值策略 (上例看的是 MA30 和 MA60)。试想这如果在 Matplotlib 里实现不是要画很多图?
比特币在 2017 年底到达最高点,差不多 20000 美元,之后一路狂泻。近期又起来了,原因是被当成像黄金一样的避险资产了。。。
不同类型的 MA
我们以以太币 (代码 ETH-USD) 举例来绘图。
label = 'ETH-USD'
data = data_converter( CFX_daily, label, 'CFX' )
data.head(3).append(data.tail(3))
数据整理好后,来看看 Matplotlib 和 PyEcharts 的 PK 吧。
Matplotlib 图
将移动平均的类型由字符型转成整数型,方便 ta.MA 函数使用。
第 1 行定义函数,label 和 data 是「位置参数」,wp 是「默认参数」而默认值为 5,MA_type 是「可变参数」。忘了这些参数类型的可回顾〖Python 入门篇 (下)〗。
第 3-6 行设置了图的大小、dpi、坐标系、标题和 x 轴范围。
第 8-9 行画出收盘价的折线图。
第 11-14 行遍历 MA_type 里所有值,用 talib 里的 ta.MA 函数计算窗口为 wp的不同类型 MA 值,再画出其折线图。
第 16 行把图例放在图的最佳位置 (loc=0)。
画出窗口为 100日的 8 种移动平均线看看。
mpl_XMA( label, data, 100,
'SMA','EMA','WMA','DEMA',
'TEMA','TRIMA','KAMA','MAMA' );
这效果啥也不说了,还是看 PyEcharts 的作品吧。
PyEcharts 图
PyEcharts 里还是用 n 条线 Line 对象画移动平均图,并用 Overlap 对象来「叠加」它们。
第 1-2 行获取日期和以太币价格。
第 4 行创建折线对象 Line,起名为 line。设置好标题 "xxx Chart" 和位置 center。第 5-6 行在 Line 上添加属性
第 8 行创建另一个折线对象 Line,起名叫 line2。
第 9-10 行设定好窗口 100 日,和 8 种移动平均类型的字符列表。
第 12-15 行在 line2 上添加 8 条折线,即 8 种类型的移动平均线。
第 17 行创建叠加对象 Overlap。第 18-19 行在 Overlap 上分别添加之前的「收盘价折线」和「8 条移动平均线」,这样就把所有对象整合在一起了。
第 20 行如果被运行,该动态图被生成到 ETHUSD Chart.html 网页文件里;如果没被运行,该动态图将显示在 Jupyter Notebook 中。
这横轴伸缩效果,这图例显示/隐藏效果,是不是和 Matplotlib 没得比。
1.3
布林带图
数据
注:本节和 1.4, 2.1, 2.2 都使用从 csv 里读取的股票数据。
本节使用的数据描述如下:
data = pd.read_csv( '1Y Stock Data.csv',
parse_dates=[0],
dayfirst=True )
data.head().append(data.tail())
上小节介绍了移动均值,这小节介绍另一个技术指标 - 布林线。
知识点:布林线
布林线 (Bollinger Line) 原理是,价格总是围绕某个中轴在一定的范围内波动,这个范围就形成了一个带状区间 (band)。
价格就在这个区间的上限和下限之间进行波动。而这条带状区间的宽窄也会随着价格波动幅度的大小而变化。
布林线由三条曲线组成,分别是上轨线 (upper band)、中轨线 (mid band) 和下轨线 (lower band)。上图只画出上轨线和下轨线。
根据布林线指标的交易策略如下。
观察两点:
一般来说,下轨对价格有支撑作用,上轨对价格有阻力作用,中轨对价格既有支撑也有阻力作用。
此外,要结合带状口的开合,如果出现极度收缩的带状口时,如果价格开始抬升,带状口重新扩张的时候,买入。
了解好布林带后,来看看 Matplotlib 和 PyEcharts 的 PK 吧。
Matplotlib 图
第 1 行定义函数,code 和 data 是「位置参数」,wp 是「默认参数」而默认值为 5,MAtype 是「可变参数」。忘了这些参数类型的可回顾〖Python 入门篇 (下)〗。
第 3 行根据 code 获取股票信息。
第 5-8 行设置了图的大小、dpi、坐标系、标题和 x 轴范围。
第 10-23 行在 1.1 节画 K 线图解释的很清楚了。
第 27 行用 talib 里的 ta.BBANDS 函数计算上轨线、中轨线和下轨线。在本例中设定 5 日 EMA,2 倍的波动率水平。即
第 29-33 行创建第二个坐标系,把三轨线叠加到 K 线上,图例放在图的最佳位置 (loc=0)。
运行程序看看苹果股票的布林带。
mpl_BBAND( 'AAPL', data, MAtype='EMA' );
不吐槽了。。。
PyEcharts 图
PyEcharts 里画 K 线用到 Kline 对象,再用 Line 对象画上轨线、中轨线和下轨线,最后 Overlap 对象来「叠加」它们。
代码很简单,用的原件 Kline, Line 和 Overlap 之前都解释过了,自己看问题不大。
效果好到爆有没有?
1.4
相对强弱指标图
这小节介绍最后一个技术指标 - 相对强弱指标。
知识点:相对强弱指标
相对强弱指数 (Relative Strength Index, RSI) 是通过特定时期价格变动情况计算市场买卖力量对比,来判断价格内部本质强弱、推测价格未来的变动方向。
RSI 的计算公式如下 (RSI 是一个 0 到 100 的数)
RSI = 100 - 100/(1+a)
a = 平均收益 / |平均损失|
计算平均损益通常用 14 天的历史数据。
根据相对强弱指标的交易策略如下。
RSI 是个趋势指标,通常来讲
来看看 Matplotlib 和 PyEcharts 的 PK 吧。
Matplotlib 图
第 1 行定义函数,code 和 data 是「位置参数」,wp 是「默认参数」而默认值为 5。忘了这些参数类型的可回顾〖Python 入门篇 (下)〗。
第 3 行根据 code 获取股票信息。
第 5-8 行设置了图的大小、dpi、坐标系、标题和 x 轴范围。
第 10-23 行在 1.1 节画 K 线图解释的很清楚了。
第 25 行用 talib 里的 ta.RSI 函数计算 RSI 值。在本例中设定 14 日历史窗口。
第 27-31 行创建第二个坐标系,把 RSI 线、支撑线 (30)、阻力线 (70) 叠加到 K 线上,图例放在图的最佳位置 (loc=0)。
运行程序看看高盛股票的 RSI。
mpl_RSI( 'GS', data );
RSI 突破 30 -70 的点还是能看清楚的,但看完 PyEcharts 画的图再作评价。
PyEcharts 图
PyEcharts 里画 K 线用到 Kline 对象,再用 Line 对象画 RSI 线、支撑线和阻力线,最后 Overlap 对象来「叠加」它们。
代码很简单,用的原件 Kline, Line 和 Overlap 之前都解释过了,自己看问题不大。
把 K 线去掉,看 RSI 是否突破支撑线或阻力线特别清楚。
2
PyEcharts 多图
2.1
网格 (Grid) 图
数据
本小节用上节用到的 5 个股票数据,再加上标准普尔 500 指数 (SPX),和恐慌指数 (VIX)。数据如下:
stock_data = pd.read_csv( '1Y Stock Data.csv',
parse_dates=[0],
dayfirst=True )
stock_data.head().append(stock_data.tail())
data = pd.read_csv( 'S&P500.csv',
index_col=0,
parse_dates=True,
dayfirst=True )
spx = data[['Adj Close']].loc['2018-02-26':'2019-02-26']
spx.head(3).append(spx.tail(3))
data = pd.read_csv( 'VIX.csv',
index_col=0,
parse_dates=True,
dayfirst=True )
vix = data[['Adj Close']].loc['2018-02-26':'2019-02-26']
vix.head(3).append(vix.tail(3))
绘图
我们想把苹果股票的 K 线图,和 SPX 和 VIX 折线图放在一起看。如果再用 Overlap 来叠加它们会显得图很乱,这时可以借用 pyecharts 里的 Grid 对象,它是将上面三个图放在三个坐标系中。
代码如下:
第 1-5 行用 code 获取股票数据,并获取日期和价格。为了画 K 线,价格数组的列必须按 pyecharts 里 API 要求的顺序 - [开盘价, 收盘价, 最低价, 最高价]。
第 6 -7 行创建 Kline 对象 (标题放左边),并添加 x 轴数据、y 轴数据和“允许横轴拉伸”。
第 10 -12 行创建 Line 对象 (标题为 SPX,位置离顶 55%) 并起名为 line1,再添加若干属性,比如 y 轴范围、标识最小值、允许横轴拉伸。最关键的是 datazoom_xaxis_index=[2,1,0],就说伸缩功能控制三个轴,AAPL 一个,SPX 一个,VIX 一个。这样拉伸 x 轴三幅子图可以同时动,非常酷!
第 15 -18 行创建 Line 对象 (标题为 VIX,位置离顶 75%) 并起名为 line2,再添加若干属性。
第 20 行创建 Grid 对象,宽 1000,高 600 (这些数值是不断尝试看效果设置的)。
第 20-23 行将三幅图加在 Grid 中,关键点是如何设置里面的 grid_top 和 grid_bottom 里的百分数而使得图看起来好看,这个没有标准的,不停地尝试到你最终满意为止。本例中 AAPL 占了 5% 到 50% 的位置,SPX 占了 55% 到 70% 的位置,VIX 占了 75% 到 90% 的位置 (还有 10% 位置留给了拉缩轴)。
第 24 行如果被运行,该动态图被生成到 APPL&VIX.html 网页文件里;如果没被运行,该动态图将显示在 Jupyter Notebook 中。
惊不惊喜?意不意外?炫不炫酷?从图上可以看到在 2018 年底 SPX 和 VIX 同时到达最低点和最高点,对应的苹果 K 线看,在那一点前后苹果股价有一个大跌和大涨。
2.2
时间线轮播图
本节想画出不同时点 (每月月底) 时五支股票 (苹果、阿里巴巴、京东、脸书和高盛) 交易额 (价格×交易量) 的成分图。
如果用 Matplotlib,是不是要画 n 张饼状图 (pie chart),其中 n 为月份个数?但是用 PyEcharts 里面的 Timeline 神器,可画出随时间线轮播动态图。一图包含 n 张饼状图。
由于我们需要每个股票在每个月底的数据,原来讲的 pandas 里的 split-apply-combine 的方法可以派上用场了。详情参考〖数据结构之 Pandas (下)〗。
数据
stock_data 还是之前用的含有 5 只股票完整信息的 DataFrame,下列代码做
data = stock_data[['Date', 'Symbol', 'Adj Close', 'Volume']]
data.insert( 1, 'Year', pd.DatetimeIndex(data['Date']).year )
data.insert( 2, 'Month', pd.DatetimeIndex(data['Date']).month )
data.head(3).append(data.tail(3))
接下来定义个 print_groups 函数便于打印组的名字和前五行信息。
def print_groups( group_obj ):
for name, group in group_obj:
print( name )
print( group.head() )
grouped = data.groupby(['Symbol', 'Year', 'Month'])
print_groups(grouped)
对分好的组想进行什么操作可以用高阶函数 apply() 来实现。比如想获取月底的数据,那么就对每个组 df 获取最后一行,用匿名函数
lambda df: df.iloc[-1,:]
显示结果 group 的头和尾部三行。
group = grouped.apply( lambda df: df.iloc[-1,:] )
group.head(3).append(group.tail(3))
按 Symbol, Year 和 Month 获取出来了每个月底的 Adj Close 和 Volume。
绘图
接着就可以用 Timeline 来画轮播图了。
第 1-2 行获取 5 个股票代号,并且存储股票个数。
第 4 行计算交易额,即收盘价和交易量的乘积。
第 5 行将一维的交易额数组重塑成二维数组,每一行代表一个股票的月末交易额数据。第 6 行获取日期。
第 7-8 行创建 Timeline 对象,允许自动播放,时间线放在底部,宽 800,高 400。
第 11-15 行遍历每个日期,即在每个月末做三件事
第 18 行如果被运行,该动态图被生成到 Pie.html 网页文件里;如果没被运行,该动态图将显示在 Jupyter Notebook 中。
自己看展示吧,要多酷就多酷。
3
总结
如果我说在写这篇之前,我也没使用过 PyEcharts 你们信么?真的我也没用过,但是我通过看官网介绍而系统总结一套方法很快就学会它了:
方法总结
对 pyecharts 中的所有原件,都是先创建 (可以带些必要属性,比如标题和尺寸),再用 add 方法添加额外属性。其通用化流程为
object = Object( 必要属性 )
object.add( 额外属性 )
在画图之前,你应该对那些原件可以干嘛有个大概印象,比如 Kline 是画 K 线图,Heatmap 是画热力图,WordCloud 是图词云图等等。对于那些装饰原件所需的必要属性和额外属性,上官网一查便知,跟着例子看理解更快。
画多个坐标系用 Grid 对象;叠加多个原件用 Overlap 对象;随着时间轴展示不同时点的数据关系用 Timeline 对象,等等。
你不需要精通每个细节,要用什么直接去官网查找资料或者搜索正确的问题就行了。
The End