在MT4上做框形突破,最难受的环节其实不是判断,而是盯盘。我以前画好一条矩形后,总忍不住每隔几秒就瞄一眼K线,等到真正的突破出现时,人往往已经疲惫得没有了执行力。后来我换了个思路:让MT4在后台守着这个框,价格碰到上边沿就喊我,碰到下边沿也喊我,这就是我一直在用的“框形突破提醒”方案——你在图表上手动画一个矩形框,一个轻量级EA负责实时监控价格和矩形上下边沿的关系,一旦突破,弹窗、响铃、手机推送三路提醒同时触发。这篇文章会把原理、代码、部署和实测坑位一次讲透,适合做箱体突破、区间交易,又懒得长时间盯盘的人。
1. 为什么突破信号需要机器值守
1.1 框形策略的“等”与“破”
框形突破的交易逻辑,说白了就是价格在一个矩形区间里来回震荡,上下边界代表多空双方暂时的停火线。价格一旦离开这个区间,往往意味着一方暂时获胜,行情进入单边走势。所以这个策略的核心动作很简单:上破做多,下破做空,止损放在边界外侧。
但真正执行起来,难的不是“破”的那一刻,而是“等”的过程。一个矩形整理可能持续几小时、几天甚至几周,真正突破可能就在某一根K线里完成。人不可能一直保持同样的注意力,而我发现,越是等得久,突破真正出现时越容易犹豫——要么担心是假突破,要么因为盯盘太久,失去了对这笔交易该有的冷静判断。
1.2 人眼盯盘的三个致命问题
第一个问题是注意力滑坡。我自己的体会是,连续盯盘十分钟以上,对价格细微变化的敏感度就会明显下降。尤其是价格贴着矩形边沿来回试探的时候,你会开始怀疑“这算不算突破”,等回过神来,行情已经走出去一截。
第二个问题是多品种、多周期根本盯不过来。同时开着五六个图表,每个图表都画了框,靠人眼轮流扫一遍就要花不少时间,更不用说行情最活跃的时候,信号往往是同时出现的。第三个问题更现实:接电话、喝水、处理工作消息,任何一次打断都可能让你错过关键K线。突破不会等你有空的时候才发生,但提醒工具可以。
1.3 机器值守不等于自动交易
我需要先划清楚工具的边界:这个EA只做一件事,就是“价格越过边界的时候告诉你”,它不判断真假突破,不自动下单,更不会帮你管理仓位。真正的交易决策仍然留给人脑。
有人可能会问,为什么不干脆做成全自动?我的看法是,框形突破里的“框”本身就很主观——同一段行情,有人画上沿下沿,有人画趋势线,有人用布林带,自动识别杂乱区间很容易把自己绕进去。手动画框加上自动值守,正好是“人的判断”和“机器的执行力”各取所需,这也是我目前最推荐的一种做法。
2. 框形突破提醒的运行逻辑与触发规则设计
2.1 整个系统由三块构成
这套方案的核心架构只有三部分:图表上的矩形对象、一个轻量级EA、几条消息通道。
矩形对象就是你在图表上手动画出来的那个框。MT4里所有图形对象都是可以被脚本读取的,EA通过对象名称找到矩形,然后用函数读出它的上下边沿价格。EA本身做的是轮询:每隔几秒检查一次最新价格和边界的关系,一旦触发预设条件,就调用MT4的消息机制发出提醒。
提醒通道我设计了三种,可以互相搭配:
| 提醒方式 | 触发时机 | 依赖条件 | 最适用的场景 |
|---|---|---|---|
| Alert弹窗 | 每次触发 | MT4客户端处于运行状态 | 人坐在电脑前盯盘 |
| SendNotification手机推送 | 每次触发 | 桌面端与手机端完成授权 | 人离开电脑时 |
| PlaySound声音提醒 | 每次触发 | 声音文件放在指定目录 | 人不看屏幕但能听到声音 |
其中Alert弹窗有个小缺点:弹出来之后必须手动点掉,如果正在操作交易界面,会打断节奏。所以我日常更常用的是“手机推送+声音”的组合。
2.2 “突破”到底怎么定义
边界判断的核心代码其实只有几行:用ObjectGetDouble读取矩形上沿和下沿的价格,再拿当前价格和它们比较。上沿价格记为boxHigh,下沿价格记为boxLow,当前价大于boxHigh就是上破,小于boxLow就是下破。
真正需要想清楚的是“用哪个价格来判断”:
- 用实时买价Bid判断,反应最快,但容易被上下影线骗到;
- 用K线收盘价判断,更稳定,适合M15以上的周期;
- 用“突破后等待N根K线收盘仍在框外”来判断,最严格,能过滤掉不少假突破。
我把这些都做成了参数,而不是写死在代码里。实测下来,如果你是做日内短周期,建议用“收盘价判断”加“确认K线数=1”;如果你是做波段级别,确认K线数可以放到2或者3。当然,确认K线数越大,提醒越晚,你需要自己权衡及时性和准确性。
2.3 去重状态机:避免手机被提醒震坏
还有一个很现实的问题:如果每次tick发现价格在边界外就发一条推送,当价格在边界附近反复横跳时,手机可能在几十秒内收到几十条通知,直接把提醒变成骚扰。
所以要引入状态机。我自己的处理方式是:上沿触发过提醒之后,把这个框记入“已提醒名单”,直到价格重新回到框内,才把这个框从名单里移除。也就是说,价格每次离开矩形区域,我只提醒一次;价格只要还待在框外,就不会重复轰炸你;等它重新回框后再次离开,才会再次提醒。
这个逻辑用一个很朴素的比喻:门卫只在有人从门口出去的那一刻喊一声,等这个人回到院子里,下次再出去时再喊第二声。它不问原因,也不会追着人持续喊。这样既保证了信号不漏报,又让提醒保持克制。
2.4 一个EA盯多个框:命名规范
同一张图表上往往不止画一个矩形,比如左侧有一个较窄的整理框,右侧有一个较宽的区间框。为了让EA只监控你指定的框,我约定所有矩形名称必须以“Box_”开头,EA只扫描带这个前缀的矩形对象。
手动画的矩形默认名称是“Rectangle 12345”这种,需要你在对象列表里改一下名称。听起来麻烦,但这样做有两个好处:一是避免EA误监控图表上其他图形的矩形,二是提醒消息里可以直接带上框名,比如“Box_M15_上区间向上突破”,你看到推送就知道是哪个框触发的,不用再去图表上找。
3. 完整MQL4代码实现:一个可以直接用的EA
3.1 完整源码
下面这段代码可以直接在MetaEditor里编译运行,不需要任何外部库,我用的是MT4原生的MQL4语法。
//+------------------------------------------------------------------+ //| BoxBreakoutAlert.mq4 | //| 根据矩形框监控突破并触发提醒 | //+------------------------------------------------------------------+ #property strict #property description "根据图表上带有指定前缀的矩形框,监控价格突破并提醒" extern string InpBoxPrefix = "Box_"; // 矩形名称前缀 extern bool InpUseClose = true; // true: 用收盘价判断; false: 用实时买价判断 extern int InpConfirmBars = 0; // 突破确认K线数: 0为立即触发 extern bool InpAlert = true; // 允许弹窗提醒 extern bool InpPush = true; // 允许手机推送 extern bool InpSound = true; // 允许声音提醒 extern string InpSoundFile = "alert.wav"; // 提醒声音文件名 extern int InpTimerSec = 5; // 轮询间隔(秒) string g_alertedUp = ""; // 已经在上沿触发过提醒的框名列表 string g_alertedDn = ""; // 已经在下沿触发过提醒的框名列表 int OnInit() { EventSetTimer(InpTimerSec); return(INIT_SUCCEEDED); } void OnDeinit(const int reason) { EventKillTimer(); } void OnTick() { CheckBreakout(); } void OnTimer() { CheckBreakout(); } void CheckBreakout() { int total = ObjectsTotal(); if(total <= 0) return; for(int i = total - 1; i >= 0; i--) { string name = ObjectName(i); if(StringFind(name, InpBoxPrefix) != 0) continue; if(ObjectGetInteger(name, OBJPROP_TYPE) != OBJ_RECTANGLE) continue; double boxHigh = ObjectGetDouble(name, OBJPROP_PRICE1); double boxLow = ObjectGetDouble(name, OBJPROP_PRICE2); if(boxHigh < boxLow) { double tmp = boxHigh; boxHigh = boxLow; boxLow = tmp; } double price = 0; if(InpUseClose) price = iClose(Symbol(), PERIOD_CURRENT, InpConfirmBars); else price = Bid; bool isUp = price > boxHigh; bool isDown = price < boxLow; if(isUp && !IsInList(g_alertedUp, name)) { AddToList(g_alertedUp, name); Notify("向上突破", name, price, boxHigh); } if(!isUp) RemoveFromList(g_alertedUp, name); if(isDown && !IsInList(g_alertedDn, name)) { AddToList(g_alertedDn, name); Notify("向下突破", name, price, boxLow); } if(!isDown) RemoveFromList(g_alertedDn, name); } } void Notify(string direction, string boxName, double price, double edge) { string msg = StringFormat("[%s] %s 框 %s: 现价 %.5f, 边界 %.5f", Symbol(), direction, boxName, price, edge); if(InpAlert) Alert(msg); if(InpPush) SendNotification(msg); if(InpSound) PlaySound(InpSoundFile); Print(msg); } bool IsInList(string list, string name) { return(StringFind(list, name + ";") >= 0); } void AddToList(string &list, string name) { list += name + ";"; } void RemoveFromList(string &list, string name) { StringReplace(list, name + ";", ""); }这段代码里有一个容易被忽略的设计:我用事件定时器EventSetTimer做轮询,而不是完全依赖OnTick。原因是,如果某个品种长时间没有新的报价跳动,OnTick就不会触发,突破提醒也可能跟着延迟。定时器则保证每隔固定秒数检查一次,低频品种也能稳定工作。
3.2 核心检测函数CheckBreakout
CheckBreakout是整个EA的心脏。它首先遍历当前图表上的所有图形对象,用前缀和对象类型过滤出我们关心的矩形框,然后读取上下边沿价格。
这里有个细节:画矩形时如果从左上角拖到右下角,PRICE1就是上沿价、PRICE2是下沿价;但如果你反向拖拽,两个值的顺序会反过来。所以代码里加了一个大小判断,确保boxHigh永远是大的那个,boxLow永远是小的那个,否则判断方向就会反掉。
取价格的方式由InpUseClose参数控制。用收盘价时,iClose的shift参数直接绑定了InpConfirmBars,所以确认K线数设为2时,取的就是两根K线以前的收盘价。这意味着当突破刚发生时,你会等到第二根K线收盘那一下才收到提醒,信号会更稳定,但也会更慢。
3.3 状态管理为什么用字符串列表
为了防止重复提醒,我用了一个比较“朴素”的数据结构:一个字符串,里面用分号分隔所有已提醒的框名。比如某个框“Box_01”已经触发过向上突破,那么g_alertedUp就可能是“Box_01;”。
每次遍历到某个框时,先查列表里有没有这个框;没有且价格越界,就提醒并加入列表;只要价格回到框内,立刻从列表里把它移除。这个设计支持同一张图表上多个框同时被监控,而且逻辑非常直白,不容易出bug。
用字符串做列表肯定不是最高级的方式,但胜在代码短、可读性好。MT4的EA本身不追求极致的运行效率,这种量级的字符串操作完全可以忽略不计。
3.4 编译与挂载步骤
编译很简单。在MT4里按F4打开MetaEditor,新建一个专家顾问文件,把上面的代码粘贴进去,保存,然后按F7编译。看到“0 errors, 0 warnings”就说明编译通过,MetaEditor会在MQL4/Experts目录下生成对应的.ex4文件。
然后回到MT4客户端,在导航器里刷新一下,找到刚编译好的EA,拖到你要监控的图表上。这时会弹出设置窗口,在“输入参数”选项卡里可以调整前缀、确认K线数、声音文件名等配置。设置好后点击确定,EA就开始运行了。
需要注意一点:如果你改了代码重新编译,必须先把图表上的EA删掉,再重新拖入一次,否则MT4会继续运行旧版本。这个坑我踩过不止一次,改了半天参数发现根本没生效。
4. 部署清单:让提醒真正到达你手机
4.1 提醒通道怎么选
很多人装上EA之后第一反应是“为什么不弹窗”,或者“为什么手机没有推送”。其实MT4的通知体系和普通软件有点不一样,需要几条通道分别配置。
我更倾向的组合是:电脑在眼前时,保留声音提醒和Alert弹窗;人离开时,依赖手机推送。如果你既不在电脑前、手机也不方便看,那声音提醒基本就没用了,手机推送才是唯一能联系到你的通道。
4.2 手机推送的配置四步
SendNotification是MT4自带的消息推送机制,配置一次之后基本不用再管。步骤是:
- 在手机上下载并登录MT4官方App,保持登录状态;
- 在桌面MT4里打开“工具”->“选项”->“通知”,勾选“启用通知”;
- 用手机App扫描桌面端弹出的二维码,完成设备绑定;
- 确认手机系统允许MT4 App发送通知,关闭省电模式对后台推送的限制。
配置好之后,可以用EA里的InpPush参数控制是否启用推送。实测正常的网络环境下,消息从桌面端到手机的延迟一般在1到3秒左右,对突破提醒来说完全够用。
4.3 声音文件的放置位置
PlaySound这个函数有一点隐蔽:声音文件必须放在MT4数据目录下的MQL4/Sounds文件夹里,文件名要和EA参数里的InpSoundFile一致,比如“alert.wav”。
如果文件放错了位置,PlaySound不会报错,只会静默失败,很多人装了EA没有声音,排查半天才发现是文件路径不对。所以部署的时候,先检查MQL4/Sounds目录下有没有那个wav文件,再检查参数里填的是不是完整匹配的文件名。
4.4 轮询间隔的选择
代码默认的轮询间隔是5秒。为什么不是1秒?因为突破提醒这个场景本身不需要毫秒级的反应速度——5秒的延迟对M15以上的级别来说完全可以接受,而且能减少无谓的CPU占用和网络推送请求。
如果你做的是1分钟级别的区间突破,想更激进一点,可以把InpTimerSec改成1或者2。但我不推荐低于1秒,一方面MT4定时器本身也有精度限制,另一方面过高的轮询频率还会增加手机推送被频繁触发的风险,反而违背了提醒工具的初衷。
5. 实测运行中踩过的坑
5.1 矩形对象被误删或者被改名的静默故障
EA没有界面,运行起来之后你很难直观看到它到底在监控什么。最常见的故障是:矩形框被误删,或者被改了个名字,EA找不到目标对象,于是什么都不做。
这个问题最坑的地方在于“静默”——EA不会报错,日志里也没有明显异常,你只是发现很久没有提醒了。我的解决方案是给EA加上监控状态提示:在图表左上角用注释显示当前正在监控几个框、每个框的上下沿价格是多少。这样一眼就能看出EA是否正常工作。
实际操作中,画完框之后我会把矩形选中,然后在属性里把它设置为“禁止选择”,防止鼠标不小心拖动或者删除。这个操作不影响EA读取数据,但能有效避免手误。
5.2 假突破和长影线怎么过滤
使用过程中我收到最多的抱怨就是“提醒太多了”,基本都发生在价格贴着边界反复试探的时候。一根长上影刺穿上沿,收盘前又收回去,实时价判断就会立刻触发一次“向上突破”。
我的过滤梯度有三挡。第一挡,InpUseClose设为true,只用收盘价判断,这一下就能滤掉不少瞬时影线。第二挡,把InpConfirmBars设为1或2,等突破出现后的第N根K线收盘了再确认。第三挡,如果你还是觉得假信号多,可以在边界外追加一个缓冲带,价格必须越过边界一定距离才触发,这个会在后面进阶部分展开。
没有公式能百分百过滤假突破,但“少打扰、保留决策权”这个原则是对的。提醒太频繁会让你麻木,真正的大行情来临时你可能反而不当回事。
5.3 手机推送失灵时先查哪里
手机推送发不出去,我通常按这个顺序排查:先看桌面端MT4有没有弹窗提醒。如果弹窗正常,说明EA和检测逻辑都没问题,问题出在手机推送通道上。
接下来检查桌面端“通知”页面里的设备绑定是否还生效,手机App是否允许通知,手机系统有没有把MT4 App的后台活动限制掉。另一个容易被忽略的情况是:桌面端MT4如果已经退出登录,或者长时间挂机被服务器主动断开,推送也会跟着失效。保持登录状态是确保推送稳定的前提。
5.4 切换周期和缩放图表对矩形的影响
矩形对象的两个时间坐标是固定的历史时间点,当你把图表周期从M15切换到M30,或者用缩放工具拖动K线显示范围时,矩形看起来可能会缩成一小块,或者位置变得很怪异。
但这其实不影响EA工作,因为判断只依赖矩形的价格边沿,和时间坐标无关。真正需要警惕的是另一种操作:你手动拖动了矩形的一条边,以为只是微调视觉效果,结果把边界价改了,EA会立刻按新位置监控。所以画完框之后,我建议把矩形的“图标拖运”属性关掉,避免无意中改动关键边界。
5.5 多框同时触发的提醒顺序
同一张图表上画了好几个框,如果几个框在相近的时间点先后突破,EA会按对象列表的遍历顺序逐条触发提醒,手机上可能连续收到好几条推送。
这不是Bug,但也确实需要适应。我的处理方法是给每个框起带顺序的名字,比如“Box_01_上区间”“Box_02_下区间”,这样即便同时触发,你也知道先处理哪个。更保守的做法是,一个品种的一个时间周期只画一个框,把注意力集中在最值得关注的整理区间上。
6. 进阶:从“提醒”到“半自动交易流程”
6.1 不要自动下单,做半自动确认
把提醒和下单直接连起来,听起来很诱人,但我不建议这么做。框形突破最值钱的其实是“人确认风险”这一环——你收到提醒之后,打开图表看一眼当前的成交量、K线形态、整体趋势,再决定做不做。
所以我的交易流程是:手机收到突破提醒,看一眼推送里的框名和价格;如果认可,打开MT4手动下单;如果不认可,就把它当作一次观察信号。这套EA本身不承载交易决策,这也正是它稳定可靠的原因。
6.2 加上ATR缓冲带过滤假突破
如果你试完“收盘价判断+确认K线数”还是觉得假突破多,可以给边界加上一个动态缓冲带。ATR(平均真实波幅)能反映当前品种的波动水平,用“边界±N倍ATR”作为实际触发线,比固定点数更合理。
在EA的参数区加一行:
input double InpAtrFilterMultiple = 0.0; // ATR倍数缓冲, 0为关闭然后把判断逻辑改成:
double atr = iATR(Symbol(), PERIOD_CURRENT, 14, 1); double buffer = InpAtrFilterMultiple * atr; bool isUp = price > boxHigh + buffer; bool isDown = price < boxLow - buffer;这样设置之后,价格必须突破到边界外ATR倍数对应的高度,才算有效突破。数值设得越大,信号越少、越稳定,但提醒也会越滞后。我自己的习惯是设在0.3到0.5之间,既能滤掉大部分影线试探,又不会拖太多节奏。
6.3 多品种多周期的部署方式
EA只能读取当前图表对应品种的数据,所以如果你要监控多个品种,最稳妥的办法是给每个品种开一个图表,分别挂上同一个EA,用参数里的前缀区分各自要监控的框。
另一个思路是在同一个品种的不同周期各挂一份,比如M15图上监控短线区间,H1图上监控波段区间。这样各周期互不干扰,而且推送消息里会带上品种名,你一眼就能分清信号来自哪里。
我不太推荐做那种一个EA遍历所有品种、自动开隐藏图表的全自动监控方案。首先是MT4的图表对象和窗口管理在这种场景下很容易出问题,其次是监控太多品种本身就会让注意力失焦,反而违背了“减少盯盘负担”的初衷。
6.4 记录突破日志,复盘画框质量
最后分享一个我坚持在做的习惯:把每次突破提醒记录下来,过一段时间回看,统计自己画的框到底有多少次真的走出了趋势。
实现很简单,在EA的Notify函数里加一行Print输出,把品种、框名、方向、价格、时间写到MT4日志里。等积累了二三十次突破记录,你就能看出自己画的框“有效突破率”大概是多少,哪些品种的框更容易出趋势,哪些框只是反复被影线扫到。这个复盘数据比任何指标都更能告诉你,问题到底出在画框经验上,还是出在突破确认条件上。
我自己用这套EA最大的体会是,它把“等待”这个最耗神的部分从交易里剥离出去了。框是你画的,边界是你定的,EA只是在信号出现的那一刻喊你一声,至于相不相信这个信号,能不能执行到位,仍然是你自己的功课。工具最大的价值不是让你偷懒,而是让你在关键信号来临时,拥有一个清醒的头脑去做决定。