Save this script as TrueExecutionCost.mq4 inside your MT4 MQL4/Indicators/ directory.
Code: Select all
#property copyright "Custom"
#property link ""
#property version "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1 clrGray
#property indicator_color2 clrOrange
#property indicator_width1 1
#property indicator_width2 2
#property indicator_label1 "Raw Spread (Pips)"
#property indicator_label2 "All-In Cost (Pips)"
//--- Inputs
input string InpCostsGroup = "--- Cost Settings ---";
input double InpCommissionPerLot = 6.0; // Round-turn Commission per Lot ($)
input double InpPipValuePerLot = 10.0; // Pip Value per Lot ($)
input string InpTimeGroup = "--- Time Offset (Hours) ---";
input int InpBrokerGmtOffset = 2; // Broker Server GMT Offset (e.g., 2 or 3)
input int InpLondonGmtOffset = 0; // London GMT Offset (0 in Winter, 1 in Summer)
//--- Buffers
double SpreadBuffer[];
double AllInCostBuffer[];
double g_pipSize;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
IndicatorDigits(2);
SetIndexBuffer(0, SpreadBuffer);
SetIndexStyle(0, DRAW_LINE);
SetIndexBuffer(1, AllInCostBuffer);
SetIndexStyle(1, DRAW_LINE);
// Determine 1 pip based on instrument digits
g_pipSize = (_Digits == 3 || _Digits == 5) ? _Point * 10.0 : _Point;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Comment(""); // Clear chart HUD
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
if(rates_total <= 0 || g_pipSize <= 0) return(0);
// Only calculate on live incoming ticks
int lastBar = rates_total - 1;
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double commPips = (InpPipValuePerLot > 0) ? (InpCommissionPerLot / InpPipValuePerLot) : 0.0;
double currentSpread = (ask - bid) / g_pipSize;
double allInCost = currentSpread + commPips;
SpreadBuffer[lastBar] = currentSpread;
AllInCostBuffer[lastBar] = allInCost;
// Update HUD Dashboard
UpdateDashboard(currentSpread, commPips, allInCost);
return(rates_total);
}
//+------------------------------------------------------------------+
//| Session Evaluation & Dashboard HUD |
//+------------------------------------------------------------------+
void UpdateDashboard(double spread, double comm, double totalCost)
{
datetime serverTime = TimeCurrent();
datetime londonTime = serverTime - (InpBrokerGmtOffset * 3600) + (InpLondonGmtOffset * 3600);
MqlDateTime dt;
TimeToStruct(londonTime, dt);
int totalMinutes = (dt.hour * 60) + dt.min;
string sessionText = "Off-Peak / Outside Window";
// Asian Session: 00:30 (30m) to 03:00 (180m)
if(totalMinutes >= 30 && totalMinutes <= 180)
sessionText = "Asian (00:30 - 03:00 London)";
// London Session: 07:00 (420m) to 10:00 (600m)
else if(totalMinutes >= 420 && totalMinutes <= 600)
sessionText = "London (07:00 - 10:00 London)";
string dashboard = StringFormat(
"=== TRUE EXECUTION COST ===\n" +
"Session Window : %s\n" +
"London Time : %02d:%02d\n" +
"Real-Time Spread : %.2f pips\n" +
"Commission (RT) : %.2f pips\n" +
"Total All-In Cost: %.2f pips",
sessionText, dt.hour, dt.min, spread, comm, totalCost
);
Comment(dashboard);
}