如何利用 MQL5 创建简单的多币种智能交易系统(第 4 部分):三角移动平均线  指标信号·进阶篇
📘

如何利用 MQL5 创建简单的多币种智能交易系统(第 4 部分):三角移动平均线 指标信号·进阶篇

第 2/3 篇

把交易时段与品种拆成枚举常量

在 MT5 写多品种、多周期扫描器时,最忌把『6点』『M5』『USD系』这类字面量直接散落在逻辑里。下面这组枚举把小时、分钟、品种分类、开关、仓位模式、时间周期全部抽成可读常量,改参数时只动枚举不改判断式。 小时枚举覆盖了 hr_06 到 hr_23,共 18 个整点(06:00–23:00),跳过 0–5 点是因为这段流动性在主要外汇品种上偏低。分钟枚举按 5 分钟一格从 mn_00 排到 mn_55,刚好 12 档,配合小时就能拼出任意整 5 分触发的扫描时刻。 品种枚举 PairsTrade 给了 10 种范围:从 All30(全部 30 个外汇对)到按基准货币拆的 Usds / Eurs / Gbps 等,再到 TrdWi 让用户自选白名单。YN 就两个值 No/Yes 管开关,mmt 区分 FixedLot 与 DynamLot 两种仓位算法。 周期枚举 TFMTF 把 PERIOD_M5 到 PERIOD_D1 收成 11 个缩写,回测时切周期只改枚举不入参字符串,编译器就能帮你排错。 把这些枚举原样贴进 EA 头文件,后续 OnTimer 或 OnInit 里写 if(hour==hr_08 && minute==mn_00) 比写魔法数字直观得多,也方便小布这类外部工具直接读结构体生成参数面板。

MQL5 / C++
hr_06=class="num">6,   class=class="str">"cmt">// class="num">06:class="num">00
hr_07=class="num">7,   class=class="str">"cmt">// class="num">07:class="num">00
hr_08=class="num">8,   class=class="str">"cmt">// class="num">08:class="num">00
hr_09=class="num">9,   class=class="str">"cmt">// class="num">09:class="num">00
hr_10=class="num">10,  class=class="str">"cmt">// class="num">10:class="num">00
hr_11=class="num">11,  class=class="str">"cmt">// class="num">11:class="num">00
hr_12=class="num">12,  class=class="str">"cmt">// class="num">12:class="num">00
hr_13=class="num">13,  class=class="str">"cmt">// class="num">13:class="num">00
hr_14=class="num">14,  class=class="str">"cmt">// class="num">14:class="num">00
hr_15=class="num">15,  class=class="str">"cmt">// class="num">15:class="num">00
hr_16=class="num">16,  class=class="str">"cmt">// class="num">16:class="num">00
hr_17=class="num">17,  class=class="str">"cmt">// class="num">17:class="num">00
hr_18=class="num">18,  class=class="str">"cmt">// class="num">18:class="num">00
hr_19=class="num">19,  class=class="str">"cmt">// class="num">19:class="num">00
hr_20=class="num">20,  class=class="str">"cmt">// class="num">20:class="num">00
hr_21=class="num">21,  class=class="str">"cmt">// class="num">21:class="num">00
hr_22=class="num">22,  class=class="str">"cmt">// class="num">22:class="num">00
hr_23=class="num">23   class=class="str">"cmt">// class="num">23:class="num">00
};
class=class="str">"cmt">//--
class=class="str">"cmt">//--
enum inmnt
  {
  mn_00=class="num">0,   class=class="str">"cmt">// Minute class="num">0
  mn_05=class="num">5,   class=class="str">"cmt">// Minute class="num">5
  mn_10=class="num">10,  class=class="str">"cmt">// Minute class="num">10
  mn_15=class="num">15,  class=class="str">"cmt">// Minute class="num">15
  mn_20=class="num">20,  class=class="str">"cmt">// Minute class="num">20
  mn_25=class="num">25,  class=class="str">"cmt">// Minute class="num">25
  mn_30=class="num">30,  class=class="str">"cmt">// Minute class="num">30
  mn_35=class="num">35,  class=class="str">"cmt">// Minute class="num">35
  mn_40=class="num">40,  class=class="str">"cmt">// Minute class="num">40
  mn_45=class="num">45,  class=class="str">"cmt">// Minute class="num">45
  mn_50=class="num">50,  class=class="str">"cmt">// Minute class="num">50
  mn_55=class="num">55   class=class="str">"cmt">// Minute class="num">55
  };
class=class="str">"cmt">//--
class=class="str">"cmt">//--
enum PairsTrade
{
  All30,   class=class="str">"cmt">// All Forex class="num">30 Pairs
  TrdWi,   class=class="str">"cmt">// Trader Wishes Pairs 
  Usds,    class=class="str">"cmt">// Forex USD Pairs
  Eurs,    class=class="str">"cmt">// Forex EUR Pairs
  Gbps,    class=class="str">"cmt">// Forex GBP Pairs
  Auds,    class=class="str">"cmt">// Forex AUD Pairs
  Nzds,    class=class="str">"cmt">// Forex NZD Pairs
  Cads,    class=class="str">"cmt">// Forex CDD Pairs
  Chfs,    class=class="str">"cmt">// Forex CHF Pairs
  Jpys     class=class="str">"cmt">// Forex JPY Pairs
};
class=class="str">"cmt">//--
class=class="str">"cmt">//--
enum YN
  {
  No,
  Yes
  };
class=class="str">"cmt">//--
class=class="str">"cmt">//--
enum mmt
  {
  FixedLot,   class=class="str">"cmt">// Fixed Lot Size
  DynamLot    class=class="str">"cmt">// Dynamic Lot Size
  };
class=class="str">"cmt">//--
class=class="str">"cmt">//--
enum TFMTF
  {
  TFM5,       class=class="str">"cmt">// PERIOD_M5
  TFM15,      class=class="str">"cmt">// PERIOD_M15
  TFM30,      class=class="str">"cmt">// PERIOD_M30
  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">//--

◍ EA 输入参数的分组与可调边界

这段 MQL5 片段把一套策略 EA 的外部参数按功能切成四组:全局计算框架、交易品种筛选、仓位管理、特定时段开关。每组用 input group 做界面分隔,MT5 用户在「属性」面板里能直接看到分类,不会把所有参数堆在一列。 计算框架里先定义一个枚举 SMTF,只有 MTF(多周期)和 STF(单周期)两个值,由 tfinuse 控制。多周期模式靠 tfstart(默认 M15)和 tfclose(默认 H4)框定扫描区间;单周期则由 singletf 锁定(默认 H1)。三角均线 Trmaperiod 默认 14、应用于收盘价,属于经典中速设置。 品种组用 usepairs = All30 表示默认覆盖 30 个主流对,也可在 traderwishes 写 "eurusd,usdchf" 做白名单;sym_prefix / sym_suffix 留给券商后缀(如 .m 微点差账号),不填就空串。 仓位组 mmlot 默认 DynamLot 动态手数,Risk 区间锁死 1.0%–10.0%(代码里给的默认 10.0 是上限值,实盘用满即重仓,外汇/贵金属杠杆高、回撤可能超预期,建议从 1%–2% 起调)。固定手数 Lots 仅当切到 manual 模式才生效。最后一组 trd_time_zone = Yes 配合 session = Cus_Session,让 EA 只在自定义时段下单,避免流动性差的时刻被扫。 开 MT5 把这段贴进 EA 输入区,重点改 Risk 和 usepairs 两项,就能看出分组逻辑是否贴合你的盯盘习惯。

MQL5 / C++
enum SMTF
  {
    MTF,   class=class="str">"cmt">// Use Multi-Timeframe
    STF    class=class="str">"cmt">// Use Single-Timeframe
  };
class=class="str">"cmt">//--
class=class="str">"cmt">//---
input group                 "=== Global Strategy EA Parameter ==="; class=class="str">"cmt">// Global Strategy EA Parameter
input SMTF                  tfinuse = MTF;                         class=class="str">"cmt">// Select Calculation in Multi or Single Timeframe
input TFMTF                 singletf = TFH1;                       class=class="str">"cmt">// Select Single Calculation TimeFrame, class="kw">default PERIOD_H1
input TFMTF                 tfstart = TFM15;                       class=class="str">"cmt">// Select Multi Timeframe calculation start
input TFMTF                 tfclose = TFH4;                        class=class="str">"cmt">// Select Multi Timeframe calculation end
input class="type">int                   Trmaperiod = class="num">14;                       class=class="str">"cmt">// Input Triangular MA Indicator period, class="kw">default class="num">14
input ENUM_APPLIED_PRICE    Trprice = PRICE_CLOSE;                 class=class="str">"cmt">// Select Triangular MA Applied Price, class="kw">default Price Close
class=class="str">"cmt">//---
input group                 "=== Select Pairs to Trade ===";       class=class="str">"cmt">// Selected Pairs to trading
input PairsTrade            usepairs = All30;                      class=class="str">"cmt">// Select Pairs to Use
input class="type">class="kw">string                traderwishes = "eg. eurusd,usdchf";    class=class="str">"cmt">// If Use Trader Wishes Pairs, input pair name here, separate by comma
input class="type">class="kw">string                sym_prefix = "";                      class=class="str">"cmt">// Input the symbol prefix in case sensitive(if any)
input class="type">class="kw">string                sym_suffix = "";                      class=class="str">"cmt">// Input the symbol suffix in case sensitive(if any)
class=class="str">"cmt">//--
input group                 "=== Money Management Lot Size Parameter ==="; class=class="str">"cmt">// Money Management Lot Size Parameter
input mmt                   mmlot = DynamLot;                     class=class="str">"cmt">// Money Management Type
input class="type">class="kw">double                Risk = class="num">10.0;                          class=class="str">"cmt">// Percent Equity Risk per Trade(Min=class="num">1.0% / Max=class="num">10.0%)
input class="type">class="kw">double                Lots = class="num">0.01;                          class=class="str">"cmt">// Input Manual Lot Size FixedLot
class=class="str">"cmt">//--Trade on Specific Time
input group                 "=== Trade on Specific Time ===";      class=class="str">"cmt">// Trade on Specific Time
input YN                    trd_time_zone = Yes;                  class=class="str">"cmt">// Select If You Like to Trade on Specific Time Zone
input tm_zone               session = Cus_Session;                class=class="str">"cmt">// Select Trading Time Zone

「自定义交易时段与星期开关的写法」

EA 里把交易时间切成「自定义会话」和「星期开关」两层,比直接用经纪商服务器时间更可控。下面这段输入参数定义了每天允许下单的起止钟点,以及周日、周六默认关闭、周一到周五默认开启的开关。 会话起止用小时+分钟两个 input 拼出来:开始设为 00:15,结束设为 23:55,意味着除开每天最后 5 分钟结算边缘,几乎覆盖全交易日。外汇与贵金属杠杆高,这种接近 24 小时的窗口在重大数据夜可能放大滑点风险,实盘前建议在 MT5 策略测试器里把结束分钟改到 55 之前观察成交分布。 星期维度用 ttd0~ttd6 七个 YN 枚举控制,默认 ttd0=No、ttd6=No 把周末剔掉,避免流动性枯竭时挂单。订单管理部分给出止损止盈的自动/手动双路:use_sl=No 但 autosl=Yes 时,SLval=30 只是备用值,不会生效;use_tp=Yes 且 autotp=Yes 则盈利目标由算法推算。复制下面代码到 MQ5 文件头部,编译后就能在属性框里直接勾选调参。

MQL5 / C++
input swhour                stsescuh = hr_00;                class=class="str">"cmt">// Time Hour to Start Trading Custom Session(class="num">0-class="num">23)
input inmnt                 stsescum = mn_15;                class=class="str">"cmt">// Time Minute to Start Trading Custom Session(class="num">0-class="num">55)
input swhour                clsescuh = hr_23;                class=class="str">"cmt">// Time Hour to Stop Trading Custom Session(class="num">0-class="num">23)
input inmnt                 clsescum = mn_55;                class=class="str">"cmt">// Time Minute to Stop Trading Custom Session(class="num">0-class="num">55)
class=class="str">"cmt">//--Day Trading On/Off
input group                "=== Day Trading On/Off ==="; class=class="str">"cmt">// Day Trading On/Off
input YN                    ttd0 = No;                     class=class="str">"cmt">// Select Trading on Sunday(Yes) or(No)
input YN                    ttd1 = Yes;                    class=class="str">"cmt">// Select Trading on Monday(Yes) or(No)
input YN                    ttd2 = Yes;                    class=class="str">"cmt">// Select Trading on Tuesday(Yes) or(No)
input YN                    ttd3 = Yes;                    class=class="str">"cmt">// Select Trading on Wednesday(Yes) or(No)
input YN                    ttd4 = Yes;                    class=class="str">"cmt">// Select Trading on Thursday(Yes) or(No)
input YN                    ttd5 = Yes;                    class=class="str">"cmt">// Select Trading on Friday(Yes) or(No)
input YN                    ttd6 = No;                     class=class="str">"cmt">// Select Trading on Saturday(Yes) or(No)
class=class="str">"cmt">//--Trade & Order management Parameter
input group                "=== Trade & Order management Parameter ==="; class=class="str">"cmt">// Trade & Order management Parameter
input YN                    use_sl = No;                   class=class="str">"cmt">// Use Order Stop Loss(Yes) or(No)
input YN                    autosl = Yes;                  class=class="str">"cmt">// Use Automatic Calculation Stop Loss(Yes) or(No)
input class="type">class="kw">double                SLval = class="num">30;                    class=class="str">"cmt">// If Not Use Automatic SL - Input SL value in Pips
input YN                    use_tp = Yes;                  class=class="str">"cmt">// Use Order Take Profit(Yes) or(No)
input YN                    autotp = Yes;                  class=class="str">"cmt">// Use Automatic Calculation Take Profit(Yes) or(No)

EA 参数与多周期映射怎么配

这段输入变量定义了 EA 的出场与信号控制开关。TPval=10 表示不用自动止盈时,手动止盈距离为 10 点;TrailingSLTP 与 autotrl 都默认 Yes,即开启追踪止损且用自动追踪距离,若关掉自动则 TSval=5 生效,追踪启动门槛 TSmin=5 点、锁定利润门槛 TPmin=25 点。 Close_by_Opps=Yes 代表反向信号出现时平仓,SaveOnRev=Yes 则在弱信号时落袋保利润;这两个开关直接决定回撤形状。其余参数里 magicEA=2023111 是订单识别码,alerts 默认开,邮件与推送默认关,图表交易信息默认显示。 下面这段代码把 11 个周期塞进数组并做下标映射: input double TPval = 10; // If Not Use Automatic TP - Input TP value in Pips input YN TrailingSLTP = Yes; // Use Trailing SL/TP (Yes) or (No) input YN autotrl = Yes; // Use Automatic Trailing (Yes) or (No) input double TSval = 5; // If Not Use Automatic Trailing Input Trailing value in Pips input double TSmin = 5; // Minimum Pips to start Trailing Stop input double TPmin = 25; // Input Trailing Profit Value in Pips input YN Close_by_Opps = Yes; // Close Trade By Opposite Signal (Yes) or (No) input YN SaveOnRev = Yes; // Close Trade and Save profit due to weak signal (Yes) or (No) //--Others Expert Advisor Parameter input group "=== Others Expert Advisor Parameter ==="; // Others EA Parameter input YN alerts = Yes; // Display Alerts / Messages (Yes) or (No) input YN UseEmailAlert = No; // Email Alert (Yes) or (No) input YN UseSendnotify = No; // Send Notification (Yes) or (No) input YN trade_info_display = Yes; // Select Display Trading Info on Chart (Yes) or (No) input ulong magicEA = 2023111; // Expert ID (Magic Number) //--- ENUM_TIMEFRAMES TFs[]={PERIOD_M5,PERIOD_M15,PERIOD_M30,PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,PERIOD_D1}; int arTFs=ArraySize(TFs); //-- for(int x=0; x<arTFs; x++) { if(singletf==x) TFt=TFs[x]; // TF for single-timeframe if(tfstart==x) arstr=x; // multi-timeframe start calculation timeframe if(tfclose==x) arend=x; // multi-timeframe end calculation timeframe } //-- if(arstr>=arend) { 逐行看:TFs 数组从 M5 到 D1 共 11 个周期;arTFs 拿到数组长度 11。for 循环里用 singletf、tfstart、tfclose 三个整型输入去匹配下标,分别给单周期变量 TFt、多周期起点 arstr、终点 arend 赋值。最后 if(arstr>=arend) 是防护——多周期计算要求起点严格小于终点,否则逻辑会错乱。 开 MT5 把这段贴进 EA 输入区,先把 tfstart 设 1(M15)、tfclose 设 3(H1)跑一遍,再改成相等看是否触发 arstr>=arend 的分支,就能验证周期映射有没有按预期走。外汇与贵金属杠杆高,参数回测和实盘偏差可能很大,任何开关都先用模拟盘验。

MQL5 / C++
input class="type">class="kw">double TPval = class="num">10; class=class="str">"cmt">// If Not Use Automatic TP - Input TP value in Pips
input YN TrailingSLTP = Yes; class=class="str">"cmt">// Use Trailing SL/TP(Yes) or(No)
input YN autotrl = Yes; class=class="str">"cmt">// Use Automatic Trailing(Yes) or(No)
input class="type">class="kw">double TSval = class="num">5; class=class="str">"cmt">// If Not Use Automatic Trailing Input Trailing value in Pips
input class="type">class="kw">double TSmin = class="num">5; class=class="str">"cmt">// Minimum Pips to start Trailing Stop
input class="type">class="kw">double TPmin = class="num">25; class=class="str">"cmt">// Input Trailing Profit Value in Pips
input YN Close_by_Opps = Yes; class=class="str">"cmt">// Close Trade By Opposite Signal(Yes) or(No)
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
input group "=== Others Expert Advisor Parameter ==="; class=class="str">"cmt">// Others EA Parameter
input YN alerts = Yes; class=class="str">"cmt">// Display Alerts / Messages(Yes) or(No)
input YN UseEmailAlert = No; class=class="str">"cmt">// Email Alert(Yes) or(No)
input YN UseSendnotify = No; class=class="str">"cmt">// Send Notification(Yes) or(No)
input YN trade_info_display = Yes; class=class="str">"cmt">// Select Display Trading Info on Chart(Yes) or(No)
input class="type">ulong magicEA = class="num">2023111; class=class="str">"cmt">// Expert ID(Magic Number)
class=class="str">"cmt">//---
   ENUM_TIMEFRAMES TFs[]={PERIOD_M5,PERIOD_M15,PERIOD_M30,PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,PERIOD_D1};
   class="type">int arTFs=ArraySize(TFs);
   class=class="str">"cmt">//--
   for(class="type">int x=class="num">0; x<arTFs; x++)
     {
      if(singletf==x) TFt=TFs[x]; class=class="str">"cmt">// TF for single-timeframe
      if(tfstart==x)  arstr=x;   class=class="str">"cmt">// multi-timeframe start calculation timeframe
      if(tfclose==x)  arend=x;   class=class="str">"cmt">// multi-timeframe end calculation timeframe
     }
   class=class="str">"cmt">//--
   if(arstr>=arend)
     {

◍ 多周期数组与品种清单的初始化落点

EA 在启动时若检测到起始周期大于结束周期,会直接弹窗报错并调用 ExpertRemove() 把自身从图表卸掉,而不是静默运行。这段防护意味着你手动填参数时,M5 必须排在 H4 前面,否则策略根本不会跑。 switch(tfinuse) 里分了 MTF 与 STF 两种模式:MTF 下 TFTri 数组长度由 arend-arstr+1 算出,尾段一半位置 tftrlst 对应的周期拿去做移动止损(TFts),而 tfcinws 位置周期用于弱信号平仓(TFCWS);STF 模式则直接用当前选定周期做止损,弱信号平仓周期往前推 2 档,越界时锁死为 1。 下方 TFs[] 写死了 11 个周期从 M5 到 D1,TFMTF 枚举一一映射,方便用索引而不是裸数字去引用。HandlingSymbolArrays() 开头把 EURUSD、GBPUSD、AUDUSD、NZDUSD、USDCAD、USDCHF、USDJPY、EURGBP 等主流外汇对塞进 All30[],说明这套多周期逻辑默认就奔着跨品种扫描去的。 开 MT5 把 TFs[] 改成你常看的周期组合,再故意把 Start/End Timeframe 填反,能当场验证 ExpertRemove() 是否触发——外汇与贵金属杠杆高,参数错配可能让实盘不挂单,先用策略测试器跑一遍再上真仓。

MQL5 / C++
Alert("Error selecting Start and End Timeframe, Start Timeframe must be smaller than End Timeframe");
Alert("-- "+expname+" -- ",Symbol()," -- expert advisor will be Remove from the chart.");
ExpertRemove();
   }
   class=class="str">"cmt">//--
   class="kw">switch(tfinuse)
     {
      case MTF:
        {
         TFArrays=arend-arstr+class="num">1;
         ArrayResize(TFTri,TFArrays,TFArrays);
         ArrayCopy(TFTri,TFs,class="num">0,class="num">0,WHOLE_ARRAY);
         tfcinws=arstr+class="num">1;
         tftrlst=(class="type">int)TFArrays/class="num">2;
         TFts=TFs[tftrlst+arstr-class="num">1];   class=class="str">"cmt">// TF for Trailing Stop
         TFCWS=TFs[tfcinws];          class=class="str">"cmt">// TF for Close Order in weak signal
         break;
        }
      case STF:
        {
         TFArrays=arTFs;
         ArrayResize(TFTri,TFArrays,TFArrays);
         ArrayCopy(TFTri,TFs,class="num">0,class="num">0,WHOLE_ARRAY);
         tfcinws=TFIndexArray(TFt)-class="num">2 <=class="num">0 ? class="num">1 : TFIndexArray(TFt)-class="num">2;
         TFts=TFt;                    class=class="str">"cmt">// TF for Trailing Stop
         TFCWS=TFs[tfcinws];   class=class="str">"cmt">// TF for Close Order in weak signal
         break;
        }
     }
ENUM_TIMEFRAMES TFs[]={PERIOD_M5,PERIOD_M15,PERIOD_M30,PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,PERIOD_D1};
class=class="str">"cmt">//--
enum TFMTF
  {
   TFM5,      class=class="str">"cmt">// PERIOD_M5
   TFM15,     class=class="str">"cmt">// PERIOD_M15
   TFM30,     class=class="str">"cmt">// PERIOD_M30
   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="type">void MCEA::HandlingSymbolArrays(class="type">void)
  {
class=class="str">"cmt">//---
   class="type">class="kw">string All30[]={"EURUSD","GBPUSD","AUDUSD","NZDUSD","USDCAD","USDCHF","USDJPY","EURGBP",

「把货币篮子塞进数组再切分」

做跨品种扫描时,先把盯盘范围固化成数组最省事。下面这段把 30 个直盘与交叉盘(含 XAUUSD、XAGUSD)收进 All30,注释里标了 // 30 pairs,实际数一下正好是 22 个非美交叉 + 2 个贵金属 + 其余美系,总长度 30。 按币种再拆出 USDs、EURs、GBPs 等子数组,每个长度 7~9 不等,例如 USDs 含 9 个品种、JPYs 含 7 个。这样后续算相对强弱,直接按数组下标轮询,不用硬写一串 if。 初始化阶段用 ArraySize 取长度,ArrayResize 给 VSym 扩到 sall,再 ArrayCopy 把 All30 整块搬过去;WHOLE_ARRAY 表示从头拷到尾。 如果用户选了自定义白名单(usepairs==TrdWi)且 traderwishes 里没写占位的 "eg.",就进入字符串切分:拿逗号当分隔符,用 ushort 存分隔符编码,下一步 StringSplit 就能把 "EURUSD,GBPJPY" 这类手写清单拆成可交易的子数组。外汇与贵金属杠杆高,数组跑出来的信号仅作概率参考,实盘前务必在 MT5 策略测试器里过一遍。

MQL5 / C++
class="type">class="kw">string All30[]={"EURAUD","EURNZD","EURCAD","EURCHF","EURJPY","GBPAUD","GBPNZD","GBPCAD",
"GBPCHF","GBPJPY","AUDNZD","AUDCAD","AUDCHF","AUDJPY","NZDCAD","NZDCHF",
"NZDJPY","CADCHF","CADJPY","CHFJPY","XAUUSD","XAGUSD"}; class=class="str">"cmt">// class="num">30 pairs
class="type">class="kw">string USDs[]={"USDCAD","USDCHF","USDJPY","AUDUSD","EURUSD","GBPUSD","NZDUSD","XAUUSD","XAGUSD"}; class=class="str">"cmt">// USD pairs
class="type">class="kw">string EURs[]={"EURAUD","EURCAD","EURCHF","EURGBP","EURJPY","EURNZD","EURUSD"}; class=class="str">"cmt">// EUR pairs
class="type">class="kw">string GBPs[]={"GBPAUD","GBPCAD","GBPCHF","EURGBP","GBPJPY","GBPNZD","GBPUSD"}; class=class="str">"cmt">// GBP pairs
class="type">class="kw">string AUDs[]={"AUDCAD","AUDCHF","EURAUD","GBPAUD","AUDJPY","AUDNZD","AUDUSD"}; class=class="str">"cmt">// AUD pairs
class="type">class="kw">string NZDs[]={"AUDNZD","NZDCAD","NZDCHF","EURNZD","GBPNZD","NZDJPY","NZDUSD"}; class=class="str">"cmt">// NZD pairs
class="type">class="kw">string CADs[]={"AUDCAD","CADCHF","EURCAD","GBPCAD","CADJPY","NZDCAD","USDCAD"}; class=class="str">"cmt">// CAD pairs
class="type">class="kw">string CHFs[]={"AUDCHF","CADCHF","EURCHF","GBPCHF","NZDCHF","CHFJPY","USDCHF"}; class=class="str">"cmt">// CHF pairs
class="type">class="kw">string JPYs[]={"AUDJPY","CADJPY","CHFJPY","EURJPY","GBPJPY","NZDJPY","USDJPY"}; class=class="str">"cmt">// JPY pairs
class=class="str">"cmt">//--
sall=ArraySize(All30);
arusd=ArraySize(USDs);
aretc=ArraySize(EURs);
ArrayResize(VSym,sall,sall);
ArrayCopy(VSym,All30,class="num">0,class="num">0,WHOLE_ARRAY);
class=class="str">"cmt">//--
if(usepairs==TrdWi && StringFind(traderwishes,"eg.",class="num">0)<class="num">0)
  {
   class="type">class="kw">string to_split=traderwishes; class=class="str">"cmt">// A class="type">class="kw">string to split into substrings pairs name
   class="type">class="kw">string sep=",";                class=class="str">"cmt">// A separator as a character 
   class="type">class="kw">ushort u_sep;                  class=class="str">"cmt">// The code of the separator character 
   class=class="str">"cmt">//--- Get the separator code 

常见问题

把货币对字符串塞进 string 数组,再用 ArrayResize 按实际数量切分,初始化时循环读取数组元素下单即可。
用 input group 注释做分组,数值类参数加 min、max 边界,星期用 bool 开关数组逐个控制。
可以,小布能读取你的参数配置并标出冲突或空窗时段,把重复核对劳动交给它,你只看异常就行。
用枚举常量定义星期,配合 if 判断当前 day_of_week 与自定义 bool 开关,再叠加时段起止比较过滤。
放在 OnInit 里按品种清单和周期映射逐个绑定数组,确保每次新品种加载时重新初始化缓冲。