EA接收AI信号后,为什么还要用已收K线时间做幂等校验?

 
今天复盘一个XAUUSD网页信号流程时,我再次遇到一个工程问题:同一轮行情里,网页计算、消息传输与EA轮询可能以不同频率运行。如果EA只判断“当前条件为真”,重连、延迟或重复推送都可能造成同一结构被处理多次。

我更倾向于把“已收K线时间 + 规则版本 + 方向”组合成事件键。EA收到消息后,先校验事件是否属于上一根已完成K线,再检查是否已经处理。下面是一个最小化示例:

// MQL5
 datetime last_closed_bar = 0;

bool IsNewClosedBarSignal(const ENUM_TIMEFRAMES tf)
{
   datetime closed_bar = iTime(_Symbol, tf, 1);
   if(closed_bar <= 0 || closed_bar == last_closed_bar)
      return false;

   last_closed_bar = closed_bar;
   return true;
}

void OnTick()
{
   if(!IsNewClosedBarSignal(PERIOD_M5))
      return;

   // 1. 读取并校验外部事件时间
   // 2. 核对规则版本与交易品种
   // 3. 再进入本地风险门;此处不直接下单
}

这个示例不解决策略是否有效,它只解决一层工程问题:避免同一根已收K线被重复消费。生产环境还需要把事件键持久化,并分别记录接收时间、校验结果、拒绝原因和本地风险门状态。

我把“消息收到”“规则成立”“允许执行”“策略有效”视为四个不同状态。前一层通过,不能替后一层背书。欢迎讨论你们在MT5重启后如何恢复幂等状态:终端全局变量、文件,还是外部数据库?

仅用于MQL5工程交流,不构成交易建议,也不代表任何策略表现。
 
补充一条今天的前向记录:事件模型只评估到1个事件,候选为0,同时缺少完整官方事件表和对应的历史Bid/Ask序列。因此我没有把这次空结果记为 RULE_NOT_TRIGGERED,而是记为 DATA_NOT_READY。

在EA侧我准备把“没有动作”的原因写成显式状态,而不是只写一条 No trade:

// MQL5
enum ENUM_GATE_RESULT
  {
   DATA_NOT_READY = 0,
   RULE_NOT_TRIGGERED,
   RISK_REJECTED,
   DELIVERY_FAILED,
   EXECUTION_READY
  };

ENUM_GATE_RESULT EvaluateGate(const bool event_ok,
                              const bool bidask_ok,
                              const bool rule_ok,
                              const bool risk_ok)
  {
   if(!event_ok || !bidask_ok)
      return DATA_NOT_READY;
   if(!rule_ok)
      return RULE_NOT_TRIGGERED;
   if(!risk_ok)
      return RISK_REJECTED;
   return EXECUTION_READY;
  }

void LogGate(const ENUM_GATE_RESULT state, const datetime event_time)
  {
   PrintFormat("event=%s state=%d symbol=%s bid=%.2f ask=%.2f",
               TimeToString(event_time, TIME_DATE|TIME_SECONDS),
               (int)state, _Symbol,
               SymbolInfoDouble(_Symbol, SYMBOL_BID),
               SymbolInfoDouble(_Symbol, SYMBOL_ASK));
  }

关键点不是枚举本身,而是让 DATA_NOT_READY 与 RULE_NOT_TRIGGERED 永远不能合并统计。前者说明证据链不完整,后者才说明规则在完整输入下没有成立。否则统计“空信号率”时,会把数据故障误算成策略过滤能力。

这段仍只是状态分层示例,不代表策略已验证,也不直接触发订单。大家在MQL5里会把数据就绪状态放在本地EA、服务端,还是两边都校验?