Problem Description
Solution
Here is a complete, fully functional Expert Advisor (trading bot) for MetaTrader 4 that uses Heikin-Ashi candles for trading decisions.
The Strategy Logic
This bot uses a Trend Reversal strategy based on Heikin-Ashi color changes:
- Buy Signal: The previous Heikin-Ashi candle was Red (Bearish), and the current closed Heikin-Ashi candle is Green (Bullish).
- Sell Signal: The previous Heikin-Ashi candle was Green (Bullish), and the current closed Heikin-Ashi candle is Red (Bearish).
- Exit Rule: It closes the position if the Heikin-Ashi color changes against the trade direction (or hits Stop Loss/Take Profit).
MQL4 Code
//+------------------------------------------------------------------+
//| HeikinAshi_Bot.mq4 |
//| Copyright 2023, Quantitative AI |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Quantitative AI"
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
//--- Input Parameters
input double InpLots = 0.1; // Lot Size
input int InpStopLoss = 50; // Stop Loss in pips (0 = none)
input int InpTakeProfit = 100; // Take Profit in pips (0 = none)
input int InpMagicNumber = 12345; // Magic Number to identify orders
input int InpSlippage = 3; // Max Slippage in pips
//--- Global Variables
double m_point;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Adjust point for 3/5 digit brokers
if(Digits == 3 || Digits == 5) m_point = Point * 10;
else m_point = Point;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// We only trade on the close of a bar, but for simplicity in this example,
// we check conditions every tick. The logic ensures we don't open multiple trades
// because we check if an order is already open.
// 1. Calculate Heikin Ashi values for the last two closed candles (Index 1 and 2)
double haOpen1, haClose1, haOpen2, haClose2;
// Get HA values for Bar 1 (Most recently closed)
CalculateHeikinAshi(1, haOpen1, haClose1);
// Get HA values for Bar 2 (The one before that)
CalculateHeikinAshi(2, haOpen2, haClose2);
// 2. Determine Candle Colors (Green/Bullish or Red/Bearish)
bool isBullish1 = (haClose1 > haOpen1);
bool isBearish1 = (haClose1 < haOpen1);
bool isBullish2 = (haClose2 > haOpen2);
bool isBearish2 = (haClose2 < haOpen2);
// 3. Manage Open Positions (Exit Logic)
if(OrdersTotal() > 0)
{
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderMagicNumber() == InpMagicNumber && OrderSymbol() == Symbol())
{
// Close Buy if Candle 1 turns Bearish
if(OrderType() == OP_BUY && isBearish1)
{
bool closed = OrderClose(OrderTicket(), OrderLots(), Bid, InpSlippage, clrRed);
}
// Close Sell if Candle 1 turns Bullish
if(OrderType() == OP_SELL && isBullish1)
{
bool closed = OrderClose(OrderTicket(), OrderLots(), Ask, InpSlippage, clrGreen);
}
}
}
}
}
// 4. Check for Entry Signals (Only if no orders are open for this symbol/magic)
if(CountOpenOrders() == 0)
{
// BUY SIGNAL: Bar 2 was Bearish, Bar 1 is Bullish (Color Flip)
if(isBearish2 && isBullish1)
{
double sl = (InpStopLoss > 0) ? Ask - InpStopLoss * m_point : 0;
double tp = (InpTakeProfit > 0) ? Ask + InpTakeProfit * m_point : 0;
int ticket = OrderSend(Symbol(), OP_BUY, InpLots, Ask, InpSlippage, sl, tp, "HA Buy", InpMagicNumber, 0, clrBlue);
if(ticket < 0) Print("OrderSend failed with error #", GetLastError());
}
// SELL SIGNAL: Bar 2 was Bullish, Bar 1 is Bearish (Color Flip)
if(isBullish2 && isBearish1)
{
double sl = (InpStopLoss > 0) ? Bid + InpStopLoss * m_point : 0;
double tp = (InpTakeProfit > 0) ? Bid - InpTakeProfit * m_point : 0;
int ticket = OrderSend(Symbol(), OP_SELL, InpLots, Bid, InpSlippage, sl, tp, "HA Sell", InpMagicNumber, 0, clrRed);
if(ticket < 0) Print("OrderSend failed with error #", GetLastError());
}
}
}
//+------------------------------------------------------------------+
//| Helper: Calculate Heikin Ashi values manually |
//| This makes the EA standalone (no custom indicators needed) |
//+------------------------------------------------------------------+
void CalculateHeikinAshi(int index, double& haOpen, double& haClose)
{
// HA Close is the average of OHLC
haClose = (Open[index] + High[index] + Low[index] + Close[index]) / 4.0;
// HA Open is the average of the PREVIOUS HA Open and HA Close.
// Since we don't store history in arrays here, we approximate by smoothing
// over a small loop of previous bars to stabilize the value.
double prevOpen = Open[index + 10];
double prevClose = Close[index + 10];
// Loop forward from 10 bars back to the requested index to calculate accurate HA Open
for(int i = index + 10; i >= index; i--)
{
double tempClose = (Open[i] + High[i] + Low[i] + Close[i]) / 4.0;
// Standard HA Open formula: (PrevHAOpen + PrevHAClose) / 2
double tempOpen = (prevOpen + prevClose) / 2.0;
prevOpen = tempOpen;
prevClose = tempClose;
}
haOpen = prevOpen;
}
//+------------------------------------------------------------------+
//| Helper: Count open orders for this EA |
//+------------------------------------------------------------------+
int CountOpenOrders()
{
int count = 0;
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == InpMagicNumber)
count++;
}
}
return count;
}
//+------------------------------------------------------------------+
How to Install and Run
- Open MetaTrader 4.
- Press
F4to open the MetaEditor. - Click New -> Expert Advisor (template) -> Name it "HeikinAshi_Bot".
- Delete everything in the new file and paste the code above.
- Press
F7to Compile. Ensure there are no errors. - Go back to the MT4 terminal. You will find "HeikinAshi_Bot" in the Navigator window under Expert Advisors.
- Drag it onto a chart (e.g., EURUSD H1).
- Ensure the "AutoTrading" button at the top is Green.
Key Features of This Code
- Standalone Calculation: It calculates Heikin-Ashi values mathematically inside the code (
CalculateHeikinAshifunction). It does not require you to download or install a separate custom indicator file (ex4), making it very reliable. - 5-Digit Broker Support: It automatically detects if your broker uses 5 digits (points) or 4 digits (pips) and adjusts the Stop Loss and Take Profit calculations accordingly.
- Risk Management: Includes inputs for Stop Loss and Take Profit.
- Exit Logic: It will close a trade immediately if the Heikin-Ashi candle changes color against your trade, even if the Stop Loss hasn't been hit yet. This is crucial for trend-following strategies.
Q&A
Q: Why does the bot calculate HA values using a loop?
A: The Heikin-Ashi "Open" price depends on the previous Heikin-Ashi Open and Close. To get an accurate value without storing years of history in memory, we calculate a small sequence (10 bars back) to let the mathematical formula stabilize. This ensures the values match what you see on your chart.
Q: Can I use this on any timeframe?
A: Yes. However, Heikin-Ashi strategies usually perform better on higher timeframes (H1, H4, Daily) because they filter out the "noise" found on M1 or M5 charts.
Q: Why does it wait for the candle to close (Index 1)?
A: Heikin-Ashi candles repaint while the current bar (Index 0) is forming. To avoid fake signals, the bot looks at Index 1 (the most recently completed bar) and Index 2 to confirm a color change.