Fresh MQL5 code release – perfect for enhancing your MT4/MT5 strategies.
//+------------------------------------------------------------------+ //| SpreadMonitorDemo.mq5 |
//| Copyright 2026, Algosphere |
//| https://algosphere-quant.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, Algosphere"
#property link "https://algosphere-quant.com"
#property version "1.00"
#property description "Demo indicator for SpreadMonitor Library"
#property description "Displays real-time spread statistics and alerts"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 0
//+------------------------------------------------------------------+
//| Includes |
//+------------------------------------------------------------------+
#include "SpreadMonitor.mqh"
//+------------------------------------------------------------------+
//| Input parameters |
//+------------------------------------------------------------------+
input group "=== Display Settings ==="
input int InpPanelX=10; // Panel X Position
input int InpPanelY=30; // Panel Y Position
input color InpBackgroundColor=C'32,32,32'; // Background Color
input color InpTextColor=clrWhite; // Text Color
input group "=== Spread Thresholds (Pips) ==="
input double InpLowThreshold=1.0; // Low Spread Threshold
input double InpNormalThreshold=2.0; // Normal Spread Threshold
input double InpHighThreshold=5.0; // High Spread Threshold
input group "=== Filter Settings ==="
input double InpMaxSpread=3.0; // Maximum Acceptable Spread
input int InpHistorySize=500; // History Size (samples)
input group "=== Alert Settings ==="
input bool InpAlertOnHigh=true; // Alert on High Spread
input bool InpAlertOnExtreme=true; // Alert on Extreme Spread
//+------------------------------------------------------------------+
//| Defines |
//+------------------------------------------------------------------+
#define PREFIX "SPM_"
#define PANEL_WIDTH 200
#define PANEL_HEIGHT 230
#define ROW_SPACING 18
//+------------------------------------------------------------------+
//| Global variables |
//+------------------------------------------------------------------+
CSpreadMonitor g_spread_monitor;
double g_spread_buffer[];
ENUM_SPREAD_CONDITION g_last_condition=SPREAD_LOW;
datetime g_last_alert_time=0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- Initialize spread monitor
if(!g_spread_monitor.Init(_Symbol,InpHistorySize,
InpLowThreshold,InpNormalThreshold,InpHighThreshold))
{
Print("Error: Failed to initialize SpreadMonitor");
return(INIT_FAILED);
}
//--- Set indicator buffer (not plotted, just for data storage)
SetIndexBuffer(0,g_spread_buffer,INDICATOR_CALCULATIONS);
//--- Create panel
CreatePanel();
//--- Initial update
g_spread_monitor.Update();
UpdatePanel();
//--- Set timer for frequent updates
EventSetMillisecondTimer(250);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
EventKillTimer();
ObjectsDeleteAll(0,PREFIX);
}
//+------------------------------------------------------------------+
//| Timer function - updates spread display |
//+------------------------------------------------------------------+
void OnTimer()
{
//--- Record spread sample
g_spread_monitor.Update();
//--- Update display
UpdatePanel();
//--- Check for alerts
CheckAlerts();
}
//+------------------------------------------------------------------+
//| 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[])
{
//--- Store current spread
if(rates_total>0)
g_spread_buffer[rates_total-1]=g_spread_monitor.GetCurrentSpread();
return(rates_total);
}
//+------------------------------------------------------------------+
//| Check and trigger alerts |
//+------------------------------------------------------------------+
void CheckAlerts()
{
ENUM_SPREAD_CONDITION current_condition=g_spread_monitor.GetSpreadCondition();
//--- Only alert on condition change to avoid spam
if(current_condition==g_last_condition)
return;
//--- Check if enough time passed since last alert (30 seconds)
if(TimeCurrent()-g_last_alert_time<30)
return;
//--- Alert on high spread
if(InpAlertOnHigh && current_condition==SPREAD_HIGH && g_last_condition<SPREAD_HIGH)
{
Alert(_Symbol," - HIGH SPREAD: ",DoubleToString(g_spread_monitor.GetCurrentSpread(),1)," pips");
g_last_alert_time=TimeCurrent();
}
//--- Alert on extreme spread
if(InpAlertOnExtreme && current_condition==SPREAD_EXTREME && g_last_condition<SPREAD_EXTREME)
{
Alert(_Symbol," - EXTREME SPREAD: ",DoubleToString(g_spread_monitor.GetCurrentSpread(),1)," pips!");
g_last_alert_time=TimeCurrent();
}
g_last_condition=current_condition;
}
//+------------------------------------------------------------------+
//| Create information panel |
//+------------------------------------------------------------------+
void CreatePanel()
{
int x=InpPanelX;
int y=InpPanelY;
//--- Background
CreateRectangleLabel(PREFIX+"Background",x,y,PANEL_WIDTH,PANEL_HEIGHT,
InpBackgroundColor,C'60,60,60');
//--- Title
CreateTextLabel(PREFIX+"Title",x+10,y+8,"SPREAD MONITOR",
InpTextColor,11,"Arial Bold");
//--- Symbol
CreateTextLabel(PREFIX+"Symbol",x+PANEL_WIDTH-60,y+10,_Symbol,
clrDodgerBlue,9,"Arial");
//--- Separator
CreateRectangleLabel(PREFIX+"Sep1",x+10,y+30,PANEL_WIDTH-20,1,
clrDimGray,clrDimGray);
int row_y=y+40;
//--- Current spread (large display)
CreateTextLabel(PREFIX+"LblCurrent",x+15,row_y,"Current:",clrGray,9,"Arial");
CreateTextLabel(PREFIX+"ValCurrent",x+80,row_y,"0.0",clrLime,14,"Arial Bold");
CreateTextLabel(PREFIX+"UnitCurrent",x+130,row_y,"pips",clrGray,9,"Arial");
row_y+=24;
//--- Condition
CreateTextLabel(PREFIX+"LblCondition",x+15,row_y,"Status:",clrGray,9,"Arial");
CreateTextLabel(PREFIX+"ValCondition",x+80,row_y,"LOW",clrLime,10,"Arial Bold");
row_y+=ROW_SPACING+5;
//--- Separator
CreateRectangleLabel(PREFIX+"Sep2",x+10,row_y,PANEL_WIDTH-20,1,
clrDimGray,clrDimGray);
row_y+=10;
//--- Statistics section
CreateTextLabel(PREFIX+"LblStats",x+15,row_y,"Statistics",clrWhite,9,"Arial Bold");
row_y+=ROW_SPACING;
CreateTextLabel(PREFIX+"LblAvg",x+15,row_y,"Average:",clrGray,9,"Arial");
CreateTextLabel(PREFIX+"ValAvg",x+100,row_y,"0.0 pips",InpTextColor,9,"Arial");
row_y+=ROW_SPACING;
CreateTextLabel(PREFIX+"LblMin",x+15,row_y,"Minimum:",clrGray,9,"Arial");
CreateTextLabel(PREFIX+"ValMin",x+100,row_y,"0.0 pips",clrLime,9,"Arial");
row_y+=ROW_SPACING;
CreateTextLabel(PREFIX+"LblMax",x+15,row_y,"Maximum:",clrGray,9,"Arial");
CreateTextLabel(PREFIX+"ValMax",x+100,row_y,"0.0 pips",clrOrange,9,"Arial");
row_y+=ROW_SPACING;
//--- Separator
CreateRectangleLabel(PREFIX+"Sep3",x+10,row_y+5,PANEL_WIDTH-20,1,
clrDimGray,clrDimGray);
row_y+=15;
//--- Filter status
CreateTextLabel(PREFIX+"LblFilter",x+15,row_y,"Trade Filter:",clrGray,9,"Arial");
CreateTextLabel(PREFIX+"ValFilter",x+100,row_y,"ALLOW",clrLime,9,"Arial Bold");
row_y+=ROW_SPACING;
//--- Samples
CreateTextLabel(PREFIX+"LblSamples",x+15,row_y,"Samples:",clrGray,9,"Arial");
CreateTextLabel(PREFIX+"ValSamples",x+100,row_y,"0",clrGray,9,"Arial");
ChartRedraw();
}
//+------------------------------------------------------------------+
//| Update panel values |
//+------------------------------------------------------------------+
void UpdatePanel()
{
//--- Get statistics
SSpreadStats stats=g_spread_monitor.GetStatistics();
//--- Update current spread
ObjectSetString(0,PREFIX+"ValCurrent",OBJPROP_TEXT,
DoubleToString(stats.current,1));
ObjectSetInteger(0,PREFIX+"ValCurrent",OBJPROP_COLOR,
g_spread_monitor.GetConditionColor(stats.condition));
//--- Update condition
ObjectSetString(0,PREFIX+"ValCondition",OBJPROP_TEXT,
g_spread_monitor.GetConditionName(stats.condition));
ObjectSetInteger(0,PREFIX+"ValCondition",OBJPROP_COLOR,
g_spread_monitor.GetConditionColor(stats.condition));
//--- Update statistics
ObjectSetString(0,PREFIX+"ValAvg",OBJPROP_TEXT,
DoubleToString(stats.average,1)+" pips");
ObjectSetString(0,PREFIX+"ValMin",OBJPROP_TEXT,
DoubleToString(stats.minimum,1)+" pips");
ObjectSetString(0,PREFIX+"ValMax",OBJPROP_TEXT,
DoubleToString(stats.maximum,1)+" pips");
//--- Update filter status
bool acceptable=g_spread_monitor.IsSpreadAcceptable(InpMaxSpread);
ObjectSetString(0,PREFIX+"ValFilter",OBJPROP_TEXT,
acceptable ? "ALLOW" : "BLOCK");
ObjectSetInteger(0,PREFIX+"ValFilter",OBJPROP_COLOR,
acceptable ? clrLime : clrRed);
//--- Update samples count
ObjectSetString(0,PREFIX+"ValSamples",OBJPROP_TEXT,
IntegerToString(stats.sample_count));
ChartRedraw();
}
//+------------------------------------------------------------------+
//| Create text label |
//+------------------------------------------------------------------+
void CreateTextLabel(const string name,
const int x,
const int y,
const string text,
const color clr,
const int font_size,
const string font_name)
{
if(ObjectFind(0,name)>=0)
ObjectDelete(0,name);
if(!ObjectCreate(0,name,OBJ_LABEL,0,0,0))
return;
ObjectSetInteger(0,name,OBJPROP_XDISTANCE,x);
ObjectSetInteger(0,name,OBJPROP_YDISTANCE,y);
ObjectSetInteger(0,name,OBJPROP_CORNER,CORNER_LEFT_UPPER);
ObjectSetString(0,name,OBJPROP_TEXT,text);
ObjectSetInteger(0,name,OBJPROP_COLOR,clr);
ObjectSetInteger(0,name,OBJPROP_FONTSIZE,font_size);
ObjectSetString(0,name,OBJPROP_FONT,font_name);
ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false);
ObjectSetInteger(0,name,OBJPROP_HIDDEN,true);
}
//+------------------------------------------------------------------+
//| Create rectangle label |
//+------------------------------------------------------------------+
void CreateRectangleLabel(const string name,
const int x,
const int y,
const int width,
const int height,
const color bg_color,
const color border_color)
{
if(ObjectFind(0,name)>=0)
ObjectDelete(0,name);
if(!ObjectCreate(0,name,OBJ_RECTANGLE_LABEL,0,0,0))
return;
ObjectSetInteger(0,name,OBJPROP_XDISTANCE,x);
ObjectSetInteger(0,name,OBJPROP_YDISTANCE,y);
ObjectSetInteger(0,name,OBJPROP_XSIZE,width);
ObjectSetInteger(0,name,OBJPROP_YSIZE,height);
ObjectSetInteger(0,name,OBJPROP_CORNER,CORNER_LEFT_UPPER);
ObjectSetInteger(0,name,OBJPROP_BGCOLOR,bg_color);
ObjectSetInteger(0,name,OBJPROP_BORDER_COLOR,border_color);
ObjectSetInteger(0,name,OBJPROP_BORDER_TYPE,BORDER_FLAT);
ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false);
ObjectSetInteger(0,name,OBJPROP_HIDDEN,true);
}
//+------------------------------------------------------------------+
Grid trading done right – try the robust Grid Expert Advisor for controlled risk. Details here.
Thanks for reading. Discover premium MetaTrader solutions at RobotFX.
69096