绘制之字转向的不同方法
显然,之字转向有两种状态: 它的方向向上或者向下。当线的方向是向上时 — 监视价格看是否有新高出现, 而当线的方向是向下时 — 等待新低的出现。还需要监视看是否满足条件指示有方向的改变,所以,为了画出一条之字转向,需要做的是:
![](https://gbres.dfcfw.com/Files/iimage/20240523/A2035A47796A83652B1AB634CBD3EB42_w520h520.jpg)
添加图片注释,不超过 140 字(可选)
获取源数据;
构建线形改变方向的条件公式;
监视价格新高和新低的出现。
源数据可以是单独一个序列 (例如,柱的收盘价) 或者两个序列 (例如,柱的最高价和最低价),如果使用了一个数据序列,它可以不仅使用收盘价,而且可以是任何指标,震荡指标或者移动平均。当根据指标数据绘制之字转向时,也可能使用两个数据序列: 一个是基于柱的最高价的指标数据,而另一个是基于柱的最低价的数据。
方向改变的条件是最重要的一点,它定义了之字转向的不同类型。这些条件可能有很大的不同。例如,这样的条件可以是根据当前柱与n个柱的最高价/最低价做比较而构成,换句话说,如果当前柱的源数据的值是最近n个柱的最大值或者最小值,这就定义了之字转向的方向。这个原则应用在经典的之字转向指标中。另一个方法 — 根据从固定最大值或者最小值回滚的大小。回滚的大小可以以点数衡量 (如果源序列为价格) 或者是约定的单位 (如果是某些指标)。可以使用的方法并不局限于这两种,也可以使用任何指标判断方向 — 如随机震荡指标, ADX, 等等。如果随机震荡指标在50以上,之字转向指标就指向上方,如果它低于50 - 就指向下方。现在,根据 ADX 判断方向:如果 PDI 线在 MDI 线上方,之字转向线就指向上方,如果 PDI 低于 MDI,就指向下方。 这样,为第一点和第二点通过组合不同的变化,就能获得各种不同的之字转向。另外,当然还可以使用 RSI 数据用于第一点而根据随机震荡指标来判断方向,以此类推。第三点只对看起来类似于之字转向的指标有必要,尽管绘制选项可以有很大不同。 因为赫兹量化交易软件这里的任务是获得一个通用指标,有必要尽可能小心地把算法分成两个部分: 对于所有之字转向都同样的部分 (把它称为共用部分) 以及依赖于之字转向的不同部分 (把它称为个体部分)。个体部分使用源数据填充指标缓冲区: 价格或者指标数据。另一个缓冲区 (决定之字转向线的方向)用1或者-1值来填充。这三个缓冲区传给共用部分,在其中会使用它们绘制指标本身。 为了使过程更加清楚,首先创建一个单独的指标,它基于柱的最高/最低价,并且根据第n个柱的最高/最低价来改变放向。 基于最高价/最低价的简单之字转向指标 在 MetaEditor 中创建一个新指标 (主菜单 — 文件 — 新建或者按下 Ctrl+N). 在指标创建向导中,输入名称“iHighLowZigZag”,创建一个外部参数 "period" (int 类型, 数值为 12), 选择 OnCalculate(...,open,high,low,close) 事件处理函数, 创建一个缓冲区,名称为 "ZigZag" (Section 类型, 使用红色) 以及另外三个缓冲区,名称分别为 "Direction", "LastHighBar" 和 "LastLowBar" (line 类型, 颜色为 none)。 "ZigZag" 缓冲区将用于显示之字转向,其余的缓冲区是辅助的。对于所有的辅助缓冲区,在OnInit()函数中,调用SetIndexBuffer()函数把 INDICATOR_DATA 类型改为 INDICATOR_CALCULATIONS类型。在文件的顶部,修改 indicator_plots 属性的值: 把数值设为 1。在那以后,指标会只画一个 "ZigZag" 缓冲区, 并且指标不会画任何多余的线,但是同时,另外的缓冲区可以用来由 iCustom() 函数做处理。 首先,开始计算的柱的索引('start'变量)是在OnCalculate()函数中确定的,所以只有在指标开始的时候才会计算所有的柱,以后的计算只在每个新柱上进行。另外,还要初始化缓冲区的元素: int start; // 开始计算的柱的索引 if(prev_calculated==0) { // 在启动时 // 初始化缓冲区元素 DirectionBuffer[0]=0; LastHighBarBuffer[0]=0; LastLowBarBuffer[0]=0; start=1; // 从初始化之后的元素开始计算 } else { // 在运行中 start=prev_calculated-1; } } 现在,主指标循环: for(int i=start;i<rates_total;i++) { 就像上面描述的那样,为了获得通用性,需要把代码分为之字转向方向的计算以及它的绘制两个部分,这个原则将要遵循。首先写出用于确定方向的代码,为了确定方向,使用ArrayMaximum()和ArrayMinimum()函数。如果在计算的柱上出现了高价或者低价,Direction 数组的元素就被赋值为 1 或者 -1,为了得到之字转向在每个柱的当前方向的信息,在计算方向之前,从 Direction 缓冲区的前一个元素取得数值并赋给当前的元素: // 取得前一个 // 确定方向数组元素的值 DirectionBuffer[i]=DirectionBuffer[i-1]; // 计算初始柱的 // ArrayMaximum() 和 ArrayMinimum() 函数值 int ps=i-period+1; // 确定最高价和最低价 // 在 'period' 个柱的范围之内 int hb=ArrayMaximum(high,ps,period); int lb=ArrayMinimum(low,ps,period); // 如果识别到最高价或者最低价 if(hb==i && lb!=i) { // 找到了最高价 DirectionBuffer[i]=1; } else if(lb==i && hb!=i) { // 找到了最低价 DirectionBuffer[i]=-1; } 请注意代码的最后部分: 它识别最高价或者最低价,检查当前柱上是否同时有最高价并且没有最低价,或者相反:有最低价而没有最高价。有时候,可能会有非常长的柱形,可能同时在上面确定两个方向,在这种情况下,Direction 缓冲区会包含之前确认的方向。 一般来说,在 MetaTrader 5 终端内,可以创建一个之字转向,画出垂直的线段,这使得可以在同一个柱上显示指标方向的两个变化,但是,这样的之字转向类型不在本文讨论范围之内。 让我们继续在主循环中写代码: 以下片段将用于画出之字转向线,其余两个缓冲区将与 Direction 缓冲区作相同的处理: LastHighBarBuffer[i]=LastHighBarBuffer[i-1]; LastLowBarBuffer[i]=LastLowBarBuffer[i-1]; 这两个缓冲区将包含之字转向中最近的最高价和最低价柱的索引数据。除了那些需要画出指标的柱的索引,那些缓冲区在从EA交易中调用之字转向指标也是被大量应用的,那样就不需要在循环中迭代所有的柱来找到最近的高点了。 确保清除之字转向指标的缓冲区: ZigZagBuffer[i]=EMPTY_VALUE; 必须这样做是因为只有在启动时才会完整计算指标,并且在有一些事件发生时也会完整计算,例如下载历史时。缓冲区可能有旧的数据,这可能会扰乱指标线的外观。 现在,让我们转到绘图,在此,算法被分为四个分支: 开始新的向上移动,开始新的向下移动,继续向上移动,继续向下移动。为了检查方向值,在计算和前一个柱上使用了 switch 操作符: switch((int)DirectionBuffer[i]) { case 1: switch((int)DirectionBuffer[i-1]) { case 1: // 继续向上的移动 ... break; case -1: // 开始新的向上移动 ... break; } break; case -1: switch((int)DirectionBuffer[i-1]) { case -1: // 继续向下的移动 ... break; case 1: // 开始新的向下移动 ... break; } break; 剩下的工作是写四个代码块,它们其中的两个将要详细探讨: 开始新的向上移动和继续向上移动。当 Direction 缓冲区的值从-1变成1的时候开始新的向上移动,当出现这种情况时,算法会画出之字转向的一个新点,并保存新方向开始时的柱的索引: ZigZagBuffer[i]=high[i]; LastHighBarBuffer[i]=i;
本文作者可以追加内容哦 !