资讯详情

MT4自动交易EA合集:四类策略源码拆解与实战回测指南

📅 2026/10/18 21:43:16 | 华诺云谱 👁 阅读
MT4自动交易EA合集:四类策略源码拆解与实战回测指南
简介MT4自动交易系统资源包面向外汇交易者、EA开发爱好者及初学量化策略的投资者汇总了多套自动交易策略与配套学习材料覆盖从策略逻辑理解、MQL4源码修改到MT4平台加载运行的完整链路。压缩包内共151个文件主要包括53个mq4源码文件与51个ex4编译程序便于对照学习或直接挂载到图表上运行另外还提供了rar/zip打包的策略合集、doc文档说明、tpl图表模板、txt使用笔记等辅助理解规则细节与风控思路。整体包体大小约16.99MB目前已有998人学习下载。内容还包含海豚交易系统7.0交易规则、文字版对照录音以及正确理解亏损、遵守纪律高于一切等交易理念文档适合希望把自动执行与人工监督结合的中级交易者按需选用也可作为编写自研EA的参考范例。1. MT4自动交易EA合集四个能直接编译挂载的策略源码入口MT4自动交易里有个反直觉的现象回测曲线最漂亮的EA往往爆仓最快。尤其是网格马丁类利润曲线看着像稳步爬坡实际是在给一次大回撤攒风险。这篇文章要拆解的这套资源是一份包含四个完整EA源码的合集包涵盖均线交叉、网格马丁、通道突破、趋势跟踪这四类最常见的自动交易策略。每个EA都是独立的.mq4源码带止损止盈、魔术编号和仓位控制编译后拖到图表上就能跑。适合刚到MT4自动交易门口、想找一个现成EA跑通全流程的新手也适合想拿现成代码改参数做二次开发的熟手。下面按我的拆包顺序先看资源落地到家目录的完整路径再逐段拆核心逻辑然后讲回测参数最后写常见坑和改造思路。2. 目录结构与工作台准备从压缩包到策略测试器的完整落地拿到源码包先别急着双击第一步是搞清里面每个文件是干什么的。MT4对文件目录有严格约定放错文件夹导航器里就找不到程序这一步卡住的人不少。2.1 资源包构成.mq4源码、.set参数与.ex4程序的各自分工资源解压后通常是这样的目录结构MT4_EA_Pack/ ├── MQL4/ │ └── Experts/ │ ├── MACrossEA.mq4 │ ├── GridMartinEA.mq4 │ ├── BreakoutEA.mq4 │ └── TrendFollowEA.mq4 ├── Presets/ │ ├── MACrossEA_Default.set │ ├── GridMartinEA_Conservative.set │ └── BreakoutEA_H4.set └── 说明文档.txt这个结构里.mq4是MQL4语言的源代码用MetaEditor打开后按F7即可编译。.ex4是编译后的可执行程序正常OBJ存在于MQL4/Experts目录图表导航器左侧的“智能交易系统”列表就是扫描这个目录显示的。.set是参数预设文件回测时在策略测试器“参数”选项卡里一键加载也可以在挂载EA到图表后右键加载。我一般拿到EA源码的第一件事就是打开MetaEditor重新编译一遍而不是直接用包里带的.ex4。原因很简单MT4版本更新频繁旧编译产物经常出现“incompatible version”提示自己本地编译保证了EA与当前平台版本匹配。编译成功后底部信息窗口会显示类似MACrossEA.mq4 MACrossEA.ex4: 0 errors, 0 warnings出现这个结果说明源码至少在语法层面是健康的。如果报错进到第5章的排查部分看。2.2 MetaEditor环境准备数据目录、编译选项与常用快捷键把资源包放进MT4的正确姿势是打开数据目录。在MT4主界面按CtrlR是打开策略测试器但打开数据目录的入口在“文件”菜单里点击“打开数据文件夹”会弹出一个资源管理器窗口里面能看到MQL4目录、tester目录、config目录等。然后把压缩包里的文件分别合并进去.mq4文件放进MQL4/Experts/.set文件没有强制目录放哪都行加载时手动定位.txt文档随意放置不参与平台运行。复制文件时如果MT4正在运行建议先关闭MT4再复制或者复制完成后在导航器窗口按F4刷新否则资源管理器不会自动感知新文件。我踩过一次这个坑文件复制进去了导航器里怎么找都找不到后来发现是MT4启动时缓存了目录列表重启才好。MetaEditor里常用的是F7编译、F4切回MT4主界面。编译输出窗口在下方双击错误行会直接跳到对应代码位置。写EA时我习惯把#property strict放在第一行这行声明让编译器做严格的类型检查能提前暴露很多隐藏问题。挂载EA到图表还有一个高频翻车点自动交易总开关。MT4工具栏上有两个相关按钮一个是“算法交易”总开关一个在“选项→智能交易系统”里勾选“允许算法交易”。图表被加载EA后右上角会显示一个笑脸图标灰色笑脸表示自动交易被禁用黄色笑脸才是运行中。很多新手把EA拖上图表就不管了看到灰色的笑脸还以为EA坏了其实是总开关没打开。3. 核心模块拆解均线交叉EA的完整交易链路这个EA是整套资源里最适合逐行精读的一个。逻辑不复杂但开仓、平仓、仓位管理、订单隔离这些完整链路都在读懂它另外三个EA只是换策略信号而已。3.1 初始化与主循环双均线信号怎么进入状态机先看整体骨架然后是开仓信号的核心判断#property strict input double LotSize 0.01; input int FastMAPeriod 5; input int SlowMAPeriod 20; input int SL_Pips 30; input int TP_Pips 60; input int MagicNumber 202401; datetime lastBarTime 0; int OnInit() { return INIT_SUCCEEDED; } void OnTick() { if(Time[0] lastBarTime) return; lastBarTime Time[0]; double fastNow iMA(_Symbol, PERIOD_CURRENT, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 0); double fastPrev iMA(_Symbol, PERIOD_CURRENT, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1); double slowNow iMA(_Symbol, PERIOD_CURRENT, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 0); double slowPrev iMA(_Symbol, PERIOD_CURRENT, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1); if(fastPrev slowPrev fastNow slowNow) OpenOrder(OP_BUY); else if(fastPrev slowPrev fastNow slowNow) OpenOrder(OP_SELL); }Time[0]是当前正在形成的K线开盘时间戳lastBarTime用来记录上一次处理过的K线时间。这段代码的核心作用是把策略从“每个tick都判断”降频成“每根新K线判断一次”。这样做最直接的好处是避免同一根K线内反复触发同一个信号导致在同一个价位附近开出好几笔方向相同的单子。iMA这里取了四条数据快线当前值和前一根K线的值、慢线当前值和前一根K线的值。金叉的定义就是快线从慢线下方跑到上方也就是fastPrev slowPrev fastNow slowNow死叉反过来。PERIOD_CURRENT表示跟随当前图表周期挂到H1图上就按H1计算挂到M15就按M15这个设计能让同一个EA在不同周期上复用。3.2 开仓函数手数换算、止损止盈与魔术编号隔离信号触发后进入开仓函数这个函数是每次写EA都会用到的模板void OpenOrder(int cmdType) { int count CountMyTrades(); if(count 0) return; double point _Point; if(_Digits 3 || _Digits 5) point _Point * 10; double price (cmdType OP_BUY) ? Ask : Bid; double sl 0, tp 0; if(SL_Pips 0) sl (cmdType OP_BUY) ? price - SL_Pips * point : price SL_Pips * point; if(TP_Pips 0) tp (cmdType OP_BUY) ? price TP_Pips * point : price - TP_Pips * point; int ticket OrderSend(_Symbol, cmdType, LotSize, price, 3, sl, tp, MA Cross, MagicNumber, 0, clrGreen); if(ticket 0) Print(开仓失败错误码 IntegerToString(GetLastError())); else PrintFormat(开仓成功ticket%d价格%f, ticket, price); }CountMyTrades这个函数的写法很典型它倒序遍历整个订单列表只统计当前图表、当前魔术编号下的订单int CountMyTrades() { int cnt 0; for(int i OrdersTotal() - 1; i 0; i--) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if(OrderSymbol() _Symbol OrderMagicNumber() MagicNumber) cnt; } } return cnt; }魔术编号是EA自我保护的关键。一个账户里可以有多个EA在跑甚至同图表挂两个策略如果把OrderSelect选中后直接对订单操作很可能会动到别的EA甚至手工单。通过OrderMagicNumber()和OrderSymbol()双重过滤保证这个EA只管自己名下的单子。我在写多策略组合时会给每个EA分配一个独立的MagicNumber区间这样后续做统计和风控时一眼就能识别订单归属。止损止盈这里有个单位换算问题_Point在5位报价下是0.00001而传统意义上的1 pip在5位报价下是10点所以要用_Point * 10来做换算。如果参数里SL_Pips设成30实际价格距离就是30个pipette。不同平台的点值定义不一样这个换算逻辑要配合自己平台做调整。3.3 平仓与移动止损尾盘离场、浮盈保护开仓只是开始资金曲线好不好看更取决于平仓管理。这个EA的平仓函数做了两件事移动止损和尾盘清仓void ManagePosition() { for(int i OrdersTotal() - 1; i 0; i--) { if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue; if(OrderMagicNumber() ! MagicNumber || OrderSymbol() ! _Symbol) continue; if(MoveSL_Pips 0) { double newSL 0; if(OrderType() OP_BUY) newSL Bid - MoveSL_Pips * point; else newSL Ask MoveSL_Pips * point; if((OrderType() OP_BUY newSL OrderStopLoss()) || (OrderType() OP_SELL newSL OrderStopLoss())) { OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble(newSL, _Digits), OrderTakeProfit(), 0, clrRed); } } if(CloseBeforeBarClose_Minutes 0) { datetime barClose Time[0] PeriodSeconds(); if(TimeCurrent() barClose - CloseBeforeBarClose_Minutes * 60) CloseOrder(OrderTicket()); } } }移动止损的逻辑关键在于只往盈利方向推。newSL OrderStopLoss()买单调用来判断新止损价是否高于当前止损价只有浮盈推进时才调用OrderModify否则频繁修改止损既增加系统调用开销也可能触发平台限制。OrderModify前必须用NormalizeDouble(newSL, _Digits)对齐精度否则个别平台会返回“invalid stops”错误。尾盘清仓是一种典型的日内交易纪律参数CloseBeforeBarClose_Minutes设为30就是提前30分钟把当根K线的持仓全部平掉避免隔夜跳空和突发事件。这个逻辑对新手特别友好它强制策略在固定的时间段内结束交易不会留下一堆隔夜单等第二天开盘被甩。3.4 点差保护与手工单隔离防止买在最高点EA还有一个容易被忽视的细节——点差过滤。在数据公布时段点差会突然拉大此时信号可能刚好触发如果照常开仓等于买在明显不利的价位input int MaxSpreadPips 30; int spreadPips (int)((Ask - Bid) / point); if(spreadPips MaxSpreadPips) { Print(当前点差过大跳过开仓); return; }Ask - Bid就是即时点差把它除以point得到以点表示的值。当超过参数阈值时直接跳过本次开仓这就是把“不做这笔交易”当成一种有效风控手段。马丁EA尤其需要这个保护它总在亏损后加仓如果加仓时点差过大等于在额外的成本上方继续放大风险敞口。4. 参数回测与实盘挂载网格EA与突破EA的验证流程均线交叉EA看懂后剩下三个EA的核心逻辑快速过一遍重点讲回测怎么做才可信。4.1 网格马丁EA加仓间距、倍数与熔断参数网格马丁EA的策略思路是价格每下跌一档买入一单每上涨一档卖出一单持仓数量越多单笔手数越大整体浮亏靠最后一批单子回本。核心加仓逻辑如下input double StartLot 0.01; input double LotMultiplier 1.5; input int GridStepPips 50; input int MaxTrades 6; input int MaxDrawdownPercent 30; void OnTick() { if(nextBuyPrice 0) { nextBuyPrice Ask - GridStepPips * point; nextSellPrice Bid GridStepPips * point; } if(Bid nextBuyPrice) { int cnt CountGridTrades(); if(cnt MaxTrades) { double lot NormalizeDouble(StartLot * MathPow(LotMultiplier, cnt), 2); OrderSend(_Symbol, OP_BUY, lot, Ask, 3, 0, 0, Grid, MagicNumber, 0, clrBlue); nextBuyPrice Ask - GridStepPips * point; } } if(Ask nextSellPrice) { int cnt CountGridTrades(); if(cnt MaxTrades) { double lot NormalizeDouble(StartLot * MathPow(LotMultiplier, cnt), 2); OrderSend(_Symbol, OP_SELL, lot, Bid, 3, 0, 0, Grid, MagicNumber, 0, clrRed); nextSellPrice Bid GridStepPips * point; } } }这里MathPow(LotMultiplier, cnt)计算加仓后的手数第一单0.01第二单0.015第三单0.0225呈几何级数增长。MaxTrades是总单数上限这是网格马丁EA最关键的熔断参数没有它遇到单边趋势会一直加仓到爆仓。浮亏熔断是网格马丁的“后悔药”当全部网格单的总浮亏超过账户余额一定比例时强制清仓double globalProfit 0; for(int i OrdersTotal() - 1; i 0; i--) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if(OrderSymbol() _Symbol OrderMagicNumber() MagicNumber) globalProfit OrderProfit() OrderSwap(); } } if(globalProfit 0) { double lossPercent MathAbs(globalProfit) / AccountBalance() * 100; if(lossPercent MaxDrawdownPercent) { CloseAllGridOrders(); Print(触发熔断全部网格单已清仓); } }我在跑这个EA的回测时会把GridStepPips分别设成30、50、80把MaxTrades设成4、6、8交叉对比。很多人只看总利润曲线却忽略了一个致命指标——最大回撤。网格马丁EA的利润和回撤几乎成正比参数越激进回测曲线越好看实盘爆仓风险越高。这个EA最好配合单一品种不要跨品种同时跑多个网格否则账户总仓位会瞬间失控。4.2 突破EA通道识别与订单执行突破EA的策略逻辑是统计过去N根K线的最高价和最低价形成一个箱体通道价格向上突破箱体上沿就做多向下跌破箱体下沿就做空。代码比网格EA简洁input int ChannelPeriod 24; input int BreakoutPips 10; input int SL_Pips 40; input int TP_Pips 80; double upLevel iHigh(_Symbol, PERIOD_H1, iHighest(_Symbol, PERIOD_H1, MODE_HIGH, ChannelPeriod, 1)); double dnLevel iLow(_Symbol, PERIOD_H1, iLowest(_Symbol, PERIOD_H1, MODE_LOW, ChannelPeriod, 1)); if(Bid upLevel BreakoutPips * point) OrderSend(_Symbol, OP_BUY, LotSize, Ask, 3, Ask - SL_Pips * point, Ask TP_Pips * point, Break, MagicNumber, 0, clrGreen); if(Ask dnLevel - BreakoutPips * point) OrderSend(_Symbol, OP_SELL, LotSize, Bid, 3, Bid SL_Pips * point, Bid - TP_Pips * point, Break, MagicNumber, 0, clrRed);iHighest返回过去24根K线中最高价的位置索引把这个索引再传给iHigh取出具体价格值。BreakoutPips是过滤假突破的偏移量价格必须突破通道上沿并超过10点才触发开仓。这样做的目的是减少在通道边缘反复震荡时被反复打脸的次数。突破EA的回测参数重点在ChannelPeriod。周期太小通道窄触发频繁手续费和止损成本会吃掉利润周期太大通道宽信号少一年可能就几笔交易。我一般用H1配合24周期做基准再用48和72周期做对比观察交易次数和净利润之间的平衡点。4.3 策略测试器跑出可信结果的参数模板回测不是简单点“开始”就完事参数设置直接影响结论是否可信。我给这套资源跑回测时的固定模板如下配置项推荐设置原因交易品种与周期EURUSD H1主流品种流动性好历史数据完整回测区间至少2年覆盖趋势和震荡行情建模方式每个tick基于真实tick最接近实盘成交路径点差设置按当前交易商默认加点差忽略了点差会让回测虚高参数加载加载对应的.set文件保证和实盘挂载参数一致在策略测试器里加载.set文件的方式是选好EA后右侧“参数”选项卡底部有一个“加载”按钮点击后定位到Presets目录即可。加载后参数表会变成预设值再点“开始”跑回测。跑完主要看四个指标净利润、最大回撤、盈利因子、总交易笔数。我特别留意总交易笔数如果一年只有不到20笔样本量太小统计意义有限如果笔数很大但盈利因子只略高于1说明策略靠堆交易次数赚小钱手续费一上调可能就转为亏损。回测报告只能帮你排除明显不合理的策略不能用来断言未来收益这一点一定记牢。5. 常见问题排查编译报错、回测失真与订单不成交的实例记录这套资源挂载过程中有几个高频问题我按实测踩坑记录的形式整理出来每一条都按现象、原因、解决三步写清楚。5.1 编译不过历史函数与新版MQL4的兼容差异现象把.mq4文件拖进MetaEditor按F7下方错误窗口弹出一片红色最常见的报错是OrderSend - wrong parameters count和iMA - parameter conversion not allowed。原因新版MQL4编译器默认开启严格模式要求函数参数数量和类型必须完全匹配。早期写的EA代码没有#property strict声明依赖编译器自动转换类型在新版本下全部暴露成了错误。另外Print里直接用拼接数字和字符串在新版里也被禁止必须用类型转换函数。解决在源码第一行加上#property strict。然后逐个错误行修正整数参数用(int)显式强转打印字符串用IntegerToString(GetLastError())替换直接拼接。这类报错不是程序逻辑问题纯粹是语法规范和版本兼容一般几分钟能修完。5.2 回测失真tick模式、点差与历史数据质量现象同一个EA用“每根K线”模式回测年化收益翻倍换成“每个tick基于真实tick”后利润缩水一半在某交易商平台的历史数据上回测很漂亮换一家交易商数据后曲线完全变形。原因每根K线模式下系统假设订单只在K线收盘价成交忽略了K线运行过程中最高价、最低价对止损止盈的触发路径。点差设置也是一样默认的0点差回测会把每次开仓成本节省下来累积起来就是一笔虚拟利润。解决回测建模方式一律选“每个tick基于真实tick”点差按实盘默认值加上去。如果平台没有该品种的详细tick数据在历史数据中心先下载完整数据再回测。跑实盘前还要用可视化回测模式播放一遍确认订单开平仓位置和信号标注一致。5.3 订单不成交止损止盈距离、挂单距离与算法交易开关现象EA日志里打印invalid stops或直接没有报错但图表右上角EA图标是灰色的单子始终不开。原因invalid stops通常是止损价距离现价太近不满足交易商的最小止损距离要求灰色图标是自动交易总开关没打开还有一种情况是前一次OrderSend还没有返回结果下一次OrderSend已经触发系统返回trade context busy。解决止损参数先按平台规定的最小止损距离设置比如某平台要求止损至少距现价20点那么SL_Pips低于20就会被拒单。挂载EA前确认工具栏“算法交易”按钮已点亮。代码层面在OrderSend前加while(IsTradeContextBusy()) Sleep(50);做等待并在下单后加少量Sleep(100)给平台时间完成订单上下文切换。5.4 回测最佳参数实盘翻车参数过拟合的自查点现象用2019到2021年的数据优化出一组参数实盘跑了三个月开始连续亏损而同一时间段的回测曲线依然漂亮。原因这是一类典型过拟合问题。EA的input参数越多组合空间越大优化器越容易找到一条只在历史数据上成立的参数组合。真实施加行情里价格路径不会完全重复过去最赚钱的参数往往也是对未来最敏感的参数。解决优化完参数后用样本外数据做验证——假设用2019-2021优化就保留2022-2023的数据不参与优化直接拿优化后的参数去跑这一段。如果两段数据表现差距过大说明参数过拟合。排查时还看两个点策略中的逻辑是否依赖特定品种的波动特性以及交易笔数是否足够支撑结论。我自己的经验是把参数数量控制在6个以内同时只优化最核心的三四个能显著降低过拟合概率。6. 二次开发把单品种EA改造成多品种轮询的风控管理器最后给一个具体的改造方向把单图表EA改成一份代码同时监控多个品种用一个图表管理整个账户的自动交易。核心思路是抽离品种相关的部分。原代码里大量使用_Symbol、PERIOD_CURRENT改造后全部换成参数传入。我在OnInit里用StringSplit解析逗号分隔的品种列表再为每个品种分配独立的MagicNumber段input string TradeSymbols EURUSD,GBPUSD,XAUUSD; input int BaseMagic 202410; input double MaxTotalLot 0.5; string Symbols[]; int Magics[]; int OnInit() { string parts[]; int n StringSplit(TradeSymbols, ,, parts); ArrayResize(Symbols, n); ArrayResize(Magics, n); for(int i 0; i n; i) { Symbols[i] parts[i]; Magics[i] BaseMagic i; } return INIT_SUCCEEDED; } void OnTick() { for(int i 0; i ArraySize(Symbols); i) { string sym Symbols[i]; if(TotalOpenLot() MaxTotalLot) continue; CheckSignal(sym, Magics[i]); } }CheckSignal就是原来均线交叉EA里的开仓判断只是把_Symbol替换成了sym参数把MagicNumber替换成Magics[i]。TotalOpenLot统计账户所有订单的总手数超过阈值就跳过新开仓这是多品种版最需要的全局风控原先每个EA只管自己多个EA同时开仓时账户总体仓位可能失控。改造后的验证流程我每次必走四步先用原来的单品种参数跑一遍回测作为基线记录净利润和最大回撤然后跑多品种版本对比总手数曲线是否超出预期接着用可视化模式观察一遍订单序列确认多个品种之间的下单顺序和风控逻辑没有互相干扰最后在小仓位模拟盘挂一周观察真实点差下执行是否正常。从那以后我每次改完EA都强制走一遍这四步缺一步都不上实盘这套流程帮我避掉过好几回改造引入莫名其妙的亏损源。希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑