Re: cTrader liquidity differences that showed up in my gold log
Posted: Sat Sep 19, 2026 10:25 pm
To ensure your data remains perfectly aligned with London cash hours regardless of your broker's server time zone or seasonal Daylight Saving Time shifts, this adaptation logs execution timestamps in strict GMT (TimeGMT()).
I’ve structured the file I/O to use the FILE_COMMON flag. This saves the CSV to your shared Terminal Common/Files directory, making it immediately accessible for data analysis without having to dig through isolated instance folders.
I’ve structured the file I/O to use the FILE_COMMON flag. This saves the CSV to your shared Terminal Common/Files directory, making it immediately accessible for data analysis without having to dig through isolated instance folders.
Code: Select all
//+------------------------------------------------------------------+
//| Background_Execution_Logger.mq5 |
//+------------------------------------------------------------------+
#property copyright "Execution Logger"
#property version "1.10"
input string InpFileName = "Liquidity_Sweeps_Log.csv";
int fileHandle = INVALID_HANDLE;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Open file in common folder so it's easily accessible and shared
// FILE_COMMON saves to: %APPDATA%\MetaQuotes\Terminal\Common\Files
fileHandle = FileOpen(InpFileName, FILE_READ | FILE_WRITE | FILE_CSV | FILE_ANSI | FILE_COMMON, ',');
if(fileHandle != INVALID_HANDLE)
{
if(FileSize(fileHandle) == 0)
{
// Write headers if file is new
FileWrite(fileHandle, "GMT_Time", "Local_Ms_Tick", "Symbol", "Action", "Requested_Price", "Fill_Price", "Slippage_Points", "Volume", "Deal_Ticket");
}
// Move pointer to the end of the file for rolling append
FileSeek(fileHandle, 0, SEEK_END);
Print("Background Execution Logger Initialized. Writing to Common/Files/", InpFileName);
}
else
{
Print("Error opening file: ", GetLastError());
return(INIT_FAILED);
}
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(fileHandle != INVALID_HANDLE)
{
FileClose(fileHandle);
Print("Execution Logger file closed.");
}
}
//+------------------------------------------------------------------+
//| TradeTransaction function |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
const MqlTradeRequest &request,
const MqlTradeResult &result)
{
if(trans.type != TRADE_TRANSACTION_DEAL_ADD)
return;
ulong dealTicket = trans.deal;
if(HistoryDealSelect(dealTicket))
{
ulong orderTicket = HistoryDealGetInteger(dealTicket, DEAL_ORDER);
if(HistoryOrderSelect(orderTicket))
{
string symbol = HistoryDealGetString(dealTicket, DEAL_SYMBOL);
double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
if(point == 0) return;
ENUM_ORDER_TYPE orderType = (ENUM_ORDER_TYPE)HistoryOrderGetInteger(orderTicket, ORDER_TYPE);
long orderReason = HistoryOrderGetInteger(orderTicket, ORDER_REASON);
double requestedPrice = HistoryOrderGetDouble(orderTicket, ORDER_PRICE_OPEN);
double fillPrice = HistoryDealGetDouble(dealTicket, DEAL_PRICE);
double volume = HistoryDealGetDouble(dealTicket, DEAL_VOLUME);
double slippagePoints = 0;
if(orderType == ORDER_TYPE_BUY || orderType == ORDER_TYPE_BUY_STOP || orderType == ORDER_TYPE_BUY_LIMIT || orderType == ORDER_TYPE_BUY_STOP_LIMIT)
{
slippagePoints = (fillPrice - requestedPrice) / point;
}
else if(orderType == ORDER_TYPE_SELL || orderType == ORDER_TYPE_SELL_STOP || orderType == ORDER_TYPE_SELL_LIMIT || orderType == ORDER_TYPE_SELL_STOP_LIMIT)
{
slippagePoints = (requestedPrice - fillPrice) / point;
}
string orderTypeStr = EnumToString(orderType);
if(orderReason == ORDER_REASON_SL) orderTypeStr = "STOP_LOSS";
else if(orderReason == ORDER_REASON_TP) orderTypeStr = "TAKE_PROFIT";
// Format timestamp for London hour alignment (GMT baseline)
datetime timeGMT = TimeGMT();
string timeStr = TimeToString(timeGMT, TIME_DATE | TIME_SECONDS);
ulong localMs = GetMicrosecondCount() / 1000; // Track millisecond pacing
// Append row to CSV
if(fileHandle != INVALID_HANDLE)
{
FileWrite(fileHandle, timeStr, localMs, symbol, orderTypeStr, requestedPrice, fillPrice, slippagePoints, volume, dealTicket);
// Force write to disk immediately. Prevents data loss if the terminal crashes
// or connection is lost during high-frequency liquidity events.
FileFlush(fileHandle);
}
PrintFormat("LOGGED -> %s | Vol: %.2f | Slippage: %.1f pts", symbol, volume, slippagePoints);
}
}
}