
您应当知道的 MQL5 向导技术(第 42 部分):ADX 振荡器
概述
ADX 指标是一款振荡器,旨在衡量其所附着证券于市场上的趋势强度。本文与之前的一些文章一样,为了向导汇编智能系统,验证在自定义信号类文件中该指标展现的各种形态。正如我们之前涵盖 RSI、布林带、和 SAR 的文章中所做的那样,我们一次审查一种形态,然后以包含所有形态的测试结束,从而了解哪种形态的权重最高。
在我们开始之前,我们还未结束对抛物线 SAR 的介绍,就此我们先从涵盖它的结局章节开始。
SAR 和成交量背离
回顾那篇文章,抛物线 SAR 主要用于识别潜在的逆转点,并在趋势市场中尾随止损。它们是“潜在的逆转点”,因为如果价格突破它们,那么指标将通过在高低价位范围的另一测标记点线来翻折,由此价格图表上生成的点线是价格动作的潜在逆转价位。这些点位标记为点线,随价格或低(在上升趋势中)、或高(在下降趋势中),令交易者去留意这些逆转。
成交量背离是指价格和成交量头朝相反方向发展。对于外汇交易者来说,“交易量”数据并非一个实用的概念,因为它跨越多个经纪商和平台分散。对此的折衷代替是价格柱线范围或波动性。因此,价格向任意方向延伸,并结合波动性下降,都可以作为延续形式的信号指标。
例如,如果抛物线 SAR 从价格下方翻折到上方(示意卖出信号),并且伴随着价格柱线范围的下降,这可以被解释为一个微弱的卖出信号,而更像是先前长期趋势延续的预兆。同样,当价格达到 SAR 上点线(在下降趋势中高于价格),并观察到波动性背离(价格-柱线-范围减小)时,该信号示意下降趋势可能加强、或开始向下延续。我们按如下方式编写该形态:
//+------------------------------------------------------------------+ //| Check for Pattern 7. | //+------------------------------------------------------------------+ bool CSignalSAR::IsPattern_7(ENUM_POSITION_TYPE T) { m_sar.Refresh(-1); m_sar_alt.Refresh(-1); if(T == POSITION_TYPE_BUY && Base(StartIndex() + 1) < Low(StartIndex() + 1) && Base(StartIndex()) > High(StartIndex())) { return(Range(StartIndex()) < Range(StartIndex() + 1) && Range(StartIndex() + 1) < Range(StartIndex() + 2)); } else if(T == POSITION_TYPE_SELL && Base(StartIndex() + 1) > High(StartIndex() + 1) && Base(StartIndex()) < Low(StartIndex())) { return(Range(StartIndex()) < Range(StartIndex() + 1) && Range(StartIndex() + 1) < Range(StartIndex() + 2)); } return(false); }
值得注意的是,从上面的源码,我们现在专注于更大的先前趋势,而不像在最先的第一个形态 0 那样按同样简单方式使用信号。效果上,这是一个逆势信号,因为我们正在猎捕弱翻折的延续形态。这种“弱”翻折可通过价格柱线下跌超过 3 根柱线范围来确认。这个长度 3 是可调的,但出于测试目的,我们将坚持使用它。
相较之,如果价格在波动性上升时触及任一 SAR 点线阈值,则应是 SAR 翻折的确认信号。该信号也基于成交量背离论点,本质上就像我们在早前关于 SAR 的文章中讲述的形态 0,加上检查增加价格柱线范围。这个特定的形态没有编码或测试,但一如既往,欢迎读者对其考察。
此外,按这种形态,交易者可用成交量背离加之抛物线 SAR 来放置策略性止损调整。如果我们回到上面提到的第一个成交量背离设置,我们正在寻找指向强劲延续的弱翻折,这些信号意味着趋势暂停,并可能表示主要支撑位或阻力位。好在可据弱 SAR 翻折和波动性下降来识别它们,交易者可为持仓设置止损、或随主导趋势移动,如果持仓为空头,则位于这些区域的上方,如果持仓是多头,则略低于它们。
抛物线 SAR 可以在区间或波动的市场中产生许多假信号,这就是为什么在纸面上,成交量背离检查可能是一个福音。特别是在波动性增加的情况下,它能有助于避免过早入场,因为波动性上升不断刺穿 SAR 标记,往往表明趋势发展的势头明显。如果这还不够,它还能与其它指标相结合。
这些组合可能更适合一些振荡指标,诸如 RSI,并且由于我们只编写了 SAR 交易量背离的第一个实现代码,即确认延续而非确认逆转,故读者需要准备编写代码,检查这些额外的指标,以备逆转。依据外汇对 EUR USD,2022 年的日线时间帧,测试形态 7,我们得到以下结果:
我们用于形态 7 的位图整数是 0x80,它转换为十进制值的输入整数为 128,一旦设置好,智能系统仅用形态 7 进行交易。
在更高的时间帧上的逆转 SAR
更高时间帧上的抛物线 SAR 能很好地提供更广阔的趋势视角,并有助于过滤掉较小时间帧中普遍存在的假翻折噪音。如果周线图表上的 SAR 是强劲上升趋势信号,则使用 4-小时图表的交易者可以优先考虑做多,并忽略较低时间帧上的卖出信号,仅将其视为潜在的噪音、或短期回调。
在两个时间帧上的信号一致的情况下,它体现的信号更强。如果 4-小时时间帧看涨,并且 15-分钟时间帧 SAR 点下限于价格范围断裂,则示意翻折,那么这个特定点不仅可以发出强烈的信号,还有“更清晰”的入场。也有一些策略运用逆势交易,但这些策略可能充满风险,因为“趋势是您的朋友”这句格言对大多数交易者而言有益。通过依赖多个时间帧上的 SAR 确认,能避免不可靠的逆势入场风险。
SAR 不仅当作入场信号,还当作离场指标。通过使用由向导汇编的智能系统及其附带类,即利用开仓和平仓阈值,我们可以更好地真正实现这一点,而无需提供任何补充代码。本文末尾所附代码的使用、及其汇编智能系统的内容,在 此处 和 此处 为新读者准备的文章中进行了讲述。包含的 MQ5 扩展文件简单地展示运行向导后所汇编文件的外观,以及正确引用所汇编智能系统时需要存在的所有必要文件。故此,检查更多而非一个时间帧能确保离场更精确,这在纸面上应该会产生更好的性能。
交易者可在较低时间帧上开仓,并用更高时间帧上的 SAR 价位为其设置止损价位。这种方式确保止损设置在显要价位,从而降低因短期波动而过早止损的机会。较高时间帧的 SAR 趋势可能示意更长久的市场趋势,而较低时间帧则捕捉利用这些主要动向的入场点。我们的 MQL5 实现如下:
//+------------------------------------------------------------------+ //| Check for Pattern 8. | //+------------------------------------------------------------------+ bool CSignalSAR::IsPattern_8(ENUM_POSITION_TYPE T) { m_sar.Refresh(-1); m_sar_alt.Refresh(-1); if(T == POSITION_TYPE_BUY && Base(StartIndex() + 1) > High(StartIndex() + 1) && Base(StartIndex()) < Low(StartIndex())) { return(Alt(StartIndex()) < LowAlt(StartIndex())); } else if(T == POSITION_TYPE_SELL && Base(StartIndex() + 1) < Low(StartIndex() + 1) && Base(StartIndex()) > High(StartIndex())) { return(Alt(StartIndex()) > HighAlt(StartIndex())); } return(false); }
我们执行测试时采用与上述形态 7 类似的设置,但采用周线时间帧作为我们的备用时间帧,并产生了以下结果:
我们使用输入位图 256 来表示第九个形态,形态-8。因此,总而言之,较高时间帧 SAR 有助于交易者了解更大市场境况,并据较低时间帧信号操作。这种上下文视图有助于避免过度交易、或依据与更宽广趋势不一致的微不足道信号采取行动。
SAR 和 RSI 重叠
正如本系列最近一篇文章所强调的那样,RSI 是一款衡量价格走势速度和变化的振荡指标,通常用于检测超买和超卖条件。它的操作范围在 0 到 100 拉伸,其中读数高于 70 表示超买情况,低于 30 表示超卖。当与 SAR 配对时,可以实现互补,并有助于识别趋势。
抛物线 SAR 可有效地识别当前趋势、或潜在的趋势逆转,但它也能在波动或横盘整理的市场中产生假信号。这就是为什么 RSI 可以添加一个动量分析层,帮助确认市场是否确实超买或超卖,从而再次确认据 SAR 所识别趋势的强弱。故此,当抛物线 SAR 低于价格,表明上升趋势,并且 RSI 显示读数在 30 附近(表明超卖情况)时,它加强了趋势逆转像是可靠的、并有上升势头的信号。
不过,与 SAR 的组合可采取两次翻折。回想一下,RSI 是一款动量计量器,市场上经常会出现突发,其中动量或给定的波动可能会持久。为此,即使默认情况下,如上所述,我们会用 SAR 来确认“超买”状况,更常用它确认普遍动量,特别是如果考虑缩小 SAR 的翻折指标状况,并查看沿每个趋势的点-价格敞口、或点变化。这些显然可作为 SAR-RSI 配对的备案。不过,我们并未实现这一点,但在此只作为一个论点。代之,我们使用 “传统” 方法,我们利用 MQL5 实现该方式,如下所示:
//+------------------------------------------------------------------+ //| Check for Pattern 9. | //+------------------------------------------------------------------+ bool CSignalSAR::IsPattern_9(ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && Base(StartIndex()) < Low(StartIndex())) { return(RSI(StartIndex()) <= 30.0); } else if(T == POSITION_TYPE_SELL && Base(StartIndex()) > High(StartIndex())) { return(RSI(StartIndex()) >= 70.0); } return(false); }
用我们上面的清单测试,并没有给我们带来很多交易,因为在日线时间帧内往往会持续存在,这一切都为我们实现上述 SAR-RSI 组合的第二种方式提供了理由。这些测试的结果如下所示:
如查看各种形态指标时的情况,我们以一份优化的测试报告作为结论,该报告在我们的测试窗口期间为每个形态挑选了多个模式和自定义阈值。抛物线 SAR 的这些类似测试结果如下所示:
使用多个形态,每个形态都伴以其理想的阈值,以我的观点,如果这些阈值未经某个狭窄区间前向测试的情况下被挑选或优化,那么是合适的。最好基于个人对实况运用性能的评估,按预设值使用、或测试它们。
ADX 概览
ADX 振荡器通过使用 3 个缓冲区来衡量给定趋势的强度。其中,DI+ 和 DI- 能视作单独的指标,因为它们衡量价格在预设方向上的强度。DI+(又名正方向指数)衡量上行走势的强度,而 DI-(负向指数)则为价格下行走势的强度打上一个数字。因此,当 DI+ 高于 DI- 时,表明买家比卖家拥有更大的影响力,反之亦然。
DI+ 缓冲区得自历史价格走势中高于前一高点,这意味着如果今天的高点大于昨天的高点,则会记录一个正 DI+ 值。相反,DI- 得自当前低点低于前一低点,因此,如果我们得到低于前一低点的低点,如此缓冲区里就会记录一个 DI- 值,以上均假设采用日线时间帧。
DI+ 和 DI- 的公式为:
DI+ =(平滑正向走势 / 平均真实范围)× 100
DI- =(平滑负向走势 / 平均真实范围)× 100
平均真实范围、或 ATR 组件是这些缓冲区的关键部分,在于它通过参考当时普遍的波动性来归一化指标值。这是因为,正如人们所料,在波动的环境中,高点或低点的大幅变化往往频繁发生,因此通过归一化到真实范围(TR),在指标缓冲区中只有大的波动(尽管有 TR)才得到相应的权重。TR 是通过选择 3 个选项中最大的一个来计算,即当前高点减去当前低点,当前高点减去前一收盘价,前一收盘价减去当前低点。然后,依据它们的交叉点、以及其它指标的组合,观察来自这些缓冲区的信号,如我们下面所见。
ADX 的 DI+ 和 DI- 交叉
对于我们的第一个形态 pattern-0,当 DI+ 上穿 DI- 时表示看涨信号,它表明买入压力大于卖出压力,可能标志着上行趋势的开始。相反,当 DI- 上穿 DI+ 时,为看跌信号(DI -> DI+),表明卖出压力强于买入压力,可能标志着下行趋势的开始。我们实现该形态的 MQL5 版本如下:
//+------------------------------------------------------------------+ //| Check for Pattern 0. | //+------------------------------------------------------------------+ bool CSignalADX::IsPattern_0(ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && BasePlus(X() + 1) < BaseMinus(X() + 1) && BasePlus(X()) > BaseMinus(X())) { return(true); } else if(T == POSITION_TYPE_SELL && BasePlus(X() + 1) > BaseMinus(X() + 1) && BasePlus(X()) < BaseMinus(X())) { return(true); } return(false); }
ADX 主缓冲区衡量趋势的强度,而非其方向。它在 0 到 100 之间振荡,读数高于 25 表示趋势强劲,而低于 25 表示市场疲软、或无趋势。重点要再次强调,ADX 并不表示趋势是看涨还是看跌,它只简单地衡量趋势强度。当 ADX 上升且 DI+ 高于 DI- 时,表明强劲的看涨趋势。如果 ADX 正在上升,并且 DI- 高于 DI+,则表明强劲的看跌趋势。
据外汇对 EUR CHF,2022 年日线时间帧, 优化该形态的开仓和平仓阈值,以及止盈水平,为我们提供“理想”设置之一的结果:
ADX 高于 25 — 强劲趋势入场
我们已考察上面的两个 DMI 缓冲区,DI+ 和 DI-,但 ADX 的第 3 个缓冲区是其主缓冲区。它还提供 0 到 100 范围内的读数。它是通过首先判定方向指数来计算的,该指数由以下公式给出:
其中:
- DX 是寻求的方向指标
- +DI 是已判定的正方向走势,其公式如上所示
- -DI 是负数对应物,其公式也如上
一旦我们有了方向指数(DX),获取平均方向指数只涉及过去 14 个方向指数值的指数移动平均线。备案是,采用遵循下面所分享公式的平滑方式:
其中:
- n 是 14,或输入到 ADX 指标中的任何合适的平均周期。
我们的 MQL5 实现如下:
//+------------------------------------------------------------------+ //| Check for Pattern 1. | //+------------------------------------------------------------------+ bool CSignalADX::IsPattern_1(ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && Base(X()) > 25.0 && BasePlus(X()) > BaseMinus(X())) { return(true); } else if(T == POSITION_TYPE_SELL && Base(X()) > 25.0 && BasePlus(X()) < BaseMinus(X())) { return(true); } return(false); }
在优化时,搭配形态 0 类似的环境设置,其中我们的交易品种是 EURCHF,2022 年日线时间帧,我们得到以下结果:
ADX 跌破 25 — 趋势疲软
形态 2 是形态-1 的逆反,通过寻找 ADX 主缓冲区下穿 25 的实例,与 DI+ 到 DI- 价差所指示的当前趋势相反。故此,每当 ADX 从上方穿越至 25 下方,并且 DI- 高于 DI+ 时,这被解释为看涨,因为这是看跌势头减弱的迹象。同样,如果当 DI+ 高于 DI- 时发生相同的 ADX 交叉,应当是看跌,同样是一个早期迹象。我们的 MQL5 实现如下:
//+------------------------------------------------------------------+ //| Check for Pattern 2. | //+------------------------------------------------------------------+ bool CSignalADX::IsPattern_2(ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && Base(X()+1) > 25.0 && Base(X()) < 25.0 && BasePlus(X()) < BaseMinus(X())) { return(true); } else if(T == POSITION_TYPE_SELL && Base(X()+1) > 25.0 && Base(X()) < 25.0 && BasePlus(X()) > BaseMinus(X())) { return(true); } return(false); }
优化测试的运行设置如上述形态,为我们提供形态 2 的结果如下:
ADX 与移动平均线交叉
对于形态-3,所应用的补充移动平均线不是典型的价格移动平均线,而是来自 ADX 主缓冲区的另一个移动平均线值。即使这也能作为 ADX 的并行缓冲区进行跟踪,当 ADX 按照穿越价格图表移动均线的同样方式穿越它时,这往往是一个强大的信号。回想一下 ADX 本身是方向中性的,但它仅通过类似的交叉来表示当下信号的强度,无论是多头还是空头。我们在代码中实现这一点,如下所示:
//+------------------------------------------------------------------+ //| Check for Pattern 3. | //+------------------------------------------------------------------+ bool CSignalADX::IsPattern_3(ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && Base(X()+1) < BaseAverage(X()+1) && Base(X()) > BaseAverage(X()) && BasePlus(X()) > BaseMinus(X())) { return(true); } else if(T == POSITION_TYPE_SELL && Base(X()+1) < BaseAverage(X()+1) && Base(X()) > BaseAverage(X()) && BasePlus(X()) < BaseMinus(X())) { return(true); } return(false); }
按上述形态类似的设置,对选定的优化结果运行测试,如下所示:
ADX 与价格背离
在主要证券价格图表上,基于当下价格动作与 ADX 的背离。不过,这种“背离”有点古怪,是因人们总在寻找 ADX 主缓冲的下降,与价格图表上任一方向的强劲趋势相悖。故此,看涨背离的标志是证券价格图表上的价格下跌,同时 ADX 振荡器主缓冲区下跌。看跌背离的特征是价格图表上的看涨趋势,同时 ADX 振荡指标也下跌。我们的 MQL5 实现如下:
//+------------------------------------------------------------------+ //| Check for Pattern 4. | //+------------------------------------------------------------------+ bool CSignalADX::IsPattern_4(ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && Close(X()+2) > Close(X()+1) && Close(X()+1) > Close(X()) && Base(X()+2) > Base(X()+1) && Base(X()+1) > Base(X()) && Base(X()) <= 25) { return(true); } else if(T == POSITION_TYPE_SELL && Close(X()+2) < Close(X()+1) && Close(X()+1) < Close(X()) && Base(X()+2) > Base(X()+1) && Base(X()+1) > Base(X()) && Base(X()) <= 25) { return(true); } return(false); }
按其最佳设置运行测试得到以下结果:
ADX 与范围突破
形态-5 很像上面的形态-4,依靠来自证券价格图表中的价格行为来打造并确认其信号。不过,在这种情况下,我们是在寻找长时间盘整后的价格突破,且得到 ADX 上穿 25 阈值的背书。看涨信号是价格越过阻力位上涨,同时 ADX 上涨至 25 以上。同样,看跌信号是价格下跌,越过支撑位,并得到 ADX 越过 25 的背书。我们的 MQL5 实现如下:
//+------------------------------------------------------------------+ //| Check for Pattern 5. | //+------------------------------------------------------------------+ bool CSignalADX::IsPattern_5(ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && ATRAverage(X()+1) > ATR(X()+1) && ATRAverage(X()) < ATR(X()) && ATR(X()) < High(X())-Low(X()) && Base(X()+1) < 25 && Base(X()) > 25 && Close(X()+1) < Close(X())) { return(true); } else if(T == POSITION_TYPE_SELL && ATRAverage(X()+1) > ATR(X()+1) && ATRAverage(X()) < ATR(X()) && ATR(X()) < High(X())-Low(X()) && Base(X()+1) < 25 && Base(X()) > 25 && Close(X()+1) > Close(X())) { return(true); } return(false); }
在代码中简洁地定义盘整和突破非常麻烦,尽管折对于手工交易者来说很简单。我们的变通之法是依靠 ATR 指标,并获取其在相当长的历史时间内的读数,并将其与最近的价格柱线范围进行比较。如果 ATR 在合理的时间内保持低迷,并且小于最近的价格柱线范围,那么这可能意味着突破。无论如何这都是不精确的,我确信可以做到更彻底的实现,但就我们的目的而言,在本文中,它已足够了!按类似于上面曾讲述形态的设置,最佳优化结果的测试运行为我们提供了以下报告:
尽管我们努力为所有形态提供相似的测试环境和设置,但在日线时间帧上,这种特定形态几乎没有产生任何交易。这就是为什么破例来优化小时时间帧,看看是否可以看到更多的突破,从而可以下单。因此,上面的结果基于每小时,而不是每天,就像上面的其它形态一样。
结束语
于此,我们将不得不暂停对 ADX 的观察,是因还有 3 种形态会作为我们下一个研究指标的一部分。回顾一下,我们已在形态的基础上研究了 ADX,其可在向导汇编的智能系统里的信号类所用,因为智能信号类中已经有一些代码可以帮助处理这些。在汇编智能系统里所用的向导汇编类提供了许多函数和方法,如此显然消除了从零开始编码的需要,尤其是在探索或测试思路的初步阶段。除了形态用法之外,还有其它领域我们尚未在本系列中研究,例如挂单的使用、自定义订单流、或可以随时并发开仓的数量、使用 ATR 等指标来指导价格跳空,不仅可输入尾随止损参数,还有初始止损和止盈水平, 以及更多。希望我们在未来的某个时候能看到这些、以及更多,与此同时,我们将深化基础知识。形态和常见指标。
本文由MetaQuotes Ltd译自英文
原文地址: https://www.mql5.com/en/articles/16085
注意: MetaQuotes Ltd.将保留所有关于这些材料的权利。全部或部分复制或者转载这些材料将被禁止。
This article was written by a user of the site and reflects their personal views. MetaQuotes Ltd is not responsible for the accuracy of the information presented, nor for any consequences resulting from the use of the solutions, strategies or recommendations described.



