Advertisement IC Markets

Tightest Spreads Forex: Low Latency Broker Test

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

Tightest Spreads Forex: Low Latency Broker Test

Post by PTScalper »

Hi traders,

Advertised "raw spread" is merely Top of Book (Level 1) data, which represents only a fraction of true transaction cost. A headline spread of 0.0 pips is meaningless if it can only absorb a 0.5-lot or 1.0-lot retail market order before sweeping into wider price tiers.

1. Top-of-Book Illusion vs. VWAP Execution

As shown in your cTrader Depth of Market (DoM) captures, liquidity is tiered:

The 1-Lot Clip: In the EUR/USD book, the top tier shows a pure 0.0 pip spread ($1.13790 / 1.13790$), but only for 1.00 lot.

Slicing Deeper into the Book: If an algorithm or market order hits for 20 lots, it takes 1 lot at $1.13790$, 15 lots at the next tier ($1.13792$), and the remaining 4 lots at the third tier ($1.13795$).

Effective Spread (VWAP): The Volume-Weighted Average Price for buying 20 lots is not 0.0 pips; it averages out to ~0.33 pips. Brokers with shallow liquidity pools might advertise 0.0 pips, but their second tier jumps 1.5–2.0 pips out for even modest sizes (e.g., 5–10 lots).

2. Execution Latency and Cross-Connects

Low latency is not just ping to the broker's front-end server; it is the entire round-trip time (RTT) to the matching engine and Liquidity Providers (LPs):

Server Colocation: Institutional retail setups host their matching engines in Equinix LD4 (London) or NY4 (New York). Running a VPS cross-connected via optical cross-connect inside the same data center drops local transit latency to $<1\text{ ms}$.

Price Movement Risk: In fast markets (e.g., London/NY overlap or data releases), price updates occur every few milliseconds. If execution latency is 40–80 ms, the quoted top-of-book tier vanishes before the order reaches the matching engine, resulting in adverse slippage.
Attachments
IMG_2399.jpg
IMG_2399.jpg (145.5 KiB) Viewed 56 times
IMG_2398.jpg
IMG_2398.jpg (117 KiB) Viewed 56 times
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: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: Tightest Spreads Forex: Low Latency Broker Test

Post by PTScalper »

3. LP Quality, Fill Models, and "Last Look"

True execution quality depends on the broker's liquidity bridge (e.g., oneZero, PrimeXM) and liquidity aggregator:

Last Look vs. Firm Liquidity: Many non-bank market makers retain "last look" privileges (holding an order for 20–100 ms to see if the market moves against them before accepting or rejecting it). Brokers with top-tier prime of prime (PoP) relationships mix firm liquidity streams, minimizing rejections and asymmetric slippage.

Positive Slippage Asymmetry: A reputable broker passes positive slippage through symmetrically. Market makers running virtual dealer plugins frequently cap positive slippage while executing full negative slippage.

Are you running automated execution via FIX API/cTrader Open API, or manual scalping around session openings?
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: Tightest Spreads Forex: Low Latency Broker Test

Post by PTScalper »

To objectively benchmark a broker's execution infrastructure and liquidity depth, testing must isolate two critical variables during live order routing: the Round-Trip Time (RTT) latency and the Volume-Weighted Average Price (VWAP) slippage.

Latency can cause negative slippage when the market moves away while the order is delayed in transit, but slippage also occurs independently of latency when a large order size sweeps through multiple pricing tiers in the Depth of Market (DoM).

The scripts below utilize GetMicrosecondCount() to measure network and matching engine delays down to the microsecond. By comparing the exact Top-of-Book price requested against the final executed price returned by the server, they calculate precise transaction costs.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: Tightest Spreads Forex: Low Latency Broker Test

Post by PTScalper »

MQL5 Execution Benchmark Script

In MT5, measuring the full RTT requires sending a synchronous OrderSend request. The script dynamically handles broker-specific filling modes (FOK vs. IOC) to prevent rejection errors.

Code: Select all

//+------------------------------------------------------------------+
//|                                    ExecutionBenchmark_MT5.mq5    |
//+------------------------------------------------------------------+
#property script_show_inputs

input double InpLotSize   = 1.0;    // Test Volume (Sweep the DoM)
input ulong  InpDeviation = 100;    // Max Slippage (points)
input ulong  InpMagic     = 99999;  // Magic Number

void OnStart()
{
    MqlTradeRequest request = {0};
    MqlTradeResult  result  = {0};

    request.action    = TRADE_ACTION_DEAL;
    request.symbol    = _Symbol;
    request.volume    = InpLotSize;
    request.type      = ORDER_TYPE_BUY;
    request.price     = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
    request.deviation = InpDeviation;
    request.magic     = InpMagic;

    // Determine allowed filling mode dynamically to avoid broker rejections
    int filling = (int)SymbolInfoInteger(_Symbol, SYMBOL_FILLING_MODE);
    if((filling & SYMBOL_FILLING_FOK) != 0)
        request.type_filling = ORDER_FILLING_FOK;
    else if((filling & SYMBOL_FILLING_IOC) != 0)
        request.type_filling = ORDER_FILLING_IOC;

    // 1. Capture exact dispatch time in microseconds
    ulong startTime = GetMicrosecondCount();
    
    // 2. Dispatch order synchronously to measure full RTT
    bool success = OrderSend(request, result);
    
    // 3. Capture exact return time
    ulong endTime = GetMicrosecondCount();
    
    double latencyMs = (endTime - startTime) / 1000.0;

    if(success)
    {
        double slippagePoints = (result.price - request.price) / _Point;
        
        Print("========================================");
        PrintFormat("MT5 BENCHMARK | Symbol: %s | Volume: %.2f", _Symbol, InpLotSize);
        PrintFormat("Requested (Top-of-Book): %f", request.price);
        PrintFormat("Executed (VWAP): %f", result.price);
        PrintFormat("-> SLIPPAGE: %.1f points", slippagePoints);
        PrintFormat("-> LATENCY (RTT): %.3f ms", latencyMs);
        Print("========================================");
    }
    else
    {
        PrintFormat("Execution Failed! Error: %d | Latency: %.3f ms", result.retcode, latencyMs);
    }
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: Tightest Spreads Forex: Low Latency Broker Test

Post by PTScalper »

MQL4 Execution Benchmark Script

For MT4, the logic is identical, relying on the OrderSend() function to return a ticket number. It is critical to call RefreshRates() immediately before fetching the Ask price to ensure the requested price matches the market exactly at dispatch.

Code: Select all

//+------------------------------------------------------------------+
//|                                    ExecutionBenchmark_MT4.mq4    |
//+------------------------------------------------------------------+
#property script_show_inputs

input double InpLotSize   = 1.0;    // Test Volume
input int    InpDeviation = 100;    // Max Slippage (points)
input int    InpMagic     = 99999;  // Magic Number

void OnStart()
{
    // Ensure market info is absolutely fresh before dispatch
    RefreshRates();
    double reqPrice = Ask;
    
    // 1. Capture exact dispatch time in microseconds
    ulong startTime = GetMicrosecondCount();
    
    // 2. Dispatch market order
    int ticket = OrderSend(_Symbol, OP_BUY, InpLotSize, reqPrice, InpDeviation, 0, 0, "LatencyBench", InpMagic, 0, clrBlue);
    
    // 3. Capture exact return time
    ulong endTime = GetMicrosecondCount();
    
    double latencyMs = (endTime - startTime) / 1000.0;

    if(ticket > 0)
    {
        if(OrderSelect(ticket, SELECT_BY_TICKET))
        {
            double execPrice = OrderOpenPrice();
            double slippagePoints = (execPrice - reqPrice) / Point;
            
            Print("========================================");
            PrintFormat("MT4 BENCHMARK | Symbol: %s | Volume: %.2f", _Symbol, InpLotSize);
            PrintFormat("Requested (Top-of-Book): %f", reqPrice);
            PrintFormat("Executed (VWAP): %f", execPrice);
            PrintFormat("-> SLIPPAGE: %.1f points", slippagePoints);
            PrintFormat("-> LATENCY (RTT): %.3f ms", latencyMs);
            Print("========================================");
        }
    }
    else
    {
        PrintFormat("Execution Failed! Error: %d | Latency: %.3f ms", GetLastError(), latencyMs);
    }
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: Tightest Spreads Forex: Low Latency Broker Test

Post by PTScalper »

To accurately map a broker's liquidity profile, execute these scripts progressively using staggered lot sizes (e.g., 0.1, 1.0, 5.0, 10.0 lots). An institutional-grade liquidity feed will consistently execute 0.1 lots with near-zero slippage and a latency under 10 ms (if routed from a properly cross-connected VPS). As the test volume increases to 5.0 or 10.0 lots, the printout for -> SLIPPAGE will reveal the exact penalty incurred as the trade sweeps deeper into the broker's liquidity tiers, definitively separating synthetic zero-spread marketing from true deep-pool execution.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: Tightest Spreads Forex: Low Latency Broker Test

Post by PTScalper »

To elevate this to an institutional grade, the scripts must move beyond terminal printouts and generate structured telemetry. When benchmarking market microstructure and execution quality for price action scalping, you need persistent data to analyze the true cost of trading across different sessions and liquidity sweeps.

These upgraded "Pro" versions introduce three major architectural improvements:

Persistent CSV Logging: Writes execution metrics directly to a CSV file, allowing you to ingest the data into MS SQL Server or a custom C# backend for long-term broker profiling.

Total Cost Analysis (TCA): Extracts the actual commission charged from the deal history and calculates the exact spread-to-slippage ratio.

Advanced Microstructure Metrics: Logs the exact Bid/Ask spread immediately prior to execution to determine if adverse slippage was caused by spread widening during latency or by sweeping the Depth of Market (DoM).
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: Tightest Spreads Forex: Low Latency Broker Test

Post by PTScalper »

MQL5: Pro Execution Telemetry Script

This MT5 version parses the deal history post-execution to extract the exact transaction cost (commissions) and logs all data to MQL5\Files\BrokerTelemetry_MT5.csv.

Code: Select all

//+------------------------------------------------------------------+
//|                               ExecutionTelemetry_Pro_MT5.mq5     |
//+------------------------------------------------------------------+
#property script_show_inputs

input double   InpLotSize   = 1.0;                   // Execution Volume
input ulong    InpDeviation = 0;                     // Max Slippage (0 = True Market)
input ulong    InpMagic     = 888888;                // Magic Number
input string   InpFileName  = "BrokerTelemetry_MT5.csv"; // Telemetry Log

void OnStart()
{
    MqlTradeRequest request = {0};
    MqlTradeResult  result  = {0};

    // Pre-Execution Microstructure Snapshot
    double askPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
    double bidPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
    double initialSpread = (askPrice - bidPrice) / _Point;

    request.action    = TRADE_ACTION_DEAL;
    request.symbol    = _Symbol;
    request.volume    = InpLotSize;
    request.type      = ORDER_TYPE_BUY;
    request.price     = askPrice;
    request.deviation = InpDeviation;
    request.magic     = InpMagic;

    int filling = (int)SymbolInfoInteger(_Symbol, SYMBOL_FILLING_MODE);
    if((filling & SYMBOL_FILLING_FOK) != 0) request.type_filling = ORDER_FILLING_FOK;
    else if((filling & SYMBOL_FILLING_IOC) != 0) request.type_filling = ORDER_FILLING_IOC;

    ulong startTime = GetMicrosecondCount();
    bool success = OrderSend(request, result);
    ulong endTime = GetMicrosecondCount();
    
    double latencyMs = (endTime - startTime) / 1000.0;

    if(success && result.deal > 0)
    {
        // Extract post-trade data from history
        HistorySelect(TimeCurrent() - 10, TimeCurrent() + 10);
        double commission = HistoryDealGetDouble(result.deal, DEAL_COMMISSION);
        double slippagePoints = (result.price - request.price) / _Point;
        
        LogToCSV(InpFileName, _Symbol, InpLotSize, initialSpread, request.price, result.price, slippagePoints, commission, latencyMs);
        PrintFormat("Success | Vol: %.2f | Slip: %.1f pts | Latency: %.2f ms | Saved to CSV", InpLotSize, slippagePoints, latencyMs);
    }
    else
    {
        PrintFormat("Execution Failed: %d | Latency: %.2f ms", result.retcode, latencyMs);
    }
}

//+------------------------------------------------------------------+
//| Append telemetry to CSV for external database ingestion          |
//+------------------------------------------------------------------+
void LogToCSV(string fileName, string sym, double vol, double spread, double reqPrice, double execPrice, double slip, double comm, double lat)
{
    int fileHandle = FileOpen(fileName, FILE_WRITE|FILE_CSV|FILE_READ|FILE_ANSI, ',');
    if(fileHandle != INVALID_HANDLE)
    {
        ulong fileSize = FileSize(fileHandle);
        FileSeek(fileHandle, 0, SEEK_END);
        
        // Write headers if file is new
        if(fileSize == 0)
        {
            FileWrite(fileHandle, "Timestamp", "Symbol", "Volume", "Spread_Pts", "Req_Price", "Exec_Price", "Slippage_Pts", "Commission", "Latency_ms");
        }
        
        string timestamp = TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS);
        FileWrite(fileHandle, timestamp, sym, DoubleToString(vol, 2), DoubleToString(spread, 1), 
                  DoubleToString(reqPrice, _Digits), DoubleToString(execPrice, _Digits), 
                  DoubleToString(slip, 1), DoubleToString(comm, 2), DoubleToString(lat, 3));
                  
        FileClose(fileHandle);
    }
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: Tightest Spreads Forex: Low Latency Broker Test

Post by PTScalper »

MQL4: Pro Execution Telemetry Script

MT4 lacks native asynchronous deals and comprehensive history structs, but we can replicate the exact same Total Cost Analysis utilizing OrderSelect and strict compilation standards.

Code: Select all

//+------------------------------------------------------------------+
//|                               ExecutionTelemetry_Pro_MT4.mq4     |
//+------------------------------------------------------------------+
#property strict
#property script_show_inputs

input double InpLotSize   = 1.0;                     // Execution Volume
input int    InpDeviation = 0;                       // Max Slippage (0 = True Market)
input int    InpMagic     = 888888;                  // Magic Number
input string InpFileName  = "BrokerTelemetry_MT4.csv"; // Telemetry Log

void OnStart()
{
    RefreshRates();
    double reqPrice = Ask;
    double initialSpread = (Ask - Bid) / Point;
    
    ulong startTime = GetMicrosecondCount();
    int ticket = OrderSend(_Symbol, OP_BUY, InpLotSize, reqPrice, InpDeviation, 0, 0, "ProBench", InpMagic, 0, clrNONE);
    ulong endTime = GetMicrosecondCount();
    
    double latencyMs = (endTime - startTime) / 1000.0;

    if(ticket > 0)
    {
        if(OrderSelect(ticket, SELECT_BY_TICKET))
        {
            double execPrice = OrderOpenPrice();
            double commission = OrderCommission();
            double slippagePoints = (execPrice - reqPrice) / Point;
            
            LogToCSV(InpFileName, _Symbol, InpLotSize, initialSpread, reqPrice, execPrice, slippagePoints, commission, latencyMs);
            PrintFormat("Success | Vol: %.2f | Slip: %.1f pts | Latency: %.2f ms | Saved to CSV", InpLotSize, slippagePoints, latencyMs);
        }
    }
    else
    {
        PrintFormat("Execution Failed: %d | Latency: %.2f ms", GetLastError(), latencyMs);
    }
}

//+------------------------------------------------------------------+
//| Append telemetry to CSV for external database ingestion          |
//+------------------------------------------------------------------+
void LogToCSV(string fileName, string sym, double vol, double spread, double reqPrice, double execPrice, double slip, double comm, double lat)
{
    int fileHandle = FileOpen(fileName, FILE_WRITE|FILE_CSV|FILE_READ|FILE_ANSI, ',');
    if(fileHandle != INVALID_HANDLE)
    {
        int fileSize = FileSize(fileHandle);
        FileSeek(fileHandle, 0, SEEK_END);
        
        if(fileSize == 0)
        {
            FileWrite(fileHandle, "Timestamp", "Symbol", "Volume", "Spread_Pts", "Req_Price", "Exec_Price", "Slippage_Pts", "Commission", "Latency_ms");
        }
        
        string timestamp = TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS);
        FileWrite(fileHandle, timestamp, sym, DoubleToString(vol, 2), DoubleToString(spread, 1), 
                  DoubleToString(reqPrice, Digits), DoubleToString(execPrice, Digits), 
                  DoubleToString(slip, 1), DoubleToString(comm, 2), DoubleToString(lat, 3));
                  
        FileClose(fileHandle);
    }
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: Tightest Spreads Forex: Low Latency Broker Test

Post by PTScalper »

Analyzing the Output

By binding these scripts to a hotkey and executing them across different volume tranches (0.1, 1.0, 5.0, 10.0 lots) during various market conditions (e.g., London open vs. late NY session), the resulting CSV file provides a precise map of the broker's underlying order book. You can easily import this into Excel, or pipe it into a C# analytical tool to graph the exact point where volume exceeds Top-of-Book liquidity and triggers wider Tier 2 or Tier 3 pricing.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Post Reply