Save this file as ScalpFrictionCheck.mq5 in your MT5 MQL5/Indicators directory.
Code: Select all
//+------------------------------------------------------------------+
//| ScalpFrictionCheck.mq5 |
//| All-In Cost & Scalp Friction |
//+------------------------------------------------------------------+
#property copyright "Assistant"
#property link ""
#property version "1.00"
#property indicator_chart_window
#property indicator_plots 0
// --- Input Parameters ---
input group "=== Scalp Parameters ==="
input double InpTargetPips = 5.0; // Scalp Target (Pips)
input double InpCommRoundTurn = 7.0; // Commission ($ RT per 100k Lot)
input double InpPipValueUSD = 10.0; // Pip Value ($ per 100k Lot)
input group "=== Spread Mode ==="
input bool InpUseLiveSpread = false; // Use Real-Time Broker Spread? (false = Sheet Median)
input double InpManualSpread = 0.1; // Tracked Median Spread (Pips)
input group "=== HUD Display ==="
input ENUM_BASE_CORNER InpCorner = CORNER_RIGHT_UPPER; // Screen Corner
input int InpXOffset = 20; // X Offset (px)
input int InpYOffset = 30; // Y Offset (px)
input int InpFontSize = 10; // Font Size
input color InpNormalColor = clrWhite;
input color InpWarningColor = clrCrimson;
input color InpPassColor = clrMediumSeaGreen;
#define PREFIX "SFC5_"
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
ObjectsDeleteAll(0, PREFIX);
ChartRedraw(0);
}
//+------------------------------------------------------------------+
//| Pip Size Determination |
//+------------------------------------------------------------------+
double GetPipPoint()
{
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
double pt = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
if(digits == 3 || digits == 5) return(pt * 10.0);
return(pt);
}
//+------------------------------------------------------------------+
//| 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[])
{
double pipPoint = GetPipPoint();
double currentSpreadPips = 0.0;
if(InpUseLiveSpread)
{
MqlTick lastTick;
if(SymbolInfoTick(_Symbol, lastTick))
{
double rawSpread = lastTick.ask - lastTick.bid;
currentSpreadPips = (pipPoint > 0) ? (rawSpread / pipPoint) : 0.0;
}
}
else
{
currentSpreadPips = InpManualSpread;
}
// Normalized Commission in Pips
double commPips = (InpPipValueUSD > 0) ? (InpCommRoundTurn / InpPipValueUSD) : 0.0;
double allInCostPips = currentSpreadPips + commPips;
// Friction Ratio (% of Target consumed by friction)
double frictionRatio = (InpTargetPips > 0) ? (allInCostPips / InpTargetPips) * 100.0 : 0.0;
double grossTargetRequired = InpTargetPips + allInCostPips;
// Update Dashboard HUD
RenderHUD(currentSpreadPips, commPips, allInCostPips, frictionRatio, grossTargetRequired);
return(rates_total);
}
//+------------------------------------------------------------------+
//| Draw or Update HUD Label |
//+------------------------------------------------------------------+
void UpdateLabel(string name, string text, int x, int y, color clr, int fontSize, bool isBold = false)
{
string objName = PREFIX + name;
if(ObjectFind(0, objName) < 0)
{
ObjectCreate(0, objName, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, objName, OBJPROP_CORNER, InpCorner);
ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, y);
ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, objName, OBJPROP_HIDDEN, true);
}
ObjectSetString(0, objName, OBJPROP_TEXT, text);
ObjectSetString(0, objName, OBJPROP_FONT, isBold ? "Arial Bold" : "Arial");
ObjectSetInteger(0, objName, OBJPROP_FONTSIZE, fontSize);
ObjectSetInteger(0, objName, OBJPROP_COLOR, clr);
}
//+------------------------------------------------------------------+
//| Render HUD Lines |
//+------------------------------------------------------------------+
void RenderHUD(double spreadPips, double commPips, double allIn, double friction, double gross)
{
int y = InpYOffset;
int step = InpFontSize + 8;
color frictionColor = (friction > 20.0) ? InpWarningColor : InpPassColor;
UpdateLabel("H1", "=== VENUE FRICTION CHECK ===", InpXOffset, y, clrSilver, InpFontSize, true);
y += step;
string spreadSource = InpUseLiveSpread ? "[Live]" : "[Sheet]";
UpdateLabel("L1", "Spread " + spreadSource + ": " + DoubleToString(spreadPips, 2) + " pips", InpXOffset, y, InpNormalColor, InpFontSize);
y += step;
UpdateLabel("L2", "Commission: " + DoubleToString(commPips, 2) + " pips", InpXOffset, y, InpNormalColor, InpFontSize);
y += step;
UpdateLabel("L3", "All-In Drag: " + DoubleToString(allIn, 2) + " pips", InpXOffset, y, InpNormalColor, InpFontSize);
y += step;
UpdateLabel("L4", "Friction: " + DoubleToString(friction, 1) + "% of " + DoubleToString(InpTargetPips, 1) + "p Target", InpXOffset, y, frictionColor, InpFontSize, true);
y += step;
UpdateLabel("L5", "Required Move: " + DoubleToString(gross, 2) + " pips", InpXOffset, y, InpNormalColor, InpFontSize);
}