Summary: Gold K-Bar Stabilizer EA is an MQL4 expert advisor for XAUUSD that identifies inside bars, momentum candles, and false breakout rejection signals. Designed for stable, low-risk operation on H1.




Gold K-Bar Stabilizer EA focuses purely on candlestick analysis without traditional indicators. It identifies inside bars (narrow range consolidation), momentum candles (large body with small wicks), and false breakout rejections (price spikes beyond range but closes back inside). The EA waits for a compression pattern (inside bar) followed by a momentum candle breaking the range, then enters on a pullback retest. A dynamic stop loss based on the inside bar's range and a risk-controlled profit target ensure stability.

Recommended Timeframe: H1
Trading Logic:
1. Inside Bar Detection: Current candle's high <= previous candle's high AND low >= previous candle's low.
2. Compression Confirmation: Require inside bar with body-to-range ratio > 0.6 (strong consolidation).
3. Momentum Signal: Next candle closes above inside bar high (bullish) or below inside bar low (bearish) with body > 2x wick.
4. Pullback Entry: Wait for price to retest the broken level (50-80% retracement) before entering.
5. Risk Management: Stop loss at opposite side of inside bar, take profit at 2x inside bar range, trailing stop at 1x range.

```mql4
//+------------------------------------------------------------------+
//| GoldKBarStabilizer.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 lot for gold)
input double BodyToRangeMinRatio = 0.6; // Minimum body/range ratio for inside bar strength
input double MomentumBodyWickRatio = 2.0; // Minimum body/wick ratio for momentum candle
input double RetracementMinPercent = 0.5; // Minimum retracement percent (50% of breakout range)
input double RetracementMaxPercent = 0.8; // Maximum retracement percent (80% of breakout range)
input double StopLossMultiplier = 1.0; // Stop loss as multiplier of inside bar range
input double TakeProfitMultiplier = 2.0; // Take profit as multiplier of inside bar range
input double TrailingActivate = 1.0; // Trailing activates at profit (x inside bar range)
input double TrailingStep = 0.5; // Trailing step (x inside bar range)
input int MagicNumber = 202418; // Unique EA identifier
input int MaxSpread = 35; // Maximum allowed spread in points (gold)
input double DailyLossLimit = 5.0; // Daily loss limit as percentage of balance
input bool UseFridayClose = true; // Close trades before Friday 21:00 GMT

//--- global variables
double dailyStartBalance = 0;
datetime lastBarTime = 0;
bool fridayCloseExecuted = false;
double insideBarHigh = 0;
double insideBarLow = 0;
double insideBarRange = 0;
double breakoutPrice = 0;
int breakoutDirection = 0; // 1 = long, -1 = short
datetime insideBarTime = 0;

//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
dailyStartBalance = AccountBalance();
lastBarTime = 0;
fridayCloseExecuted = false;
insideBarHigh = 0;
insideBarLow = 0;
breakoutDirection = 0;
return(INIT_SUCCEEDED);
}

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

//+------------------------------------------------------------------+
//| Calculate candle body to range ratio |
//+------------------------------------------------------------------+
double BodyToRangeRatio(int shift)
{
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 range = high - low;
if(range <= 0) return 0;
return body / range;
}

//+------------------------------------------------------------------+
//| Detect inside bar pattern |
//+------------------------------------------------------------------+
bool IsInsideBar(int shift)
{
double currHigh = iHigh(Symbol(), PERIOD_H1, shift);
double currLow = iLow(Symbol(), PERIOD_H1, shift);
double prevHigh = iHigh(Symbol(), PERIOD_H1, shift + 1);
double prevLow = iLow(Symbol(), PERIOD_H1, shift + 1);

return (currHigh <= prevHigh && currLow >= prevLow);
}

//+------------------------------------------------------------------+
//| Detect momentum candle (strong body, small wicks) |
//+------------------------------------------------------------------+
bool IsMomentumCandle(int shift, 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 maxWick = MathMax(upperWick, lowerWick);

if(maxWick <= 0) return false;
if(body / maxWick < MomentumBodyWickRatio) return false;

if(direction == 1) // bullish momentum
return (close > open && close > insideBarHigh);
else if(direction == -1) // bearish momentum
return (close < open && close < insideBarLow);

return false;
}

//+------------------------------------------------------------------+
//| Check for retracement entry opportunity |
//+------------------------------------------------------------------+
bool CheckRetracementEntry(int &cmd, double &entryPrice, double &stopLoss, double &takeProfit)
{
if(breakoutDirection == 0) return false;
if(insideBarRange <= 0) return false;

double currentPrice = (breakoutDirection == 1) ? Bid : Ask;
double breakoutHigh = insideBarHigh;
double breakoutLow = insideBarLow;
double retraceRange = insideBarRange * (RetracementMaxPercent - RetracementMinPercent);
double retraceLow = breakoutHigh - (insideBarRange * RetracementMaxPercent);
double retraceHigh = breakoutLow + (insideBarRange * RetracementMaxPercent);

if(breakoutDirection == 1) // long: price broke above inside bar high, now pulling back
{
if(currentPrice <= breakoutHigh && currentPrice >= retraceLow)
{
cmd = OP_BUY;
entryPrice = Ask;
stopLoss = insideBarLow - (insideBarRange * StopLossMultiplier * 0.3);
takeProfit = insideBarHigh + (insideBarRange * TakeProfitMultiplier);
return true;
}
}
else if(breakoutDirection == -1) // short: price broke below inside bar low, now pulling back
{
if(currentPrice >= breakoutLow && currentPrice <= retraceHigh)
{
cmd = OP_SELL;
entryPrice = Bid;
stopLoss = insideBarHigh + (insideBarRange * StopLossMultiplier * 0.3);
takeProfit = insideBarLow - (insideBarRange * TakeProfitMultiplier);
return true;
}
}

return false;
}

//+------------------------------------------------------------------+
//| Manage trailing stop |
//+------------------------------------------------------------------+
void ManageTrailing()
{
if(insideBarRange <= 0) return;

for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
double activateLevel = insideBarRange * TrailingActivate;
double step = insideBarRange * 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) >= 21)
{
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
if(CountPositions() > 0)
{
ManageTrailing();
return;
}

// Reset breakout state if inside bar is too old (more than 5 bars)
if(insideBarTime > 0 && TimeCurrent() - insideBarTime > 5 * 3600)
{
breakoutDirection = 0;
insideBarHigh = 0;
insideBarLow = 0;
insideBarRange = 0;
}

// Step 1: Detect inside bar on previous candle (shift=1)
if(IsInsideBar(1))
{
double ratio = BodyToRangeRatio(1);
if(ratio >= BodyToRangeMinRatio)
{
insideBarHigh = iHigh(Symbol(), PERIOD_H1, 1);
insideBarLow = iLow(Symbol(), PERIOD_H1, 1);
insideBarRange = insideBarHigh - insideBarLow;
insideBarTime = iTime(Symbol(), PERIOD_H1, 1);
breakoutDirection = 0;
}
}

// Step 2: After inside bar detected, check momentum breakout on current bar (shift=0)
if(insideBarRange > 0 && breakoutDirection == 0)
{
if(IsMomentumCandle(0, 1))
{
breakoutDirection = 1;
breakoutPrice = iClose(Symbol(), PERIOD_H1, 0);
}
else if(IsMomentumCandle(0, -1))
{
breakoutDirection = -1;
breakoutPrice = iClose(Symbol(), PERIOD_H1, 0);
}
}

// Step 3: After breakout, wait for retracement and enter
if(breakoutDirection != 0 && CountPositions() == 0)
{
int cmd = -1;
double entryPrice = 0, sl = 0, tp = 0;

if(CheckRetracementEntry(cmd, entryPrice, sl, tp))
{
int ticket = OrderSend(Symbol(), cmd, LotSize, entryPrice, 5, sl, tp, "Gold K-Bar", MagicNumber, 0, clrNONE);
if(ticket < 0)
{
Print("OrderSend failed: ", GetLastError());
}
else
{
Print("Retracement entry opened. Direction: ", cmd==OP_BUY?"BUY":"SELL");
// Reset to avoid duplicate entries for same pattern
breakoutDirection = 0;
}
}
}
}

//+------------------------------------------------------------------+
//| 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 leverage. This EA is provided as-is without any guarantee of profit. Test thoroughly on a demo account for at least 1 month before live trading. Past performance does not guarantee future results.