Summary: Gold CandleFlow EA is an MQL4 expert advisor for gold that identifies high-probability candlestick patterns (inside bars, pin bars, engulfing) with trend alignment and ATR filter. Suitable for H1.




Gold CandleFlow EA is built specifically for gold (XAUUSD) using pure candlestick price action. Instead of complex indicators, it focuses on reliable reversal and continuation patterns: inside bars, pin bars, and engulfing candles. The EA combines pattern recognition with a simple EMA trend filter and ATR volatility filter to reduce false signals. Each trade includes a fixed stop loss based on the pattern's high/low and a take profit at 2.5x risk. A trailing stop helps capture extended moves.

Recommended Timeframe: H1
Trading Logic:
1. Pattern Detection: Identify inside bar (range inside previous bar), pin bar (long wick), or engulfing candle on the closed bar.
2. Trend Filter: EMA(50) provides direction (long only above, short only below).
3. Volatility Filter: ATR(14) must be below 1.8x average to avoid extreme volatility.
4. Entry: At the start of next bar, place pending order at pattern breakout level with stop beyond pattern extreme.

```mql4
//+------------------------------------------------------------------+
//| GoldCandleFlowEA.mq4 |
//+------------------------------------------------------------------+
#property copyright ""
#property link ""
#property version "1.00"
#property strict

//--- input parameters with comments
input double LotSize = 0.01; // Fixed lot size (0.01 lots)
input int TrendMAPeriod = 50; // EMA period for trend filter
input int ATRPeriod = 14; // ATR period for volatility filter
input double MaxATRMultiplier = 1.8; // Max ATR multiplier (skip high volatility)
input double RiskRewardRatio = 2.5; // Risk reward ratio (TP = SL * this)
input double TrailingStart = 1.2; // Trailing activates after profit x risk
input double TrailingStep = 0.5; // Trailing step x risk
input int MagicNumber = 202418; // Unique EA identifier
input int MaxSpread = 35; // Maximum allowed spread in points
input double DailyLossLimit = 5.0; // Daily loss limit as percentage of balance
input bool UseFridayClose = true; // Close trades before Friday 20:00 GMT

//--- global variables
double dailyStartBalance = 0;
datetime lastBarTime = 0;
bool fridayCloseExecuted = false;
double avgATR = 0;
double lastPatternSL = 0;
double lastPatternRisk = 0;

//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
dailyStartBalance = AccountBalance();
lastBarTime = 0;
fridayCloseExecuted = false;
avgATR = iATR(Symbol(), PERIOD_H1, ATRPeriod, 1);
if(avgATR <= 0) avgATR = 200 * Point;
return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Comment("");
}

//+------------------------------------------------------------------+
//| Detect Inside Bar Pattern |
//+------------------------------------------------------------------+
bool IsInsideBar(int shift, double &patternHigh, double &patternLow)
{
double high = iHigh(Symbol(), PERIOD_H1, shift);
double low = iLow(Symbol(), PERIOD_H1, shift);
double prevHigh = iHigh(Symbol(), PERIOD_H1, shift + 1);
double prevLow = iLow(Symbol(), PERIOD_H1, shift + 1);

patternHigh = high;
patternLow = low;

return (high <= prevHigh && low >= prevLow);
}

//+------------------------------------------------------------------+
//| Detect Pin Bar Pattern (long wick, small body) |
//+------------------------------------------------------------------+
bool IsPinBar(int shift, double &patternHigh, double &patternLow, int &direction)
{
double open = iOpen(Symbol(), PERIOD_H1, shift);
double close = iClose(Symbol(), PERIOD_H1, shift);
double high = iHigh(Symbol(), PERIOD_H1, shift);
double low = iLow(Symbol(), PERIOD_H1, shift);

double body = MathAbs(close - open);
double upperWick = high - MathMax(open, close);
double lowerWick = MathMin(open, close) - low;
double totalRange = high - low;

if(totalRange <= 0) return false;

// Bullish pin bar (hammer): lower wick > 2 * body, upper wick small
if(lowerWick > 2 * body && upperWick < body)
{
direction = 1; // bullish
patternHigh = high;
patternLow = low;
return true;
}
// Bearish pin bar (shooting star): upper wick > 2 * body, lower wick small
else if(upperWick > 2 * body && lowerWick < body)
{
direction = -1; // bearish
patternHigh = high;
patternLow = low;
return true;
}

return false;
}

//+------------------------------------------------------------------+
//| Detect Engulfing Pattern |
//+------------------------------------------------------------------+
bool IsEngulfing(int shift, double &patternHigh, double &patternLow, int &direction)
{
double open = iOpen(Symbol(), PERIOD_H1, shift);
double close = iClose(Symbol(), PERIOD_H1, shift);
double prevOpen = iOpen(Symbol(), PERIOD_H1, shift + 1);
double prevClose = iClose(Symbol(), PERIOD_H1, shift + 1);
double high = iHigh(Symbol(), PERIOD_H1, shift);
double low = iLow(Symbol(), PERIOD_H1, shift);
double prevHigh = iHigh(Symbol(), PERIOD_H1, shift + 1);
double prevLow = iLow(Symbol(), PERIOD_H1, shift + 1);

// Bullish engulfing: previous bearish, current bullish, covers previous
if(prevClose < prevOpen && close > open && close > prevOpen && open < prevClose)
{
direction = 1;
patternHigh = high;
patternLow = low;
return true;
}
// Bearish engulfing: previous bullish, current bearish, covers previous
else if(prevClose > prevOpen && close < open && close < prevOpen && open > prevClose)
{
direction = -1;
patternHigh = high;
patternLow = low;
return true;
}

return false;
}

//+------------------------------------------------------------------+
//| Manage trailing stop |
//+------------------------------------------------------------------+
void ManageTrailingStop(double riskAmount)
{
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
double activateLevel = riskAmount * TrailingStart;
double step = riskAmount * TrailingStep;

double newSL = 0;
if(OrderType() == OP_BUY)
{
double profit = Bid - OrderOpenPrice();
if(profit >= activateLevel)
{
newSL = Bid - step;
if(newSL > OrderStopLoss())
OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE);
}
}
else if(OrderType() == OP_SELL)
{
double profit = OrderOpenPrice() - Ask;
if(profit >= activateLevel)
{
newSL = Ask + step;
if(newSL < OrderStopLoss() || OrderStopLoss() == 0)
OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE);
}
}
break;
}
}
}
}

//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Daily equity protection
double currentEquity = AccountEquity();
double lossPercent = (dailyStartBalance - currentEquity) / dailyStartBalance * 100;
if(lossPercent >= DailyLossLimit)
{
Comment("Daily loss limit reached. No new trades.");
return;
}

// Friday close before weekend
if(UseFridayClose && !fridayCloseExecuted)
{
datetime currentTime = TimeCurrent();
if(TimeDayOfWeek(currentTime) == 5 && TimeHour(currentTime) >= 20)
{
CloseAllOrders();
fridayCloseExecuted = true;
return;
}
if(TimeDayOfWeek(currentTime) != 5)
fridayCloseExecuted = false;
}

// Spread filter
if(MarketInfo(Symbol(), MODE_SPREAD) > MaxSpread)
{
Comment("Spread too high: ", MarketInfo(Symbol(), MODE_SPREAD));
return;
}

// New bar logic (H1)
if(Time[0] == lastBarTime)
return;
lastBarTime = Time[0];

// Manage existing position
int posCount = CountPositions();
if(posCount > 0)
{
if(lastPatternRisk > 0)
ManageTrailingStop(lastPatternRisk);
return;
}

// Volatility filter
double atr = iATR(Symbol(), PERIOD_H1, ATRPeriod, 1);
if(atr > 0) avgATR = (avgATR * 0.95) + (atr * 0.05);
if(atr > avgATR * MaxATRMultiplier)
{
Comment("Volatility too high. ATR: ", atr);
return;
}

// Trend filter
double ema = iMA(Symbol(), PERIOD_H1, TrendMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
double close1 = iClose(Symbol(), PERIOD_H1, 1);

// Pattern detection on previous candle (shift 1)
double patternHigh = 0, patternLow = 0;
int patternDir = 0;
bool patternFound = false;

if(IsInsideBar(1, patternHigh, patternLow))
{
patternFound = true;
// Inside bar direction follows breakout direction (determined by EMA trend)
patternDir = (close1 > ema) ? 1 : -1;
}
else if(IsPinBar(1, patternHigh, patternLow, patternDir))
{
patternFound = true;
}
else if(IsEngulfing(1, patternHigh, patternLow, patternDir))
{
patternFound = true;
}

if(!patternFound)
{
Comment("No candlestick pattern detected");
return;
}

// Check trend alignment
bool trendOk = (patternDir == 1 && close1 > ema) || (patternDir == -1 && close1 < ema);
if(!trendOk)
{
Comment("Pattern direction against trend");
return;
}

// Calculate entry, stop, take profit
double entry = 0, sl = 0, tp = 0;
double riskAmount = 0;

if(patternDir == 1) // Bullish - buy above pattern high
{
entry = patternHigh + 10 * Point;
sl = patternLow - 10 * Point;
tp = entry + (entry - sl) * RiskRewardRatio;
riskAmount = entry - sl;
}
else if(patternDir == -1) // Bearish - sell below pattern low
{
entry = patternLow - 10 * Point;
sl = patternHigh + 10 * Point;
tp = entry - (sl - entry) * RiskRewardRatio;
riskAmount = sl - entry;
}

if(entry > 0 && sl > 0 && tp > 0)
{
int ticket = OrderSend(Symbol(), (patternDir==1?OP_BUY:OP_SELL), LotSize, entry, 5, sl, tp, "Gold CandleFlow", MagicNumber, 0, clrNONE);
if(ticket > 0)
{
lastPatternRisk = riskAmount;
Print("Trade opened based on candlestick pattern");
}
else
Print("OrderSend failed: ", GetLastError());
}
}

//+------------------------------------------------------------------+
//| Count open positions with this MagicNumber |
//+------------------------------------------------------------------+
int CountPositions()
{
int count = 0;
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
count++;
}
}
return count;
}

//+------------------------------------------------------------------+
//| Close all orders for this symbol and magic |
//+------------------------------------------------------------------+
void CloseAllOrders()
{
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
if(OrderType() == OP_BUY)
OrderClose(OrderTicket(), OrderLots(), Bid, 5, clrNONE);
else if(OrderType() == OP_SELL)
OrderClose(OrderTicket(), OrderLots(), Ask, 5, clrNONE);
}
}
}
}
//+------------------------------------------------------------------+
```
Reference: Original MQL4 code for educational purposes.
Disclaimer: Gold trading involves significant risk due to high volatility and market gaps. This EA is provided as-is without any guarantee of profit. Always test on a demo account for at least one month before live deployment. Past performance does not guarantee future results.