本文实现了对 TA-Lib 技术分析库的 Python 封装库 ta-lib 的进一步封装和扩展。此次共计封装 73 个指标,其中 35 个是对原有 ta-lib 实现的封装,剩余的 38 个则作为扩展,实现了部分 TradingView 支持的技术指标。本文主要列举扩展部分的一些指标的 Python 实现,并在文末列出此次封装的完成和拟合程度的统计信息。

正如在「Pandas 库部分核心技术在技术分析中的应用」一文中提到的算法和数据结构在时间序列数据处理上性能差异,这里大部分的实现都使用了向量化运算,部分甚至直接使用了 NumPy 的数组结构。但是需要注意的是,此次的实现,并没有过多关注性能上的优化,大部分的向量化运算仍然是基于 Pandas 的 SeriesDataFrame 结构。另一方面,封装库 ta-lib 本身也还有很大的性能提升空间。以真是波动幅度 TRange 指标为例,测试发现直接基于 NumPy 的实现要比调用 ta-lib 的封装实现性能高出 2 倍多。技术分析库的性能优化也将作为后续工作的主要内容之一。

除了标量参数外,如无特殊说明,传入接口的数据均为 Pandas 的 Series 数据类型。后续会像 ta-lib 一样同时支持 Seriesndarray 数据类型。

import numpy as np
import pandas as pd
import talib as ta

测试环境:macOS 10.13.3;Python 3.6.5;Pandas 0.23.0;NumPy 1.14.2;TA-Lib 0.4.17。

Arnaud Legoux Moving Average (ALMA)

  • Arnaud Legoux 移动均线(ALMA)是由 Arnaud Legoux 和 Dimitris Kouzis-Loukas 在 2009 年创造的,应该算是均线指标家族的一个比较新的成员了。它较好地解决了传统均线指标的两大缺陷:自适应性(responsiveness)和平滑性(smoothness)。具体的说明和计算公式,可参考代码注释中的链接。
  • 以下是 ALMA 指标的 Python 实现,和 TradingView 数据的比对结果略有差异,后续有待进一步调试。
def ALMA(close, win_size=9, offset=0.85, sigma=6):
    """Arnaud Legoux Moving Average (ALMA)

    PDF:  https://bit.ly/2JhEX7p
    """
    def alma(c, i):
        m = offset * (win_size-1)
        s = win_size / sigma
        w = np.exp(-(i-m) * (i-m) / (2*s*s))
        alma = (c[::-1] * w).sum()
        wsum = w.sum()
        return alma/wsum
    index = np.arange(0, win_size, 1)
    ALMA = close.rolling(win_size).apply(
        lambda x: alma(x.values, index), raw=False)
    name = 'ALMA({}, {}, {})'.format(win_size, offset, sigma)
    return pd.Series(ALMA, name=name)

Hull Moving Average (HMA)

  • HMA 均线是由 Alan Hull 所创造的,是基于加权移动平均线(WMA)的一种十分快速和平滑的均线。具体的说明和计算公式,可参考代码注释中的链接。
  • 以下是 HMA 指标的 Python 实现,和 TradingView 数据的比对结果完全一致。
def HMA(close, length=9):
    """Hull Moving Average (HMA)

    Fidelity:   https://bit.ly/2Jhuvge
    InstaForex: https://bit.ly/2Hi4Su0
    """
    n = length
    n1 = np.ceil(length/2)
    n2 = np.ceil(np.sqrt(length))
    HMA = ta.WMA(2*ta.WMA(close, n1) - ta.WMA(close, n), n2)
    name = 'HMA({})'.format(length)
    return pd.Series(HMA, name=name)

Ichimoku Cloud (ICLOUD)

  • Ichimoku Cloud 一目均衡表指标,也称为 Ichimoku Kinkō Hyō,是由日本记者细田悟一在 1969 年公开发布的。该指标的用途较为广泛,既可以可来于定位支撑位和阻力位,也可以用来判断趋势。它一共包括五条线,其中四条是基于最高价和最低价来计算的,第五条则是根据收盘价计算的。具体的说明和计算公式,可参考代码注释中的链接。
  • 以下是 ICLOUD 指标的 Python 实现,和 TradingView 数据的比对结果完全一致。
def ICLOUD(high, low, close,
           conv_len=9, base_len=26, span_len=52, disp_len=26):
    """Ichimoku Cloud (ICLOUD)

    Fidelity:     https://bit.ly/2J9VqPl
    Investopedia: https://bit.ly/2qYIosE
    StockCharts:  https://bit.ly/1viraOI
    Wiki:         https://bit.ly/2JdU3za
    """
    TS = (ta.MAX(high, conv_len)+ta.MIN(low, conv_len)) / 2
    KS = (ta.MAX(high, base_len)+ta.MIN(low, base_len)) / 2
    CS = close.shift(-disp_len)
    SSA = ((TS+KS) / 2).shift(disp_len)
    SSB = ((ta.MAX(high, span_len)+ta.MIN(low, span_len)) / 2).shift(disp_len)
    ts_name = 'TS({})'.format(conv_len)
    ks_name = 'KS({})'.format(base_len)
    cs_name = 'CS({})'.format(-disp_len)
    ssa_name = 'SSA({})'.format(disp_len)
    ssb_name = 'SSB({}, {})'.format(span_len, disp_len)
    return pd.Series(TS, name=ts_name), \
        pd.Series(KS, name=ks_name), \
        pd.Series(CS, name=cs_name), \
        pd.Series(SSA, name=ssa_name), \
        pd.Series(SSB, name=ssb_name)

Keltner Channels (KC)

  • KC 指标类似于布林通道(Bollinger Bands),是一种带状指标,其中行线是价格的(指数)移动均线,而上行线和下行线通常都是最高价和最低价的平均真实波幅(ATR)的倍数。具体的说明和计算公式,可参考代码注释中的链接。
  • 以下是 KC 指标的 Python 实现,和 TradingView 数据的比对结果几乎一致,误差小于 4e-5。误差的来源主要是在计算 ATR 指标时已经引入了误差。

另外需要注意的是,TradingView 的 KC 指标中并没有 ATR 指标中周期参数的设置,因此直接使用默认值 14,其结果也最为接近。

def KC(high, low, close, length=20, mult=1):
    """Keltner Channels

    Investopedia: https://bit.ly/2HiIwIT
    StockCharts:  https://bit.ly/2GFGS8Q
    TradingView:  https://bit.ly/2JvU4Og
    """
    KC_ML = ta.EMA(close, length)
    KC_UL = KC_ML + mult*ta.ATR(high, low, close, 14)
    KC_LL = KC_ML - mult*ta.ATR(high, low, close, 14)
    ml_name = 'KC({}, {})_ML'.format(length, mult)
    ul_name = 'KC({}, {})_UL'.format(length, mult)
    ll_name = 'KC({}, {})_LL'.format(length, mult)
    return pd.Series(KC_UL, name=ul_name), \
        pd.Series(KC_ML, name=ml_name), \
        pd.Series(KC_LL, name=ll_name)

Coppock Curve (COPP)

  • COPP 指标,即估波曲线,是经济学家 Edwin Coppock 在 1965 年发明的一种动量指标,主要用于识别长线的买入信号。具体的说明和计算公式,可参考代码注释中的链接。
  • 以下是 COPP 指标的 Python 实现,和 TradingView 数据的比对结果完全一致。
def COPP(close, wma_len=10, roc_long=14, roc_short=11):
    """Coppock Curve

    Investopedia: https://bit.ly/2JfQK6n
    StockCharts:  https://bit.ly/1Rccu0L
    """
    COPP = ta.WMA(ta.ROC(close, roc_long) + ta.ROC(close, roc_short), wma_len)
    name = 'COPP({}, {}, {})'.format(wma_len, roc_long, roc_short)
    return pd.Series(COPP, name=name)

Relative Vigor Index (RVGI)

  • 相对能量指数指标 RVGI 的核心思想是在上升趋势中,收盘价总是会高于开盘价;而在下降趋势中,则反之。RVGI 线和其信号线之间的关系预示着买入或卖出的时机。具体的说明和计算公式,可参考代码注释中的链接。
  • 以下是 RVGI 指标的 Python 实现,和 TradingView 数据的比对结果完全一致。
def RVGI(open, high, low, close, length=10):
    """Relative Vigor Index (RVGI)

    Fidelity:    http://bit.ly/2kNZea8
    LinnSoft:    http://bit.ly/2HmdzmW
    MetaTrader5: http://bit.ly/2HjTH3O
    TradingView: http://bit.ly/2kNM0tX
    """
    CO = close - open
    HL = high - low
    NT = ta.SUM((CO + 2*CO.shift(1) + 2*CO.shift(2) + CO.shift(3)) / 6, length)
    DT = ta.SUM((HL + 2*HL.shift(1) + 2*HL.shift(2) + HL.shift(3)) / 6, length)
    RVGI = NT / DT
    r_name = 'RVGI({})'.format(length)
    SIG = (RVGI + 2*RVGI.shift(1) + 2*RVGI.shift(2) + RVGI.shift(3)) / 6
    s_name = 'SIG'
    return pd.Series(RVGI, name=r_name), \
        pd.Series(SIG, name=s_name)

Vortex Indicator (VTX)

  • 漩涡指标(VTX)由 Etienne Botes 和 Douglas Siepman 所创造,它包含两个振荡线来捕捉正向和反向的移动趋势,而牛熊信号则在两线交叉时触发。具体的说明和计算公式,可参考代码注释中的链接。
  • 以下是 VTX 指标的 Python 实现,和 TradingView 数据的比对结果完全一致。
def VTX(high, low, close, timeperiod=14):
    """Vortex Indicator

    PDF:         http://bit.ly/2sD5fKc
    TraderHQ:    http://bit.ly/2Jb1Uxg
    StockCharts: http://bit.ly/2JfRbBS
    Wiki:        http://bit.ly/2J9FXPb
    """
    PLUS_VM = (high - low.shift(1)).abs()
    S_PLUS_VM = ta.SUM(PLUS_VM, timeperiod)
    MINUS_VM = (low - high.shift(1)).abs()
    S_MINUS_VM = ta.SUM(MINUS_VM, timeperiod)
    TR = ta.TRANGE(high, low, close)
    S_TR = ta.SUM(TR, timeperiod)
    PLUS_VI = S_PLUS_VM / S_TR
    p_name = '+VI({})'.format(timeperiod)
    MINUS_VI = S_MINUS_VM / S_TR
    m_name = '-VI({})'.format(timeperiod)
    return pd.Series(PLUS_VI, name=p_name), \
        pd.Series(MINUS_VI, name=m_name)

技术分析封装库的数值比对结果

  • 下图是某交易代码 2018-05-30 12:00:00 时刻 TradingView 给出的 K 线指标数据,同时列出了上述 Python 实现的数值结果以供比对。

虽然本文只列举了部分 TradingView 指标的 Python 实现,但其他指标都可以依据指标的原理和计算公式,辅以 ta-lib 库和 Pandas 与 NumPy 的向量化运算来实现。

FhINM7YQnrKzCPOC.png

# [INFO] Inidicator: Arnaud Legoux Moving Average (ALMA)
           datetime  ALMA(9, 0.85, 6)
2018-05-30 12:00:00       7469.484217
# [INFO] Inidicator: Hull Moving Average (HMA)
           datetime       HMA(9)
2018-05-30 12:00:00  7499.848519
# [INFO] Inidicator: Ichimoku Cloud (ICLOUD)
           datetime    TS(9)   KS(26)  CS(-26)      SSA(26)  SSB(52, 26)
2018-05-30 12:00:00  7478.05  7305.50   7570.2  7194.175000  7238.850000
# [INFO] Inidicator: Keltner Channels (KC)
           datetime  KC(20, 1)_UL  KC(20, 1)_ML  KC(20, 1)_LL
2018-05-30 12:00:00   7484.580190   7419.546482   7354.512774
# [INFO] Inidicator: Coppock Curve (COPP)
           datetime  COPP(10, 14, 11)
2018-05-30 12:00:00          3.505868
# [INFO] Inidicator: Relative Vigor Index (RVGI)
           datetime  RVGI(10)       SIG
2018-05-30 12:00:00  0.059599  0.082475
# [INFO] Inidicator: Vortex Indicator (VTX)
           datetime   +VI(14)   -VI(14)
2018-05-30 12:00:00  1.071844  0.959893

技术分析封装库的统计和说明

具体的封装统计信息可参见「此文档」。除了上述几个指标的说明之外,其他一些指标的备注说明如下。

  • Chande Momentum Oscillator(CMO)指标的扩展实现比原生的 ta-lib 的实现更为接近 TradingView 的结果。
  • ta-lib 中的 DX() 函数对应 Directional Movement Index(DMI)指标,但只返回一列数据。而 TradingView 中的 DMI 指标实际上同时包含了三个指标:+DI、-DI 和 ADX。
  • TradingView 中的 Moving Average Convergence/Divergence(MACD)指标对快慢线使用的是 EMA 均线,而信号线则使用的是 MA。因此,不能直接使用原生的 MACD() 函数,而应使用 MA 可控型函数,即 MACDEXT()
  • Percentage Price Oscillator(PPO)的计算公式要求使用 EMA 均线,而 TradingView 使用的是 SMA 均线。
  • ta-lib 原生的 STOCHRSI() 函数和 TradingView 的结果差异较大,且不同交易所对该指标的实现也不尽相同。作为折中,应依照该指标的计算公式进行实现。
  • TradingView 的 Mass Index(MASS)指标只接受一个 Mass 长度参数,其中的 EMA 均线长度则默认使用 9。类似地,Relative Volatility Index(RVI)指标的 EMA 均线长度默认为 14。

发表新评论

沪ICP备17018959号-3