Renko EA MQL5: Build a Brick Breakout Trader Step by Step

Learn to build a Renko brick breakout EA in MQL5 from scratch. Covers custom Renko calculation, trade logic, dynamic stop-loss based on brick size, and honest.

renko-ea-mql5-build-a-brick-breakout-trader-step

Why Renko? And Why Build Your Own EA?

If you've spent any time staring at standard candlestick charts, you know the problem: noise. One minute price is up ten pips, the next it's down twelve, and your trailing stop gets taken out before the real move starts. Renko charts solve that by filtering out time entirely and only plotting bricks when price moves a fixed amount. Each brick is the same size — say 10 pips — and a new brick only appears when price moves that full distance from the previous brick's high or low.

This makes Renko a natural fit for breakout trading. You wait for a new brick to close, then enter in that direction with a stop-loss tied directly to the brick size. The logic is clean, the risk is quantifiable, and there's no intra-bar noise to deal with.

But here's the catch: MetaTrader 5 does not natively support Renko charts. You can't just drop an indicator on a standard MT5 chart and get real Renko bars. You have to calculate them yourself inside the EA. That's what we're going to do today — build a complete Renko brick breakout EA in MQL5 that calculates bricks on every tick, trades breakouts, and sets a dynamic stop-loss based on the brick size.

I've been developing EAs for over a decade, and Renko strategies are among the most requested but least well-implemented. Most traders either use a third-party Renko chart indicator and try to trade it manually, or they buy a black-box EA that they don't understand. Neither is ideal. By building your own, you control the logic, the brick size, the trade management, and — most importantly — the risk.

Understanding Renko Bricks and Breakout Logic

Before we write a single line of code, let's be crystal clear on how Renko bricks work in an algorithmic context.

A Renko brick is a fixed-size price movement. In our EA, we'll define the brick size as a parameter, say 20 points (for forex) or 10 ticks (for futures). The EA maintains two variables: the current brick's open price and its direction (up or down). Every tick, we check if price has moved enough to form a new brick.

The rules are straightforward:

  • Up brick: If price exceeds the current brick's high by at least one brick size, a new up brick forms. The new brick's open is the previous brick's high, and its close is that plus the brick size.
  • Down brick: If price falls below the current brick's low by at least one brick size, a new down brick forms. The new brick's open is the previous brick's low, and its close is that minus the brick size.
  • Reversal brick: If price moves more than one brick size in the opposite direction, that forms a reversal brick. For example, if we're in an up brick and price drops by two brick sizes, we get two down bricks.

Our breakout strategy trades when a brick closes in a new direction. We enter on the close of the first brick in that direction, with a stop-loss set at one brick size away from entry. For a long entry, the stop goes one brick size below the entry price. For a short, one brick size above.

This is where the dynamic stop-loss comes in. Since the brick size is a parameter you can change, your stop-loss automatically scales with market conditions. In a low-volatility pair like EURCHF, you might use a 10-point brick. In GBPJPY, you might use 30 points. The stop adjusts accordingly.

Building the EA in MQL5: Step by Step

We'll build this as a single-file EA. No external dependencies, no custom indicators. Everything happens inside the OnTick() handler. Let me walk you through the core components.

1. Input Parameters

Start with the parameters you'll expose in the EA's input dialog. Keep it minimal but flexible.

//+------------------------------------------------------------------+
//| Input parameters                                                 |
//+------------------------------------------------------------------+
input double   BrickSize          = 20.0;     // Brick size in points
input double   LotSize            = 0.1;      // Fixed lot size
input int      StopLossBricks     = 1;        // Stop-loss in bricks (1 = 1x brick size)
input int      TakeProfitBricks   = 3;        // Take-profit in bricks
input bool     UseTrailingStop    = false;    // Enable trailing stop
input int      TrailingBricks     = 2;        // Bricks to trail behind
input int      MagicNumber        = 202401;   // EA magic number

Notice I use points, not pips. In MQL5, 1 point is the smallest price change for a symbol. For most forex pairs, 10 points = 1 pip. So a brick size of 20 points equals 2 pips. Adjust based on what you're trading.

2. Global Variables for Brick State

We need to track the current brick's open, high, low, and close. Plus a flag for whether we're in an uptrend or downtrend.

//+------------------------------------------------------------------+
//| Global variables                                                 |
//+------------------------------------------------------------------+
double   g_brickOpen   = 0.0;
double   g_brickHigh   = 0.0;
double   g_brickLow    = 0.0;
double   g_brickClose  = 0.0;
bool     g_isUpBrick   = true;   // true = current brick is up
bool     g_brickJustClosed = false;

3. Initializing the Brick

On the first tick, we need to set the initial brick based on the current price. A simple approach: set the brick open to the current bid/ask rounded to the nearest brick size.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   // Set initial brick
   double price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   g_brickOpen  = NormalizeDouble(MathFloor(price / BrickSize) * BrickSize, _Digits);
   g_brickHigh  = g_brickOpen + BrickSize;
   g_brickLow   = g_brickOpen;
   g_brickClose = g_brickOpen;
   g_isUpBrick  = true;
   
   return(INIT_SUCCEEDED);
}

This floors the price to the nearest brick multiple. It's not perfect — you'll miss the first brick if price is already mid-brick — but it gets us started. For a production EA, you'd want to backfill from history, but that's a separate article.

4. Core Brick Calculation in OnTick()

This is the heart of the EA. Every tick, we check if a new brick has formed.

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   
   // Reset flag
   g_brickJustClosed = false;
   
   if(g_isUpBrick)
   {
      // Check for continuation up
      if(bid >= g_brickHigh + BrickSize)
      {
         // New up brick
         g_brickOpen  = g_brickHigh;
         g_brickHigh  = g_brickOpen + BrickSize;
         g_brickLow   = g_brickOpen;
         g_brickClose = g_brickHigh;
         g_brickJustClosed = true;
      }
      // Check for reversal down (need 2 bricks down to reverse)
      else if(bid <= g_brickLow - BrickSize * 2)
      {
         // Reversal: two down bricks
         g_brickOpen  = g_brickLow - BrickSize;
         g_brickHigh  = g_brickOpen + BrickSize;
         g_brickLow   = g_brickOpen;
         g_brickClose = g_brickLow;
         g_isUpBrick  = false;
         g_brickJustClosed = true;
      }
   }
   else // Down brick
   {
      // Check for continuation down
      if(bid <= g_brickLow - BrickSize)
      {
         g_brickOpen  = g_brickLow;
         g_brickLow   = g_brickOpen - BrickSize;
         g_brickHigh  = g_brickOpen;
         g_brickClose = g_brickLow;
         g_brickJustClosed = true;
      }
      // Check for reversal up
      else if(bid >= g_brickHigh + BrickSize * 2)
      {
         g_brickOpen  = g_brickHigh + BrickSize;
         g_brickHigh  = g_brickOpen + BrickSize;
         g_brickLow   = g_brickOpen;
         g_brickClose = g_brickHigh;
         g_isUpBrick  = true;
         g_brickJustClosed = true;
      }
   }
   
   // Update brick high/low for current tick
   if(g_isUpBrick)
   {
      if(bid > g_brickHigh) g_brickHigh = bid;
      g_brickClose = g_brickHigh;
   }
   else
   {
      if(bid < g_brickLow) g_brickLow = bid;
      g_brickClose = g_brickLow;
   }
   
   // Trade logic
   if(g_brickJustClosed)
      CheckForEntry();
}

Notice the reversal logic requires two bricks in the opposite direction. This is standard for Renko — a single brick in the opposite direction is just a wick, not a reversal. Some implementations use a three-brick reversal for smoother signals. You can parameterize that later.

5. Trade Entry and Dynamic Stop-Loss

Now for the breakout entry. When a brick closes, we check if it's the first brick in a new direction. We track this with a simple trend flag.

//+------------------------------------------------------------------+
//| Check for entry signals                                          |
//+------------------------------------------------------------------+
void CheckForEntry()
{
   static int lastDirection = 0; // 1 = up, -1 = down, 0 = none
   int currentDirection = g_isUpBrick ? 1 : -1;
   
   // Only trade if direction changed
   if(currentDirection != lastDirection && lastDirection != 0)
   {
      double entryPrice, slPrice, tpPrice;
      
      if(currentDirection == 1) // Long
      {
         entryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
         slPrice    = entryPrice - (StopLossBricks * BrickSize * _Point);
         tpPrice    = entryPrice + (TakeProfitBricks * BrickSize * _Point);
         
         OpenOrder(ORDER_TYPE_BUY, entryPrice, slPrice, tpPrice);
      }
      else // Short
      {
         entryPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
         slPrice    = entryPrice + (StopLossBricks * BrickSize * _Point);
         tpPrice    = entryPrice - (TakeProfitBricks * BrickSize * _Point);
         
         OpenOrder(ORDER_TYPE_SELL, entryPrice, slPrice, tpPrice);
      }
   }
   
   lastDirection = currentDirection;
}

The stop-loss is literally one brick size away (or whatever multiple you set). That's the beauty of Renko — the brick size IS your volatility measure. You don't need ATR or Bollinger Bands. The market tells you how far it's willing to move before reversing.

6. Order Placement Function

Here's a minimal order placement function. In production, you'd add more error handling and slippage control.

//+------------------------------------------------------------------+
//| Open a market order                                              |
//+------------------------------------------------------------------+
void OpenOrder(ENUM_ORDER_TYPE type, double price, double sl, double tp)
{
   MqlTradeRequest request = {};
   MqlTradeResult  result  = {};
   
   request.action    = TRADE_ACTION_DEAL;
   request.symbol    = _Symbol;
   request.volume    = LotSize;
   request.type      = type;
   request.price     = price;
   request.sl        = NormalizeDouble(sl, _Digits);
   request.tp        = NormalizeDouble(tp, _Digits);
   request.deviation = 10;
   request.magic     = MagicNumber;
   request.comment   = "Renko Breakout";
   
   if(!OrderSend(request, result))
      Print("OrderSend failed: ", result.retcode);
   else
      Print("Order placed: ", result.order);
}

Testing and Optimization Tips

Before you throw this at a live account, spend serious time in the Strategy Tester. Renko EAs behave differently than standard trend-following systems. Here are specific things to test:

  • Brick size sensitivity: Test brick sizes from 10 to 50 points in 5-point increments. You'll likely find a sweet spot where win rate and profit factor peak. For EURUSD on M15 data, I've seen brick sizes around 15-25 points work well.
  • Stop-loss bricks: 1 brick is tight. It'll get stopped out frequently. Try 1.5 or 2 bricks. But remember, wider stops mean bigger losses per trade.
  • Take-profit bricks: 3 is a good starting point. Test 2, 3, 4, 5. The Renko structure means you'll catch trends well, but reversals can wipe out profits quickly.
  • Data quality: Renko EAs are sensitive to tick data quality. Use real tick data if possible, not M1 OHLC. The Strategy Tester's "Every tick" mode is mandatory.

Pros, Cons, and Honest Risks

Let's be real about what this EA does and doesn't do.

What Works

  • Noise reduction: Renko inherently filters out small retracements. Your EA won't trade every 5-pip wiggle.
  • Clear risk management: The stop-loss is directly tied to market volatility via brick size. No guesswork.
  • Trend following: In strong trends, this EA will ride them beautifully. Each new brick adds to the trend, and you're always positioned with the trend.
  • Parameter simplicity: You only have a few knobs to turn. Less overfitting potential than a 50-parameter monster.

What Hurts

  • Whipsaws in ranges: When price oscillates within a range just larger than your brick size, you'll get repeated reversal signals. Each one triggers a trade that quickly reverses. This is the biggest killer of Renko strategies.
  • Brick size selection is critical: Too small, and you're back to noise. Too large, and you miss moves entirely. There's no universal "best" brick size.
  • MT5 limitations: MT5's Strategy Tester doesn't natively support Renko. You're testing on standard timeframes, which means the EA's behavior depends on the tick data's granularity. A 1-minute chart with 20-point bricks will behave differently than a 5-minute chart with the same brick size.
  • No visual feedback: You can't see the Renko bricks on the chart while testing. You're flying blind unless you add custom chart drawing (which is possible but adds complexity).

I've seen traders blow accounts on Renko EAs because they used too small a brick size on a volatile pair, getting stopped out 15 times in a row. Start with a larger brick size than you think you need. Test for at least 100 trades before making any conclusions.

Worked Example: EURUSD with 20-Point Bricks

Let's walk through a realistic scenario. You set BrickSize to 20 points, StopLossBricks to 1, TakeProfitBricks to 3. You run this on EURUSD H1 data from January to June 2024.

  1. Initial state: Price is at 1.0800. The EA sets the first brick open at 1.0800.
  2. First move up: Price rises to 1.0820. A new up brick closes at 1.0820. The EA enters long at the ask (say 1.0821), stop at 1.0801, target at 1.0881.
  3. Continuation: Price reaches 1.0840. Another up brick closes. The EA doesn't enter again unless you enable pyramiding (not covered here).
  4. Reversal: Price drops to 1.0780 — a 40-point drop. That's two down bricks. The EA detects the reversal, closes the long (if still open) and enters short at 1.0780, stop

Want to build your own version?

Recreate similar entry logic, risk rules, and filters in TradingBotMaker—no MQL coding. Start free.

Community

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

0 claps0 comments

Related articles