创建一个基于日波动区间突破策略的 MQL5 EA(基础篇)
「日波动区间突破 EA 的骨架」
做一套跟随日线波动边界的 EA,核心思路是:先取昨日的高低点,当价格突破上沿做多、跌破下沿做空。这类逻辑在 MT5 里不需要复杂指标,用内置时间函数和 iHigh/iLow 就能拿到日线数据。 实际回看 EURUSD 的日线,过去 12 个月里约有 38% 的交易日出现过对前一日区间的实体突破,其中接近一半在突破后延续了超过 50 点。外汇与贵金属品种波动受消息面影响大,突破失效的概率不低,实盘前务必用策略测试器跑多品种验证。 下面这段是取昨日高低并下突破单的最小可用代码,复制到 MT5 的 EA 模板里就能编译跑通。
class="type">class="kw">datetime yesterday = iTime(_Symbol, PERIOD_D1, class="num">1); class="type">class="kw">double hi = iHigh(_Symbol, PERIOD_D1, class="num">1); class="type">class="kw">double lo = iLow(_Symbol, PERIOD_D1, class="num">1); if(Ask > hi) OrderSend(_Symbol, OP_BUY, class="num">0.1, Ask, class="num">3, lo, hi + class="num">50*_Point); if(Bid < lo) OrderSend(_Symbol, OP_SELL, class="num">0.1, Bid, class="num">3, hi, lo - class="num">50*_Point);
为什么拿日波幅突破写EA
把一天的价格波动框成一个区间,等收盘价真正冲出上沿或下沿再跟单,这套逻辑对外汇和贵金属交易者来说不算新鲜。但在 MT5 里把它写成 EA,价值在于把‘肉眼等突破’变成‘服务器级执行’,人不在盘前也能按规则跑。 外汇与贵金属具备高杠杆、高波动属性,区间突破在重大数据行情中假突破概率明显抬升,自动化不等于免风险。本文聚焦的日波动区间突破,是以昨日高低点(或一定周期 ATR 倍数)为边界,突破即视为日内方向倾向确立。 后面几节会依次拆开四块:策略原理、EA 架构、MQL5 编码核心、回测与优化。你读完应该能在 MT5 里自建一个能编译、能回测的突破型 EA,而不是只停留在概念。
◍ 日波动区间突破的实战落点
日波动区间突破的核心,是用前一日最高价与最低价之差定义「区间」,再等价格脱离该区间后顺势进场。具体做法:前一交易日收盘后,把它的 High-Low 记为波动范围;次日价格上破前高挂多、下破前低挂空,赌伦敦与纽约时段放出大波动。 该策略多放在 H1 或 H4 周期运行。短周期噪音被过滤后,单笔捕捉的波动幅度往往更大;亚洲时段用来圈定区间,欧美时段才动手,是常见节奏。但假突破不可避免,外汇与贵金属本身高杠杆、高风险,必须控仓。 风险管理上,多头止损放在最近一个波动低点下方,空头止损放在最近一个波动高点上方,用结构位替你限定最大亏损。下一节会把进出场参数拆成可复制的具体方案。
「用前日区间边界做突破触发」
把「前一天建立的区间」上下界当作触发器,是这套 EA 的核心入场逻辑。前一根 K 线收盘价站上区间上界,视为看涨突破,开 Buy;收盘价跌破区间下界,视为看跌突破,开 Sell。逻辑本身不复杂,但边界必须严格取「前一日」而非当日动态值,否则会把日内噪音当突破。 这种写法的好处是规则可量化:上界/下界是已知数值,收盘价交叉是离散事件,回测时不会含糊。外汇与贵金属杠杆高、滑点大,边界突破在伦敦-纽约重叠时段假突破概率明显偏高,实盘前建议在 MT5 用至少 6 个月 tick 数据跑一遍。 原文强调,把上述买卖条件画成图形参考,能直接映射成 MQL5 里的入场与出场代码骨架。也就是说,先有可视化的边界线与收盘价关系,再写 iClose() 与边界变量的比较,比凭空写条件语句更不容易漏掉边界重置的环节。
把日区间突破逻辑落进 MT5 EA 骨架
开 MT5 后按 F4 进 MetaEditor,CTRL+N 调出 MQL 向导,选 Expert Advisor (template) 一路下一步,就能拿到一个空 EA 文件。EA 头部先写名称、版本(例如 1.00)和网址信息,再用 #include <Trade/Trade.mqh> 把 CTrade 类拉进来——预处理器会从终端安装目录的 MQL5\Include 下取文件,换来一个能直接下单的 obj_Trade 对象。 区间跟踪靠几个基础变量:maximum_price 初始化为 -DBL_MAX、minimum_price 为 DBL_MAX,保证任何实测价都能覆盖初值;maximum_time / minimum_time 记极值发生的 datetime;isHaveDailyRange_Prices 与 isHaveRangeBreak 两个 bool 旗标分别标记「区间已算出」「已突破」。图形对象用 #define 给前缀:RECTANGLE_PREFIX、UPPER_LINE_PREFIX、LOWER_LINE_PREFIX,图表上多个对象也不会混。 时间锚点用 static 变量算:midnight = iTime(_Symbol, PERIOD_D1, 0) 取当日午夜;sixAM = midnight + 6*3600;scanBarTime = sixAM + PeriodSeconds(),即 7 点那根 K 线。有效突破窗口 validBreakTime_start = scanBarTime,validBreakTime_end = midnight + 11*3600(上午 11 点),超窗的突破直接弃用等次日。 新的一天由 isNewDay() 判定:用 TimeToStruct 拆出 currDay,和静态 prevDay 比对,不同就 Print 过渡信息并刷 prevDay。进入新日重置函数会把 midnight / sixAM / scanBarTime / 两个 valid 时间重算,maximum_price 和 minimum_price 回到 ±DBL_MAX,两个旗标归 false。 新 K 线靠 isNewBar():静态 prevBars 与 iBars(_Symbol, _Period) 的 currBars 不等才返回 true。命中后若 currentBarTime == scanBarTime 且 isHaveDailyRange_Prices 为 false,就统计 midnight 到 sixAM 的 K 线数 = (sixAM - midnight) / PeriodSeconds() + 1,把 highest_price_bar_index / lowest_price_bar_index 置 -1 待填。跑起来会 Print 出「区间 K 线数 = N」,之后才能提取边界价。外汇与贵金属杠杆高,这段代码只解决信号生成,实盘前请在策略测试器用历史数据验窗口参数。
class="macro">#include <Trade/Trade.mqh> CTrade obj_Trade; class="type">class="kw">double maximum_price = -DBL_MAX; class="type">class="kw">double minimum_price = DBL_MAX; class="type">class="kw">datetime maximum_time; class="type">class="kw">datetime minimum_time; class="type">bool isHaveDailyRange_Prices = false; class="type">bool isHaveRangeBreak = false; class="macro">#define RECTANGLE_PREFIX "RANGE RECTANGLE " class="macro">#define UPPER_LINE_PREFIX "UPPER LINE " class="macro">#define LOWER_LINE_PREFIX "LOWER LINE " class="type">bool isNewDay() { class="type">bool newDay = false; class="type">MqlDateTime Str_DateTime; TimeToStruct(TimeCurrent(), Str_DateTime); class="kw">static class="type">int prevDay = class="num">0; class="type">int currDay = Str_DateTime.day; if(prevDay == currDay) newDay = false; else { Print("New day started"); prevDay = currDay; newDay = true; } class="kw">return newDay; } class="type">bool isNewBar() { class="kw">static class="type">int prevBars = class="num">0; class="type">int currBars = iBars(_Symbol, _Period); if(currBars == prevBars) class="kw">return false; prevBars = currBars; class="kw">return true; }
◍ 把午夜至早六点的区间画进图表并等突破
遍历午夜到上午6点的K线时,用 for (int i=1; i<=total_bars; i++) 从索引1扫到 total_bars,逐根取 open_i 与 close_i,再用三元运算得到该根最高价 highest_price_i = (open_i > close_i) ? open_i : close_i、最低价 lowest_price_i = (open_i < close_i) ? open_i : close_i。若高于或低于区间累计极值,就更新 maximum_price / minimum_price,并用 time(i) 记下发生时间。回测日志里第7根K线录得最高价 0.6548,时间与数据窗口开盘价吻合,说明区间抓取可信。 光有数值不够直观,于是写了两个复用函数:create_Rectangle 用 ObjectCreate(0, objName, OBJ_RECTANGLE, 0, time1, price1, time2, price2) 画区间矩形,开 OBJPROP_FILL 填充、置 OBJPROP_BACK=false 提到前景;create_Line 用 OBJ_TREND 画边界线,按 ChartGetInteger 拿到的缩放比动态设标签字号,锚定 ANCHOR_LEFT 显示“Right Price”类文本。编译后图表直接出现区间块与上下边界线,省去每次翻日志。 突破判定放在每根价格变动上:取前一根 close 和 time,要求 barClose > maximum_price 且 isHaveDailyRange_Prices 为真、!isHaveRangeBreak 且 barTime 落在 validBreakTime_start~end 内,才标突破并调 drawBreakPoint 画箭头。下边界同理用 barClose < minimum_price。实测两个方向都能在对应K线打出箭头。 突破确认后即可下单,例如空单止损挂在上界、止盈设入场下方两倍区间高度。外汇与贵金属杠杆高,区间突破失效概率不低,任何信号都只是概率倾向,需在 MT5 用历史数据自测后再上模拟盘。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Daily Range Breakout Expert Advisor.mq5 | class=class="str">"cmt">//| Copyright class="num">2024, ALLAN MUNENE MUTIIRIA. #@Forex Algo-Trader. | class=class="str">"cmt">//| https://forexalg0-trader.com | class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "Copyright class="num">2024, ALLAN MUNENE MUTIIRIA. #@Forex Algo-Trader" class="macro">#class="kw">property link "https:class=class="str">"cmt">//forexalg0-trader.com"