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:
``
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.