Summary: BTC Volatility Shield EA is a low-risk MQL4 expert advisor for Bitcoin (BTCUSD). It uses ATR volatility bands, ADX trend filter, and dynamic stop loss. Suitable for H4 timeframe.




BTC Volatility Shield EA is designed specifically for Bitcoin (BTCUSD) to handle its extreme volatility and erratic price behavior. The EA combines ATR-based volatility bands with ADX trend strength filter to avoid ranging and low-volatility chop zones. A unique dynamic position sizing reduces lot size during high volatility periods. Each trade is protected by a trailing stop mechanism that locks in profits as price moves favorably. The EA also includes a weekly drawdown limit and a post-loss cooldown timer.

Recommended Timeframe: H4
Trading Logic:
1. Volatility Regime: ATR(14) calculates current volatility; if ATR > ATR_Max_Threshold, skip trading.
2. Trend Strength: ADX(14) > ADX_Min (25) ensures trending market, no trades in ranging markets.
3. Entry Signal: Price touches lower ATR band (MA20 - ATR*BandMultiplier) for buys, or upper band for sells, with ADX confirming direction.
4. Risk Control: Dynamic trailing stop starts at 5x ATR, trailing step 2x ATR. Maximum 1 trade, weekly loss limit 8%.

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

//--- input parameters with comments
input double BaseLotSize = 0.01; // Base lot size (0.01 BTC)
input int ATRPeriod = 14; // Period for ATR volatility indicator
input double ATRMaxMultiplier = 2.5; // Max ATR multiplier (skip if ATR > avgATR * this)
input double BandMultiplier = 1.8; // ATR band multiplier for entry levels
input int ADXPeriod = 14; // Period for ADX trend strength
input int ADXMinThreshold = 25; // Minimum ADX value to allow trading
input int MAPeriod = 20; // MA period for band center
input int TrailingStart = 5; // Trailing stop start in ATR multiples
input int TrailingStep = 2; // Trailing stop step in ATR multiples
input int MagicNumber = 202413; // Unique EA identifier
input int MaxSpread = 150; // Maximum allowed spread (in points, BTC is wide)
input double WeeklyLossLimit = 8.0; // Weekly loss limit in percentage of balance
input int CooldownMinutes = 60; // Cooldown after a losing trade (minutes)
input bool UseCloseOnSunday = true; // Close all trades before Sunday 22:00

//--- global variables
double weeklyStartBalance = 0;
datetime lastBarTime = 0;
bool isSundayCloseExecuted = false;
datetime lastLossTime = 0;
double avgATR = 0;
double currentTrailingSL = 0;

//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
weeklyStartBalance = AccountBalance();
lastBarTime = 0;
isSundayCloseExecuted = false;
lastLossTime = 0;
avgATR = iATR(Symbol(), PERIOD_H4, ATRPeriod, 1);
if(avgATR <= 0) avgATR = 500;
return(INIT_SUCCEEDED);
}

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

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

// Sunday close before weekend gap (Bitcoin trades 24/7 but broker may have gaps)
if(UseCloseOnSunday && !isSundayCloseExecuted)
{
datetime currentTime = TimeCurrent();
if(TimeDayOfWeek(currentTime) == 0 && TimeHour(currentTime) >= 22)
{
CloseAllOrders();
isSundayCloseExecuted = true;
return;
}
if(TimeDayOfWeek(currentTime) != 0)
isSundayCloseExecuted = false;
}

// Cooldown after losing trade
if(lastLossTime > 0 && TimeCurrent() - lastLossTime < CooldownMinutes * 60)
{
Comment("Cooldown period active after loss");
return;
}

// Spread filter (Bitcoin spread is wider)
if(MarketInfo(Symbol(), MODE_SPREAD) > MaxSpread)
{
Comment("Spread too high for BTC");
return;
}

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

// Check for existing position
if(CountPositions() > 0)
{
// Trailing stop management for open position
ManageTrailingStop();
return;
}

// Get ATR and update average
double atr = iATR(Symbol(), PERIOD_H4, ATRPeriod, 1);
double atrThreshold = avgATR * ATRMaxMultiplier;
if(atr > atrThreshold && atrThreshold > 0)
{
Comment("Extreme volatility, no trade. ATR: ", atr);
return;
}
avgATR = (avgATR * 0.95) + (atr * 0.05);

// ADX trend strength filter
double adx = iADX(Symbol(), PERIOD_H4, ADXPeriod, PRICE_CLOSE, MODE_MAIN, 1);
if(adx < ADXMinThreshold)
{
Comment("No strong trend, ADX: ", adx);
return;
}

// Moving average center for ATR bands
double ma = iMA(Symbol(), PERIOD_H4, MAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);
double close1 = iClose(Symbol(), PERIOD_H4, 1);

double lowerBand = ma - (atr * BandMultiplier);
double upperBand = ma + (atr * BandMultiplier);

int cmd = -1;
double sl = 0, tp = 0;
double dynamicLot = BaseLotSize;

// Reduce lot size if ATR is above average
if(atr > avgATR)
dynamicLot = BaseLotSize * (avgATR / atr);
if(dynamicLot < 0.01) dynamicLot = 0.01;

// Buy signal: price touched lower band, ADX confirms upward trend (DI+ > DI-)
double diPlus = iADX(Symbol(), PERIOD_H4, ADXPeriod, PRICE_CLOSE, MODE_PLUSDI, 1);
double diMinus = iADX(Symbol(), PERIOD_H4, ADXPeriod, PRICE_CLOSE, MODE_MINUSDI, 1);

if(close1 <= lowerBand && diPlus > diMinus)
{
cmd = OP_BUY;
sl = SymbolInfoDouble(Symbol(), SYMBOL_BID) - (atr * TrailingStart);
tp = SymbolInfoDouble(Symbol(), SYMBOL_BID) + (atr * TrailingStart * 2);
}
// Sell signal: price touched upper band, ADX confirms downward trend (DI- > DI+)
else if(close1 >= upperBand && diMinus > diPlus)
{
cmd = OP_SELL;
sl = SymbolInfoDouble(Symbol(), SYMBOL_ASK) + (atr * TrailingStart);
tp = SymbolInfoDouble(Symbol(), SYMBOL_ASK) - (atr * TrailingStart * 2);
}

if(cmd != -1)
{
int ticket = OrderSend(Symbol(), cmd, dynamicLot, (cmd==OP_BUY?Ask:Bid), 3, sl, tp, "BTC Volatility EA", MagicNumber, 0, clrNONE);
if(ticket < 0)
{
Print("OrderSend failed: ", GetLastError());
}
else
{
currentTrailingSL = (cmd==OP_BUY) ? sl : sl;
}
}
}

//+------------------------------------------------------------------+
//| Manage trailing stop for open position |
//+------------------------------------------------------------------+
void ManageTrailingStop()
{
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
double atr = iATR(Symbol(), PERIOD_H4, ATRPeriod, 1);
if(atr <= 0) atr = avgATR;

double newSL = 0;
if(OrderType() == OP_BUY)
{
newSL = Bid - (atr * TrailingStep);
if(newSL > OrderStopLoss())
{
if(OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE))
Print("Trailing stop updated for BUY #", OrderTicket());
}
}
else if(OrderType() == OP_SELL)
{
newSL = Ask + (atr * TrailingStep);
if(newSL < OrderStopLoss() || OrderStopLoss() == 0)
{
if(OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE))
Print("Trailing stop updated for SELL #", OrderTicket());
}
}
break;
}
}
}
}

//+------------------------------------------------------------------+
//| 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, 3, clrNONE);
else if(OrderType() == OP_SELL)
OrderClose(OrderTicket(), OrderLots(), Ask, 3, clrNONE);
}
}
}
}

//+------------------------------------------------------------------+
//| Record loss time when order closes in loss (call from external) |
//+------------------------------------------------------------------+
void RecordLoss()
{
lastLossTime = TimeCurrent();
}
//+------------------------------------------------------------------+
```
Reference: Original MQL4 code for educational purposes.
Disclaimer: Bitcoin trading carries extremely high risk due to volatility. This EA is provided as-is without any guarantee of profit. Test thoroughly on demo before live trading. Past performance does not guarantee future results.