如何利用 MQL5 处理指示线·进阶篇
「用最高价数组重画下降趋势线」
这段逻辑先清空旧的趋势线对象,再依据最近 N 根 K 线的最高价数组重新锚定一条向右延伸的下降趋势线。外汇与贵金属市场波动剧烈,这类自动重画对象仅作辅助参考,实际突破概率需结合成交量与更高周期确认。 核心做法是把最高价数组设为时间序列(下标 0 为最新棒),用 CopyHigh 拉取指定根数,再借 ArrayMaximum 定位波段最高点所在下标。以下代码逐行拆解其落点方式。 ObjectDelete 先删同名对象避免重绘冲突;ObjectCreate 用 OBJ_TREND 连接波段高点与当前棒高点,形成斜向下射线。颜色蓝、实线、宽度 3、向右延伸,都是视觉上把压制位突出的设定。 在 MT5 里把 candles 参数设为 100 回看,EURUSD 小时图常见效果是该线在波段见顶后 3~5 根内给出可观测的反弹压制,但是否生效仍取决于当时波动率。
class="type">class="kw">double pHigh[]; ArraySetAsSeries(pHigh,true); CopyHigh(_Symbol,_Period,class="num">0,candles,pHigh); class="type">int candleHigh = ArrayMaximum(pHigh,class="num">0,candles); ObjectDelete(_Symbol,"DnwardTrendline"); ObjectCreate(_Symbol,"DnwardTrendline",OBJ_TREND,class="num">0,pArray[candleHigh].time,pArray[candleHigh].high,pArray[class="num">0].time,pArray[class="num">0].high); ObjectSetInteger(class="num">0,"DnwardTrendline",OBJPROP_COLOR,Blue); ObjectSetInteger(class="num">0,"DnwardTrendline",OBJPROP_STYLE,STYLE_SOLID); ObjectSetInteger(class="num">0,"DnwardTrendline",OBJPROP_WIDTH,class="num">3); ObjectSetInteger(class="num">0,"DnwardTrendline",OBJPROP_RAY_RIGHT,true);
用 EA 在 MT5 上自动跟画支撑线
支撑位处在当前价格下方,价格触及后往往出现买盘推动反弹,因此可当作买入触发区的参考。水平支撑是最直白的一种:在 K 线低点下方拉一条横线,价格回踩到这条线附近时反弹概率偏高。外汇与贵金属波动剧烈,支撑被瞬间击穿也属常态,只能作为概率参考而非保本线。 手动拖线太费眼,不如让 EA 在每次跳价时重算可见范围内的最低价,删掉旧线、在最新低点下重画一条绿色水平线。下面这段 MQL5 逻辑编译后挂到图表,就能看到价格下方始终有一条跟随最低低点移动的支撑线。 代码逐行拆解:
| //+------------------------------------------------------------------+ 与 // | ... Support Line System.mq5 | 只是文件头注释,无执行作用 |
|---|
void OnTick() 每次行情跳价触发该函数 int candles=ChartGetInteger(0,CHART_FIRST_VISIBLE_BAR,0); 取图表上第一根可见柱的索引,确定计算范围 double pLow[]; 声明存放最低价的数组 ArraySetAsSeries(pLow,true); 让数组按时间倒序,索引0为最新 CopyLow(_Symbol,_Period,0,candles,pLow); 把当前品种周期的最低价拷进数组 int candleLow = ArrayMinimum(pLow,0,candles); 在范围内找最低价所在的柱索引 MqlRates pArray[]; 声明 K 线结构体数组 ArraySetAsSeries(pArray,true); 同样倒序排列 int Data = CopyRates(_Symbol,_Period,0,candles,pArray); 拷贝 K 线数据(开高低收时间) ObjectDelete(_Symbol,"supportLine"); 删掉名为 supportLine 的旧对象 ObjectCreate(_Symbol,"supportLine",OBJ_HLINE,0,pArray[candleLow].time,pArray[candleLow].low,pArray[0].time,pArray[0].low); 在最低低点处创建水平线 OBJ_HLINE ObjectSetInteger(0,"supportLine",OBJPROP_COLOR,Green); 线条设为绿色 ObjectSetInteger(0,"supportLine",OBJPROP_STYLE,STYLE_SOLID); 实线样式 ObjectSetInteger(0,"supportLine",OBJPROP_WIDTH,3); 线宽 3 ObjectSetInteger(0,"supportLine",OBJPROP_RAY,true); 向右无限延伸(射线) 末段那几行 ObjectDelete / ObjectCreate / ObjectSetInteger 与 OnTick 内重复,是脱离函数的冗余写法,实盘用应只保留函数体内部分。 把 WIDTH 从 3 改成 1,或把 COLOR 换成 clrDodgerBlue,线就会更细或更醒目;若把 RAY 设 false,线只画到最新柱不再右延。打开 MT5 按 F4 贴入编译,拖到 XAUUSD 的 M15 图上,就能直观比对价格与动态支撑的触碰表现。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Support Line System.mq5 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnTick() { class="type">int candles=ChartGetInteger(class="num">0,CHART_FIRST_VISIBLE_BAR,class="num">0); class="type">class="kw">double pLow[]; ArraySetAsSeries(pLow,true); CopyLow(_Symbol,_Period,class="num">0,candles,pLow); class="type">int candleLow = ArrayMinimum(pLow,class="num">0,candles); class="type">MqlRates pArray[]; ArraySetAsSeries(pArray,true); class="type">int Data = CopyRates(_Symbol,_Period,class="num">0,candles,pArray); ObjectDelete(_Symbol,"supportLine"); ObjectCreate(_Symbol,"supportLine",OBJ_HLINE,class="num">0,pArray[candleLow].time,pArray[candleLow].low,pArray[class="num">0].time,pArray[class="num">0].low); ObjectSetInteger(class="num">0,"supportLine",OBJPROP_COLOR,Green); ObjectSetInteger(class="num">0,"supportLine",OBJPROP_STYLE,STYLE_SOLID); ObjectSetInteger(class="num">0,"supportLine",OBJPROP_WIDTH,class="num">3); ObjectSetInteger(class="num">0,"supportLine",OBJPROP_RAY,true); } class=class="str">"cmt">//+------------------------------------------------------------------+ ObjectDelete(_Symbol,"supportLine"); ObjectCreate(_Symbol,"supportLine",OBJ_HLINE,class="num">0,pArray[candleLow].time,pArray[candleLow].low, pArray[class="num">0].time,pArray[class="num">0].low); ObjectSetInteger(class="num">0,"supportLine",OBJPROP_COLOR,Green); ObjectSetInteger(class="num">0,"supportLine",OBJPROP_STYLE,STYLE_SOLID); ObjectSetInteger(class="num">0,"supportLine",OBJPROP_WIDTH,class="num">3); ObjectSetInteger(class="num">0,"supportLine",OBJPROP_RAY,true);
◍ 用EA把阻力线钉在最高点上
阻力位是当前价格上方卖压聚集的区域,价格触碰后倾向回落,因此可当作潜在的卖出触发参考。水平阻力线是最直白的一种:在可见K线区间的最高点下方画一条横线,每次新跳价就重算、重画。 下面这段逻辑在 OnTick 里干的事很明确:先取图表首根可见bar序号,把最高价数组按时间倒序,再用 CopyHigh 把可见区间的高点拷进来;ArrayMaximum 定位最高点的下标,CopyRates 取对应时间的 rates 结构。 随后删掉旧名为 resistanceLine 的对象,用 OBJ_HLINE 建新横线,锚在最高那根bar的 high 上;颜色设 Red、样式 STYLE_SOLID、宽度 3,并开 RAY_RIGHT 向右延伸。编译无错后挂到图表,右上角EA跑起来就能看到价格上方实时跟着最高点的红色阻力线。 [CODE] 里的逐行拆解: //+------------------------------------------------------------------+
| // | Resistance Line System.mq5 |
|---|
//+------------------------------------------------------------------+ void OnTick() // 每跳价触发的主函数 { int candles=ChartGetInteger(0,CHART_FIRST_VISIBLE_BAR,0); // 取首根可见bar索引,即可见K线数量 double pHigh[]; // 声明最高价数组 ArraySetAsSeries(pHigh,true); // 数组按时间倒序(0号是最新bar) CopyHigh(_Symbol,_Period,0,candles,pHigh); // 拷贝可见区间全部最高价 int candleHigh = ArrayMaximum(pHigh,0,candles); // 找可见区间最高价的下标 MqlRates pArray[]; // 声明rates结构数组 ArraySetAsSeries(pArray,true); // 同样倒序排列 int Data = CopyRates(_Symbol,_Period,0,candles,pArray); // 拷贝可见区间OHLC+时间 ObjectDelete(_Symbol,"resistanceLine"); // 删除上一跳的阻力线对象 ObjectCreate(_Symbol,"resistanceLine",OBJ_HLINE,0,pArray[candleHigh].time,pArray[candleHigh].high,pArray[0].time,pArray[0].high); // 以最高点时间和价格创建水平线 ObjectSetInteger(0,"resistanceLine",OBJPROP_COLOR,Red); // 线染红 ObjectSetInteger(0,"resistanceLine",OBJPROP_STYLE,STYLE_SOLID); // 实线 ObjectSetInteger(0,"resistanceLine",OBJPROP_WIDTH,3); // 线宽3 ObjectSetInteger(0,"DnwardTrendline",OBJPROP_RAY_RIGHT,true); // 向右射线(注意对象名拼错,不会作用于resistanceLine) } //+------------------------------------------------------------------+ ObjectDelete(_Symbol,"resistanceLine"); // 重复删除调用,置于函数外无效 ObjectCreate(_Symbol,"resistanceLine",OBJ_HLINE,0,pArray[candleHigh].time,pArray[candleHigh].high,pArray[0].time,pArray[0].high); // 同上创建 ObjectSetInteger(0,"resistanceLine",OBJPROP_COLOR,Red); ObjectSetInteger(0,"resistanceLine",OBJPROP_STYLE,STYLE_SOLID); ObjectSetInteger(0,"resistanceLine",OBJPROP_WIDTH,3); ObjectSetInteger(0,"DnwardTrendline",OBJPROP_RAY_RIGHT,true); // 同样名字拼写不一致 值得留意:末尾函数外的几行不在 OnTick 内,实际不会执行;且 RAY_RIGHT 设的对象名是 DnwardTrendline 而非 resistanceLine,复制代码时要改对名字,否则射线属性白写。外汇与贵金属波动剧烈,这类动态阻力线仅作参考,价格突破的概率始终存在。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Resistance Line System.mq5 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnTick() { class="type">int candles=ChartGetInteger(class="num">0,CHART_FIRST_VISIBLE_BAR,class="num">0); class="type">class="kw">double pHigh[]; ArraySetAsSeries(pHigh,true); CopyHigh(_Symbol,_Period,class="num">0,candles,pHigh); class="type">int candleHigh = ArrayMaximum(pHigh,class="num">0,candles); class="type">MqlRates pArray[]; ArraySetAsSeries(pArray,true); class="type">int Data = CopyRates(_Symbol,_Period,class="num">0,candles,pArray); ObjectDelete(_Symbol,"resistanceLine"); ObjectCreate(_Symbol,"resistanceLine",OBJ_HLINE,class="num">0,pArray[candleHigh].time,pArray[candleHigh].high,pArray[class="num">0].time,pArray[class="num">0].high); ObjectSetInteger(class="num">0,"resistanceLine",OBJPROP_COLOR,Red); ObjectSetInteger(class="num">0,"resistanceLine",OBJPROP_STYLE,STYLE_SOLID); ObjectSetInteger(class="num">0,"resistanceLine",OBJPROP_WIDTH,class="num">3); ObjectSetInteger(class="num">0,"DnwardTrendline",OBJPROP_RAY_RIGHT,true); } class=class="str">"cmt">//+------------------------------------------------------------------+ ObjectDelete(_Symbol,"resistanceLine"); ObjectCreate(_Symbol,"resistanceLine",OBJ_HLINE,class="num">0,pArray[candleHigh].time,pArray[candleHigh].high,pArray[class="num">0].time,pArray[class="num">0].high); ObjectSetInteger(class="num">0,"resistanceLine",OBJPROP_COLOR,Red); ObjectSetInteger(class="num">0,"resistanceLine",OBJPROP_STYLE,STYLE_SOLID); ObjectSetInteger(class="num">0,"resistanceLine",OBJPROP_WIDTH,class="num">3); ObjectSetInteger(class="num">0,"DnwardTrendline",OBJPROP_RAY_RIGHT,true);
「画得少,看得清」
三条指示线——上升与下降趋势线、支撑线、阻力线——的核心价值不在画得多,而在锚点选得准。前文给的示例系统里,第二个锚点若固定取 0 号柱,每来一根新 K 线趋势线就被重画,实战里基本失效;有读者在回测中验证,把第二锚点改为「距第一锚点至少 30 根、且为区间最高价柱」后,线才真正有参考意义。 附件四个 .mq5(UpwardTrendline_System、DownwardTrendline_System、Support_System、Resistance_System,均 1.04~1.07 KB)只负责自动绘图,不含下单逻辑。想在真实账户跑之前,必须自己补发送订单代码,并用历史数据测盈利性——外汇和贵金属杠杆高,未经验证的 EA 可能迅速吃掉本金。 开 MT5 把这四个文件拖进策略测试器,先只看线画得对不对,再谈别的。代码能改、参数能调,这才是硬东西。