技术量化: 如何调用talib.STOCH函数才能使得KDJ指标计算值与常用股票软件一致?

发布于: 修改于:雪球转发:0回复:9喜欢:6

近日,想给我的小站ashares.info增添技术指标信号,本来觉得这个事情很简单,因为Python有现成的技术指标库,调用里面函数就可以了。结果折腾了一番发现不是那么回事。

首先介绍一下技术指标库,ta-lib 是一套使用C/C++写的技术指标库,形态指标、动量指标,应有尽有,非常丰富,包含了近200种。 TA-Lib 是ta-lib的一套python wrapper, 它方便了python开发人员调用ta-lib的库,毕竟底层语言C/C++的流行程度没有Python那么高。

我在投资助手小站上尝试实现了两种指标,一种是MACD, 另一种是KDJ。MACD 的实现很顺利,直接调用talib里面的MACD方法就可以了;而KDJ的实现却出现了问题。调用talib.STOCH函数求出的K、D、J三个值与主流股票软件图形上的值不一致。talib得出的金叉信号,在主流股票软件图形上并不是金叉,这就问题很大了。于是又深入研究了一下talib的实现算法,发现他们的具体实现还是有很大差别。

talib的实现是按照 Dr. George Lane最初创造的指标公式来实现的,详细见这里

下面是George Lane博士的公式

下面这个是我们股票软件上的实现公式:

两个公式变量名字有些不同,这里简单说一下

上图的FASTK就是下图的RSV;上图的FASTD在下图没有对应,上图的SLOWK对应下图的K, SLOWD对应下图的D, 上图没有变量J, 因为J=3*K-2*D (George Lane博士的公式说3*D -2*K)

实际上这个函数talib.STOCH只返回了两个变量slowd 和slowk, slowj可有这个两个变量求得。

fastk和fastd是快速随机变量函数talib.STOCH FAST返回的,因为快速随机变量实际应用有问题,很少有软件实现。

软件中的SMA是这样定义的:SMA(X,N,M) X的M日加权移动平均,M为权重,如Y=(XM+Y’(N-M))/N (Y’ 为前一日的Y值);并非talib中的SMA,talib实现的SMA是简单移动平均(Simple Moving Average),这一点要特别注意。

在求得RSV这一步两者是一致的,都是:

RSV =(单日收盘价-最低价集合中的最低价)/ (最高价集合中的最高价-最低价集合中的最低价)*100【观察周期是P1】

对K值的计算,从George Lane博士的公式上看,和软件中的实现也是一致的,软件中的公式是

SMA(RSV,P2,1) , George Lane博士的公式是MA Smoothed FastK over FastPeriod. 意思和公式是一致的,都是在P2 周期对RSV求平滑移动平均。两者的意思是一致的。问题出在具体实现上,因为两个SMA不一样。

STOCH的函数声明是这样的:

slowk, slowd = STOCH(high, low, close, fastk_period=5, slowk_period=3, slowk_matype=0, slowd_period=3, slowd_matype=0)

注意有两个参数slowk_matype=0和slowd_matype=0,这两个参数指定使用什么样的ma计算K和D,0代表SMA(Simple Moving Average),这个SMA与股票软件中的那个SMA实现是不一样的。股票软件中实现的SMA实际上是talib中的EMA函数。

 talib这样做显然是对ma的计算算法保持开放态度,因此不能说talib求出的K和D值与常用股票软件中不一致就是talib算错了。我相信talib经历了20年的发展,还是经得住时间的考验的。

按照网上一些帖子给出的自己计算K和D的算法:

K = pd.DataFrame(rsv).ewm(com=slowk_period-1).mean()

D = K.ewm(com=slowd_period-1).mean()

经过测试验证这样求的K和D,和我们常用的股票软件上显示的是一致的。这样进一步确定了股票软件上的算法:即是求的指数平均值(Exponential Moving Average).

我们再看看talib中EMA函数的实现算法:

看了talib WMA的实现公式发现,在计算EMA的alpha系数时,使用了span参数,而股票软件中的算法相当于dataframe.ewm()使用了com参数,这样在计算alpha权重系数时会有差别。

这两个参数是可以转换的,由上述alpha系数计算公式可以推导出s=2c+1 , 股票软件的计算公式相当于dataframe.ewm(com=m-1).mean, 代入c=m-1得出,当s=2m-1时,使用talib.EMA(cose,s=2m-1) 计算K和D的值与股票软件一致。

经多方查阅终于找到matype的值了:

matype :0 = SMA, 1=EMA,2=WMA,3=DEMA,4=TEMA,5=TRIMA,6=KAMA,7=MAMA,8=T3

这样就终于搞明白了,要想得到与股票软件中KDJ一样的数据,应这样调用talib.STOCH

这里贴出部分代码:

# 初始化KDJ参数:注意ma_type=1

 def init_kdj(self, fastk_period=9, slowk_period=3, slowk_matype=1,

             slowd_period=3,

             slowd_matype=1):

    self.fastk_period = fastk_period

    # s=2m-1 ,由com参数换算成span参数

    self.slowk_period = 2 * slowk_period - 1

    self.slowk_matype = slowk_matype

    self.slowd_period = 2 * slowd_period - 1

    self.slowd_matype = slowd_matype

调用函数计算KDJ

slowk, slowd = talib.STOCH(high_prices, low_prices, close_prices, self.fastk_period, self.slowk_period,

                           self.slowk_matype, self.slowd_period,

                           self.slowd_matype)

slowk = slowk.values

slowd = slowd.values

slowj = 3 * slowk - 2 * slowd

经过测试,果然丝毫不差!

参考资料:

网页链接

网页链接

网页链接

网页链接

全部讨论

01-27 00:01

特来谢一下帖子,另外补充一下,如果上面的代码计算结果仍对不上,可以把数据的时间段范围拉长,这样数据就能对上了。

01-21 10:02

请问,如何在iquant里对kdj的参数进行设置?

2023-02-04 09:51

若ma_type=0时,则不需要s=2m-1转换

2022-05-27 23:56

改成1还是不一致。