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:
  • Volatility Contraction: Wait for ATR(14) to fall below its 20-period moving average (calm market).

  • Volatility Expansion: Enter on the first H4 close above/below the 20-period SMA with ATR rising.

  • Entry Signal: Price closes above SMA20 (buy) or below SMA20 (sell) after volatility contraction.

  • 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.