Advertisement IC Markets

Logging real slippage on market orders (MT5 + a dumb Python script)

Compare ECN/Raw spread brokers, analyze execution speeds, report slippage, and evaluate commission structures for high-frequency traders.
PTScalper
Site Admin
Posts: 1604
Joined: Mon Jul 20, 2026 1:28 pm

Re: Logging real slippage on market orders (MT5 + a dumb Python script)

Post by PTScalper »

2. The MQL5 Execution Gate

On the MQL5 side, you wrap your execution logic with a fast validation check. Because memory reads are incredibly cheap, the EA can safely poll this variable on every single OnTick() or right before building the MqlTradeRequest struct.

Code: Select all

//+------------------------------------------------------------------+
//| Function to check the Python kill switch                         |
//+------------------------------------------------------------------+
bool IsCircuitBreakerTripped()
  {
   string switch_name = "GLOBAL_KILL_SWITCH";
   
   // Check if the variable exists and equals 1.0
   if(GlobalVariableCheck(switch_name))
     {
      double is_halted = GlobalVariableGet(switch_name);
      if(is_halted == 1.0)
        {
         return true; // Breaker is tripped, halt trading
        }
     }
   
   // Variable doesn't exist or is set to 0.0, safe to trade
   return false;
  }

//+------------------------------------------------------------------+
//| Main Tick Function                                               |
//+------------------------------------------------------------------+
void OnTick()
  {
   // 1. Hard execution gate
   if(IsCircuitBreakerTripped())
     {
      // Optional: Add logic to manage/close existing open positions 
      // even while rejecting new entries.
      Comment("TRADING HALTED: Python Circuit Breaker Active");
      return; 
     }
     
   Comment(""); // Clear halt message

   // 2. Your standard signal generation and execution logic follows...
   // ...
  }
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Recommended broker for automated trading & scalping IC Markets
PTScalper
Site Admin
Posts: 1604
Joined: Mon Jul 20, 2026 1:28 pm

Re: Logging real slippage on market orders (MT5 + a dumb Python script)

Post by PTScalper »

Advanced Architecture Note: Position Management

A full halt often requires nuance. A tripped breaker means liquidity is toxic, so you absolutely want to block new entries (ORDER_TYPE_BUY / ORDER_TYPE_SELL). However, you usually still want your EAs to manage trailing stops or attempt to exit currently open positions, even if the fills will be ugly.

By handling the gate strictly inside MQL5, you can compartmentalize the kill switch: checking IsCircuitBreakerTripped() before opening new trades, while allowing your existing PositionClose() or OrderModify() routines to continue functioning.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 1604
Joined: Mon Jul 20, 2026 1:28 pm

Re: Logging real slippage on market orders (MT5 + a dumb Python script)

Post by PTScalper »

Building an automated reset introduces a classic algorithmic Catch-22: The Blind Problem.

Once your circuit breaker trips and halts your EAs, you no longer have live market orders to calculate slippage from. You cannot measure execution quality if you aren't executing. To safely resume trading, the system must rely on a proxy metric to determine when the order book has stabilized.

The most reliable proxy is top-of-book spread compression paired with a hard time-based cooldown. Once the spread remains tight for a sustained window, the script clears the MT5 Global Variable and flushes its internal memory.

Here is the recovery architecture.

The Recovery Logic
Hard Cooldown: Enforce an absolute blackout period (e.g., 5 minutes). If a tier-1 news event destroys the book, it takes time for liquidity providers to step back in.

Spread Polling: After the cooldown, begin polling the live spread (ask - bid). We track this over a rolling window (e.g., 30 seconds) to ensure the book isn't just flashing tight for a single tick before widening again.

The Memory Flush (Critical): Before clearing the MT5 Global Variable, the Python script must clear the deque containing the historic bad slippage. If you don't flush the contaminated memory, the very first new trade will combine with the old p90 data and instantly trip the breaker again.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 1604
Joined: Mon Jul 20, 2026 1:28 pm

Re: Logging real slippage on market orders (MT5 + a dumb Python script)

Post by PTScalper »

The Python Implementation

Add this recovery logic to your existing listener.

Code: Select all

import time
from collections import deque
import MetaTrader5 as mt5

# --- Recovery Configuration ---
COOLDOWN_SECONDS = 300       # 5 minutes hard wait before checking the market
NORMAL_SPREAD_LIMIT = 15.0   # Max spread in points to be considered "safe" (e.g., 1.5 pips)

# Track when the breaker tripped per symbol
trip_times = {}

# Spread memory to ensure sustained stability
spread_windows = {symbol: deque(maxlen=30) for symbol in SLIPPAGE_THRESHOLDS}

def check_recovery(symbol):
    global TRADING_ACTIVE
    
    # 1. Enforce hard time cooldown
    time_since_trip = time.time() - trip_times.get(symbol, time.time())
    if time_since_trip < COOLDOWN_SECONDS:
        return 
        
    # 2. Pull live tick data as a proxy for book depth
    tick = mt5.symbol_info_tick(symbol)
    if not tick:
        return
        
    point = mt5.symbol_info(symbol).point
    current_spread = (tick.ask - tick.bid) / point
    spread_windows[symbol].append(current_spread)
    
    # 3. Wait until we have a full window of spread data to evaluate
    if len(spread_windows[symbol]) == spread_windows[symbol].maxlen:
        max_spread = max(spread_windows[symbol])
        
        if max_spread <= NORMAL_SPREAD_LIMIT:
            print(f"\n[{symbol}] Liquidity normalized. Max spread over last 30 ticks: {max_spread:.1f} pts.")
            reset_breaker(symbol)
        else:
            # Book is still volatile. Clear the spread window and wait for a fresh batch.
            spread_windows[symbol].clear()
            print(f"[{symbol}] Spread still volatile ({max_spread:.1f} pts). Extending wait.")

def reset_breaker(symbol):
    global TRADING_ACTIVE
    
    # 4. CRITICAL: Flush the contaminated slippage memory
    rolling_windows[symbol].clear()
    spread_windows[symbol].clear()
    
    # 5. Clear the MT5 Terminal Global Variable
    # Writing 0.0 maps to 'false' in MQL5, effectively un-tripping the switch
    success = mt5.global_variable_set("GLOBAL_KILL_SWITCH", 0.0)
    
    if success:
        TRADING_ACTIVE = True
        print(f"✅ BREAKER RESET for {symbol}. EAs re-armed and memory flushed.")
    else:
        print(f"CRITICAL ERROR: Failed to reset MT5 Global Variable for {symbol}.")
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 1604
Joined: Mon Jul 20, 2026 1:28 pm

Re: Logging real slippage on market orders (MT5 + a dumb Python script)

Post by PTScalper »

Integrating with the Polling Loop

You will need to modify the main while True: block to gracefully switch between "listening mode" and "recovery mode".

Code: Select all

while True:
            if not TRADING_ACTIVE:
                # System is halted. Run recovery protocol for affected symbols.
                for symbol in halted_symbols:
                    check_recovery(symbol)
                
                # Poll slower during recovery to save CPU
                time.sleep(1.0)
                continue

            # ... (Existing deal listener logic goes here) ...
Pro-Tip: The Canary Protocol

If spread polling isn't a reliable enough proxy for your specific liquidity provider, you can design a three-state system. Instead of setting the variable back to 0.0 immediately, set it to 0.5. Your MQL5 EA reads 0.5 as a "Probationary State" and is programmed to execute exactly one 0.01 lot micro-trade. If your Python listener logs that canary trade and the slippage is acceptable, it fully resets the global variable to 0.0, unlocking normal lot sizing.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Post Reply