MQL5 简介(第 7 部分):在 MQL5 中构建 EA 交易和使用 AI 生成代码的初级指南·进阶篇
📘

MQL5 简介(第 7 部分):在 MQL5 中构建 EA 交易和使用 AI 生成代码的初级指南·进阶篇

第 2/2 篇

「让 AI 写 MQL5 前先把伪代码拆细」

AI 写 MQL5 确实能把重复性编码压缩掉一大块,但现阶段它生成的代码只是“指导性模型”,不是交付终版。实测中,若你不直接给项目背景,AI 返回的变量定义常常漏掉外部依赖;先写详尽伪代码再喂给模型,回应的准确率会明显提升。 以一个简单的交易语音提醒 EA 为例,伪代码要拆到四步:初始化变量、用户设提醒时间和声音、持续比对本地与提醒时间、到点播声音文件。每一步都逼你回答具体问题,比如“提醒时间用什么格式”“声音文件存哪”。这些问题就是给 AI 的精确路线图。 AI 对“EA 需要哪些变量”的典型回应会列出:datetime 型提醒时间、string 型声音路径、datetime 型当前时间等。它给的代码并不完美,但你能从中抽出下一轮问题,例如用户怎么输入参数。用 input string 声音乐件名,用户就能在 EA 属性里填,而不是写死在代码里。 到第三步监控时区,AI 给出的核心逻辑是在 OnTick 里用 TimeLocal() 取本地时间,StringToTime() 转提醒时间,相等就 PlaySound()。这一步越往后,AI 的解释越贴项目,说明分阶段喂伪代码比一次性丢需求靠谱得多。 第四步把 WAV 丢进 MT5 安装目录的 Sounds 文件夹,代码里直接引文件名播。重点:AI 不是替你干完,而是和你来回碰,把项目复杂度摊开。外汇和贵金属波动剧烈、高风险,这类提醒 EA 只解决“别漏看时间”,下单决策还得你自己扛。

在 MT5 里用 EA 挂多时段声音闹钟

做外汇或贵金属盯盘,固定时间点容易漏看,用 EA 在终端本地挂几个声音闹钟比人工记表更稳。下面这段 MQL5 代码演示了如何声明 3 个闹钟时间、对应声音文件,并在 OnTick 里比对本地时间触发播放,外汇与贵金属波动受消息面影响大,属于高风险品种,闹钟只作提醒、不构成交易依据。 代码里先定义了 Alarm1~Alarm3 三个 datetime 变量和 Sound1~Sound3 字符串,默认声音文件名为 alert1.wav 等;NumberOfAlarms 写死为 3,表示最多同时挂 3 个提醒点。input 层的 Alarm1/Alarm2/Alarm3 默认都是 "00:00:00",你在 EA 参数里改成 "08:30:00" 这类字符串即可生效。 OnTick 中通过 TimeLocal() 取本机时间,再用 StringToTime() 把输入字符串转成 datetime 做相等比较。注意原文用了 currentTime == StringToTime(AlarmX) 的精确相等判断,Tick 频率若错过那一秒就可能不响,实盘建议改成区间判断(如差值小于 1 秒)。PlaySound(Sound) 负责播放在 input 里指定的声音文件,声音需放在 MT5 的 Sounds 目录下。 OnInit 与 OnDeinit 这里是空壳,初始化直接 return 0,去初始化没做资源回收。若你要在闹钟触发时同时发手机推送,可在相等判断里补 SendNotification,但先确认 MetaQuotes ID 已绑定。

MQL5 / C++
class=class="str">"cmt">// Define variables for alarm times
class="type">class="kw">datetime Alarm1;
class="type">class="kw">datetime Alarm2;
class="type">class="kw">datetime Alarm3;
class=class="str">"cmt">// Define variables for sound selection
class="type">class="kw">string Sound1 = "alert1.wav";
class="type">class="kw">string Sound2 = "alert2.wav";
class="type">class="kw">string Sound3 = "alert3.wav";
class=class="str">"cmt">// Define variables for current time and notification message
class="type">class="kw">datetime CurrentTime;
class="type">class="kw">string NotificationMessage;
class=class="str">"cmt">// Define other configuration variables
class="type">int NumberOfAlarms = class="num">3;
class="kw">input class="type">class="kw">string Alarm1 = "class="num">00:class="num">00:class="num">00";
class="kw">input class="type">class="kw">string Alarm2 = "class="num">00:class="num">00:class="num">00";
class="kw">input class="type">class="kw">string Alarm3 = "class="num">00:class="num">00:class="num">00";
class="kw">input class="type">class="kw">string Sound = ""; class=class="str">"cmt">// User-selected sound filename
class=class="str">"cmt">// Inside the OnTick() function
class=class="str">"cmt">// Get the current time
  class="type">class="kw">datetime currentTime = TimeLocal();
class=class="str">"cmt">// Check if the current time matches any of the alarm times
  if(currentTime == StringToTime(Alarm1) ||
      currentTime == StringToTime(Alarm2) ||
      currentTime == StringToTime(Alarm3))
    {
    class=class="str">"cmt">// Trigger the audio alert
    PlaySound(Sound);
    }
PlaySound("alert.wav");
class=class="str">"cmt">// Define class="kw">input variables
class="kw">input class="type">class="kw">string Alarm1 = "class="num">00:class="num">00:class="num">00"; class=class="str">"cmt">// Default value for first alarm
class="kw">input class="type">class="kw">string Alarm2 = "class="num">00:class="num">00:class="num">00"; class=class="str">"cmt">// Default value for second alarm
class="kw">input class="type">class="kw">string Alarm3 = "class="num">00:class="num">00:class="num">00"; class=class="str">"cmt">// Default value for third alarm
class="kw">input class="type">class="kw">string Sound = "alert.wav"; class=class="str">"cmt">// Default sound file
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert initialization function                                     |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit()
  {
class=class="str">"cmt">// Initialization function, executed once when the EA is launched
   class="kw">return class="num">0; class=class="str">"cmt">// Return class="num">0 to indicate successful initialization
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert deinitialization function                                   |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnDeinit(const class="type">int reason)
  {
class=class="str">"cmt">// Deinitialization function, executed before the EA is removed
class=class="str">"cmt">// Perform any cleanup or necessary actions here
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert tick function                                               |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnTick()
  {
class=class="str">"cmt">// Convert alarm strings to class="type">class="kw">datetime objects
   class="type">class="kw">datetime first_Alarm = StringToTime(Alarm1);
   class="type">class="kw">datetime second_Alarm = StringToTime(Alarm2);
   class="type">class="kw">datetime third_Alarm = StringToTime(Alarm3);
class=class="str">"cmt">// Get current local time

◍ 用本地时间触发三段式声音提醒

在 MT5 里做定时提醒,核心是把输入的字符串时间转成 datetime 再做等值比对。下面这段逻辑放在 OnTick 里,每次报价到来都会取一次本地时间,若命中任一时点就播声音文件。 输入参数给了三个 alarm 字符串,默认全是 00:00:00,Sound 默认 alert.wav。实际用的时候把 Alarm1~Alarm3 改成你的关键时点,比如伦敦开盘 08:00:00、美盘重叠 13:30:00,就能靠声音防漏单。外汇与贵金属波动剧烈,定时提醒只解决「不在屏前」的问题,不替代风控。 注意 TimeLocal() 返回的是终端所在机器的系统时间,不是服务器时间。若 VPS 时区设错,提醒会偏移到奇怪的时刻——这是实盘里最容易踩的坑。 代码逐行看:StringToTime 把 'HH:HH:SS' 文本解析为 datetime;TimeLocal 抓当前本地钟;if 里用 == 直接比,命中即 PlaySound。OnInit 仅返回 0 表示加载成功,OnDeinit 留空可做清理,OnStart 里的 Print 则方便你手动跑脚本确认本地时间格式。

MQL5 / C++
class="type">class="kw">datetime Time = TimeLocal();
class=class="str">"cmt">// Check if current time matches any of the alarm times
if(first_Alarm == Time || second_Alarm == Time || third_Alarm == Time)
  {
  class=class="str">"cmt">// Play sound if any alarm time is reached
  PlaySound(Sound);
  }
}
class="type">void OnStart()
  {
class=class="str">"cmt">// Get the current local time
class="type">class="kw">datetime localTime = TimeLocal();
class=class="str">"cmt">// Print the local time to the console
Print("Current Local Time: ", localTime);
}
class=class="str">"cmt">// Define class="kw">input variables
class="kw">input class="type">class="kw">string Alarm1 = "class="num">00:class="num">00:class="num">00"; class=class="str">"cmt">// Default value for first alarm
class="kw">input class="type">class="kw">string Alarm2 = "class="num">00:class="num">00:class="num">00"; class=class="str">"cmt">// Default value for second alarm
class="kw">input class="type">class="kw">string Alarm3 = "class="num">00:class="num">00:class="num">00"; class=class="str">"cmt">// Default value for third alarm
class="kw">input class="type">class="kw">string Sound = "alert.wav"; class=class="str">"cmt">// Default sound file
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert initialization function                                     |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit()
  {
class=class="str">"cmt">// Initialization function, executed once when the EA is launched
class="type">class="kw">datetime localTime = TimeLocal();
class="kw">return class="num">0; class=class="str">"cmt">// Return class="num">0 to indicate successful initialization
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert deinitialization function                                   |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnDeinit(const class="type">int reason)
  {
class=class="str">"cmt">// Deinitialization function, executed before the EA is removed
class=class="str">"cmt">// Perform any cleanup or necessary actions here
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert tick function                                               |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnTick()
  {
class=class="str">"cmt">// Convert alarm strings to class="type">class="kw">datetime objects
class="type">class="kw">datetime first_Alarm = StringToTime(Alarm1);
class="type">class="kw">datetime second_Alarm = StringToTime(Alarm2);
class="type">class="kw">datetime third_Alarm = StringToTime(Alarm3);
class=class="str">"cmt">// Get current local time
class="type">class="kw">datetime Time = TimeLocal();
class=class="str">"cmt">// Check if current time matches any of the alarm times
if(first_Alarm == Time || second_Alarm == Time || third_Alarm == Time)
  {
  class=class="str">"cmt">// Play sound if any alarm time is reached
  PlaySound(Sound);
  }
  }

「记住这一条就够了」

把复杂语法拆成小项目练手,配合 AI 辅助写伪代码和迭代测试,是摸熟 MQL5 最务实的路径。前面附带的报警 EA 片段里,OnInit 只做一次 StringToTime 转换,比在每个 tick 里重复转三次更省资源。 但这段代码的触发逻辑有硬伤:OnTick 里的 first_Alarm == Time 用等号比对本地时间,tick 到达时刻很难精确命中秒级报警点,漏报概率偏高。真要落地,得改用时间区间判断或 OnTimer 配合状态变量。 外汇与贵金属自带高杠杆风险,任何自动化脚本先在策略测试器跑历史数据,再上模拟盘验证。开 MT5 把上面代码贴进新 EA,改几个报警字符串,你能立刻看到漏触发的现象。

MQL5 / C++
class="kw">input class="type">class="kw">string Alarm1 = "class="num">00:class="num">00:class="num">00"; class=class="str">"cmt">// 第一个警报的默认值
class="kw">input class="type">class="kw">string Alarm2 = "class="num">00:class="num">00:class="num">00"; class=class="str">"cmt">// 第二次警报的默认值
class="kw">input class="type">class="kw">string Alarm3 = "class="num">00:class="num">00:class="num">00"; class=class="str">"cmt">// 第三警报的默认值
class="kw">input class="type">class="kw">string Sound = "alert.wav"; class=class="str">"cmt">// 默认声音文件
class=class="str">"cmt">// 为持久值定义全局项
class="type">class="kw">datetime first_Alarm, second_Alarm, third_Alarm;
class="type">int OnInit()
{
  class=class="str">"cmt">// 初始化函数,启动 EA 时执行一次
  class=class="str">"cmt">// 每个输入只进行一次转换
  first_Alarm = StringToTime(Alarm1);
  second_Alarm = StringToTime(Alarm2);
  third_Alarm = StringToTime(Alarm3);
  class="kw">return class="num">0; class=class="str">"cmt">// 返回 class="num">0 表示初始化成功
}
class="type">void OnTick()
{
  class=class="str">"cmt">// 获取当前当地时间
  class="type">class="kw">datetime Time = TimeLocal();
  class=class="str">"cmt">// 检查当前时间是否与任何警报时间一致
  if(first_Alarm == Time || second_Alarm == Time || third_Alarm == Time) class=class="str">"cmt">// 这里还有一个逻辑错误(见下文)
  {
    class=class="str">"cmt">// 达到任何闹钟时间时播放声音
    PlaySound(Sound);
  }
}

常见问题

先把交易逻辑拆成「条件—动作」小步,例如「金价破前高且RSI<70才开多」,再逐条写成伪代码,AI出错率会低很多。
用EA在M1、M15、H1各挂一个时间触发模块,到时播不同音效,比盯多个窗口轻松,外汇贵金属波动快仍属高风险。
小布可读取你的策略描述与代码摘要,标出伪代码与实现不一致的地方,并提示可能的边界报错,省去你逐行排查。
在EA里用TimeLocal()取本地时间,并预留30秒容差窗口分段播报,避免服务器与本地时区偏移导致漏提醒。
记住先伪代码后生成、先模拟后实盘;任何AI产出都只是概率优势,实盘前必在模拟跑两周以上。