FX NOOKAI CODE LAB
Loading

MT4 Support and Resistance Indicator: Levels and Setup

By FXNook Lab team

An MT4 support and resistance indicator marks prices or price areas where the market has previously turned, stalled, or reacted. You can install one from an EX4 or MQ4 file, adjust its timeframe and lookback, or build a simple MQL4 indicator that draws horizontal lines at confirmed swing highs and lows. These marks describe past price action; they do not guarantee where price will move next.

What a support and resistance indicator displays

A support level is a price where prior declines paused or reversed, while resistance is a price where prior advances paused or reversed. An indicator turns selected price points into chart lines, bands, or zones so you can see those areas without scanning every candle manually.

A level is a single price, commonly drawn as a horizontal line through a swing high or low. A zone covers a price range, which can better represent a group of nearby reactions. In live markets, turns rarely occur at exactly the same price, so a zone can be more practical than treating every small difference as a new level.

Indicators use rules to decide which reactions count. One may mark recent swing points, another may require several touches, and a manually maintained tool may show prices chosen by the user. The resulting chart depends on those rules and settings, not on a universal definition of support or resistance.

Choose how the indicator identifies levels

MethodStrengthsLimitations
Confirmed swing highs and lowsClear, rule-based marks that can be calculated consistently from price bars. Suitable for a compact indicator and straightforward testing.A swing is known only after later bars confirm it. The method can produce many nearby lines, and it does not measure how important each turn is.
Repeated touchesCan highlight prices or ranges that have attracted several reactions. A touch count can help rank candidate areas.The result depends on how the indicator defines a touch, the allowed price distance, and the time window. Close prices may be grouped differently by different indicators.
Manually selected pricesLets the trader choose which areas matter and avoid automatic marks that add little to the chart.Requires ongoing input and can vary between users. Manual lines may not be reproduced automatically when a chart or symbol changes.

For an initial MT4 setup, confirmed swings are easy to understand because you can compare each mark with the candles that formed it. Repeated-touch methods can be useful when you want fewer, ranked areas, but read the indicator’s description to learn its touch and grouping rules. Manual prices make sense when you want direct control over the chart rather than automatic detection.

Install and configure an MT4 indicator

  1. In MT4, select File > Open Data Folder. Open MQL4, then Indicators, and copy the indicator file into that folder. An .ex4 file is compiled and ready to run; an .mq4 file is source code that you can open and compile in MetaEditor.

  2. Return to MT4 and right-click Navigator > Indicators, then choose Refresh. If the indicator does not appear, restart MT4 and look in the same Navigator section.

  3. Drag the indicator onto a chart or double-click its name. Review the Inputs tab before selecting OK. Common settings include the number of bars to scan, the swing confirmation distance, the maximum number of displayed levels, and line colours or styles.

  4. Set the chart timeframe deliberately. Some indicators calculate on the chart’s current timeframe; others have a timeframe input and can display levels calculated from a higher or lower timeframe. If the indicator offers a lookback setting, begin with a limited number of bars so you can see which marks are recent.

  5. Use the Colors tab, where available, to make support and resistance distinct without overpowering candles. To change inputs later, open the chart’s indicator list, select the indicator, and choose Edit.

If you have MQ4 source, open it in MetaEditor with F4 from MT4, then press F7 to compile. A successful compile should create or update an EX4 file in the Indicators folder. Compilation confirms that the source passed the compiler; it does not establish that the indicator’s level rules behave as you expect.

Build confirmed swing levels with MQL4

This example finds local highs and lows using closed bars and draws dotted horizontal lines. A swing high must be higher than the selected bars on both sides; a swing low must be lower. The RightBars input controls how many newer bars must close before the swing is confirmed, so the indicator does not treat an unfinished candle as a confirmed turning point.

The indicator uses chart objects rather than indicator buffers because the output is a set of horizontal lines at fixed prices. It scans a limited history and caps the number of lines on each side. The example keeps these lines as individual levels; it does not merge nearby prices into zones.

#property strict
#property indicator_chart_window
#property version   "1.00"

input int   LeftBars = 3;
input int   RightBars = 3;
input int   LookbackBars = 500;
input int   MaxLevelsPerSide = 10;
input color ResistanceColor = clrTomato;
input color SupportColor = clrDodgerBlue;

string Prefix = "SwingSR_";

void DeleteOurObjects()
{
   for(int i = ObjectsTotal(0, -1, -1) - 1; i >= 0; i--)
   {
      string name = ObjectName(0, i, -1, -1);
      if(StringFind(name, Prefix) == 0)
         ObjectDelete(0, name);
   }
}

bool IsSwingHigh(const double &values[], const int shift,
                 const int left, const int right)
{
   for(int j = 1; j <= left; j++)
      if(values[shift] <= values[shift + j]) return false;

   for(int j = 1; j <= right; j++)
      if(values[shift] <= values[shift - j]) return false;

   return true;
}

bool IsSwingLow(const double &values[], const int shift,
                const int left, const int right)
{
   for(int j = 1; j <= left; j++)
      if(values[shift] >= values[shift + j]) return false;

   for(int j = 1; j <= right; j++)
      if(values[shift] >= values[shift - j]) return false;

   return true;
}

void DrawLevel(const string name, const double price, const color lineColor)
{
   if(!ObjectCreate(0, name, OBJ_HLINE, 0, 0, price)) return;
   ObjectSetInteger(0, name, OBJPROP_COLOR, lineColor);
   ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_DOT);
   ObjectSetInteger(0, name, OBJPROP_WIDTH, 1);
   ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
}

int OnInit()
{
   IndicatorShortName("Confirmed Swing Support and Resistance");
   return INIT_SUCCEEDED;
}

void OnDeinit(const int reason)
{
   DeleteOurObjects();
}

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[])
{
   ArraySetAsSeries(time, true);
   ArraySetAsSeries(high, true);
   ArraySetAsSeries(low, true);

   int left = LeftBars;
   int right = RightBars;
   if(left < 1) left = 1;
   if(right < 1) right = 1;

   DeleteOurObjects();
   if(MaxLevelsPerSide < 1 || rates_total < left + right + 3)
      return rates_total;

   int oldest = LookbackBars;
   int available = rates_total - left - 1;
   if(oldest > available) oldest = available;

   int resistanceCount = 0;
   int supportCount = 0;

   // Smaller shifts are more recent; shift 0 is the live bar.
   for(int shift = right + 1; shift <= oldest; shift++)
   {
      if(resistanceCount < MaxLevelsPerSide &&
         IsSwingHigh(high, shift, left, right))
      {
         string name = Prefix + "R_" + IntegerToString((long)time[shift]);
         DrawLevel(name, high[shift], ResistanceColor);
         resistanceCount++;
      }

      if(supportCount < MaxLevelsPerSide &&
         IsSwingLow(low, shift, left, right))
      {
         string name = Prefix + "S_" + IntegerToString((long)time[shift]);
         DrawLevel(name, low[shift], SupportColor);
         supportCount++;
      }

      if(resistanceCount >= MaxLevelsPerSide &&
         supportCount >= MaxLevelsPerSide)
         break;
   }

   return rates_total;
}

In MT4’s series indexing, shift 0 is the current, still-forming bar; larger shifts are older bars. The loop starts at RightBars + 1, which leaves the required newer confirmation bars at shifts 1 and above. The indicator uses the bar’s time in each object name, so each marked swing has a stable, distinct name on that chart.

The inputs control the pattern and the amount of chart history displayed. Increasing LeftBars or RightBars makes the swing definition more selective; increasing LookbackBars allows older marks into the scan. MaxLevelsPerSide limits visible highs and lows separately, while the two colour inputs distinguish resistance from support.

This compact example deletes and redraws its own objects each time it calculates. That keeps the displayed set aligned with the current inputs, but it is not the most efficient approach for a large production indicator. A more optimized version can update objects only when a new bar appears or when relevant settings change. It also uses strict comparisons, so equal highs or lows across neighbouring bars do not qualify as swings.

Keep levels readable and useful

When several swing prices sit close together, separate lines can obscure the candles. A zone-based version can group prices within a chosen distance, such as a number of points or a fraction of the symbol’s recent range, then draw a band or one representative line. The grouping rule should be visible in the settings because changing the tolerance changes which turns are treated as one area.

Limit old marks with a lookback window or a maximum number of levels, as the example does. If the chart remains crowded, reduce the limit or use a shorter lookback before changing the swing rules. Keep support and resistance visually distinct, and use subtle lines so the plotted levels do not hide price bars.

For indicators that create objects, use a unique name prefix and include information that distinguishes each mark, such as its side and bar time. Before deleting or updating an object, restrict the operation to that prefix. Otherwise, an indicator can remove drawings belonging to the trader or another tool. If you modify an existing indicator, avoid creating a second copy of each line on every tick.

Check for repainting and indicator errors

A confirmed swing cannot be identified until enough later bars have closed. A tool that places the mark immediately on the candidate bar may move or remove it while those bars form; that is different from a swing confirmed after the chosen right-side bars are complete. Also distinguish a changing live-bar calculation from a mark that changes after its confirmation conditions have already been met.

In MT4’s Strategy Tester, visual mode can help you observe when a swing becomes confirmed as bars advance. Use the tester to examine calculation and display behaviour, not to treat historical marks as proof that future reactions will occur. Past or tested results do not guarantee future results.

Test across charts and timeframes

Start with one symbol and one timeframe, then repeat the same setup on a second symbol and a different timeframe. Note the inputs and compare the marks after attaching, refreshing, and reopening each chart. A chart-timeframe indicator should calculate from that chart’s bars; a multi-timeframe indicator may instead read a selected timeframe, so its settings and display rules need to make that distinction clear.

Look for stable output after a refresh, sensible spacing between levels, and an amount of history that is easy to read. If levels appear to shift, identify whether the swing is still waiting for confirmation, whether the chart received additional history, or whether the indicator groups nearby prices dynamically. A visually consistent historical chart is useful for checking implementation, but does not establish that any level will hold in later market conditions.

If you want to create a custom version without writing the MQL4 specification from scratch, the FXNook AI indicator builder can build MT4 or MT5 indicators from a description, compile the code, and check it before download. Specify whether marks should appear on closed bars, how swings are confirmed, and how nearby prices should be displayed; those details determine the indicator’s behaviour.

Next step

Install a swing-based indicator on a demo chart, note its inputs, and run the refresh and closed-bar checks before relying on its display. If the default rules do not match what you need, define the confirmation, grouping, and display rules first, then build or edit the indicator to match them.

Questions

How do I add a support and resistance indicator to MT4?

Copy the EX4 or MQ4 file into the MT4 Data Folder under MQL4/Indicators. Refresh the Navigator’s Indicators list or restart MT4, then drag the indicator onto a chart and set its inputs, such as timeframe, lookback, and line display.

Do MT4 support and resistance indicators repaint?

Some can, depending on their rules. A swing indicator that waits for its chosen number of later bars to close can keep confirmed marks fixed, while a mark shown before confirmation may move or disappear as new bars form.

Can I create my own support and resistance indicator in MQL4?

Yes. MQL4 indicators can inspect bar highs and lows, apply rules such as confirmed swing detection, and draw lines or zones with chart objects. You can compile an MQ4 file in MetaEditor and test its closed-bar behaviour on MT4 charts.