MetaTrader 5 中的斐波那契之锯齿指标设置指南

Mike 2025.03.03 08:57 41 0 0
附件

指标设置

要设置斐波那契锯齿指标,我们需要:

  • 1 个锯齿图形
  • 2 个数据缓冲区用于存储高点和低点
  • 输入参数
  • 一组系统变量,指标重新计算时会重置

代码示例:

#property indicator_buffers 2
#property indicator_plots 1
input double retracement=23.6; //回撤比例
input double minSizeInAtrUnits=0.0; //波动最小尺寸
input int rollingAtrPeriod=14; //滚动 ATR 周期
input color Color=clrDodgerBlue; //波动颜色
input int Width=3; //波动宽度
input ENUM_LINE_STYLE Style=STYLE_SOLID; //波动样式
//--- 上升波动和下降波动
 double upWaves[], dwWaves[];

upWaves 数组将存储高点,dwWaves 数组将存储低点。

系统变量:

我们需要跟踪最后的波动类型、开始和结束位置、起始和结束的柱数距离。

另外,我们还需要本地高点和低点变量,以及每个点的柱数距离。

//--- 记录锯齿波动状态
int wave_type=0; //波动类型 [0] 无 [1] 上升 [2] 下降
 double wave_start_price=0.0; //波动开始价格
 double wave_end_price=0.0; //波动结束价格
 int wave_start_distance=0; //开始价格到当前的柱数距离
 int wave_end_distance=0; //结束价格到当前的柱数距离
 double high_mem=0.0; //高点跟踪
 int distance_from_high=0; //距离高点的柱数
 double low_mem=0.0; //低点跟踪
 int distance_from_low=0; //距离低点的柱数
 double rollingAtr=0.0; //滚动 ATR
 int rollingAtrs=0; //已计算的滚动 ATR

最后,我们需要定义一个系统重置函数:

void resetSystem(){
ArrayFill(upWaves,0,ArraySize(upWaves),0.0);
ArrayFill(dwWaves,0,ArraySize(dwWaves),0.0);
wave_type=0;
wave_start_price=0.0;
wave_end_price=0.0;
wave_start_distance=0;
wave_end_distance=0;
high_mem=0.0;
low_mem=0.0;
distance_from_high=0;
distance_from_low=0;
rollingAtr=0.0;
rollingAtrs=0;
}

标准操作,填充数组为零并重置系统变量。

在初始化时,我们设置缓冲区、绘图并第一次调用重置函数:

SetIndexBuffer(0, upWaves, INDICATOR_DATA);
SetIndexBuffer(1, dwWaves, INDICATOR_DATA);
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0);
PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_ZIGZAG);
PlotIndexSetInteger(0, PLOT_LINE_COLOR, 0, Color);
PlotIndexSetInteger(0, PLOT_LINE_WIDTH, Width);
PlotIndexSetInteger(0, PLOT_LINE_STYLE, Style);
resetSystem();

现在让我们深入计算部分。

首先,我们需要处理滚动 ATR。

在收集的柱数未超过 ATR 周期之前,我们不会进行其他操作。

管理滚动 ATR 的代码如下:

  • 如果未收集超过周期的柱数,则继续将找到的柱数范围添加到总和中
  • 一旦达到周期,进行第一次除法(平均)
  • 之后,减去滚动 ATR 的一部分,并添加新的一部分
我们将最后一部分放在前面,因为它会更频繁地发生,避免访问两个 if 语句。

代码如下:

//--- 管理 ATR
rollingAtrs++;
if(rollingAtrs>rollingAtrPeriod){
 double new_portion=((high[i]-low[i])/_Point)/((double)rollingAtrPeriod);
 rollingAtr=(rollingAtr)-(rollingAtr/((double)rollingAtrPeriod))+new_portion;
}
else if(rollingAtrs<=rollingAtrPeriod){
 rollingAtr+=(high[i]-low[i])/_Point;
 if(rollingAtrs==rollingAtrPeriod){
 rollingAtr/=((double)rollingAtrs);
 high_mem=high[i];
 low_mem=low[i];
 distance_from_high=0;
 distance_from_low=0;
}
}

接下来,我们需要处理的是回撤的问题。

为了能够进行回撤,必须至少有一个波动。

但第一波会回撤什么呢?:D

为此,我们将进行如下处理:

  • 一旦 ATR 滿足(ATR 收集 = 周期),我们将抓取系统变量中的高点和低点
  • 无论哪个方向形成的波动满足有效尺寸并且形成新的高点(上升波)或新的低点(下降波),我们就以此为胜

这样我们就能开始波动序列,而不需要用回撤来作为初始波动。

注意,我们也可以选择在这里采用经典的分形方法来处理第一波,然后继续使用回撤。

以下是当我们还没有波动类型时的处理代码:

else{
 //--- 如果突破高点而未突破低点
 if(high[i]>high_mem&&low[i]>=low_mem){
 double new_wave_size_in_atr_units=((high[i]-low_mem)/_Point)/rollingAtr;
 if(new_wave_size_in_atr_units>=minSizeInAtrUnits){
 wave_type=1;
 wave_start_price=low_mem;
 wave_start_distance=distance_from_low;
 wave_end_price=high[i];
 wave_end_distance=0;
 dwWaves[i-wave_start_distance]=low_mem;
 upWaves[i]=high[i];
 high_mem=high[i];
 distance_from_high=0;
 low_mem=low[i];
 distance_from_low=0;
}
}
//--- 如果突破低点而未突破高点
 else if(low[i]<low_mem&&high[i]<=high_mem){
 double new_wave_size_in_atr_units=((high_mem-low[i])/_Point)/rollingAtr;
 if(new_wave_size_in_atr_units>=minSizeInAtrUnits){
 wave_type=-1;
 wave_start_price=high_mem;
 wave_start_distance=distance_from_high;
 wave_end_price=low[i];
 wave_end_distance=0;
 upWaves[i-wave_start_distance]=high_mem;
 dwWaves[i]=low[i];
 high_mem=high[i];
 distance_from_high=0;
 low_mem=low[i];
 distance_from_low=0;
}
}
//--- 如果突破高低点
 else if(low[i]<low_mem&&high[i]>high_mem){
 high_mem=high[i];
 low_mem=low[i];
 distance_from_high=0;
 distance_from_low=0;
}
}

非常好,最后一块内容。

  • 如果我们有上升波:
  1. 如果产生新高,则将锯齿线从之前的高点位置移动到新高点,并更新低点和低点的距离。
  2. 如果产生新低,或设定新的低点,则计算从高点到低点的距离并将其除以波动大小,并乘以 100 以匹配输入参数规模。

相关代码如下:

if(wave_type==1){
 //--- 如果波动向上扩展
 if(high[i]>wave_end_price){
 upWaves[i-wave_end_distance]=0.0;
 upWaves[i]=high[i];
 wave_end_price=high[i];
 wave_end_distance=0;
 high_mem=high[i];
 distance_from_high=0;
 low_mem=low[i];
 distance_from_low=0;
}
 //--- 检查回撤
 if(low[i]<low_mem||distance_from_low==0){
 low_mem=low[i];
 distance_from_low=0;
 double size_of_wave=(wave_end_price-wave_start_price)/_Point;
 double size_of_retracement=(wave_end_price-low_mem)/_Point;
 if(size_of_wave>0.0){
 double retraced=(size_of_retracement/size_of_wave)*100.0;
 double new_wave_size_in_atr_units=((wave_end_price-low_mem)/_Point)/rollingAtr;
 if(new_wave_size_in_atr_units>=minSizeInAtrUnits){
 if(retraced>=retracement){
 wave_type=-1;
 wave_start_price=high[i-distance_from_high];
 wave_start_distance=distance_from_high;
 wave_end_price=low[i];
 wave_end_distance=0;
 upWaves[i-wave_start_distance]=high_mem;
 dwWaves[i]=low[i];
 high_mem=high[i];
 distance_from_high=0;
 low_mem=low[i];
 distance_from_low=0;
}
}
}
}

当我们有下降波时,处理方法是反的。

至此,我们的回撤锯齿指标就完成了。

下面是回撤比例为 23.6% 和波动最小尺寸为 0.0 的锯齿图:


而这是同样的锯齿图,波动最小尺寸为 3


列表
评论 0