Page 2 of 2

Re: Broker scorecard quarterly update: spreads, rejects, and uptime

Posted: Mon Sep 14, 2026 10:05 pm
by FTtrader
The Analytical Edge with cAlgo

cTrader generally routes through superior liquidity hubs compared to vanilla MT4 servers, meaning your limit orders and take-profits should logically experience a higher frequency of positive slippage.

When you parse this generated CSV for your Q4 scorecard update, run a quick pivot table comparing Latency_ms against Slippage_Pips. If you detect a structural correlation—for example, latency spiking from 30ms to 400ms exclusively when adverse slippage exceeds 0.5 pips—it provides empirical proof that the liquidity provider is employing a "last look" latency plugin to front-run your M1 sweeps.

Re: Broker scorecard quarterly update: spreads, rejects, and uptime

Posted: Mon Sep 14, 2026 10:06 pm
by FTtrader
To elevate this to an institutional standard, we must address a critical architectural flaw present in most retail execution trackers: I/O thread blocking.

Writing synchronously to a disk (File.AppendAllText) immediately after an order execution pollutes the hardware timer and locks the primary trading thread. In an M1 scalping environment where microstructure edges are measured in milliseconds, executing I/O operations on the hot path artificially inflates latency metrics and delays subsequent algorithmic logic.

A production-grade solution decouples the execution event from the logging mechanism. We achieve this by pushing execution telemetry into a thread-safe ConcurrentQueue on the main thread, and asynchronously flushing it to disk via an independent timer loop.

Re: Broker scorecard quarterly update: spreads, rejects, and uptime

Posted: Mon Sep 14, 2026 10:06 pm
by FTtrader
Enterprise Microstructure Auditor (C# cAlgo)

This architecture ensures zero latency drag on the execution thread, utilizes high-resolution hardware timers, and formats output for immediate parsing into a quantitative scorecard.

Code: Select all

using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Collections.Concurrent;
using cAlgo.API;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FileSystem)]
    public class InstitutionalExecutionAuditor : Robot
    {
        [Parameter("Audit Log Filename", DefaultValue = "cTrader_Microstructure_Audit.csv")]
        public string LogFileName { get; set; }

        private string _filePath;
        private readonly ConcurrentQueue<string> _telemetryQueue = new ConcurrentQueue<string>();
        
        // Timer for high-resolution profiling
        private readonly Stopwatch _executionTimer = new Stopwatch();

        protected override void OnStart()
        {
            string docPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            _filePath = Path.Combine(docPath, LogFileName);

            InitializeScorecardEngine();

            // Offload disk I/O to a background timer (every 2 seconds)
            Timer.Start(2);
            
            Print($"[ENGINE] Microstructure Auditor active. I/O decoupled.");
        }

        private void InitializeScorecardEngine()
        {
            if (!File.Exists(_filePath))
            {
                string header = "Timestamp_UTC,Symbol,Type,Latency_ms,Intended_Px,Filled_Px,Slip_Pips,Spread_Pips,Order_State\n";
                File.WriteAllText(_filePath, header);
            }
        }

        // =========================================================================
        // HOT PATH: SYNCHRONOUS EXECUTION WRAPPER
        // =========================================================================
        public void ExecuteAuditedOrder(TradeType direction, double volume)
        {
            // 1. Capture snapshot of liquidity strictly prior to FIX dispatch
            double intendedPx = direction == TradeType.Buy ? Symbol.Ask : Symbol.Bid;
            double spreadPips = (Symbol.Ask - Symbol.Bid) / Symbol.PipSize;

            // 2. Hardware-level latency profiling
            _executionTimer.Restart();
            
            // 3. Dispatch to Liquidity Provider
            TradeResult result = ExecuteMarketOrder(direction, SymbolName, volume, "Inst_Audit");
            
            _executionTimer.Stop();
            double latencyMs = _executionTimer.Elapsed.TotalMilliseconds;

            // 4. Calculate Execution Drag
            if (result.IsSuccessful)
            {
                double filledPx = result.Position.EntryPrice;
                double slipPips = direction == TradeType.Buy 
                    ? (filledPx - intendedPx) / Symbol.PipSize 
                    : (intendedPx - filledPx) / Symbol.PipSize;

                QueueTelemetry(direction, latencyMs, intendedPx, filledPx, slipPips, spreadPips, "FILLED");
            }
            else
            {
                QueueTelemetry(direction, latencyMs, intendedPx, 0, 0, spreadPips, $"REJECT_{result.Error}");
            }
        }

        // =========================================================================
        // TELEMETRY QUEUEING (NON-BLOCKING)
        // =========================================================================
        private void QueueTelemetry(TradeType dir, double lat, double req, double fill, double slip, double spread, string state)
        {
            string record = $"{Server.Time:yyyy-MM-dd HH:mm:ss.fff},{SymbolName},{dir},{lat:F2},{req},{fill},{slip:F2},{spread:F2},{state}";
            _telemetryQueue.Enqueue(record);
        }

        // =========================================================================
        // BACKGROUND I/O FLUSH
        // =========================================================================
        protected override void OnTimer()
        {
            if (_telemetryQueue.IsEmpty) return;

            var sb = new StringBuilder();
            while (_telemetryQueue.TryDequeue(out string record))
            {
                sb.AppendLine(record);
            }

            try
            {
                File.AppendAllText(_filePath, sb.ToString());
            }
            catch (Exception ex)
            {
                Print($"[I/O FAULT] Failed to flush telemetry: {ex.Message}");
            }
        }

        // =========================================================================
        // LIGHTWEIGHT TERMINAL UI
        // =========================================================================
        protected override void OnTick()
        {
            double spread = (Symbol.Ask - Symbol.Bid) / Symbol.PipSize;
            Chart.DrawStaticText("micro_dash", 
                $"INSTITUTIONAL AUDITOR\nSpread: {spread:F1} pips\nQueue Depth: {_telemetryQueue.Count}", 
                VerticalAlignment.Top, HorizontalAlignment.Right, Color.DimGray);
        }
    }
}

Re: Broker scorecard quarterly update: spreads, rejects, and uptime

Posted: Mon Sep 14, 2026 10:07 pm
by FTtrader
Analyzing the Microstructure Data

Once this runs through a quarter of high-volume overlaps, you bypass traditional platform analytics and construct a rigid scatter plot: Execution Latency (X-axis) vs. Adverse Slippage (Y-axis).

The "Last Look" Signature: If you observe a cluster of rejected orders or heavy negative slippage exclusively when Latency_ms exceeds ~150-200ms, the broker's liquidity provider is utilizing a "last look" holding window. They are pausing the execution to verify if the M1 price action moves against them before confirming your fill.

The True DMA Profile: A genuine STP/ECN environment will exhibit sub-50ms execution times regardless of market volatility, and the slippage distribution will resemble a standard bell curve (equal occurrences of positive and negative slippage).

Re: Broker scorecard quarterly update: spreads, rejects, and uptime

Posted: Tue Sep 15, 2026 9:41 am
by LondonScalper
FTtrader wrote:The broker-choice breaker was asymmetric slippage during the London/NY overlap: one broker had a 0.2-pip median spread but 0.8-pip p95 slippage and 8% rejects, while a 0.5-pip DMA broker had about 0.1-pip p95 slippage and positive slippage.
That’s exactly why raw median spread loses the scorecard. Missed or skewed fills on the overlap cost more EV than a few tenths of advertised spread.

My quarterly sheet weights p95 market-order slippage and reject/requote rate ahead of median spread. Fill feel and outage minutes sit next. A tight top-of-book that rejects 8% of tickets is a marketing quote, not an execution venue.

Desk process: I sample the same 20–30 overlap tickets per broker each quarter, side-aware, and tag positive versus adverse slip separately. Asymmetry shows up fast once you stop averaging the good fills with the bad ones.

Rule: all-in cost = p95 slip + rejects; median spread is a footnote. How many overlap samples do you need before you kill a broker on the scorecard — one bad week, or a full quarter of skewed p95?

Re: Broker scorecard quarterly update: spreads, rejects, and uptime

Posted: Mon Sep 21, 2026 6:11 pm
by LondonNewsTrader
FTtrader wrote:I stopped arguing about brokers from memory. Once a quarter I update a simple scorecard from my logs. Columns that matter for scalping • Median spread by pair + session (London / overlap) • p95 slippage on market orders • Reject / requote count
This is how broker talk should sound — logs, not slogans.

I keep the same quarterly habit, with one extra cut: scorecard rows split calm London hours versus the first five minutes after Tier-1 US data. A house that looks pristine on a quiet Tuesday can still be unusable on CPI. p95 slip versus median spread is the right comparison; if slip dominates, your "tight spread" marketing is theatre.

Rejects and time-to-fill into red folders decide whether I even leave working orders up. Argument-from-memory is how people stay loyal to a venue that has been taxing them for months.

Are you weighting London and overlap separately for each pair, or rolling one session average that hides the Friday cross problem?

Re: Broker scorecard quarterly update: spreads, rejects, and uptime

Posted: Thu Sep 24, 2026 3:45 am
by PropScalpDesk
FTtrader wrote:Moving this execution tracker into cTrader provides a massive architectural advantage. Because cAlgo runs natively on the .NET framework, you can bypass proprietary platform timers entirely and utilize OS-level hardware counters for high-resolution latency tracking. By leveraging System.Diagnostics.
Broker scorecards are quarterly work here: spread, reject, slip into London and into red folders. Marketing averages are not a scorecard.

Prop execution quality is part of edge.

What three numbers make your shortlist?

I also log refused tickets so flat time counts as work — otherwise the desk invents activity.

I would rather log a refused ticket than invent activity for the journal.

I write the walk-away before London so it is not negotiated mid-tape.

If the idea needs a story longer than one line, it waits for another window.

Topic note from my sheet for t=12325: keep risk unchanged until the sample says otherwise.

Re: Broker scorecard quarterly update: spreads, rejects, and uptime

Posted: Thu Oct 15, 2026 4:42 pm
by FXS Prop Desk
Asymmetric slippage is one of the most useful metrics in a broker scorecard. Readers can check it with a simple export: for each market order, compute fill price minus requested price, split into positive and negative, and compare counts and sizes.

In normal conditions a fair execution model shows both directions. If positive slippage never appears while negative slippage is common, that's a strong signal regardless of how tight the advertised spread is. It's also worth separating news periods from normal hours, since both sides widen during releases.