我们已经介绍了三篇关于量化投资方面绘图的文章,大家有兴趣可以了解一下
由于这一部分主要是给大家介绍指标的数学公式和计算方法,更深入的了解它们,其中有众多的数学公式和理论推导过程,我尽可能排版的工整,方便各位阅读。如果只想看代码实现可以跳到最后面“代码实现”部分
之前的绘图篇中,我们分三个篇章分别介绍如何绘制收盘价折线图、烛状图、基于收盘价绘制移动平均线、黄金分割线。在接下来的指标篇中,我们将详细介绍每个指标的计算方法以及算法实现,并绘制出指标供各位投资者使用、参考,并提供该指标的一些研判标准,希望各位学有所成!
大家可以关注我的GitHub:ExileSaber
虽然现在还没较高的水平,但是可以一起学习进步
这一部分主要是为了让初学者更容易了解MACD指标的构成原理,大家也可以先阅读后面的MACD指标,如果发现有什么地方解释的不清楚可以看一下这一块有没有说明,也可以在最后面的评论提问,博主看到了都会认真解答。
该指标的计算公式:
M A = ( C 1 + C 2 + . . . + C n ) / n MA = (C_1+C_2+...+C_n)/n MA=(C1+C2+...+Cn)/n
其中C 为收盘价,n 为移动平均周期数。之前有介绍如何绘制移动平均线,可以查看我之前的文章:量化投资常用技能——绘图篇 2:绘制移动平均线
补充一个概念:一般将3天、7天的平均线称为短线,10天、30天的平均线称为中线,150天、250天平均线称为长线
该指标的介绍来自于百度百科
这部分是讲解EMA指标的推导过程,需要一定的数学功底,大家也可以跳过,直接看递推式
E M A N ( x n ) = 2 N + 1 ∑ k = 0 ∞ ( N − 1 N + 1 ) k x n − k EMA_N(x_n) = \frac{2}{N+1} \sum^\infty_{k=0}\bigg (\frac{N-1}{N+1}\bigg )^kx_{n-k} EMAN(xn)=N+12k=0∑∞(N+1N−1)kxn−k
由于在我们的序列 { X n } \lbrace X_n \rbrace { Xn}中,没有 X 1 X_1 X1之前的数据,因此我们补充定义: X 0 = X − 1 = X − 2 = . . . = X 1 X_0=X_{-1}=X_{-2}=...=X_1 X0=X−1=X−2=...=X1
E M A N ( x 1 ) = 2 N + 1 ∑ k = 0 ∞ [ ( N − 1 N + 1 ) k x 1 ] EMA_N(x_1) = \frac{2}{N+1} \sum^\infty_{k=0}\bigg[\bigg (\frac{N-1}{N+1}\bigg )^kx_1\bigg] EMAN(x1)=N+12k=0∑∞[(N+1N−1)kx1]
其中 ( N − 1 N + 1 ) ∞ (\frac{N-1}{N+1})^\infty (N+1N−1)∞这一项由极限可知为0
∑ k = 0 ∞ [ ( N − 1 N + 1 ) k x 1 ] = x 1 ( 1 − ( N − 1 N + 1 ) ∞ ) 1 − N − 1 N + 1 = x 1 2 N + 1 = ( N + 1 ) x 1 2 \sum^\infty_{k=0}\bigg[\bigg (\frac{N-1}{N+1}\bigg )^kx_1\bigg]=\frac{x_1\big(1-(\frac{N-1}{N+1})^\infty\big)}{1-\frac{N-1}{N+1}}=\frac{x_1}{\frac{2}{N+1}}=\frac{(N+1)x_1}{2} k=0∑∞[(N+1N−1)kx1]=1−N+1N−1x1(1−(N+1N−1)∞)=N+12x1=2(N+1)x1
综上可知 E M A N ( x 1 ) = x 1 EMA_N(x_1)=x_1 EMAN(x1)=x1
通过上述推导过程,我们很容易发现一个特点,当 k k k越小、 x n − k x_{n-k} xn−k这一项的下标越大时, x n − k x_{n-k} xn−k前的系数 ( N − 1 N + 1 ) k \big(\frac{N-1}{N+1}\big)^k (N+1N−1)k越大。这说明当时间越靠近当前日期时(也就是 k k k越小、 n − k n-k n−k 越靠近 n n n时), x n − k x_{n-k} xn−k的权重越大,也就是EMA函数对近期的价格加强了权重比,更能及时反映近期价格波动情况
移动平均线MA指标对时间段内每天的价格都是同等权重,延后性较高
由EMA的定义式可以推导出如下的递推公式:
E M A N ( x n ) = 2 x n + ( N − 1 ) E M A N ( x n − 1 ) N + 1 EMA_N(x_n) = \frac{2x_n + (N-1)EMA_N(x_{n-1})}{N+1} EMAN(xn)=N+12xn+(N−1)EMAN(xn−1)
以下为其定义式,了解一下,MACD指标是从该指标上发展来的
对序列 { X n } \lbrace X_n \rbrace { Xn} 的 N 周期 EMA 再取一个 M 周期 EMA,将得到
E M A M [ E M A N ( x n ) ] = ( M − 1 ) E M A M ( x n ) − ( N − 1 ) E M A N ( x n ) M − N EMA_M\big[EMA_N(x_n)\big] = \frac{(M-1)EMA_M(x_n)-(N-1)EMA_N(x_n)}{M-N} EMAM[EMAN(xn)]=M−N(M−1)EMAM(xn)−(N−1)EMAN(xn)
MACD指标,全称Moving Average Convergence / Divergence(指数平滑移动平均线)
该指标包含三个部分:两线一柱,快线称DIF,慢线称DEA,柱状图为MACD
我们要获得第n天的MACD,那么我们的数学计算过程如下
E M A 12 ( x n ) = 11 13 E M A 12 ( x n − 1 ) + 2 13 x n EMA_{12}(x_n)=\frac{11}{13}EMA_{12}(x_{n-1})+\frac{2}{13}x_n EMA12(xn)=1311EMA12(xn−1)+132xn
其中 x n x_n xn表示第n天的价格, E M A 12 ( x n − 1 ) EMA_{12}(x_{n-1}) EMA12(xn−1)表示前一天(第 n-1 天)的12日EMA
E M A 26 ( x n ) = 25 27 E M A 26 ( x n − 1 ) + 2 27 x n EMA_{26}(x_n)=\frac{25}{27}EMA_{26}(x_{n-1})+\frac{2}{27}x_n EMA26(xn)=2725EMA26(xn−1)+272xn
计算离差值 DIF:
第n日的DIF:
D I F n = E M A 12 ( x n ) − E M A 26 ( x n ) DIF_n=EMA_{12}(x_n)-EMA_{26}(x_n) DIFn=EMA12(xn)−EMA26(xn)
定义式:
D E A n = E M A 9 ( d i f n ) = 8 10 E M A 9 ( d i f n − 1 ) + 2 10 d i f n DEA_n=EMA_9(dif_n)=\frac{8}{10}EMA_9(dif_{n-1})+\frac{2}{10}dif_n DEAn=EMA9(difn)=108EMA9(difn−1)+102difn
其中 d i f n dif_n difn表示第n天的DIF值
根据离差值计算其 9 日的EMA,即离差平均值,称为第 n n n 日DEA
D E A n = 8 10 D E A ( x n − 1 ) + 2 10 D I F ( x n ) DEA_n = \frac{8}{10}DEA(x_{n-1}) + \frac{2}{10}DIF({x_{n})} DEAn=108DEA(xn−1)+102DIF(xn)
( D I F n − D E A n ) × 2 (DIF_n-DEA_n)\times2 (DIFn−DEAn)×2
计算得到的值即为柱状图的值
结合numpy库计算MACD指标十分简单,计算时使用递推公式即可很方便的从第一个值得到之后各个时刻的值。得到MACD指标的两线一柱只有一个需要实现的函数——EMA的计算函数
先加上部分库的导入,方便学习的过程可以直接运行
import abupy
import numpy as np
from abupy import ABuSymbolPd
# ———————————————————— #
# ———— 默认参数设置 ———— #
# ———————————————————— #
__colorup__ = "red"
__colordown__ = "green"
abupy.env.enable_example_env_ipython() # 使用沙盒数据,目的是和书中一样的数据环境,不使用会报错
tsla_df = ABuSymbolPd.make_kl_df('usTSLA', n_folds=2) # 固定导入tsla的行情数据
tsla_df = tsla_df[:100] # 选取前100个,数据过多不易观察
print(tsla_df[:10])
# ———————————————————— #
def EMA(data, window):
'''
计算EMA指标
:param data: 传入的数据,需要为list、ndarray、series类型数据
:param window: 对应着计算的是几日的EMA
:return: 返回ndarray的数据类型
'''
list_ema = [] # 用于存储计算得到的每个ema,也方便递推公式的使用
list_ema.append(data[0])
for i in range(1, len(data)):
list_ema.append(2 * data[i] / (window+1) + (window-1) * list_ema[-1] / (window+1)) # 这部分是递推公式的实现
return np.array(list_ema) # 最后转换为ndarray的数据类型,方便之后的两个ndarray的相减运算
有了计算EMA指标的函数后,我们就可以很方便的实现 E M A 12 EMA_{12} EMA12, E M A 26 EMA_{26} EMA26 、DIF指标、DIF指标的 E M A 9 EMA_9 EMA9 以及MACD柱状图的值
ema_12 = EMA(data=tsla_df['close'], window=12) # 12日EMA的值
ema_26 = EMA(data=tsla_df['close'], window=26) # 26日EMA的值
dif = ema_12 - ema_26 # 利用ndarray之间的减法运算即为各对应元素相减,得到DIF
dea = EMA(data=dif, window=9) # 再计算DIF的9日EMA(该值被称为DEA)
macd = (dif - dea) * 2 # 计算MACD柱状图的值
上面的两块代码放在一起就组成了我们MACD指标的计算过程,接下来实现MACD指标的绘制
我们需要绘制的两线一柱,其中MACD柱状图会有正负两种情况,为了更好的区分正负情况,我们需要绘制两次柱状图,其中一次用红色绘制MACD值为正的情况,另外一次用绿色绘制MACD为负的情况。实现的函数如下:
def draw_macd(dif, dea, macd, axs=None, show=False):
'''
通过传入DIF、DEA、MACD的值绘制MACD指标的两线一柱
:param dif: DIF指标的list或者ndarray数据类型
:param dea: DEA指标的list或者ndarray数据类型
:param macd: 为了代码简洁,目前只支持ndarray类型的MACD数据
:param axs: 是否在子图绘制
:param show: 是否绘图
:return:
'''
x = np.arange(len(dif)) # 横坐标
drawer = axs if axs is not None else plt
drawer.plot(x, dif, label='DIF', color='b', linestyle='--') # 绘制DIF曲线
drawer.plot(x, dea, label='DEA', color='y', linestyle='-.') # 绘制DEA曲线
pos_index = x[macd >= 0] # 得到MACD值大于等于0的索引
neg_index = x[macd < 0] # 得到MACD值小于0的索引
drawer.bar(pos_index, macd[pos_index], color='r', label='macd bar', alpha=0.6) # 绘制MACD大于等于0部分的柱状图
drawer.bar(neg_index, macd[neg_index], color='g', label='macd bar', alpha=0.6) # 绘制MACD小于0部分的柱状图
drawer.legend()
if show:
plt.show()
为了绘图全面,我们将“量化投资常用技能——绘图篇 1:绘制股票收盘价格曲线和ochl烛状图”中绘制烛状图的函数 p l o t plot plot_ o c h l ochl ochl 黏贴到这一部分代码中,即可完成多图绘制,完整代码如下
缺少的库直接 pip install 安装即可
import abupy
import numpy as np
from abupy import ABuSymbolPd, nd
import matplotlib.pyplot as plt
from matplotlib.dates import date2num
import mpl_finance as mpf
# ———————————————————— #
# ———— 默认参数设置 ———— #
# ———————————————————— #
__colorup__ = "red"
__colordown__ = "green"
abupy.env.enable_example_env_ipython() # 使用沙盒数据,目的是和书中一样的数据环境,不使用会报错
tsla_df = ABuSymbolPd.make_kl_df('usTSLA', n_folds=2) # 固定导入tsla的行情数据
tsla_df = tsla_df[:100] # 选取前100个,数据过多不易观察
print(tsla_df[:10])
# ———————————————————— #
def plot_ochl(data_df=tsla_df, axs=None, show=False):
'''
绘制烛状图
:param data_df: 输入的数据,默认采用tsla的历史行情数据,输入的数据类型目前只支持DataFrame类型
:param axs: 是否在子图上绘制
:param show: 是否显示图像
:return:
'''
drawer = plt if axs is None else axs
qutotes = []
for index, (d, o, c, h, l) in enumerate(
zip(data_df.index, data_df.open, data_df.close,
data_df.high, data_df.low)):
d = date2num(d) # 蜡烛图的日期要使用matplotlib.finance.date2num进行转换为特有的数字值
val = (d, o, c, h, l) # 日期,开盘,收盘,最高,最低组成tuple对象val
qutotes.append(val) # 加val加入qutotes
# 使用mpf.candlestick_ochl进行蜡烛绘制,ochl代表:open,close,high,low
mpf.candlestick_ochl(drawer, qutotes, width=0.6, colorup=__colorup__, colordown=__colordown__)
drawer.autoscale_view()
drawer.xaxis_date()
if show:
plt.show()
def EMA(data, window):
'''
:param data: 传入的数据,需要为list、ndarray、series类型数据
:param window: 对应着计算的是几日的EMA
:return: 返回ndarray的数据类型
'''
list_ema = []
list_ema.append(data[0])
for i in range(1, len(data)):
list_ema.append(2 * data[i] / (window+1) + (window-1) * list_ema[-1] / (window+1))
return np.array(list_ema)
def draw_macd(dif, dea, macd, axs=None, show=False):
'''
通过传入DIF、DEA、MACD的值绘制MACD指标的两线一柱
:param dif: DIF指标的list或者ndarray数据类型
:param dea: DEA指标的list或者ndarray数据类型
:param macd: 为了代码简洁,目前只支持ndarray类型的MACD数据
:param axs: 是否在子图绘制
:param show: 是否绘图
:return:
'''
x = np.arange(len(dif)) # 横坐标
drawer = axs if axs is not None else plt
drawer.plot(x, dif, label='DIF', color='b', linestyle='--') # 绘制DIF曲线
drawer.plot(x, dea, label='DEA', color='y', linestyle='-.') # 绘制DEA曲线
pos_index = x[macd >= 0] # 得到MACD值大于等于0的索引
neg_index = x[macd < 0] # 得到MACD值小于0的索引
drawer.bar(pos_index, macd[pos_index], color='r', label='macd bar', alpha=0.6) # 绘制MACD大于等于0部分的柱状图
drawer.bar(neg_index, macd[neg_index], color='g', label='macd bar', alpha=0.6) # 绘制MACD小于0部分的柱状图
drawer.legend()
if show:
plt.show()
if __name__ == '__main__':
# plot_ochl() # 绘制烛状图,会新建画布
ema_12 = EMA(data=tsla_df['close'], window=12) # 12日EMA的值
ema_26 = EMA(data=tsla_df['close'], window=26) # 26日EMA的值
dif = ema_12 - ema_26 # 利用ndarray之间的减法运算即为各对应元素相减,得到DIF
dea = EMA(data=dif, window=9) # 再计算DIF的9日EMA(该值被称为DEA)
macd = (dif - dea) * 2 # 计算MACD柱状图的值
fig, ax = plt.subplots(2, 1)
plot_ochl(tsla_df, axs=ax[0])
draw_macd(dif, dea, macd, axs=ax[1], show=True)
该部分主要介绍几个常见的研判标准,实际情况并不一定会和研判标准相符合,由MACD指标的数学公式以及数学计算过程可以了解到MACD指标有一定的延后性
这部分借鉴了百度百科和多个MACD指标研究文章,放在最后供大家学习代码后也可以了解一下一些MACD指标的研判标准
GItHub:ExileSaber
目前自己也正处于学习的阶段,感谢各位的评论和建议!