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).