Page 2 of 4

Re: Why your fill time doesn't match the moment you clicked

Posted: Sat Oct 17, 2026 9:06 am
by PTScalper
The Hybrid Model

In reality, very few retail brokers are 100% A-Book or 100% B-Book. Most employ a hybrid model driven by internal risk-management algorithms.

When a new retail account is opened, it is typically placed on the B-Book. The broker absorbs the trades, knowing statistically that the vast majority of retail traders lose their initial capital. If an account demonstrates consistent profitability, uses strict money management, or trades via aggressive scalping/EAs, the broker's risk algorithm automatically flags the account and seamlessly bridges it over to the A-Book. From that point on, the trader's orders are sent directly to the LPs, allowing the broker to earn risk-free commissions while offloading the trader's winning exposure to the broader market.

Re: Why your fill time doesn't match the moment you clicked

Posted: Sat Oct 17, 2026 9:08 am
by PTScalper
You don't need access to a broker's backend servers to prove they are warehousing your trades. Because dealing desks use algorithmic plugins to manage their exposure to profitable traders, their interventions leave unmistakable mathematical signatures in your execution data. By logging the right metrics and analyzing the shape of your execution distribution, you can mathematically separate true market conditions from artificial broker interference.

Re: Why your fill time doesn't match the moment you clicked

Posted: Sat Oct 17, 2026 9:08 am
by PTScalper
1.Log the Baseline Metric Data:

Requires ~200 live trades. Configure your automated strategy or trade logger to record three exact data points for every trade: the exact millisecond the order was sent, the requested price (bid/ask) at that exact moment, and the final confirmed fill price from the broker's execution report.Verification: Your exported CSV contains the Intended Price, Actual Fill Price, and Latency (ms) for a statistically significant sample of trades.

Re: Why your fill time doesn't match the moment you clicked

Posted: Sat Oct 17, 2026 9:08 am
by PTScalper
2.Calculate the Slippage Symmetry Ratio:

The primary B-book indicator. Subtract the Actual Fill Price from the Intended Price to determine your slippage direction per trade. Plot the distribution of positive slippage (price improved in your favor) versus negative slippage (price moved against you).Verification: A fair A-book environment yields a symmetry ratio near 1.0 (a balanced distribution) over time. A ratio heavily skewed to negative slippage with almost zero positive slippage indicates asymmetric dealer filtering.

Re: Why your fill time doesn't match the moment you clicked

Posted: Sat Oct 17, 2026 9:09 am
by PTScalper
3.Profile Latency Against Account Profitability:

Detecting Virtual Dealer Plugins. Graph your average execution latency (in milliseconds) on a timeline alongside your account's equity curve.Verification: If your execution latency experiences a sudden step-up (e.g., jumping from 5ms to 200ms) immediately after your account becomes consistently profitable, you have likely been flagged and moved to a delayed B-book feed.

Re: Why your fill time doesn't match the moment you clicked

Posted: Sat Oct 17, 2026 9:09 am
by PTScalper
4.Run a Parallel Live vs. Demo Control Test

:Isolating environment variables. Run the exact same strategy, with identical parameters and lot sizes, on a Live account and a Demo account simultaneously from the same VPS.Verification: Demo servers simulate near-perfect cosmetic fills. A massive, persistent gap in execution quality and P&L between Demo and Live confirms your live flow is being aggressively managed by a dealing desk.

Re: Why your fill time doesn't match the moment you clicked

Posted: Sat Oct 17, 2026 9:09 am
by PTScalper
5.Test the Volume Risk Threshold:

Scaling test. Gradually scale up your lot size (e.g., from 0.1 to 1.0 lots) while monitoring your rejection and requote rates.Verification: True A-book execution degrades smoothly in relation to order book liquidity depth. If execution is flawless at small sizes but suddenly triggers constant requotes or rejections at a specific size threshold, you have hit the broker's internal risk warehouse limit.

Re: Why your fill time doesn't match the moment you clicked

Posted: Sat Oct 17, 2026 9:13 am
by PTScalper
To accurately measure execution quality, you need to capture the exact market price immediately before the trade request fires and calculate the time elapsed until the broker's server confirms the fill.

Here are the two most precise ways to script this for your VPS, covering both the MT5 and cTrader environments.

Re: Why your fill time doesn't match the moment you clicked

Posted: Sat Oct 17, 2026 9:13 am
by PTScalper
1. The cTrader (C#) Implementation

Because cAlgo runs on the .NET framework, you can bypass platform-specific timers and use System.Diagnostics.Stopwatch for high-resolution latency tracking. This cBot intercepts the market order execution, calculates the slippage drag, and writes directly to a CSV in your Documents folder.

Code: Select all

using System;
using System.Diagnostics;
using System.IO;
using cAlgo.API;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class ExecutionLogger : Robot
    {
        private string _filePath;

        protected override void OnStart()
        {
            // Requires AccessRights.FullAccess to write outside the sandbox
            string docsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            _filePath = Path.Combine(docsPath, "ExecutionLog_cTrader.csv");
            
            if (!File.Exists(_filePath))
                File.AppendAllText(_filePath, "Timestamp,Symbol,Type,IntendedPrice,FillPrice,Slippage(Pips),Latency(ms)\n");
        }

        public void ExecuteTestTrade(TradeType tradeType, double volume)
        {
            double intendedPrice = tradeType == TradeType.Buy ? Symbol.Ask : Symbol.Bid;
            
            Stopwatch sw = Stopwatch.StartNew();
            TradeResult result = ExecuteMarketOrder(tradeType, SymbolName, volume, "LatencyTest");
            sw.Stop();

            if (result.IsSuccessful)
            {
                double fillPrice = result.Position.EntryPrice;
                
                // Positive slippage value indicates a worse fill (cost to you)
                double slippage = tradeType == TradeType.Buy 
                    ? (fillPrice - intendedPrice) 
                    : (intendedPrice - fillPrice);
                
                double slippageInPips = slippage / Symbol.PipSize;

                string logLine = $"{Server.Time:yyyy-MM-dd HH:mm:ss.fff},{SymbolName},{tradeType},{intendedPrice},{fillPrice},{slippageInPips:F1},{sw.ElapsedMilliseconds}\n";
                File.AppendAllText(_filePath, logLine);
            }
        }
    }
}

Re: Why your fill time doesn't match the moment you clicked

Posted: Sat Oct 17, 2026 9:13 am
by PTScalper
2. The MetaTrader 5 (MQL5) Implementation

In MT5, the standard GetTickCount() is only accurate to about 15 milliseconds. To get the microsecond precision required for true ECN/STP execution testing, you must use GetMicrosecondCount() wrapped around the OrderSend function.

Code: Select all

#property strict

int file_handle;

int OnInit() {
    file_handle = FileOpen("ExecutionLog_MT5.csv", FILE_CSV|FILE_READ|FILE_WRITE|FILE_ANSI, ",");
    if(file_handle != INVALID_HANDLE) {
        FileSeek(file_handle, 0, SEEK_END);
        if(FileSize(file_handle) == 0) {
            FileWrite(file_handle, "Timestamp", "Symbol", "Type", "IntendedPrice", "FillPrice", "Slippage(Points)", "Latency(ms)");
        }
    }
    return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason) {
    if(file_handle != INVALID_HANDLE) FileClose(file_handle);
}

void ExecuteTestTrade(ENUM_ORDER_TYPE orderType, double volume) {
    MqlTradeRequest request={0};
    MqlTradeResult result={0};
    
    request.action = TRADE_ACTION_DEAL;
    request.symbol = _Symbol;
    request.volume = volume;
    request.type = orderType;
    request.price = (orderType == ORDER_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_ASK) : SymbolInfoDouble(_Symbol, SYMBOL_BID);
    request.deviation = 50; // Allow slight deviation to ensure the test trade fills
    
    ulong start_time = GetMicrosecondCount();
    bool success = OrderSend(request, result);
    ulong latency_us = GetMicrosecondCount() - start_time;
    
    if(success && result.retcode == TRADE_RETCODE_DONE) {
        double slippage = (orderType == ORDER_TYPE_BUY) ? (result.price - request.price) : (request.price - result.price);
        double slippage_points = slippage / _Point;
        double latency_ms = latency_us / 1000.0;
        
        string timestamp = TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS);
        FileWrite(file_handle, timestamp, _Symbol, EnumToString(orderType), request.price, result.price, slippage_points, latency_ms);
    }
}