首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >MT5 重启一次,你的日内亏损上限就归零了——MQL5 风控状态持久化实现

MT5 重启一次,你的日内亏损上限就归零了——MQL5 风控状态持久化实现

原创
作者头像
用户12775688
发布于 2026-09-20 16:54:22
发布于 2026-09-20 16:54:22
1190
举报

大部分 MT5「日内亏损上限」的实现是这样的:

代码语言:mql5
复制
double today_pnl = 0.0;      // 模块级变量
bool   daily_blocked = false;

平时工作得很好——直到终端重启、EA 重新编译、切换图表、重新加载配置。这些动作每一个都会重新调用 OnInit(),变量归零,你辛苦设的上限被原封不动地还回来。

如果你跑的是 prop firm 账户(5% 日回撤规则),这不是小 bug:崩溃和重启总是扎堆出现在糟糕的交易日,而那正是你最需要这道保险的时刻。

「持久化」到底要扛住什么

事件

内存变量

终端全局变量

文件(common 目录)

新 tick / 新 bar

有效

有效

有效

EA 重编译 / 重新挂载

失效

有效

有效

终端重启

失效

有效

有效

重装 / 换机器 / 多开终端

失效

失效

有效

GlobalVariableSet() 能覆盖前两种,最后一行只有落盘才行。

必须落盘的三个字段

代码语言:mql5
复制
struct GuardState
{
   long   day_stamp;          // 属于哪个交易日
   double day_start_balance;  // 当日回撤锚点
   bool   blocked;            // 今天是否已熔断
};

day_stamp 是最容易被忘掉的字段。没有它,恢复出来的状态要么永远不生效,要么永远生效——两种都是错的。

坑 1:交易日必须取券商的时钟

代码语言:mql5
复制
long TradingDayStamp()
{
   MqlDateTime t;
   TimeToStruct(TimeTradeServer(), t);   // 不是 TimeLocal()
   return((long)t.year * 10000 + t.mon * 100 + t.day);
}

TimeLocal() 会在券商交易时段中间把上限重置掉。TimeCurrent() 是最后一笔报价时间,冷清时段严重滞后。

坑 2:先落盘,再下单

代码语言:mql5
复制
if(blocked) return;                  // 便宜,且能接住外部写入的熔断
if(!risk_ok) { blocked = true; SaveState(); return; }
SendOrder();

顺序反了,两行之间崩一次就可能放过一单本不该存在的订单。

唯一有效的验收测试

  1. 设一个几分钟就会击穿的上限;
  2. 让它击穿;
  3. 杀掉终端进程(不是关 EA),保持持仓;
  4. 重开终端,试着再下一单。

如果新进程痛快地发了单,说明状态在内存里——那道守护只是摆设。

结语

三行纪律:状态写盘、用券商交易日、先写后发。这就是「风险上限」和「愿望」的区别。

我把这套实现打包成了一个免费 MT5 工具(纯 MQL5、无 DLL、无外部请求、界面只显示百分比):

https://xuks124.github.io/vigildesk/free.html

只做风控,不承诺收益。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 「持久化」到底要扛住什么
  • 必须落盘的三个字段
  • 坑 1:交易日必须取券商的时钟
  • 坑 2:先落盘,再下单
  • 唯一有效的验收测试
  • 结语
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档