如何利用 MQL5 创建简单的多币种智能交易系统(第 1 部分):基于 ADX 指标的信号,并结合抛物线 SAR(基础篇)
📘

如何利用 MQL5 创建简单的多币种智能交易系统(第 1 部分):基于 ADX 指标的信号,并结合抛物线 SAR(基础篇)

第 1/3 篇

用 ADX 搭配抛物线 SAR 搭多币种 EA 骨架

在 MT5 里做多币种交易,核心不是同时盯多少品种,而是先把单一信号逻辑写稳,再靠符号循环去横向铺开。本篇先用 ADX 判断趋势强度,再用抛物线 SAR 给进出场方向,两者组合能过滤掉一批震荡市的假突破。 ADX 默认周期 14,低于 20 通常视为趋势不足;SAR 的步长 0.02、最大值 0.2 是 MT5 内置默认值,信号翻转时价格与 SAR 点位置关系是直接可读的。实盘前建议在策略测试器里用 2023 年 EURUSD、XAUUSD 的 M15 数据各跑一遍,观察信号翻转滞后是否超过 3 根 K 线。 外汇与贵金属杠杆高,多币种同开会放大回撤,任何信号都只是概率倾向,必须先在模拟盘验证参数适应性。

◍ 为什么多币种EA在MT5上还很少见

这里说的多币种智能交易系统,指的是挂在一个品种图表上,却能对该图表以外的多个货币对执行开仓、平仓和订单管理的机器人。它和只盯一个对的普通EA最大的区别,就是交易标的跨出了宿主图表。 目前自动化交易需求很热,但MQL5社区里真正公开的多币种机器人程序不多,很多实现方式可能还被程序员捏在手里。 我们想补这个空档:用MQL5原生能力搭一个轻量多币种EA,信号源选平均方向走势指标(ADX,原文写ADM应为笔误)叠加抛物线SAR,逻辑不复杂但能直接跑。外汇和贵金属杠杆高,多币种同跑会放大回撤,实盘前务必在策略测试器里验。

「三十个品种上的双指标信号与订单管理逻辑」

这套多币种系统覆盖 28 个常见外汇直盘与交叉盘,再加 XAUUSD、XAGUSD 两个贵金属对,合计 30 个品种。它依赖经纪商标准命名,带前后缀的自定义符号名不在适用范围内,外汇与贵金属杠杆波动大,实盘前需在 MT5 策略测试器里先验证品种映射。 主信号用周期 7 的 ADX,确认信号用抛物线 SAR,两者默认取智能系统设定的同一时间帧;SAR 额外参考 M15 与 M5 来判别趋势强弱。ADX 的触发写法是 +DI 与 -DI 的跨柱比较,其中 difference 固定为 0.34,即前一根柱满足 +DI[1] > -DI[1]+0.34 视为买入条件成立,反之为卖出条件。 V0 与 V1 把正负 DI 的比值转成百分比差:V0=(当前柱 PLUSDI/MINUSDI×100)-100,V1 取前一根柱。只要 V0>V1,ADX 条件偏上行;V0<V1 则偏下行。SAR 的破位很简单——PRICE_LOW[0]>iSAR[0] 算上行,PRICE_HIGH[0]<iSAR[0] 算下行。 订单管理分四块:止损可关也可开,开了还能选自动计算或手填点数;止盈同理。尾随止损/止盈若开自动,就贴着 SAR 值走,否则用输入项里的数值,系统会同时拖俩。面板还给了三个手动键:一键给全部订单补 SL/TP、一键全平、一键只平盈利单,省得在 30 个品种间来回切图。

多币种EA的程序骨架与信号触发链

做多币种自动交易,第一步是把品种、指标句柄和风控参数塞进一个类里统一管理。OnInit() 里最先跑的是 ADXPSAR_MCEA_Config(),它负责把要用到的 30 个品种(对)、各周期指标句柄和核心函数全部配置好,避免在 OnTick() 里反复声明。 跳价函数 OnTick() 只做一件事:调用 ExpertActionTrade()。这个函数包揽了开单、平单、尾随止损/止盈等全部活动,相当于把多币种工作流的主循环收口到一处。 开平仓信号不是直接读指标,而是走 GetOpenPosition(symbol)。它内部串起四个子函数:DirectionMove 查当前周期K线方向,PARSAR15 查 M15 的 iSAR 升降,PARSAROp 查信号周期 iSAR 升降,iADXCross 查信号周期 ADX 的 +DI/-DI 交叉。其中 iADXCross 还会再调 iADXpct() 算两条线的百分比差,过滤假交叉。 要拿到指标值,每个品种都得先通过 PairsIdxArray(symbol) 取回句柄索引编号 x,否则多币种并发时会读错对象。以 PARSAR15() 为例,必须用对应品种的 iSAR 句柄去取 M15 抛物线数据,硬编码句柄在多币种环境里必然崩。 界面交互靠 ChartEvent:M 键弹出手动面板,可批量设止损止盈、全平或只平盈利单;C 键换图表品种(面板含 30 个货币对/贵金属对,点击即切换);R 键卸载 EA。外汇与贵金属波动剧烈,这类一键全平功能在滑点扩大时可能成交在预期外价格,实盘前务必在 MT5 策略测试器用历史数据跑一遍。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                                 Include                                                                 |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#include <Trade\Trade.mqh>
class="macro">#include <Trade\PositionInfo.mqh>
class="macro">#include <Trade\SymbolInfo.mqh>
class="macro">#include <Trade\AccountInfo.mqh>
class=class="str">"cmt">//--
CTrade            mc_trade;      class=class="str">"cmt">// 交易操作对象,封装下单/平仓/改单
CSymbolInfo       mc_symbol;     class=class="str">"cmt">// 品种信息对象,取点值/止损位等
CPositionInfo     mc_position;   class=class="str">"cmt">// 持仓信息对象,遍历当前仓位
CAccountInfo      mc_account;    class=class="str">"cmt">// 账户对象,读净值/杠杆
class=class="str">"cmt">//---
enum YN                       class=class="str">"cmt">// 是否类枚举,用于输入项开关
  {
   No,
   Yes
  };
class=class="str">"cmt">//--
enum mmt                      class=class="str">"cmt">// 手数管理枚举:固定或动态
  {
   FixedLot,    class=class="str">"cmt">// 固定手数
   DynamLot     class=class="str">"cmt">// 动态手数(按权益风险)
  };
class=class="str">"cmt">//--
enum TFX                      class=class="str">"cmt">// 信号周期枚举,覆盖 H1 到 D1
  {
   TFH1,       class=class="str">"cmt">// PERIOD_H1
   TFH2,       class=class="str">"cmt">// PERIOD_H2
   TFH3,       class=class="str">"cmt">// PERIOD_H3
   TFH4,       class=class="str">"cmt">// PERIOD_H4
   TFH6,       class=class="str">"cmt">// PERIOD_H6
   TFH8,       class=class="str">"cmt">// PERIOD_H8
   TFH12,      class=class="str">"cmt">// PERIOD_H12
   TFD1        class=class="str">"cmt">// PERIOD_D1
  };
class=class="str">"cmt">//--
class=class="str">"cmt">//---
class="kw">input group                "=== Global Strategy EA Parameter ==="; class=class="str">"cmt">// 全局策略参数分组
class="kw">input TFX                  TimeFrames = TFH4;                     class=class="str">"cmt">// 选信号周期,默认 H4
class="kw">input class="type">int                  ADXPeriod = class="num">7;                        class=class="str">"cmt">// ADX 周期参数
class="kw">input group                "=== Money Management Lot Size Parameter ==="; class=class="str">"cmt">// 资金管理分组
class="kw">input mmt                  mmlot = DynamLot;                     class=class="str">"cmt">// 资金管理方式,默认动态
class="kw">input class="type">class="kw">double               Risk = class="num">10.0;                         class=class="str">"cmt">// 每笔风险占净值百分比,class="num">1%~class="num">10%
class="kw">input class="type">class="kw">double               Lots = class="num">0.01;                         class=class="str">"cmt">// 固定手数模式下用手数
class=class="str">"cmt">//--Day Trading On/Off

◍ 按交易日与风控开关切EA行为

EA 的 input 分组把「哪天能跑」和「订单怎么管」拆成两块,直接决定策略在 MT5 上何时下单、止损止盈怎么挂。外汇与贵金属波动受时段影响明显,周日、周六默认关掉(ttd0=No、ttd6=No),周一到周五全开,这种设定倾向避开流动性最差的周末跳空。 下面这段是原文里的参数声明,逐行拆一下: input group "=== Day Trading On/Off ==="; // 建一个输入分组,专门放交易日开关 input YN ttd0 = No; // 周日不允许交易 input YN ttd1 = Yes; // 周一允许交易 input YN ttd2 = Yes; // 周二允许交易 input YN ttd3 = Yes; // 周三允许交易 input YN ttd4 = Yes; // 周四允许交易 input YN ttd5 = Yes; // 周五允许交易 input YN ttd6 = No; // 周六不允许交易 //--Trade & Order management Parameter input group "=== Trade & Order management Parameter ==="; // 建第二个分组管订单 input YN use_sl = No; // 总开关:不手动用止损 input YN autosl = Yes; // 但开自动止损计算 input double SLval = 30; // 若不用自动止损,则固定 30 点 input YN use_tp = No; // 总开关:不手动用止盈 input YN autotp = Yes; // 但开自动止盈计算 input double TPval = 50; // 若不用自动止盈,则固定 50 点 input YN TrailingSLTP = Yes; // 开跟踪止损止盈 input YN autotrl = No; // 但不走自动跟踪 input double TSval = 5; // 手动跟踪距离 5 点 注意 SLval=30、TPval=50 只在 autosl/autotp 为 No 时才生效;当前 autosl=Yes、autotp=Yes,所以这两个值只是备胎。真要验证,把 autotrl 改成 Yes 看跟踪逻辑是否接管,MT5 策略测试器里跑一周数据就能比对权益曲线差异。高风险品种下,这类开关组合可能放大滑点损耗,参数落地前先跑历史回测。

MQL5 / C++
class="kw">input group "=== Day Trading On/Off ==="; class=class="str">"cmt">// Day Trading On/Off
class="kw">input YN ttd0 = No; class=class="str">"cmt">// Select Trading on Sunday(Yes) or(No)
class="kw">input YN ttd1 = Yes; class=class="str">"cmt">// Select Trading on Monday(Yes) or(No)
class="kw">input YN ttd2 = Yes; class=class="str">"cmt">// Select Trading on Tuesday(Yes) or(No)
class="kw">input YN ttd3 = Yes; class=class="str">"cmt">// Select Trading on Wednesday(Yes) or(No)
class="kw">input YN ttd4 = Yes; class=class="str">"cmt">// Select Trading on Thursday(Yes) or(No)
class="kw">input YN ttd5 = Yes; class=class="str">"cmt">// Select Trading on Friday(Yes) or(No)
class="kw">input YN ttd6 = No; class=class="str">"cmt">// Select Trading on Saturday(Yes) or(No)
class=class="str">"cmt">//--Trade & Order management Parameter
class="kw">input group "=== Trade & Order management Parameter ==="; class=class="str">"cmt">// Trade & Order management Parameter
class="kw">input YN use_sl = No; class=class="str">"cmt">// Use Order Stop Loss(Yes) or(No)
class="kw">input YN autosl = Yes; class=class="str">"cmt">// Use Automatic Calculation Stop Loss(Yes) or(No)
class="kw">input class="type">class="kw">double SLval = class="num">30; class=class="str">"cmt">// If Not Use Automatic SL - Input SL value in Pips
class="kw">input YN use_tp = No; class=class="str">"cmt">// Use Order Take Profit(Yes) or(No)
class="kw">input YN autotp = Yes; class=class="str">"cmt">// Use Automatic Calculation Take Profit(Yes) or(No)
class="kw">input class="type">class="kw">double TPval = class="num">50; class=class="str">"cmt">// If Not Use Automatic TP - Input TP value in Pips
class="kw">input YN TrailingSLTP = Yes; class=class="str">"cmt">// Use Trailing SL/TP(Yes) or(No)
class="kw">input YN autotrl = No; class=class="str">"cmt">// Use Automatic Trailing(Yes) or(No)
class="kw">input class="type">class="kw">double TSval = class="num">5; class=class="str">"cmt">// If Not Use Automatic Trailing Input Trailing value in Pips

「把参数和类骨架落进 EA 里」

EA 尾部这组 input 决定了风控开关与识别号:TSmin=5 表示浮盈满 5 点后才启动追踪止损;Close_by_Opps 与 SaveOnRev 都设 Yes,意味着反向信号出现会平仓、弱信号也锁利润离场。magicEA=202307 是订单魔数,多 EA 同跑时靠它区分归属,外汇与贵金属杠杆高,魔数冲突可能误平别的单。 alerts=Yes 但 UseEmailAlert、UseSendnotify 均 No,说明只在图表弹消息不往外推;trade_info_display=Yes 会在图上画交易信息,盯盘时不用切终端窗口。 下面 MCEA 类先把时间分量(年/月/日/时/分/秒)和几个私有整型、双精度变量声明好,这是后续算信号和挂单的底层容器。开 MT5 把这段粘进 MQ4/MQ5 编辑器,改 TSmin 到 8~10 观察回撤变化,比直接跑默认更稳。

MQL5 / C++
class="kw">input class="type">class="kw">double                TSmin = class="num">5;                     class=class="str">"cmt">// Minimum Pips to start Trailing Stop
class="kw">input YN                  Close_by_Opps = Yes;                class=class="str">"cmt">// Close Trade By Opposite Signal(Yes) or(No)
class="kw">input YN                  SaveOnRev = Yes;                   class=class="str">"cmt">// Close Trade and Save profit due to weak signal(Yes) or(No)
class=class="str">"cmt">//--Others Expert Advisor Parameter
class="kw">input group               "=== Others Expert Advisor Parameter ===" ; class=class="str">"cmt">// Others EA Parameter
class="kw">input YN                  alerts = Yes;                      class=class="str">"cmt">// Display Alerts / Messages(Yes) or(No)
class="kw">input YN                  UseEmailAlert = No;                class=class="str">"cmt">// Email Alert(Yes) or(No)
class="kw">input YN                  UseSendnotify = No;                class=class="str">"cmt">// Send Notification(Yes) or(No)
class="kw">input YN    trade_info_display = Yes;                        class=class="str">"cmt">// Select Display Trading Info on Chart(Yes) or(No)
class="kw">input class="type">ulong               magicEA = class="num">202307;                  class=class="str">"cmt">// Expert ID(Magic Number)
class=class="str">"cmt">//---
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Class for working Expert Advisor                                |
class=class="str">"cmt">//+------------------------------------------------------------------+
class MCEA
  {
   class=class="str">"cmt">//---
class="kw">private:
   class=class="str">"cmt">//----
   class="type">int               x_year;       class=class="str">"cmt">// Year
   class="type">int               x_mon;        class=class="str">"cmt">// Month
   class="type">int               x_day;        class=class="str">"cmt">// Day of the month
   class="type">int               x_hour;       class=class="str">"cmt">// Hour in a day
   class="type">int               x_min;        class=class="str">"cmt">// Minutes
   class="type">int               x_sec;        class=class="str">"cmt">// Seconds
   class=class="str">"cmt">//--
   class="type">int               oBm,
                    oSm,
                    ldig;
   class="type">int               posCur1,
                    posCur2;
   class=class="str">"cmt">//--
   class="type">class="kw">double            LotPS,
                    difDi;
   class="type">class="kw">double            slv,
                    tpv;

常见问题

多币种需要同时管理几十个品种的信号与订单,逻辑比单币种复杂得多,很多开发者懒得写跨品种调度,所以少见。建议先从 5~10 个流动性高的品种试起。
按品种独立判断:ADX 过阈值且 SAR 翻向才开仓,同品种反向信号先平再开。用统一风控开关限制每日总持仓数。
可以。小布能按你设定的 ADX 阈值和 SAR 方向,跨品种扫描并标出当前触发信号的品种,省去手动切图。
在 EA 入口读当前星期几,配合风控开关变量,非允许日直接跳过信号函数。参数面板暴露开关更方便调。
漏掉跨品种句柄的释放和重置,以及 SAR 步长参数越界检查。建议每个品种独立建指标句柄并加失效重连。