[Free Source Code] Multi‑TF Linear Regression HUD (Canvas) – Trend Strength, σ Deviation, Candle Count Dashboard
//+------------------------------------------------------------------+ //| TrendlineHD_Hybrid_Wide_V2.mq5 | //| Copyright 2026, Trading Tools | //+------------------------------------------------------------------+ #property copyright "Copyright 2026, Trading Tools" #property version "1.20" #property indicator_chart_window #property indicator_plots 0 #include <Canvas\Canvas.mqh> //+------------------------------------------------------------------+ //| Linear Regression Calculation (slope, intercept, sigma) | //+------------------------------------------------------------------+ bool CalcLinearRegression(const double &close[], int period, bool reverseX, double &slope, double &intercept, double &sigma) { if(ArraySize(close) < period) return false; double sumX=0, sumY=0, sumXY=0, sumX2=0; for(int i=0; i<period; i++) { double x = reverseX ? (period - 1 - i) : i; double y = close[i]; sumX += x; sumY += y; sumXY += x * y; sumX2 += x * x; } double denom = (period * sumX2 - sumX * sumX); if(denom == 0.0) return false; slope = (period * sumXY - sumX * sumY) / denom; intercept = (sumY - slope * sumX) / period; double sumRes = 0; for(int j=0; j<period; j++) { double x = reverseX ? (period - 1 - j) : j; double fit = intercept + slope * x; double res = close[j] - fit; sumRes += res * res; } sigma = MathSqrt(sumRes / period); return true; } //--- HUD input parameters input int InpPeriod1Len = 20; // Period 1 length input int InpPeriod2Len = 50; // Period 2 length input int InpPeriod3Len = 100; // Period 3 length input int InpCountLen = 10; // Candle count window (bull/bear count) input double InpDev = 2.0; // Deviation multiplier (σ) input int InpX = 10; // HUD initial X position input int InpY = 25; // HUD initial Y position //--- Regression line drawing parameters input bool show = true; // Master switch: show/hide all regression lines input bool show1 = true; // Show Line 1 input bool show2 = true; // Show Line 2 input bool show3 = true; // Show Line 3 input bool extend1 = false; // Extend Line 1 to the right input bool extend2 = false; // Extend Line 2 to the right input bool extend3 = false; // Extend Line 3 to the right input color line1Color = clrYellow; // Color for Line 1 input color line2Color = clrGreen; // Color for Line 2 input color line3Color = clrRed; // Color for Line 3 input double BandMultiplier = 2.0; // Standard deviation band multiplier //--- Button display parameters input int btnX = 80; // Button X offset input int btnY = 30; // Button Y offset input ENUM_BASE_CORNER btnCorner = CORNER_RIGHT_UPPER; // Button anchor corner //--- Internal HUD settings CCanvas m_canvas; string m_name = "LR_HUD_Canvas_V2"; int m_width = 280; int m_height = 125; int m_row_h = 18; string m_tf_names[5] = {"M1","M5","M15","M30","H1"}; // Displayed timeframes ENUM_TIMEFRAMES m_tfs[5] = {PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1}; int m_periods[3]; // Period lengths for LR calculations //--- Regression line control bool EnableLine; // ON/OFF state for regression lines string btnName = "lineToggleBtn"; // Button object name //+------------------------------------------------------------------+ //| Regression Line Set Drawing | //+------------------------------------------------------------------+ void DrawRegressionSet(const double &close[], const datetime &time[], int period, string prefix, color col, bool showFlag, bool extendRight) { string cName = prefix+"_center"; string uName = prefix+"_upper"; string lName = prefix+"_lower"; if(!showFlag || !EnableLine) { ObjectDelete(0, cName); ObjectDelete(0, uName); ObjectDelete(0, lName); return; } if(Bars(_Symbol,_Period) < period) return; double slope = 0, intercept = 0, sigma = 0; // ★ reverseX = false(描画は正方向) if(!CalcLinearRegression(close, period, false, slope, intercept, sigma)) return; double band = sigma * BandMultiplier; datetime t0 = time[period-1]; double y0 = intercept + slope*(period-1); datetime t1 = time[0]; double y1 = intercept; ObjectDelete(0, cName); ObjectCreate(0, cName, OBJ_TREND, 0, t0, y0, t1, y1); ObjectSetInteger(0, cName, OBJPROP_COLOR, col); ObjectSetInteger(0, cName, OBJPROP_WIDTH, 1); ObjectSetInteger(0, cName, OBJPROP_STYLE, STYLE_DOT); ObjectSetInteger(0, cName, OBJPROP_RAY_RIGHT, extendRight); ObjectDelete(0, uName); ObjectCreate(0, uName, OBJ_TREND, 0, t0, y0+band, t1, y1+band); ObjectSetInteger(0, uName, OBJPROP_COLOR, col); ObjectSetInteger(0, uName, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, uName, OBJPROP_RAY_RIGHT, extendRight); ObjectDelete(0, lName); ObjectCreate(0, lName, OBJ_TREND, 0, t0, y0-band, t1, y1-band); ObjectSetInteger(0, lName, OBJPROP_COLOR, col); ObjectSetInteger(0, lName, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, lName, OBJPROP_RAY_RIGHT, extendRight); } //+------------------------------------------------------------------+ //| HUD Rendering | //+------------------------------------------------------------------+ void DrawHUD() { m_canvas.Erase(ColorToARGB(C'20,20,20', 220)); m_canvas.Rectangle(0, 0, m_width-1, m_height-1, ColorToARGB(clrDimGray)); int x_base = 45; int col_w = 58; int y = 8; m_canvas.FontSet("Consolas", -90, FW_BOLD); for(int p=0; p<3; p++) m_canvas.TextOut(x_base + (p*col_w) + 35, y, "P:"+IntegerToString(m_periods[p]), ColorToARGB(clrGray), TA_RIGHT); m_canvas.TextOut(x_base + (3*col_w) + 55, y, "Count("+IntegerToString(InpCountLen)+")", ColorToARGB(clrGray), TA_RIGHT); y += m_row_h; for(int t=0; t<5; t++) { m_canvas.TextOut(8, y, m_tf_names[t], ColorToARGB(clrWhite)); MqlRates rates[]; ArraySetAsSeries(rates, true); if(CopyRates(_Symbol, m_tfs[t], 0, InpPeriod3Len, rates) >= InpPeriod3Len) { for(int p=0; p<3; p++) { int period = m_periods[p]; double closeArr[]; ArrayResize(closeArr, period); for(int i=0; i<period; i++) closeArr[i] = rates[i].close; double slope = 0, intercept = 0, sigma = 0; // ★ reverseX = true(HUD は逆方向) if(!CalcLinearRegression(closeArr, period, true, slope, intercept, sigma)) continue; double lr_curr = intercept + slope * (period - 1); double pos_pct = (sigma > 0.0) ? (rates[0].close - lr_curr) / (sigma * InpDev) * 100.0 : 0.0; uint aCol = (slope > 0) ? ColorToARGB(clrLime) : ColorToARGB(clrRed); uint nCol = (pos_pct >= 100.0) ? ColorToARGB(clrYellow) : (pos_pct <= -100.0 ? ColorToARGB(clrAqua) : ColorToARGB(clrWhite)); string arr = (slope > 0) ? "↑" : "↓"; m_canvas.TextOut(x_base + (p*col_w) + 35, y, DoubleToString(pos_pct, 0), nCol, TA_RIGHT); m_canvas.TextOut(x_base + (p*col_w) + 38, y, arr, aCol); } int up=0, dn=0; for(int i=0; i<InpCountLen; i++) { if(rates[i].close > rates[i].open) up++; else if(rates[i].close < rates[i].open) dn++; } string cntStr = IntegerToString(up) + "u:" + IntegerToString(dn) + "d"; uint cCol = (up > dn) ? ColorToARGB(clrLime) : (dn > up ? ColorToARGB(clrRed) : ColorToARGB(clrWhite)); m_canvas.TextOut(x_base + (3*col_w) + 55, y, cntStr, cCol, TA_RIGHT); } y += m_row_h; } m_canvas.Update(); } //+------------------------------------------------------------------+ //| Draw All Regression Lines | //+------------------------------------------------------------------+ void DrawAllRegressionLines() { if(!EnableLine) { ObjectDelete(0, "LR1_center"); ObjectDelete(0, "LR1_upper"); ObjectDelete(0, "LR1_lower"); ObjectDelete(0, "LR2_center"); ObjectDelete(0, "LR2_upper"); ObjectDelete(0, "LR2_lower"); ObjectDelete(0, "LR3_center"); ObjectDelete(0, "LR3_upper"); ObjectDelete(0, "LR3_lower"); return; } int rates_total = Bars(_Symbol, _Period); if(rates_total <= 0) return; if(show1 && rates_total >= InpPeriod1Len) { double c1[]; datetime t1[]; CopyClose(_Symbol, _Period, 0, InpPeriod1Len, c1); CopyTime (_Symbol, _Period, 0, InpPeriod1Len, t1); DrawRegressionSet(c1, t1, InpPeriod1Len, "LR1", line1Color, show1, extend1); } if(show2 && rates_total >= InpPeriod2Len) { double c2[]; datetime t2[]; CopyClose(_Symbol, _Period, 0, InpPeriod2Len, c2); CopyTime (_Symbol, _Period, 0, InpPeriod2Len, t2); DrawRegressionSet(c2, t2, InpPeriod2Len, "LR2", line2Color, show2, extend2); } if(show3 && rates_total >= InpPeriod3Len) { double c3[]; datetime t3[]; CopyClose(_Symbol, _Period, 0, InpPeriod3Len, c3); CopyTime (_Symbol, _Period, 0, InpPeriod3Len, t3); DrawRegressionSet(c3, t3, InpPeriod3Len, "LR3", line3Color, show3, extend3); } } //+------------------------------------------------------------------+ //| OnInit | //+------------------------------------------------------------------+ int OnInit() { m_periods[0] = InpPeriod1Len; m_periods[1] = InpPeriod2Len; m_periods[2] = InpPeriod3Len; if(!m_canvas.CreateBitmapLabel(m_name, InpX, InpY, m_width, m_height, COLOR_FORMAT_ARGB_NORMALIZE)) return(INIT_FAILED); string obj_name = m_canvas.ChartObjectName(); ObjectSetInteger(0, obj_name, OBJPROP_SELECTABLE, true); ObjectSetInteger(0, obj_name, OBJPROP_CORNER, CORNER_LEFT_UPPER); EnableLine = show; string btnText = (EnableLine ? "Line: ON" : "Line: OFF"); if(ObjectFind(0, btnName) == -1) { ObjectCreate(0, btnName, OBJ_BUTTON, 0, 0, 0); ObjectSetInteger(0, btnName, OBJPROP_XDISTANCE, btnX); ObjectSetInteger(0, btnName, OBJPROP_YDISTANCE, btnY); ObjectSetInteger(0, btnName, OBJPROP_XSIZE, 80); ObjectSetInteger(0, btnName, OBJPROP_YSIZE, 20); ObjectSetInteger(0, btnName, OBJPROP_CORNER, btnCorner); ObjectSetString (0, btnName, OBJPROP_TEXT, btnText); } DrawHUD(); DrawAllRegressionLines(); EventSetTimer(1); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| OnDeinit | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { EventKillTimer(); m_canvas.Destroy(); ObjectDelete(0, "LR1_center"); ObjectDelete(0, "LR1_upper"); ObjectDelete(0, "LR1_lower"); ObjectDelete(0, "LR2_center"); ObjectDelete(0, "LR2_upper"); ObjectDelete(0, "LR2_lower"); ObjectDelete(0, "LR3_center"); ObjectDelete(0, "LR3_upper"); ObjectDelete(0, "LR3_lower"); ObjectDelete(0, btnName); } //+------------------------------------------------------------------+ //| OnCalculate | //+------------------------------------------------------------------+ 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[]) { DrawHUD(); DrawAllRegressionLines(); return(rates_total); } //+------------------------------------------------------------------+ //| OnTimer | //+------------------------------------------------------------------+ void OnTimer() { DrawHUD(); DrawAllRegressionLines(); } //+------------------------------------------------------------------+ //| OnChartEvent | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { if(id == CHARTEVENT_OBJECT_CLICK && sparam == btnName) { EnableLine = !EnableLine; if(EnableLine) ObjectSetString(0, btnName, OBJPROP_TEXT, "Line: ON"); else ObjectSetString(0, btnName, OBJPROP_TEXT, "Line: OFF"); DrawAllRegressionLines(); } }
“I also put together two derivative builds — a TF‑switching version and a seconds‑chart version. They’ll stay active until the end of the month, so feel free to play with them and share your thoughts.”
TF‑switching version
seconds‑chart version

This is the version referenced above.
Try publishing this to codebase. It's a more appropriate way to share open source developments than simply posting source code to a forum. For each publication in the codebase, a forum topic is automatically created for its discussion.
Moreover, if you publish your application to codebase, many more people will know about it (this is guaranteed).
- Firstly, codebase publications are available for download directly from MetaEditor.
- Secondly, MetaQuotes is highly likely to promote your codebase publication in their channels with hundreds of thousands or even millions of subscribers. Here alone they have 400 thousand subscribers; they also have Facebook, Telegram, and X.
- Thirdly, if MetaQuotes editors pick your publication, it will be translated and available for all 11 language sections of this site.
Thank you all so much for the advice!
I’ve only just started here, so I was completely unaware of the proper way to share code.
I’ll definitely check out the CodeBase!
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use

Overview
I’m sharing a free indicator I built: a Multi‑Timeframe Linear Regression HUD rendered with Canvas, designed to show trend strength, deviation from regression, and recent candle bias — all in one compact dashboard.
Useful for discretionary traders who want a quick “market condition snapshot” across multiple timeframes.
Features
5 Timeframes: M1 / M5 / M15 / M30 / H1
3 Linear Regression Periods: configurable (default 20 / 50 / 100)
σ‑Deviation Position (%): shows how far the current price is from LR (normalized by σ × deviation factor)
Slope Direction: ↑ for positive slope, ↓ for negative
Candle Count: Up/Down count for the last N candles
Canvas HUD: clean, compact, always-on-screen display
Auto‑refresh: updates on every tick + timer
Screenshot
Source Code (Full MQ5)
Feel free to modify, reuse, or integrate into your own tools.
Notes
Works on any symbol
No chart objects except the Canvas label
Lightweight and fast
License
Free to use, modify, and redistribute. No restrictions.
Enjoy!
If this helps your workflow or you create a modified version, I’d love to see it.