MQL5 Chart Objects: Draw Trendlines & Labels in Expert

Learn to draw trendlines, text labels, and arrows programmatically in MQL5. Step-by-step code examples with ObjectCreate, styling, and cleanup for your EAs.

mql5-chart-objects-draw-trendlines-labels-in

Why Programmatic Chart Objects Matter

If you've ever manually drawn a trendline on a chart and wished your EA could do it automatically, you're in the right place. Chart objects let your Expert Advisor mark support/resistance zones, label entry points, or draw arrows at trade signals — all without human intervention. I've seen traders spend hours manually updating charts with entry and exit levels, then wonder why their backtests don't match reality. Programmatic objects solve that: you get consistent, reproducible markings every time the EA runs.

This guide walks you through the core MQL5 functions to create, modify, and manage trendlines, labels, and arrows from code. By the end, you'll be able to add persistent graphical elements to any chart, control their colors and styles, and clean them up when they're no longer needed. I'll assume you've written a basic MQL5 EA before, but even if you're new to the language, the examples are self-contained and ready to test in the Strategy Tester or on a live chart.

One thing I've learned the hard way: always give your objects unique names, and always clean up after yourself. A chart cluttered with orphaned objects from a hundred test runs is a debugging nightmare. We'll cover naming conventions and deletion patterns later — trust me, you'll thank yourself when you're trying to figure out why your EA suddenly stopped drawing lines.

Prerequisites

  1. MetaTrader 5 (build 2000 or later) — The code uses MQL5-specific functions like ObjectSetInteger and ChartRedraw. MT4 uses different object functions; this guide is MT5 only. If you're on MT4, the concepts are similar but the function signatures differ — you'll need ObjectSet() instead of ObjectSetInteger(). I've ported some of my MT5 EAs to MT4 and it's doable, but expect to rewrite every object-related call.
  2. MetaEditor — Comes with MT5. You'll compile the EA here. Press F4 in MT5 to open it. The built-in debugger is useful for stepping through object creation code.
  3. A demo account — Test on a demo chart, not a live one. I've seen traders accidentally delete objects on live charts during testing — not catastrophic, but embarrassing. More importantly, you don't want to trigger any broker alerts by rapidly creating/deleting objects.
  4. Basic MQL5 knowledge — You should know how to create an EA file, compile it, and attach it to a chart. If not, start with MetaEditor's built-in template: File → New → Expert Advisor. The template gives you the OnInit(), OnTick(), and OnDeinit() stubs ready to go. That's all you need for this tutorial.

Step-by-Step: Drawing Your First Trendline

The core function is ObjectCreate(). Every graphical object in MQL5 needs a unique name, a chart ID, a type constant, and at least one anchor point. Here's the simplest trendline you can draw:

//+------------------------------------------------------------------+
//| Create a bullish trendline from the last two swing lows         |
//+------------------------------------------------------------------+
void DrawTrendline()
{
   string objName = "MyTrendline_1";
   long chartId = 0; // 0 = current chart

   // Get the low of the previous two completed bars
   double price1 = iLow(_Symbol, _Period, 2);
   double price2 = iLow(_Symbol, _Period, 1);

   // Create the trendline object
   if(!ObjectCreate(chartId, objName, OBJ_TREND, 0, iTime(_Symbol, _Period, 2), price1, iTime(_Symbol, _Period, 1), price2))
   {
      Print("Failed to create trendline. Error: ", GetLastError());
      return;
   }

   // Style it: red, solid line, width 2
   ObjectSetInteger(chartId, objName, OBJPROP_COLOR, clrRed);
   ObjectSetInteger(chartId, objName, OBJPROP_STYLE, STYLE_SOLID);
   ObjectSetInteger(chartId, objName, OBJPROP_WIDTH, 2);

   // Extend the line to the right
   ObjectSetInteger(chartId, objName, OBJPROP_RAY_RIGHT, true);

   ChartRedraw(chartId);
}

Call DrawTrendline() from your EA's OnTick() or OnInit(). The OBJ_TREND constant tells MQL5 you want a straight line. The two points are defined by time1, price1, time2, price2. I used iTime() and iLow() to get bar data, but you can supply any datetime and price values — for example, the high of a swing point or a Fibonacci level. Just make sure the times are in chronological order (earlier first, later second), otherwise the line might render backwards.

A common mistake: forgetting to check the return value of ObjectCreate(). If it returns false, call GetLastError() to find out why. Error 4200 means the object name already exists — either delete it first or use a unique name. Error 4001 means invalid parameters — double-check your anchor points. I once spent an hour debugging a trendline that wouldn't draw because I passed the same time value for both points. The line had zero length and MQL5 silently refused to create it.

Understanding ObjectCreate Parameters

ParameterTypeDescription
chart_idlongChart identifier. 0 = current chart. Use ChartID() to get a specific chart handle, e.g., when working with multiple charts or in custom indicators.
namestringUnique object name. If an object with this name exists, it will be replaced. Use a naming convention like "EA_Signal_1". Avoid generic names like "line1".
typeENUM_OBJECTObject type constant: OBJ_TREND, OBJ_ARROW, OBJ_LABEL, OBJ_FIBO, etc. Full list in MQL5 Reference under "Object Types".
sub_windowint0 = main chart window, 1+ = indicator subwindow. Most EAs use 0. If you're drawing in an indicator, pass the subwindow index.
time1, price1, ...datetime, doubleAnchor points. Number varies by object type (2 for trendlines, 1 for labels/arrows). Must be in chronological order for trendlines.

Trendline Properties You'll Use Most

Beyond the basics, you can control how the trendline appears and behaves. Here are the properties I tweak most often:

  • OBJPROP_RAY_RIGHT — Extends the line infinitely to the right (true/false). Useful for dynamic support/resistance lines that should project forward. I set this to true for breakout levels.
  • OBJPROP_RAY_LEFT — Extends to the left. Less common, but handy for drawing from a historical anchor, like showing where a level originated.
  • OBJPROP_WIDTH — Line thickness from 1 to 5. Thicker lines stand out better on busy charts. I use width 1 for minor levels, width 3 for major ones.
  • OBJPROP_STYLE — Line style: STYLE_SOLID, STYLE_DASH, STYLE_DOT, STYLE_DASHDOT, STYLE_DASHDOTDOT. Dashed lines work well for projected levels vs. confirmed ones. I use dotted for pending orders.
  • OBJPROP_BACK — If true, the object draws behind the candlesticks. I use this for background zones so they don't obscure price action. Great for highlighting support/resistance bands.
  • OBJPROP_HIDDEN — If true, the object is hidden from the chart but still exists. Useful for internal markers you don't want to see visually.

Here's how to set a dashed, background trendline that extends right only:

ObjectSetInteger(chartId, objName, OBJPROP_STYLE, STYLE_DASH);
ObjectSetInteger(chartId, objName, OBJPROP_WIDTH, 1);
ObjectSetInteger(chartId, objName, OBJPROP_RAY_RIGHT, true);
ObjectSetInteger(chartId, objName, OBJPROP_RAY_LEFT, false);
ObjectSetInteger(chartId, objName, OBJPROP_BACK, true);

Adding Text Labels

Labels are great for showing trade notes, current signal names, or risk warnings directly on the chart. Unlike trendlines, a label has a single anchor point and you position it using X/Y pixel coordinates or price/time coordinates. I prefer pixel coordinates for labels because they stay put regardless of chart scrolling. If you use price/time anchors, the label will move with the chart — sometimes useful, but often annoying.

//+------------------------------------------------------------------+
//| Place a text label at a fixed screen position                   |
//+------------------------------------------------------------------+
void DrawLabel()
{
   string labelName = "SignalLabel";
   long chartId = 0;

   if(!ObjectCreate(chartId, labelName, OBJ_LABEL, 0, 0, 0))
   {
      Print("Label creation failed. Error: ", GetLastError());
      return;
   }

   // Set text and style
   ObjectSetString(chartId, labelName, OBJPROP_TEXT, "BUY SIGNAL");
   ObjectSetInteger(chartId, labelName, OBJPROP_COLOR, clrLimeGreen);
   ObjectSetInteger(chartId, labelName, OBJPROP_FONTSIZE, 12);
   ObjectSetString(chartId, labelName, OBJPROP_FONT, "Arial Bold");

   // Position in pixels from top-left corner
   ObjectSetInteger(chartId, labelName, OBJPROP_XDISTANCE, 20);
   ObjectSetInteger(chartId, labelName, OBJPROP_YDISTANCE, 40);

   // Make it fixed so it doesn't move when scrolling
   ObjectSetInteger(chartId, labelName, OBJPROP_CORNER, CORNER_LEFT_UPPER);

   ChartRedraw(chartId);
}

Notice that for OBJ_LABEL, the anchor parameters after sub_window are zeros — labels ignore price/time anchors. Instead, you set OBJPROP_XDISTANCE and OBJPROP_YDISTANCE to position them in pixels. The OBJPROP_CORNER property determines which corner of the chart is the origin (0,0). If you use CORNER_LEFT_UPPER, X=20 means 20 pixels from the left edge, Y=40 means 40 pixels from the top.

A practical tip: if you're displaying dynamic values like current profit or signal strength, update the label text in OnTick() using ObjectSetString(). Just be careful not to recreate the object every tick — that causes flickering. Create it once in OnInit(), then update its text. I typically check if the object exists first with ObjectFind(chartId, labelName) before creating it.

Label Corner Options

ConstantValueOrigin

Community

Clap for the article and open comments only when you want to read them.

0 claps0 comments

Related articles