MQL5 编程基础: 终端中的全局变量·进阶篇
🔧

MQL5 编程基础: 终端中的全局变量·进阶篇

(2/3)·名字、存在性、时间戳与批量读取,搞懂这层才能写出断电不丢状态的策略

新手友好 第 2/3 篇
很多初学者把 MQL5 里的终端全局变量和普通程序全局变量混为一谈,结果 EA 重启后状态全丢。其实前者关掉终端都还在,是订单间复杂交互的轻量存档层。本篇接着基础概念,把命名规则与生命周期摸透。

◍ 全局变量命名的那一截长度红线

MQL5 里的全局变量名称本质就是字符串,键盘能敲出来的字符都能塞进去,空格和文件名里禁用的符号也在允许范围内,顺序随便排。 但别真这么玩。实际写 EA 或脚本时,建议只拿字母、数字和下划线拼名字,跟普通局部变量风格保持一致,后期在 MT5 全局变量表里翻查不会瞎眼。 唯一硬约束是长度:名称最多 63 个字符,超了终端直接拒收。开 MT5 按 F3 调出全局变量窗口,建一个 64 字符的名字试一下就会立刻报错,这是可当场验证的边界。

用 GlobalVariableCheck 避开取极值踩坑

MT5 里 GlobalVariableCheck() 只吃一个参数——全局变量名,存在就返 true,没有就返 false。跑 sGVTestCheck 脚本检查 "test" 和 "test2",弹窗收到 "true false",说明前者建过、后者没建。 跟踪账户最小权益时这个判断很关键。若直接用 MathMin() 去比对没初始化的变量,函数可能永远吐 0,监控线就废了。先查存在性再决定是取极小值还是首笔赋值,逻辑才稳。 外汇和贵金属保证金波动大,全局变量跨 EA 共享,误判存在性会导致风控阈值失效,实盘前务必在策略测试器里复跑确认。

MQL5 / C++
class="type">bool check1=GlobalVariableCheck("test");
class="type">bool check2=GlobalVariableCheck("test2");
Alert(check1," ",check2);
if(GlobalVariableCheck("min_equity")){
   GlobalVariableSet("min_equity",MathMin(GlobalVariableGet("min_equity"),AccountInfoDouble(ACCOUNT_EQUITY)));
}
else{
   GlobalVariableSet("min_equity",AccountInfoDouble(ACCOUNT_EQUITY));
}

「全局变量时间戳的读取与改写边界」

MT5 里每个全局变量都带一个时间戳,记录它最后一次被访问的时刻。直接调 GlobalVariableTime("变量名") 就能拿回一个 datetime 值,不需要其他参数,也不需要提前声明变量是否存在。 这个时间戳不是静态的。只有 GlobalVariableSet() 和 GlobalVariableGet() 会刷新它,终端里其他函数动不了。你在全局变量窗口里手动改了数值或名称,时间戳也会跟着变——这点很容易在排查策略状态时被忽略。 变量在最后一次访问之后会存活四个星期,到期由终端自动清除。也就是说,靠时间戳判断「多久没碰过这个变量」是可行的,但别假设它能永久留痕。 下面这段就是取时间并弹窗的最小实现,在 MT5 里新建脚本粘进去就能跑,把 "test" 换成你自己的变量名即可验证。

MQL5 / C++
class="type">class="kw">datetime result=GlobalVariableTime("test");
Alert(result);

◍ 遍历终端全局变量并按前缀筛选

MT5 终端里全局变量一多,靠记忆精确名称去查基本不现实。经常只记得开头几个字母,比如 gvar1、gvar2 这种命名,结尾早就忘了。这时候要用 GlobalVariablesTotal() 拿总数,再用 GlobalVariableName() 按索引把名称逐个取出来。 GlobalVariablesTotal() 返回当前终端全局变量总个数,GlobalVariableName() 接收单个 int 索引返回对应名称。下面这段脚本会把所有变量名和数值用 Alert 弹窗列出来,跑完你能在消息框里看到终端里每一个全局变量的实时状态。 如果只想盯某一类变量,比如名称以 'gvar' 开头的,就套一层 StringFind() 判断。StringFind 返回 0 代表子串在开头命中,非 0 或 -1 则不匹配。这样能在几十个全局变量里只把关心的那几个捞出来,省得翻屏。 外汇与贵金属交易使用全局变量跨 EA 通信时存在平台重启丢失、并发读写异常等高风险,脚本仅作本地验证用途。

MQL5 / C++
  Alert("=== 开始 ===");
  class="type">int total=GlobalVariablesTotal();
  for(class="type">int i=class="num">0;i<total;i++){
    Alert(GlobalVariableName(i)," = ",GlobalVariableGet(GlobalVariableName(i)));
  }
  Alert("=== 开始 ===");
  class="type">int total=GlobalVariablesTotal();
  for(class="type">int i=class="num">0;i<total;i++){
    if(StringFind(GlobalVariableName(i),"gvar",class="num">0)==class="num">0){
      Alert(GlobalVariableName(i)," = ",GlobalVariableGet(GlobalVariableName(i)));
    }
  }

清掉 MT5 全局变量别用手点

MT5 的全局变量活在终端进程里,不随图表关闭消失,写脚本时经常要主动清理。单删一个用 GlobalVariableDel,只吃变量名一个参数,比如删掉之前建的 "test" 就一行搞定。 想确认删没删干净,跑 sGVTestGet2-1 或 sGVTestGet2-2 脚本,也可以直接开全局变量窗口看列表。 要批量删,GlobalVariablesDeleteAll 更顺手。它有两个可选参数:不传参就全终端变量清空;传前缀字符串,就只清那组开头同名的。下面代码先建了四个变量——gr1_ 前缀两个(值 1.2、3.4),gr2_ 前缀两个(值 5.6、7.8),再调一次删光 gr1_ 开头。

MQL5 / C++
<span class="functions">GlobalVariableDel</span>(<span class="class="type">class="kw">string">"test"</span>);
&nbsp;&nbsp; <span class="functions">GlobalVariableSet</span>(<span class="class="type">class="kw">string">"gr1_var1"</span>,<span class="number">class="num">1.2</span>);
&nbsp;&nbsp; <span class="functions">GlobalVariableSet</span>(<span class="class="type">class="kw">string">"gr1_var2"</span>,<span class="number">class="num">3.4</span>);&nbsp;&nbsp; 
&nbsp;&nbsp; <span class="functions">GlobalVariableSet</span>(<span class="class="type">class="kw">string">"gr2_var1"</span>,<span class="number">class="num">5.6</span>);
&nbsp;&nbsp; <span class="functions">GlobalVariableSet</span>(<span class="class="type">class="kw">string">"gr2_var2"</span>,<span class="number">class="num">7.8</span>);&nbsp;&nbsp;
<span class="functions">GlobalVariablesDeleteAll</span>(<span class="class="type">class="kw">string">"gr1_"</span>);
<span class="functions">GlobalVariablesDeleteAll</span>(<span class="macro">NULL</span>,<span class="functions">StringToTime</span>(<span class="class="type">class="kw">string">"class="num">2016.10.class="num">01 class="num">12:class="num">37"</span>));
逐行拆:第1行删名为 test 的全局变量;2–5行用 GlobalVariableSet 写入四个变量,gr1_ 两组、gr2_ 两组,带具体数值;第6行删所有 gr1_ 前缀变量;第7行第二个参数给时间,NULL 表示不限制前缀,只删最后访问早于 2016.10.01 12:37 的变量。 第二个时间参数偏冷门,只在按老化程度回收变量时才用得上,实盘 EA 里大概率用不到。外汇和贵金属杠杆高、滑点跳变频繁,脚本误删正在被 EA 读取的全局变量可能让持仓逻辑瞬间失联,跑这类清理代码前先确认没有活策略依赖那些名。

MQL5 / C++
<span class="functions">GlobalVariableDel</span>(<span class="class="type">class="kw">string">"test"</span>);
&nbsp;&nbsp; <span class="functions">GlobalVariableSet</span>(<span class="class="type">class="kw">string">"gr1_var1"</span>,<span class="number">class="num">1.2</span>);
&nbsp;&nbsp; <span class="functions">GlobalVariableSet</span>(<span class="class="type">class="kw">string">"gr1_var2"</span>,<span class="number">class="num">3.4</span>);&nbsp;&nbsp; 
&nbsp;&nbsp; <span class="functions">GlobalVariableSet</span>(<span class="class="type">class="kw">string">"gr2_var1"</span>,<span class="number">class="num">5.6</span>);
&nbsp;&nbsp; <span class="functions">GlobalVariableSet</span>(<span class="class="type">class="kw">string">"gr2_var2"</span>,<span class="number">class="num">7.8</span>);&nbsp;&nbsp;
<span class="functions">GlobalVariablesDeleteAll</span>(<span class="class="type">class="kw">string">"gr1_"</span>);
<span class="functions">GlobalVariablesDeleteAll</span>(<span class="macro">NULL</span>,<span class="functions">StringToTime</span>(<span class="class="type">class="kw">string">"class="num">2016.10.class="num">01 class="num">12:class="num">37"</span>));

「紧急关机前的强制落盘」

MT5 退出时会自动把全局变量写进本地文件,下次启动照常读回,日常使用无需关心底层文件名和存储格式。但要是终端被任务管理器强杀、服务器掉电,这批变量有可能没来得及落盘就丢了。 GlobalVariablesFlush() 就是用来强制刷盘的:在 GlobalVariableSet() 写入或 Delete 之后顺手调一次,不带任何参数。它把内存里的全局变量立刻同步到磁盘,降低非正常关闭时的数据丢失概率。 实盘里若 EA 把仓位状态、分批止损标记存进全局变量,且在 VPS 或笔记本上跑,调用这个函数更稳妥。不过原文也提到,如今笔记本自带电池、台式机常配 UPS、服务器有断电防护,即便不主动 flush,全局变量本身已是相对可信的本地暂存手段。外汇与贵金属杠杆高,任何本地状态丢失都可能引发重复开仓,建议先在策略测试器外手动验证再上实盘。 下面这段演示了先写四个变量再强制落盘,直接拷进 MT5 脚本就能跑:

MQL5 / C++
  GlobalVariableSet("gr1_var1",class="num">1.2);
  GlobalVariableSet("gr1_var2",class="num">3.4);  
  GlobalVariableSet("gr2_var1",class="num">5.6);
  GlobalVariableSet("gr2_var2",class="num">7.8);  
  
  GlobalVariablesFlush();
让小布替你跑这套
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到全局变量窗口的实时映射,不用自己切终端查状态。

常见问题

名称是字符串,理论上可含多数字符,但建议只用字母数字下划线,避免其他 EA 或脚本读写时编码出错。
可能变量从未被 Set 过,或名称拼写与已创建的不一致;终端关掉后变量仍在,但被显式删除就会消失。
可以,小布盯盘对应品种页已内置全局变量映射视图,省去手动开工具窗口核对。
是最后一次访问(读或写)的时间戳,超过一定空闲时长终端可能自动清理,具体看终端设置。
当你在极短周期内密集写变量、且担心异常退出丢最新值,可强制刷盘;平时终端会自动处理。