MT5趋势EA开发实战:从均线判定到ADX过滤的完整策略拆解
2026/9/2 15:34:55 网站建设 项目流程

简介:这是一份面向外汇与程序化交易者的趋势跟随型 EA 资源。EA 在 MetaTrader 平台运行,利用均线、MACD、RSI 等技术指标自动识别趋势并完成开仓、平仓,同时内置止损止盈逻辑,适合希望摆脱情绪干扰、实现 24 小时自动化盯盘的用户。资源包共 3 个文件,包含可直接挂载至 MT4 平台使用的 ex4 编译程序,以及 htm 回测报告和 gif 走势图,可快速查看该策略的历史收益、回撤及盈亏分布。压缩包仅 321KB,部署便捷,目前已吸引 566 人学习下载。对程序化交易新手而言,可借助回测资料理解趋势策略的构建与验证思路;对实盘交易者,则可在模拟盘测试后评估其是否适合当前市场风格。需注意,趋势策略在震荡行情中表现可能受限,使用前应充分回测并做好风险控制。 做自动化交易这些年,我越来越觉得趋势类EA才是普通交易者最该碰的方向。不是因为它能一夜暴富,而是趋势策略的逻辑足够朴素——行情要么涨、要么跌、要么震荡,而趋势EA就是把这三种状态用代码明确写死,让程序在趋势来临时自动上车、趋势终结时自动下车。相比高频、套利那些对硬件和资金要求极高的策略,趋势EA对普通散户友好得多,MT5上跑一个MQL5写的趋势EA,配合VPS,基本上可以实现全天候盯盘。

这篇文章我会把自己做趋势自动交易EA的完整思路、核心逻辑、代码骨架、回测参数以及踩过的坑全部摊开讲,适合已经懂一点交易、准备自己写EA或者正在选EA的投资者,也适合刚接触MQL5、想搞清楚趋势类EA内部到底怎么回事的新手。

1. 为什么选趋势策略做自动交易:思路与选型

1.1 趋势策略到底解决了什么问题

先想清楚一件事:人工交易最大的敌人不是行情,是情绪。单子拿不住、亏损摊不平、盈利拿一点就跑,这些问题几乎人人都有。趋势EA的核心价值,就是把这些反人性的动作变成一条条硬性规则,由程序强制执行。

趋势策略本身的逻辑足够简洁,它默认一个前提:价格在大部分时间里会沿着某个方向惯性运动。EA要做的只有三件事——判断当前是什么趋势、趋势什么时候开始、趋势什么时候结束。把这三件事想明白了,EA的框架就出来了。市场上那些所谓“神秘指标”“稳赚策略”,本质都是在做这三件事的变体。

1.2 为什么用MT5 + MQL5,而不是其他平台

国内很多朋友一开始会接触通达信、东方财富期货这样的软件,里面也有很多趋势指标、买卖点公式。但坦白讲,这些工具更适合做分析辅助,并不适合承载完整的自动交易。通达信虽然也能写公式,但它的公式系统偏重画线和选股,真正要执行到下单那一步,链路很长,而且历史回测的颗粒度不够细。

我最后选择了MT5 + MQL5,理由有三个:

  • 回测精度高:MT5的策略测试器支持每一个tick建模,能模拟真实盘口跳动,回测结果参考价值比分钟级K线高得多。
  • 订单管理灵活:MQL5原生支持市价单、限价单、止损止盈、挂单修改,逻辑写起来非常顺手。
  • 生态成熟:MQL5社区有大量现成库和案例,遇到问题基本都能搜到解决方案。

你完全可以把通达信或东方财富的指标当作“灵感来源”,在MT5上重新实现一遍。比如缠论的分型、笔、中枢逻辑,或者欧奈尔的趋势买点,这些思路都可以用MQL5转化成可执行的判断条件。这也是我后来做第二版EA时的主要路线。

1.3 策略分级:从单均线到多因子确认

很多新手写趋势EA,第一个方案就是金叉死叉:均线上穿做多,下穿做空。回测一看,利润曲线还行,实盘一跑就露馅——震荡行情里金叉死叉反复触发,手续费和滑点吃掉了所有利润。

所以我在设计趋势EA时,把策略分成了三个层级:

  1. 基础趋势判定:用均线斜率或价格与均线的关系,确认大方向。
  2. 入场时机确认:等待回调结束的信号,避免追高和杀跌。
  3. 过滤器:用ADX、布林带宽度等指标过滤掉低波动震荡区间。

简单说,方向对了还不够,还得等一个“好价格”。这一层过滤,决定了EA是赚钱还是白给平台交手续费。

2. 核心逻辑拆解:趋势判定、入场离场与仓位控制

2.1 趋势判定体系:均线、通道和动能的组合

趋势判定是整个EA的地基,地基歪了后面全白搭。我目前用的是三重复合判定,具体逻辑如下:

第一重:均线系统

采用双均线结构——快线EMA 20、慢线EMA 60。当快线在慢线上方,且慢线本身向上倾斜时,判定为多头趋势;反之空头趋势。为什么加“慢线本身向上倾斜”这个条件?因为单纯看金叉死叉,震荡市里均线会反复缠绕,但加了斜率过滤后,很多假信号直接被挡在门外。

第二重:价格通道

引入唐奇安通道,取过去55根K线的最高价和最低价作为通道上下轨。价格突破通道上轨,视为多头动能增强;跌破下轨,视为空头动能增强。唐奇安通道的好处是它能动态适应市场波动,行情越剧烈通道越宽,天然带有波动率自适应属性。

第三重:动能过滤

ADX指标,默认周期14。ADX值低于20时,我判定市场处于震荡状态,EA直接不交易。ADX在20到40之间,趋势处于健康发展阶段,允许正常入场;ADX高于40,趋势过快,我倾向于不开新仓,只持有已有仓位,防止追在高点。

这三个条件组合起来,入场信号的胜率明显比单用均线高出一大截。

2.2 入场与离场:四类信号如何处理

做趋势EA,入场信号很容易设计,难的是离场。我的离场设计参考了通达信缠论买点思路和欧奈尔趋势买点里“做T辅助”的概念,把出场分成了四类信号:

第一类:趋势反转信号

当价格跌破关键均线(比如EMA 20)且均线斜率掉头向下,说明短期趋势已经走坏,此时无条件平多单。这是最常规的出场方式,优点是回撤小,缺点是震荡市里容易被洗下车。

第二类:固定止盈止损

入场的同时带上硬性止盈止损。止损一般放在入场前一个波段的极值点外侧,止盈则根据最近几波行情的平均幅度动态计算。不要用固定点数止盈,不同品种波动率差异太大,固定点数要么太容易被扫掉,要么永远够不到。

第三类:移动止损

当价格向有利方向走到一定幅度后,把止损位上移到“开仓价 + 已实现利润的一半”。这个位置是保本加锁定部分利润的折中方案,既能防止利润大幅回吐,又不会因为移动太紧导致被普通回调扫出局。

第四类:趋势加速离场

当ADX进入高位(比如50以上),同时价格出现连续大阳线或大阴线,说明趋势进入加速末端。此时我不等趋势反转信号出现,直接主动减仓一半,剩下的仓位继续拿着,让利润奔跑。

2.3 仓位管理:固定手数与动态风险的取舍

仓位管理是趋势EA生死攸关的一环。很多EA策略本身没问题,死于仓位过重。我见过有人用马丁格尔策略,连亏三次就爆仓,这种模式本质上是在赌“不会一直错下去”,一旦遇到单边反向行情,账户直接归零。

趋势EA的仓位管理,我推荐两种方式:

固定风险比例法

每笔交易只承担账户总资金的1%到2%风险。公式很简单:手数 = (账户净值 × 风险比例) ÷ (止损点数 × 每点价值)。这套逻辑的好处是,亏损的绝对值会随账户净值变化而自动调整,账户小了少下,账户大了多下,不会出现一把梭哈的情况。

凯利公式改良法

凯利公式告诉你最优下注比例,但实战中我从不直接用它,因为凯利假设你清楚知道胜率和盈亏比,而真实交易的胜率是动态变化的。我会把凯利计算结果的半仓,甚至三分之一仓作为实际仓位。比如凯利算出20%,我只下6%到10%。这样做的好处是,即使胜率估算有偏差,也不至于重创账户。

3. 实操过程:一套趋势自动交易EA的完整落地

3.1 MQL5代码骨架:从OnTick到下单

接下来讲代码实现。这里分享一套最简版趋势EA的核心骨架,基于EMA均线和ADX过滤,没有加唐奇安通道那些复杂逻辑,但框架是通用的,你可以在此基础上扩展。

// 输入参数 input double LotSize = 0.1; // 固定手数 input int FastMAPeriod = 20; // 快线周期 input int SlowMAPeriod = 60; // 慢线周期 input int ADXPeriod = 14; // ADX周期 input double ADXFilter = 20.0; // ADX入场阈值 input double RiskPercent = 1.0; // 风险比例(%) // 指标句柄 int hFastMA, hSlowMA, hADX; int OnInit() { hFastMA = iMA(_Symbol, _Period, FastMAPeriod, 0, MODE_EMA, PRICE_CLOSE); hSlowMA = iMA(_Symbol, _Period, SlowMAPeriod, 0, MODE_EMA, PRICE_CLOSE); hADX = iADX(_Symbol, _Period, ADXPeriod); if(hFastMA == INVALID_HANDLE || hSlowMA == INVALID_HANDLE || hADX == INVALID_HANDLE) return(INIT_FAILED); return(INIT_SUCCEEDED); }

OnTick是EA的心脏,每个价格跳动都会触发一次。为了防止同一根K线上重复开仓,我在代码里加了BarCount判断,确保每根K线只做一次决策:

datetime lastBarTime = 0; void OnTick() { MqlDateTime dt; TimeToStruct(TimeCurrent(), dt); if(dt.day_of_year * 1440 + dt.hour * 60 + dt.min == 0) // 简化演示 return; datetime curBarTime = iTime(_Symbol, _Period, 0); if(curBarTime == lastBarTime) return; lastBarTime = curBarTime; double fastMA[], slowMA[], adx[]; ArraySetAsSeries(fastMA, true); ArraySetAsSeries(slowMA, true); ArraySetAsSeries(adx, true); CopyBuffer(hFastMA, 0, 0, 3, fastMA); CopyBuffer(hSlowMA, 0, 0, 3, slowMA); CopyBuffer(hADX, 0, 0, 3, adx); bool isUptrend = (fastMA[1] > slowMA[1] && slowMA[1] > slowMA[2]); bool isDowntrend = (fastMA[1] < slowMA[1] && slowMA[1] < slowMA[2]); bool trendStrong = (adx[1] > ADXFilter); if(!trendStrong) return; if(isUptrend && CountOpenOrders(POSITION_TYPE_BUY) == 0) OpenOrder(ORDER_TYPE_BUY); else if(isDowntrend && CountOpenOrders(POSITION_TYPE_SELL) == 0) OpenOrder(ORDER_TYPE_SELL); }

下单函数里,止损设置在最近N根K线高低点外侧,止盈按止损距离的1.5倍设置。代码就不全贴了,核心是仓位计算这一行:

double riskMoney = AccountInfoDouble(ACCOUNT_BALANCE) * RiskPercent / 100.0; double stopPoints = MathAbs(entryPrice - stopLossPrice) / _Point; double lot = riskMoney / (stopPoints * _Point * _SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE)); lot = NormalizeDouble(lot, 2);

注意最后用NormalizeDouble规范小数位,否则经纪商可能拒绝订单。每个品种的最小交易量不一样,黄金通常是0.01手,原油也是0.01手,但有些指数CFD最小是1手,这个要查合约规格。

3.2 参数计算与回测验证

参数设计上,我强烈不建议一上来就优化得漂漂亮亮。回测跑得好不好看,跟实盘能不能赚钱,中间隔着一条巨大的认知鸿沟。

以EURUSD H1为例,我第一版参数是EMA 20和EMA 60,ADX 14周期,阈值20。回测一年,结果盈利不错,最大回撤控制在15%以内。

但后来我尝试优化的时候发现,EMA 18和EMA 57的组合回测结果更好,最大回撤甚至只有11%。这时候你就要警惕了——参数越精细,越可能是在拟合历史噪音。真实市场的数据分布是不稳定的,你在过去九个月找到的“最优参数”,下个月可能就失灵。

我的做法是:先跑前六个月的回测,确定一个“粗糙但逻辑通顺”的参数区间,再用后六个月的数据做样本外验证。如果样本外表现和样本内差不多,说明参数有过拟合的可能性低。如果样本外收益断崖式下跌,那参数就是被过度优化了。具体来说,我通常用最近一年数据做样本内测试,再往前找半年到一年的数据做样本外测试。

回测时还要注意几个参数设置:

  • 手续费:不要设0,默认要按真实经纪商的标准放进去。
  • 滑点:实盘不可能零滑点,回测至少设3到5点。
  • 点差:用动态点差比固定点差更接近真实情况。

能把这些细节都考虑进去的回测,才有一点参考价值。

3.3 从回测到实盘的常见细节

回测完毕,别急着实盘。先跑至少一个月的模拟盘(Demo账户),验证EA在真实行情下的表现,同时看看有没有“回测没遇到、实盘才会出现”的问题。

比如我之前遇到一个问题:VPS和经纪商服务器之间的网络延迟,导致EA在下单时价格已经偏离预期,订单一直挂不上。回测环境里网络延迟是零,实盘环境里不可能零延迟。解决办法是设置合理的滑点容忍度,或者把EA部署在离经纪商服务器最近的机房。

再比如,周五晚间到周六凌晨,行情流动性骤减,点差会突然拉大好几倍。趋势EA在这个时间段开仓,容易被异常点差吃掉成本。我的EA里加了一个时间过滤器,周五22点后不开新仓,周一早上8点半之后再恢复。每个市场开收盘时间不一样,这个要根据你交易的品种来调整。

4. 常见问题与排查技巧实录

4.1 信号闪烁与未来函数

这是新手EA最容易犯的问题。信号闪烁指的是EA在同一个K线未收盘时反复改变判断,导致信号出现又消失。问题根源在于,有些指标(比如ZigZag、分型)在K线收盘前,数值会随着价格变动而变化。

解决思路只有一个——只用已收盘K线的数据做决策。我的EA里所有指标取值都用[1],也就是上一根K线,当前这根K线无论怎么波动都不参与决策。代价是入场价格会略微滞后,但换来的是信号的确定性。这对趋势EA来说,完全值得。

4.2 回测完美、实盘亏损的元凶

回测结果有多漂亮,实盘翻车就有多容易。我用一个表格把常见原因列出来,方便对照排查:

常见原因说明排查方法
手续费设置过低回测手续费0或极低,实盘成本被严重低估按经纪商标准设置手续费和点差
忽略滑点趋势突破时往往伴随快速行情,滑点远超平时回测中设置5-10点滑点压力测试
订单执行延迟信号出现在K线收盘瞬间,但实盘下单有延迟模拟盘长时间验证,观察实际成交价差
参数过拟合过多参数被过度优化,样本外失效做样本外验证,减少参数数量
忽略了隔夜利息持仓过夜会产生库存费,趋势EA持单时间较长,这笔费用不可忽视回测中加入隔夜利息参数

4.3 平台差异、VPS与运维避坑

最后聊几点运维层面的经验。MT5的经纪商虽然都叫“MT5”,但服务器稳定性、订单执行路径、最小合约单位、保证金比例差异巨大。同一个EA,在A平台回测能跑,换了B平台可能连单都下不出去。所以策略选定之后,不要频繁更换交易平台。

VPS的话,建议选择离经纪商服务器位置较近的机房。不需要很高配置,2核4G内存就够跑EA了,关键看网络质量。

日志监控也很重要。我写了一个简单的告警脚本,EA运行异常时会发送邮件通知。实盘运行过程中,每隔几天看一次交易日志,确认订单执行情况和异常报错。别把EA挂上就不管了,它不是印钞机,是一个需要持续维护的交易系统。

说实话,趋势自动交易EA这条路,我走了不少弯路才走到今天。从一开始迷信“万能EA参数”,到后来老老实实研究每行代码背后的逻辑,最大的体会是:工具永远是工具,你对市场的理解才是决定盈亏的底层因素。趋势EA能帮你执行规则,但规则本身,需要你自己不断打磨。

最后分享一个我用了很久的小技巧:每次修改EA逻辑,先写在纸上画清楚触发条件,再动手改代码。画都画不明白的逻辑,写出来一定是个坑。趋势EA并不复杂,复杂的是你能不能坚守住自己设下的纪律。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询