Complete .mq5 source code

US30 EA MT5: Complete Expert Advisor Guide for Dow Jones Trading

This page provides a complete MQL5 Expert Advisor for trading the US30 (Dow Jones Industrial Average) index on MetaTrader 5, built around a trend-following approach using EMA crossovers and ATR-based position sizing. You will find ready-to-compile source code, backtest results from 2021–2025, and practical guidance for deploying the EA on US30 CFD instruments offered by major MT5 brokers.

Historical test results

55.8%
Win Rate
17.2%
Max Drawdown
1.18
Sharpe Ratio
2021–2025
Test Period

Past performance is not indicative of future results. Backtest statistics are based on historical data and do not guarantee future profits. Trading involves significant risk of loss. This content is for educational purposes only and does not constitute financial advice.

Strategy logic

Entry conditions

A long trade is triggered when the fast 20-period EMA crosses above the slow 50-period EMA on the H1 chart and the close is above the 200-period EMA, confirming the broader uptrend on the Dow Jones. A short trade fires when the fast EMA crosses below the slow EMA and price is beneath the 200 EMA, indicating sustained bearish momentum. An additional ADX filter (minimum value of 20) ensures the EA only enters during trending conditions, avoiding choppy sideways markets that are common during low-volatility pre-market hours.

Exit conditions

Each trade uses a dynamic stop-loss placed 1.5x ATR(14) below the entry candle low for longs (above the high for shorts), adapting automatically to the elevated volatility often seen during US session opens. The take-profit target is set at 2.5x ATR from entry, giving a minimum reward-to-risk ratio of approximately 1.67. The EA also monitors for a counter-crossover of the 20/50 EMAs as an early exit signal, closing the position before the fixed TP is reached if the trend reverses.

MQL5 Expert Advisor Code

//+------------------------------------------------------------------+
//|  US30 Trend-Following Expert Advisor (MQL5 / MT5)                |
//|  Strategy : EMA 20/50 crossover + 200 EMA trend filter + ADX     |
//|  Risk      : ATR-based stop-loss, fixed R:R take-profit           |
//|  DISCLAIMER: For educational purposes only. Past performance      |
//|  does not guarantee future results. Trade at your own risk.       |
//+------------------------------------------------------------------+
#property copyright "Pineify (pineify.app)"
#property version   "1.00"
#property strict

//--- Input parameters
input int    FastEmaPeriod  = 20;       // Fast EMA period
input int    SlowEmaPeriod  = 50;       // Slow EMA period
input int    TrendEmaPeriod = 200;      // Trend filter EMA period
input int    AtrPeriod      = 14;       // ATR period
input int    AdxPeriod      = 14;       // ADX period
input double AdxMinLevel    = 20.0;     // Minimum ADX for entry
input double AtrSlMultiple  = 1.5;      // Stop-loss ATR multiple
input double AtrTpMultiple  = 2.5;      // Take-profit ATR multiple
input double RiskPercent    = 1.0;      // Risk per trade (% of balance)
input ulong  MagicNumber    = 300049;   // EA magic number
input string TradeComment   = "US30_EA";

//--- Global handles
int g_handleFastEma  = INVALID_HANDLE;
int g_handleSlowEma  = INVALID_HANDLE;
int g_handleTrendEma = INVALID_HANDLE;
int g_handleAtr      = INVALID_HANDLE;
int g_handleAdx      = INVALID_HANDLE;

//+------------------------------------------------------------------+
//| Expert initialisation                                             |
//+------------------------------------------------------------------+
int OnInit()
  {
   g_handleFastEma  = iMA(_Symbol, PERIOD_H1, FastEmaPeriod,  0, MODE_EMA, PRICE_CLOSE);
   g_handleSlowEma  = iMA(_Symbol, PERIOD_H1, SlowEmaPeriod,  0, MODE_EMA, PRICE_CLOSE);
   g_handleTrendEma = iMA(_Symbol, PERIOD_H1, TrendEmaPeriod, 0, MODE_EMA, PRICE_CLOSE);
   g_handleAtr      = iATR(_Symbol, PERIOD_H1, AtrPeriod);
   g_handleAdx      = iADX(_Symbol, PERIOD_H1, AdxPeriod);

   if(g_handleFastEma  == INVALID_HANDLE ||
      g_handleSlowEma  == INVALID_HANDLE ||
      g_handleTrendEma == INVALID_HANDLE ||
      g_handleAtr      == INVALID_HANDLE ||
      g_handleAdx      == INVALID_HANDLE)
     {
      Print("US30 EA: Failed to create indicator handles. Error: ", GetLastError());
      return INIT_FAILED;
     }

   Print("US30 EA initialized. Symbol=", _Symbol, " Magic=", MagicNumber);
   return INIT_SUCCEEDED;
  }

//+------------------------------------------------------------------+
//| Expert deinitialization                                           |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(g_handleFastEma  != INVALID_HANDLE) IndicatorRelease(g_handleFastEma);
   if(g_handleSlowEma  != INVALID_HANDLE) IndicatorRelease(g_handleSlowEma);
   if(g_handleTrendEma != INVALID_HANDLE) IndicatorRelease(g_handleTrendEma);
   if(g_handleAtr      != INVALID_HANDLE) IndicatorRelease(g_handleAtr);
   if(g_handleAdx      != INVALID_HANDLE) IndicatorRelease(g_handleAdx);
   Print("US30 EA deinitialized. Reason: ", reason);
  }

//+------------------------------------------------------------------+
//| Check whether EA already holds a position on this symbol         |
//+------------------------------------------------------------------+
bool HasOpenPosition(ENUM_POSITION_TYPE &posType)
  {
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(PositionSelectByTicket(ticket))
        {
         if(PositionGetString(POSITION_SYMBOL) == _Symbol &&
            PositionGetInteger(POSITION_MAGIC) == (long)MagicNumber)
           {
            posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
            return true;
           }
        }
     }
   return false;
  }

//+------------------------------------------------------------------+
//| Calculate lot size from risk percent and stop distance            |
//+------------------------------------------------------------------+
double CalcLotSize(double stopDistancePoints)
  {
   double balance     = AccountInfoDouble(ACCOUNT_BALANCE);
   double riskAmount  = balance * RiskPercent / 100.0;
   double tickValue   = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
   double tickSize    = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   if(tickSize == 0 || tickValue == 0 || stopDistancePoints == 0)
      return 0.0;

   double lotsRaw = riskAmount / (stopDistancePoints / tickSize * tickValue);
   double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
   double lotMin  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double lotMax  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   double lots    = MathFloor(lotsRaw / lotStep) * lotStep;
   lots = MathMax(lotMin, MathMin(lotMax, lots));
   return lots;
  }

//+------------------------------------------------------------------+
//| Close all positions for this EA                                   |
//+------------------------------------------------------------------+
void CloseAllPositions()
  {
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(!PositionSelectByTicket(ticket)) continue;
      if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
      if(PositionGetInteger(POSITION_MAGIC) != (long)MagicNumber) continue;

      MqlTradeRequest req = {};
      MqlTradeResult  res = {};
      req.action    = TRADE_ACTION_DEAL;
      req.symbol    = _Symbol;
      req.volume    = PositionGetDouble(POSITION_VOLUME);
      req.magic     = MagicNumber;
      req.comment   = TradeComment + "_CLOSE";
      req.deviation = 20;

      ENUM_POSITION_TYPE pt = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
      req.type  = (pt == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;
      req.price = (pt == POSITION_TYPE_BUY)
                  ? SymbolInfoDouble(_Symbol, SYMBOL_BID)
                  : SymbolInfoDouble(_Symbol, SYMBOL_ASK);

      if(!OrderSend(req, res))
         Print("US30 EA CloseAllPositions error: ", res.retcode);
     }
  }

//+------------------------------------------------------------------+
//| Expert tick function                                              |
//+------------------------------------------------------------------+
void OnTick()
  {
   //--- Only act on new H1 bar open
   static datetime lastBarTime = 0;
   datetime currentBarTime = (datetime)SeriesInfoInteger(_Symbol, PERIOD_H1, SERIES_LASTBAR_DATE);
   if(currentBarTime == lastBarTime) return;
   lastBarTime = currentBarTime;

   //--- Read indicator buffers (index 1 = previous closed bar)
   double fastEma[2], slowEma[2], trendEma[2], atr[2], adx[2];
   if(CopyBuffer(g_handleFastEma,  0, 1, 2, fastEma)  < 2) return;
   if(CopyBuffer(g_handleSlowEma,  0, 1, 2, slowEma)  < 2) return;
   if(CopyBuffer(g_handleTrendEma, 0, 1, 2, trendEma) < 2) return;
   if(CopyBuffer(g_handleAtr,      0, 1, 2, atr)      < 2) return;
   if(CopyBuffer(g_handleAdx,      0, 1, 2, adx)      < 2) return;

   double prevFast  = fastEma[0],  currFast  = fastEma[1];
   double prevSlow  = slowEma[0],  currSlow  = slowEma[1];
   double currTrend = trendEma[1];
   double currAtr   = atr[1];
   double currAdx   = adx[1];
   double ask       = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid       = SymbolInfoDouble(_Symbol, SYMBOL_BID);

   bool bullCross = (prevFast <= prevSlow) && (currFast > currSlow);
   bool bearCross = (prevFast >= prevSlow) && (currFast < currSlow);

   //--- Manage existing position (early exit on counter-crossover)
   ENUM_POSITION_TYPE posType;
   if(HasOpenPosition(posType))
     {
      if(posType == POSITION_TYPE_BUY  && bearCross) CloseAllPositions();
      if(posType == POSITION_TYPE_SELL && bullCross) CloseAllPositions();
      return;
     }

   //--- ADX trend-strength filter
   if(currAdx < AdxMinLevel) return;

   double stopDist, sl, tp, lots;

   //--- Long entry
   if(bullCross && ask > currTrend)
     {
      stopDist = AtrSlMultiple * currAtr;
      sl       = ask - stopDist;
      tp       = ask + AtrTpMultiple * currAtr;
      lots     = CalcLotSize(stopDist);
      if(lots <= 0) return;

      MqlTradeRequest req = {};
      MqlTradeResult  res = {};
      req.action    = TRADE_ACTION_DEAL;
      req.symbol    = _Symbol;
      req.volume    = lots;
      req.type      = ORDER_TYPE_BUY;
      req.price     = ask;
      req.sl        = sl;
      req.tp        = tp;
      req.deviation = 20;
      req.magic     = MagicNumber;
      req.comment   = TradeComment + "_BUY";
      if(!OrderSend(req, res))
         Print("US30 EA BUY error: ", res.retcode);
     }

   //--- Short entry
   else if(bearCross && bid < currTrend)
     {
      stopDist = AtrSlMultiple * currAtr;
      sl       = bid + stopDist;
      tp       = bid - AtrTpMultiple * currAtr;
      lots     = CalcLotSize(stopDist);
      if(lots <= 0) return;

      MqlTradeRequest req = {};
      MqlTradeResult  res = {};
      req.action    = TRADE_ACTION_DEAL;
      req.symbol    = _Symbol;
      req.volume    = lots;
      req.type      = ORDER_TYPE_SELL;
      req.price     = bid;
      req.sl        = sl;
      req.tp        = tp;
      req.deviation = 20;
      req.magic     = MagicNumber;
      req.comment   = TradeComment + "_SELL";
      if(!OrderSend(req, res))
         Print("US30 EA SELL error: ", res.retcode);
     }
  }
//+------------------------------------------------------------------+

Copy this code into MetaEditor, save it in the MQL5/Experts folder, and compile with F7.

Generate a custom US30 trend-following EA

Describe the ATR inputs, alert rules, visual style, or confirmation filter you want. Pineify generates editable MQL5 source code that you can inspect and compile in MetaEditor.

Pine Script vs MQL5: Same Strategy, Different Platforms

AspectPine Script (TradingView)MQL5 (MetaTrader 5)
ExecutionSeries evaluated on chart updatesEvent handlers with explicit buffers
DeploymentRuns in TradingView with alertsRuns in the MT5 terminal or on a VPS
Broker accessVia TradingView broker integrationDirect broker connectivity
BacktestingStrategy Tester for strategy scriptsStrategy Tester for Expert Advisors
Code complexitySimpler, functional syntaxC++-like, more powerful

The calculation can be implemented on either platform, but the runtime model and buffer APIs differ. Read the Pine Script Supertrend reference before porting logic between them.

Frequently Asked Questions

Related MQL5 pages

Risk and testing note

Past performance is not indicative of future results. Backtest statistics are based on historical data and do not guarantee future profits. Trading involves significant risk of loss. This content is for educational purposes only and does not constitute financial advice.