Complete .mq5 source code

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

Review a complete H1 EMA-cross Expert Advisor for a broker-provided US30 instrument. It adds a completed 200 EMA and ADX reading, estimates lot size from ATR stop distance, and requests an early close on an opposite crossover. The source is educational; no verified 2021–2025 performance report or deployment guarantee accompanies it.

Strategy logic

Entry conditions

The 20/50 EMA cross uses two completed H1 bars. A buy also requires the current ask above the completed 200 EMA; a sell requires current bid below it. This is not a completed-close filter. ADX must meet its threshold, and no matching symbol-and-magic position may already exist. Data is checked before consuming the new-bar decision.

Exit conditions

Initial SL and TP are measured from the entry quote at 1.5 and 2.5 ATR. There is no candle-extreme stop or trailing stop. An opposite completed EMA cross requests closure; the request includes the actual position ticket, and a failed close is retried on later ticks while attached. No immediate reverse entry occurs in that decision. The nominal 2.5/1.5 distance ratio is not a guaranteed realized payoff.

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;
bool closePending=false;

//+------------------------------------------------------------------+
//| Expert initialisation                                             |
//+------------------------------------------------------------------+
int OnInit()
  {
   if(FastEmaPeriod<1 || SlowEmaPeriod<=FastEmaPeriod || TrendEmaPeriod<1 || AtrPeriod<1 || AdxPeriod<1 || AdxMinLevel<0 || AdxMinLevel>100 || AtrSlMultiple<=0 || AtrTpMultiple<=0 || RiskPercent<=0 || RiskPercent>100) return INIT_PARAMETERS_INCORRECT;
   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 stopPriceDistance)
  {
   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 || stopPriceDistance <= 0 || riskAmount<=0)
      return 0.0;

   double lotsRaw = riskAmount / (stopPriceDistance / tickSize * tickValue);
   double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
   double lotMin  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double lotMax  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   if(lotStep<=0 || lotMin<=0 || lotMax<lotMin) return 0;
   double lots=NormalizeDouble(MathFloor(MathMin(lotMax,lotsRaw)/lotStep)*lotStep,8);
   return lots>=lotMin?lots:0;
  }

//+------------------------------------------------------------------+
//| 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.position  = ticket;
      req.type_filling = ORDER_FILLING_FOK;
      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) || res.retcode!=TRADE_RETCODE_DONE)
         Print("US30 EA CloseAllPositions error: ", res.retcode);
     }
  }

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

   //--- 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);

   if(currAtr<=0 || ask<=0 || bid<=0) return;
   lastBarTime=currentBarTime;
   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) || (posType==POSITION_TYPE_SELL && bullCross))
        { CloseAllPositions(); closePending=HasOpenPosition(posType); }
      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        = NormalizeDouble(sl,_Digits);
      req.tp        = NormalizeDouble(tp,_Digits);
      req.type_filling = ORDER_FILLING_FOK;
      req.deviation = 20;
      req.magic     = MagicNumber;
      req.comment   = TradeComment + "_BUY";
      if(!OrderSend(req, res) || res.retcode!=TRADE_RETCODE_DONE)
         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        = NormalizeDouble(sl,_Digits);
      req.tp        = NormalizeDouble(tp,_Digits);
      req.type_filling = ORDER_FILLING_FOK;
      req.deviation = 20;
      req.magic     = MagicNumber;
      req.comment   = TradeComment + "_SELL";
      if(!OrderSend(req, res) || res.retcode!=TRADE_RETCODE_DONE)
         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 entry, exit, position, order, and risk rules 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 accessStrategy orders are simulated; live automation needs a separate 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.

Frequently Asked Questions

Related MQL5 pages

Risk and testing note

These educational examples require independent compilation and testing. A compile pass or an illustrative setting does not establish execution correctness or profitability. Any reported performance must be supported by reproducible data and test settings; past results do not predict future returns. Trading involves significant risk of loss. This content is not financial advice.