开发基于振荡器的之字折线 (ZigZag) 指标。 执行需求规范的示例·综合运用
(3/3)·把需求规范逐条变成可运行指标,最难的形态涂色与界面坑都在这一篇
用一个函数切五种振荡指标
在 MT5 面板里动态切换 WPR、CCI、Chaikin、RSI、Stochastic 这类振荡指标,核心是把加载逻辑收进一个 LoadIndicator() 分支函数。传入枚举类型后,函数内部用 switch 给全局的 max、min 赋值,并调用对应的 iWPR / iCCI / iChaikin / iRSI / iStochastic 拿到指标句柄 h。 句柄拿不到就直接 Print 报错并返回 false,外层用 !LoadIndicator(Type) 判断后走 INIT_FAILED,避免在 EA 初始化阶段带病启动。下面这段是分支加载的主体,注意每个 case 都只改 max/min/h 三个变量,不碰其他状态: [CODE] bool LoadIndicator(int aType){ switch(aType){ case WPR: max=WPRmax; min=WPRmin; h=iWPR(Symbol(),Period(),WPRperiod); break; case CCI: max=CCImax; min=CCImin; h=iCCI(Symbol(),Period(),CCIperiod,CCIprice); break; case Chaikin: max=CHmax; min=CHmin; h=iChaikin(Symbol(),Period(),CHfperiod,CHsperiod,CHmethod,CHvolume); break; case RSI: max=RSImax; min=RSImin; h=iRSI(Symbol(),Period(),RSIperiod,RSIprice); break; case Stochastic: max=STmax; min=STmin; h=iStochastic(Symbol(),Period(),STperiodK,STperiodD,STperiodS,STmethod,STprice); break; } if(h==INVALID_HANDLE){ Print("无法加载指标"); return(false); } return(true); } [/CODE] 面板事件里如果 radio 组被改了,先 IndicatorRelease(h) 把旧句柄释放再重新 LoadIndicator(form.m_rg.Value()),不然切指标会漏句柄。max/min 文本框改完会触发 EventSetMillisecondTimer(100),用 100 毫秒重绘节奏把新边界喂给绘图层。 取历史 K 线时用 Bars() 拿总数,bars<=0 直接 return;CopyTime() 返回 -1 也 return,这两道判断能挡掉多数 Symbol 无数据或历史未同步的空跑。外汇与贵金属波动大、杠杆高,这类面板只是辅助观测,信号失效时亏损可能快速扩大。
class="type">bool LoadIndicator(class="type">int aType){ class="kw">switch(aType){ case WPR: max=WPRmax; min=WPRmin; h=iWPR(Symbol(),Period(),WPRperiod); break; case CCI: max=CCImax; min=CCImin; h=iCCI(Symbol(),Period(),CCIperiod,CCIprice); break; case Chaikin: max=CHmax; min=CHmin; h=iChaikin(Symbol(),Period(),CHfperiod,CHsperiod,CHmethod,CHvolume); break; case RSI: max=RSImax; min=RSImin; h=iRSI(Symbol(),Period(),RSIperiod,RSIprice); break; case Stochastic: max=STmax; min=STmin; h=iStochastic(Symbol(),Period(),STperiodK,STperiodD,STperiodS,STmethod,STprice); break; } if(h==INVALID_HANDLE){ Print("无法加载指标"); class="kw">return(class="kw">false); } class="kw">return(true); }
「历史数据回填与重算的防错写法」
在自定义指标里手动拉取近期高低点,第一步必须拦截拷贝失败。CopyHigh 与 CopyLow 返回 -1 时直接 return,避免后续数组越界把 MT5 终端拖死。 时间、最高、最低三个数组若长度不足 bars,要先记下旧尺寸 sz,再 ArrayResize 到目标 bars,然后用双指针从后往前搬数据:旧数组尾元素落到新数组尾,依次前移。这样新留出的前段位置留给 OnCalculate 内部补数据。 数组齐了就调 OnCalculate(bars,0,time,open,high,low,close,tick_volume,volume,spread)。返回值非 0 才说明算完一轮,此时 ChartRedraw 重绘、EventKillTimer 停掉定时器,再把表单标题换成当前选中的枚举字符串。外汇与贵金属波动剧烈,这种异步回填若漏了返回值判断,图表可能卡在半截状态。 开 MT5 把这段塞进定时事件里,设 bars=500 跑一遍,看 ChartRedraw 前 rv 是否恒为非 0,就能验证你自己的拷贝逻辑有没有暗病。
if(CopyHigh(Symbol(),Period(),class="num">0,bars,high)==-class="num">1){ class="kw">return; } if(CopyLow(Symbol(),Period(),class="num">0,bars,low)==-class="num">1){ class="kw">return; } if(ArraySize(time)<bars){ class="type">int sz=ArraySize(time); ArrayResize(time,bars); for(class="type">int i=sz-class="num">1,j=bars-class="num">1;i>=class="num">0;i--,j--){ time[j]=time[i]; } } if(ArraySize(high)<bars){ class="type">int sz=ArraySize(high); ArrayResize(high,bars); for(class="type">int i=sz-class="num">1,j=bars-class="num">1;i>=class="num">0;i--,j--){ high[j]=high[i]; } } if(ArraySize(low)<bars){ class="type">int sz=ArraySize(low); ArrayResize(low,bars); for(class="type">int i=sz-class="num">1,j=bars-class="num">1;i>=class="num">0;i--,j--){ low[j]=low[i]; } } class="type">int rv=OnCalculate( bars, class="num">0, time, open, high, low, close, tick_volume, volume, spread ); if(rv!=class="num">0){ ChartRedraw(); EventKillTimer(); form.SetCaption(EnumToString((EIType)form.m_rg.Value())); }
◍ 之字折线重绘留下的分析坑
检测形态时对前若干个之字折线段落重绘,可能直接破坏基于历史记录的价格结构判断。新细节还能追加进已出现形态里,让肉眼读图更费劲——而这类形态本是用来做交易决策的,决策只能在形态出现时或之后下,提前猜没有意义。 一个务实改法是:不在之字折线上涂色,改为在触发柱线上画箭头;或者从确认形态那根柱起,向后拉若干根水平线,把‘已成立’区域标出来。外汇与贵金属波动剧烈、高风险,任何信号都只是概率参考。 开发中还暴露一个初读需求根本想不到的点:指标逆转时要删掉最后一个之字折线极值。用彩色之字折线缓冲区会卡住——它含两个数据缓冲加一个颜色缓冲,若单根柱两个数据缓冲都有值(贯穿柱体的竖线),两段折线会吃到同一个颜色索引。绕开办法是用普通之字折线缓冲,拿图形对象重画段落,或干脆只摆箭头、圆点。任何定制指标都得先拆透边界再动手。
一点提醒
把四个阶段指标文件 OscZigZagStep1~4.mq5 丢进 MQL5/Indicators,再把 IncGUI_v4.mqh 放进 MQL5/Includes,OscZigZagStep4 才能调出图形界面跑通。文件包 MQL5.zip 约 87.98 KB,解压后照目录放好即可在 MT5 里逐个加载验证。 评论区里有人纠结圈出 K 线处 dir 未变却搜了最小值,作者回得很直接:方向切换时会在最后一个峰值到变向点整段重扫极值,不是只盯变向那一根。若你觉得这套之字形逻辑不顺手,读懂代码后完全能改出自己的版本。 外汇与贵金属波动剧烈、杠杆风险高,这类自定义指标只帮你看清结构,不构成任何方向暗示;真要上实盘,先开 MT5 用欧美 06/06/19 那段数据回放一遍再说话。