Summary: Satoshi Pulse EA is a low-risk MQL4 expert advisor for Bitcoin (BTCUSD). It uses volatility breakout with ATR filter, trailing stop, and daily loss limit. Suitable for H4 timeframe.
Satoshi Pulse EA is designed specifically for Bitcoin (BTCUSD) with a low-risk, stable operational approach. It incorporates volatility breakout logic based on ATR, dynamic trailing stop, and strict money management to handle Bitcoin's extreme volatility and gap risk. The EA trades only when volatility expands from a calm period, using ATR to confirm genuine breakouts. Each trade has an ATR-based trailing stop and fixed risk-reward, with daily equity protection and Friday close.
Recommended Timeframe: H4
Trading Logic:
1. Volatility Contraction: Wait for ATR(14) to fall below its 20-period moving average (calm market).
2. Volatility Expansion: Enter on the first H4 close above/below the 20-period SMA with ATR rising.
3. Entry Signal: Price closes above SMA20 (buy) or below SMA20 (sell) after volatility contraction.
4. Risk Control: Trailing stop based on 2x ATR, maximum 1 trade at a time, daily loss limit 5%, maximum spread 150 points for BTC.
```mql4
//+------------------------------------------------------------------+
//| SatoshiPulseEA.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 BTCUSD)
input int ATRPeriod = 14; // Period for ATR volatility indicator
input int SMAPeriod = 20; // Period for SMA breakout filter
input double TrailATRFactor = 2.0; // ATR multiplier for trailing stop (2 = 2x ATR)
input int MagicNumber = 202413; // Unique EA identifier
input int MaxSpread = 150; // Maximum allowed spread for Bitcoin (in points)
input double DailyLossLimit = 5.0; // Daily loss limit in percentage of balance
input bool UseCloseOnFriday = true; // Close all trades before Friday 21:00
//--- global variables
double dailyStartBalance = 0;
datetime lastBarTime = 0;
bool isFridayCloseExecuted = false;
double lastATR = 0;
double atrMA = 0;
int barCount = 0;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
dailyStartBalance = AccountBalance();
lastBarTime = 0;
isFridayCloseExecuted = false;
lastATR = iATR(Symbol(), PERIOD_H4, ATRPeriod, 1);
atrMA = lastATR;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Comment("");
}
//+------------------------------------------------------------------+
//| 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 (crypto markets open but gaps common)
if(UseCloseOnFriday && !isFridayCloseExecuted)
{
datetime currentTime = TimeCurrent();
if(TimeDayOfWeek(currentTime) == 5 && TimeHour(currentTime) >= 21)
{
CloseAllOrders();
isFridayCloseExecuted = true;
return;
}
if(TimeDayOfWeek(currentTime) != 5)
isFridayCloseExecuted = false;
}
// Spread filter for Bitcoin
if(MarketInfo(Symbol(), MODE_SPREAD) > MaxSpread)
{
Comment("Spread too high for BTC");
return;
}
// Trailing stop management for existing positions
TrailAllPositions();
// New bar logic (H4)
if(Time[0] == lastBarTime)
return;
lastBarTime = Time[0];
barCount++;
// Check for existing position
if(CountPositions() > 0)
return;
// Calculate ATR and its moving average
double currentATR = iATR(Symbol(), PERIOD_H4, ATRPeriod, 1);
if(currentATR <= 0) currentATR = lastATR;
// Update rolling ATR MA (simple over last 20 bars)
double sma20 = iMA(Symbol(), PERIOD_H4, SMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);
double close1 = iClose(Symbol(), PERIOD_H4, 1);
// Volatility contraction condition: ATR below its 20-period average
double atrSMA = iMA(Symbol(), PERIOD_H4, SMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);
// Actually compute ATR SMA properly
double atrSum = 0;
for(int i = 1; i <= SMAPeriod; i++)
atrSum += iATR(Symbol(), PERIOD_H4, ATRPeriod, i);
atrSMA = atrSum / SMAPeriod;
bool volatilityContracted = (currentATR < atrSMA);
bool volatilityExpanding = (currentATR > lastATR);
// Entry logic: price breaks SMA20 after volatility contraction
int cmd = -1;
double sl = 0, tp = 0;
double entryPrice = 0;
if(volatilityContracted && volatilityExpanding)
{
// Buy breakout: close above SMA20
if(close1 > sma20 && close1 > iOpen(Symbol(), PERIOD_H4, 1))
{
cmd = OP_BUY;
entryPrice = Ask;
sl = entryPrice - (TrailATRFactor * currentATR);
tp = entryPrice + (TrailATRFactor * currentATR * 1.5); // 1.5:1 risk-reward
}
// Sell breakout: close below SMA20
else if(close1 < sma20 && close1 < iOpen(Symbol(), PERIOD_H4, 1))
{
cmd = OP_SELL;
entryPrice = Bid;
sl = entryPrice + (TrailATRFactor * currentATR);
tp = entryPrice - (TrailATRFactor * currentATR * 1.5);
}
}
lastATR = currentATR;
if(cmd != -1)
{
int ticket = OrderSend(Symbol(), cmd, LotSize, entryPrice, 5, sl, tp, "Satoshi Pulse EA", MagicNumber, 0, clrNONE);
if(ticket < 0)
Print("OrderSend failed: ", GetLastError());
}
}
//+------------------------------------------------------------------+
//| Trailing stop for all open positions |
//+------------------------------------------------------------------+
void TrailAllPositions()
{
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, 0);
if(atr <= 0) atr = lastATR;
double trailDistance = TrailATRFactor * atr;
double newSL = 0;
if(OrderType() == OP_BUY)
{
newSL = Bid - trailDistance;
if(newSL > OrderStopLoss() && OrderStopLoss() != 0)
OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE);
else if(OrderStopLoss() == 0)
OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE);
}
else if(OrderType() == OP_SELL)
{
newSL = Ask + trailDistance;
if(newSL < OrderStopLoss() && OrderStopLoss() != 0)
OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE);
else if(OrderStopLoss() == 0)
OrderModify(OrderTicket(), OrderOpenPrice(), newSL, OrderTakeProfit(), 0, clrNONE);
}
}
}
}
}
//+------------------------------------------------------------------+
//| 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: Bitcoin and cryptocurrency trading carries extreme risk. 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.