Ichimoku Cloud MT5 Indicator: MQL5 Code, Trading Rules & EA
This page provides a complete MQL5 implementation of the Ichimoku Cloud indicator for MetaTrader 5, including the five core components: Tenkan-sen, Kijun-sen, Senkou Span A, Senkou Span B, and Chikou Span. It covers trading rules for bullish and bearish cloud setups across forex, indices, and commodities, along with a ready-to-compile Expert Advisor that automates cloud-based entries and exits.
Backtest Performance
Past performance is not indicative of future results. Backtest statistics are based on historical data and do not guarantee future profits. Trading involves significant risk of loss. This content is for educational purposes only and does not constitute financial advice.
Strategy Logic
Entry Conditions
A long trade is triggered when the price closes above both Senkou Span A and Senkou Span B (inside a bullish cloud), the Tenkan-sen crosses above the Kijun-sen, and the Chikou Span is above the price from 26 periods ago. A short trade is triggered by the mirror conditions: price below a bearish cloud, Tenkan-sen crossing below Kijun-sen, and Chikou Span below historical price.
Exit Conditions
Long positions are closed when the Tenkan-sen crosses back below the Kijun-sen, or when price re-enters and closes inside the cloud, signalling trend exhaustion. A fixed stop-loss is placed below Senkou Span B at trade entry, and a trailing mechanism tightens the stop as the Kijun-sen advances in the direction of the trade.
MQL5 Expert Advisor Code
//+------------------------------------------------------------------+
//| IchimokuCloudEA.mq5 |
//| Ichimoku Cloud Expert Advisor for MetaTrader 5 |
//| Pineify.app — AI-powered MQL5 & Pine Script code generation |
//+------------------------------------------------------------------+
#property copyright "Pineify.app"
#property version "1.00"
#property strict
#include <Trade\Trade.mqh>
//--- Input parameters
input int InpTenkan = 9; // Tenkan-sen period
input int InpKijun = 26; // Kijun-sen period
input int InpSenkouB = 52; // Senkou Span B period
input double InpLotSize = 0.1; // Trade lot size
input int InpMagicNumber = 202600; // Magic number
input int InpSlippage = 10; // Max slippage (points)
input bool InpUseTrailing = true; // Enable Kijun trailing stop
//--- Global handles and objects
int g_ichiHandle = INVALID_HANDLE;
CTrade g_trade;
//+------------------------------------------------------------------+
//| Expert initialisation |
//+------------------------------------------------------------------+
int OnInit()
{
g_ichiHandle = iIchimoku(_Symbol, PERIOD_CURRENT,
InpTenkan, InpKijun, InpSenkouB);
if(g_ichiHandle == INVALID_HANDLE)
{
Print("ERROR: Failed to create Ichimoku handle — ", GetLastError());
return INIT_FAILED;
}
g_trade.SetExpertMagicNumber(InpMagicNumber);
g_trade.SetDeviationInPoints(InpSlippage);
g_trade.SetTypeFilling(ORDER_FILLING_FOK);
Print("IchimokuCloudEA initialised on ", _Symbol,
" [Tenkan=", InpTenkan,
" Kijun=", InpKijun,
" SenkouB=", InpSenkouB, "]");
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Expert tick handler |
//+------------------------------------------------------------------+
void OnTick()
{
//--- Only act on a new completed bar
static datetime s_lastBar = 0;
datetime currentBar = (datetime)SeriesInfoInteger(_Symbol, PERIOD_CURRENT,
SERIES_LASTBAR_DATE);
if(currentBar == s_lastBar)
return;
s_lastBar = currentBar;
//--- Fetch Ichimoku buffers (index 1 = previous closed bar)
double tenkan[3], kijun[3], spanA[3], spanB[3], chikou[3];
if(CopyBuffer(g_ichiHandle, 0, 1, 3, tenkan) < 3) return;
if(CopyBuffer(g_ichiHandle, 1, 1, 3, kijun) < 3) return;
if(CopyBuffer(g_ichiHandle, 2, 1, 3, spanA) < 3) return;
if(CopyBuffer(g_ichiHandle, 3, 1, 3, spanB) < 3) return;
if(CopyBuffer(g_ichiHandle, 4, 1, 3, chikou) < 3) return;
double closePrice[1];
if(CopyClose(_Symbol, PERIOD_CURRENT, 1, 1, closePrice) < 1) return;
double close = closePrice[0];
double cloudTop = MathMax(spanA[0], spanB[0]);
double cloudBottom = MathMin(spanA[0], spanB[0]);
//--- Signal detection (index 0 = bar-1, index 1 = bar-2 for crossover)
bool tkCrossUp = tenkan[0] > kijun[0] && tenkan[1] <= kijun[1];
bool tkCrossDown = tenkan[0] < kijun[0] && tenkan[1] >= kijun[1];
bool aboveCloud = close > cloudTop;
bool belowCloud = close < cloudBottom;
bool chikouBull = chikou[0] > close; // simplified: chikou vs current
bool chikouBear = chikou[0] < close;
bool longSignal = tkCrossUp && aboveCloud && chikouBull;
bool shortSignal = tkCrossDown && belowCloud && chikouBear;
//--- Manage trailing stop on existing positions
if(InpUseTrailing)
ManageTrailing(kijun[0]);
//--- Check existing positions before opening new ones
if(HasPosition(POSITION_TYPE_BUY) || HasPosition(POSITION_TYPE_SELL))
{
CheckExit(tenkan[0], kijun[0], cloudTop, cloudBottom, close);
return;
}
//--- Open new positions
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double pt = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
if(longSignal)
{
double sl = cloudBottom - 5 * pt;
g_trade.Buy(InpLotSize, _Symbol, ask, sl, 0,
"Ichimoku Long");
PrintFormat("LONG opened | Close=%.5f CloudBot=%.5f SL=%.5f",
close, cloudBottom, sl);
}
else if(shortSignal)
{
double sl = cloudTop + 5 * pt;
g_trade.Sell(InpLotSize, _Symbol, bid, sl, 0,
"Ichimoku Short");
PrintFormat("SHORT opened | Close=%.5f CloudTop=%.5f SL=%.5f",
close, cloudTop, sl);
}
}
//+------------------------------------------------------------------+
//| Check exit conditions for open positions |
//+------------------------------------------------------------------+
void CheckExit(double tenkan, double kijun,
double cloudTop, double cloudBottom, double close)
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != InpMagicNumber) continue;
ENUM_POSITION_TYPE type =
(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
bool exitLong = (type == POSITION_TYPE_BUY) &&
(tenkan < kijun ||
(close < cloudTop && close > cloudBottom));
bool exitShort = (type == POSITION_TYPE_SELL) &&
(tenkan > kijun ||
(close > cloudBottom && close < cloudTop));
if(exitLong || exitShort)
{
g_trade.PositionClose(ticket);
PrintFormat("Position %d closed — exit signal", (int)ticket);
}
}
}
//+------------------------------------------------------------------+
//| Trailing stop along Kijun-sen |
//+------------------------------------------------------------------+
void ManageTrailing(double kijun)
{
double pt = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != InpMagicNumber) continue;
ENUM_POSITION_TYPE type =
(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
double currentSL = PositionGetDouble(POSITION_SL);
if(type == POSITION_TYPE_BUY)
{
double newSL = kijun - 5 * pt;
if(newSL > currentSL)
g_trade.PositionModify(ticket, newSL,
PositionGetDouble(POSITION_TP));
}
else if(type == POSITION_TYPE_SELL)
{
double newSL = kijun + 5 * pt;
if(newSL < currentSL || currentSL == 0)
g_trade.PositionModify(ticket, newSL,
PositionGetDouble(POSITION_TP));
}
}
}
//+------------------------------------------------------------------+
//| Check whether a position of given type is open |
//+------------------------------------------------------------------+
bool HasPosition(ENUM_POSITION_TYPE posType)
{
for(int i = 0; i < PositionsTotal(); i++)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != InpMagicNumber) continue;
if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == posType)
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| Expert deinitialization |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(g_ichiHandle != INVALID_HANDLE)
IndicatorRelease(g_ichiHandle);
PrintFormat("IchimokuCloudEA deinitialized — reason %d", reason);
}
//+------------------------------------------------------------------+Copy this code into MetaEditor (F4 in MT5), save in the Experts folder, and compile with F7.
Generate a Custom Multi-pair Trend EA →
Pineify AI generates syntactically validated MQL5 Expert Advisors from plain English descriptions. Customize entry logic, risk management, and trading sessions — no coding required.
Pine Script vs MQL5: Same Strategy, Different Platforms
| Aspect | Pine Script (TradingView) | MQL5 (MetaTrader 5) |
|---|---|---|
| Execution | Bar-based, backtesting only | Tick-based, live trading |
| Deployment | TradingView alerts | Runs 24/5 on VPS/MT5 |
| Broker access | Via TradingView broker integration | Direct broker connectivity |
| Backtesting | Built-in, no data download needed | Strategy Tester, tick data required |
| Code complexity | Simpler, functional syntax | C++-like, more powerful |
Pineify supports both platforms. Prototype your strategy visually in TradingView Pine Script, then generate the equivalent MQL5 EA for live MT5 trading.