//+-----------------------------------------------------------------+ //+------------------------------------------------------------------+ //| AverageTrueSpreadLabel.mq4 | //| Enhanced version with zero errors/warnings| //+------------------------------------------------------------------+ #property strict #property indicator_chart_window //--- input parameters input ENUM_TIMEFRAMES SpreadTimeframe = PERIOD_H1; // Timeframe for simulated spread input int CandlesCount = 20; // Bars for average input int UpdateIntervalSeconds = 5; // Refresh rate input color LabelColor = clrWhite; // Text color input int FontSize = 12; // Font size input string FontName = "Arial"; // Font type input bool ShowLiveSpread = true; // Toggle for live spread display input int LabelCorner = CORNER_LEFT_UPPER; // Chart corner input int LabelXOffset = 10; input int LabelYOffset = 20; input int LabelLineSpacing = 20; // Space between lines //--- label identifiers string avgLabel = "AVG_SPREAD_LABEL"; string liveLabel = "LIVE_SPREAD_LABEL"; string warnLabel = "SPREAD_WARN_LABEL"; //+------------------------------------------------------------------+ //| Initialization | //+------------------------------------------------------------------+ int OnInit() { EventSetTimer(UpdateIntervalSeconds); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Deinitialization | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { EventKillTimer(); ObjectDelete(0, avgLabel); ObjectDelete(0, liveLabel); ObjectDelete(0, warnLabel); } //+------------------------------------------------------------------+ //| Timer-driven label update | //+------------------------------------------------------------------+ void OnTimer() { int m1Bars = iBars(Symbol(), PERIOD_M1); if (m1Bars < CandlesCount + 5) { DrawLabel(warnLabel, "M1 data missing – load M1 chart!", LabelCorner, LabelXOffset, LabelYOffset, clrRed); ObjectDelete(0, avgLabel); ObjectDelete(0, liveLabel); return; } else { ObjectDelete(0, warnLabel); } double avgSpread = CalculateAverageSpread(); double liveSpread = MarketInfo(Symbol(), MODE_SPREAD) / 10.0; string avgText = StringFormat("Avg Spread (%s, %d bars): %.1f pips", EnumToString(SpreadTimeframe), CandlesCount, avgSpread); string liveText = StringFormat("Live Spread: %.1f pips", liveSpread); DrawLabel(avgLabel, avgText, LabelCorner, LabelXOffset, LabelYOffset, LabelColor); if (ShowLiveSpread) DrawLabel(liveLabel, liveText, LabelCorner, LabelXOffset, LabelYOffset + LabelLineSpacing, LabelColor); else ObjectDelete(0, liveLabel); } //+------------------------------------------------------------------+ //| Calculate average simulated spread via M1 bars | //+------------------------------------------------------------------+ double CalculateAverageSpread() { double totalSpread = 0; int counted = 0; datetime startTime = iTime(Symbol(), SpreadTimeframe, 0) - CandlesCount * PeriodSeconds(SpreadTimeframe); int totalBars = iBars(Symbol(), PERIOD_M1); for (int i = 0; i < totalBars && counted < CandlesCount; i++) { datetime barTime = iTime(Symbol(), PERIOD_M1, i); if (barTime < startTime || barTime == 0) break; double high = iHigh(Symbol(), PERIOD_M1, i); double low = iLow(Symbol(), PERIOD_M1, i); if (high == 0 || low == 0) continue; double spread = (high - low) / Point / 10.0; totalSpread += spread; counted++; } if (counted == 0) return 0; return totalSpread / counted; } //+------------------------------------------------------------------+ //| Draw or update text label | //+------------------------------------------------------------------+ void DrawLabel(string name, string text, int corner, int x_offset, int y_offset, color clr) { if (!ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0)) ObjectSetInteger(0, name, OBJPROP_CORNER, corner); ObjectSetInteger(0, name, OBJPROP_CORNER, corner); ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x_offset); ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y_offset); ObjectSetInteger(0, name, OBJPROP_FONTSIZE, FontSize); ObjectSetInteger(0, name, OBJPROP_COLOR, clr); ObjectSetString(0, name, OBJPROP_FONT, FontName); ObjectSetString(0, name, OBJPROP_TEXT, text); } //+------------------------------------------------------------------+ //| Dummy OnCalculate to fulfill compiler requirement | //+------------------------------------------------------------------+ 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[]) { return(rates_total); // no action needed }