Study ›

[Course] [Build an EA 4] First EA: moving-average cross (copy & use)

大EADesk MasterStaff2026. 11. 01. 03:21Views 89Up 0Comments 0

Let's turn the rules from part 3 into code. In MetaEditor, delete everything in the `MyFirstEA` file from part 2, paste the code below and press F7 (compile).

#include <Trade/Trade.mqh>          // helper that makes placing orders easy

input int    FastMA  = 20;          // fast moving average period
input int    SlowMA  = 50;          // slow moving average period
input double Lots    = 0.01;        // order size
input int    StopPts = 3000;        // stop loss in points (gold, 2 decimals: 3000 = $30)
input int    TakePts = 6000;        // take profit in points
input long   Magic   = 20261103;    // tag attached to this EA's orders

CTrade   trade;
int      hFast, hSlow;              // moving average handles
datetime lastBar = 0;               // time of the last candle we checked

int OnInit()
{
   hFast = iMA(_Symbol, _Period, FastMA, 0, MODE_EMA, PRICE_CLOSE);
   hSlow = iMA(_Symbol, _Period, SlowMA, 0, MODE_EMA, PRICE_CLOSE);
   if(hFast == INVALID_HANDLE || hSlow == INVALID_HANDLE) return INIT_FAILED;
   trade.SetExpertMagicNumber(Magic);
   return INIT_SUCCEEDED;
}

void OnDeinit(const int reason)
{
   IndicatorRelease(hFast);
   IndicatorRelease(hSlow);
}

// does this EA have an open position right now?
bool HasPosition()
{
   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      ulong t = PositionGetTicket(i);
      if(PositionSelectByTicket(t)
         && PositionGetString(POSITION_SYMBOL) == _Symbol
         && PositionGetInteger(POSITION_MAGIC) == Magic) return true;
   }
   return false;
}

void OnTick()
{
   // 1) decide only when a new candle opens
   datetime bar = iTime(_Symbol, _Period, 0);
   if(bar == lastBar) return;
   lastBar = bar;

   // 2) moving averages of the candle that just closed (1) and the one before (2)
   double f[], s[];
   ArraySetAsSeries(f, true);
   ArraySetAsSeries(s, true);
   if(CopyBuffer(hFast, 0, 1, 2, f) < 2 || CopyBuffer(hSlow, 0, 1, 2, s) < 2) return;

   bool goldenCross = f[1] <= s[1] && f[0] > s[0];   // crossed from below to above
   bool deadCross   = f[1] >= s[1] && f[0] < s[0];   // crossed from above to below

   // 3) already in a position? sit out (one at a time)
   if(HasPosition()) return;

   // 4) place the order
   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   if(goldenCross)
      trade.Buy(Lots, _Symbol, ask,
                NormalizeDouble(ask - StopPts * _Point, _Digits),
                NormalizeDouble(ask + TakePts * _Point, _Digits), "MA cross");
   else if(deadCross)
      trade.Sell(Lots, _Symbol, bid,
                 NormalizeDouble(bid + StopPts * _Point, _Digits),
                 NormalizeDouble(bid - TakePts * _Point, _Digits), "MA cross");
}

What each part means

  • input: settings you can change when attaching the EA. Experiment with numbers without touching the code.
  • iMA: creates a moving average calculator. Create it once in OnInit and reuse it.
  • CopyBuffer(…, 1, 2, …): gets 2 values starting from candle 1 (the one that just closed). `f[0]` is the just-closed candle, `f[1]` the one before.
  • Magic: a tag on this EA's orders, so they don't mix with other EAs or manual trades.
  • _Point: the symbol's smallest price step. Gold (2 decimals) is 0.01, so 3000 points = $30.

Try it

  1. F7 → check for `0 errors`
  2. Attach it to an XAUUSD M15 chart in MT5 (on demo!)
  3. Check the Toolbox → Experts tab for errors
  4. When a cross happens, an order goes in. On M15 that may take a few hours.
Want results right away? The Strategy Tester in the next posts runs years of data in seconds. First, part 5 shows how to size positions properly.

Comments 0

List
Vantage 앱 광고Ad