设置
我们需要 :
- 1 个 "之 "字形曲线图
- 2 个数据缓冲器,用于存储高点和低点数据
- 输入参数
- 一组持续的系统变量,每当指标重新计算时都会重置
#property indicator_buffers 2 #property indicator_plots 1 input double retracement=23.6;//回撤量 input double minSizeInAtrUnits=0.0;// 以阿特尔为单位的最小波长 input int rollingAtrPeriod=14;//rolling atr period input color Color=clrDodgerBlue;//波色 input int Width=3;//波宽 input ENUM_LINE_STYLE Style=STYLE_SOLID;//波浪式 //+------------------------------------------------------------------+ //| 自定义指示器初始化函数 //+------------------------------------------------------------------+ //----上升浪和下降浪 double upWaves[],dwWaves[];
upWaves 数组将存储高点,dwWaves 数组将存储低点
系统变量 :
我们需要知道最后一个波浪的类型、开始位置、结束位置、开始和结束之间的距离(以条为单位)。
然后,我们需要一个本地高点和本地低点变量,以及各点之间的距离。
//----跟踪 "之 "字形路线 //----波浪的类型 [0] 无 [1] 上升 [2] 下降 int wave_type=0; //----波浪的起始价格(起始价) 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; 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; }
标准功能,在数组中填入 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 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; } }
太棒了,现在还有一个问题。
这种 "之 "字形走势的基础是回调。
但回调必须至少有一个波浪。
但是第一波回调会是什么呢?
为此,我们将采取以下措施
- 一旦 atr 填满(收集的 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; } } //--- if we broke both 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; } }
很好。现在是最后一块。
- 如果出现上升浪 :
- 如果出现了新的高点,则将之字形线从之前的高点位置移动到新的高点位置,我们可以这样做,因为我们保留了条形图的距离。我们这样做是为了捕捉最高点以来的最低点,并检查其回撤是否足以开始新的低点。
- 如果出现了新的低点,或者创下了新的低点,我们就计算峰值到低点的距离,然后除以波浪的大小。因此,如果波浪大小为 100 点,回撤为 24 点,我们得到 24/100 0.24,然后 x 100 24%。如果回撤前一个波浪的新 "将 "波浪的大小也与 atr 单位一致,我们就开始一个新的下跌波浪,设置新的局部高点和低点,设置条形图距离。
以下是上述操作的相关代码:
//----如果出现上升浪 if(wave_type==1){ //--- 如果波向上扩展 if(high[i]>wave_end_price){ //--------------------------------------从数组位置移除前一个结束价格(0.0=空) 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 the retracement is significant , start a down wave 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 的 之字形, 单位为 atr
下面是同样的 "之 "字形,以 3 分钟波长为单位
由MetaQuotes Ltd译自英文
原代码: https://www.mql5.com/en/code/56619

TradeReportExporter 脚本旨在将历史交易(交易)导出为方便的 CSV 文件。它能自动收集所安装工具去年的所有交易数据。文件包括日期和时间、交易类型(买入/卖出)、价格、成交量、佣金和盈亏等数据。结果保存到文件中,可在 Excel 或其他电子表格编辑器中打开。

用于监控单一符号的多头和空头掉期的简单实用程序。如果您的经纪商指定的掉期以点数而不是账户货币计算,该工具会自动将点数转换为账户货币。周三掉期为三倍。可在输入中调整水平和垂直对齐方式。

之字形指示器使用单一输入来调整步长,以检测波浪方向的变化

其目的是在 MQL5 开发过程中,使任何 Telegram 整合任务都能随时使用该函数。通过将此文件添加到您的代码库,您只需将其包含在您的智能交易系统中,并直接从包含的模块中调用该函数即可。这样就无需重复从头开始重新开发代码,确保了多个项目的可重用性。