How to code Your first Expert Advisor in MQL5 in 60 minutes (with source code)

Coding your first Expert Advisor (EA) in MQL5 can feel intimidating if you’re not a programmer. The good news: you don’t need a computer science degree to build a simple, working Forex robot for MetaTrader 5 (MT5).

In this tutorial you’ll go from zero to a complete EA that:

  • Trades a Moving Average crossover strategy
  • Uses stop loss and take profit
  • Trades automatically using the CTrade class
  • Can be backtested in the MT5 Strategy Tester

You’ll also get the full source code, tables of parameters, and explanations of how everything works.

1. What You’ll Build (and How We’ll Do It)

We’ll create a simple trend-following Moving Average crossover EA:

  • When a fast MA crosses above a slow MA → open a BUY
  • When a fast MA crosses below a slow MA → open a SELL
  • Only one position at a time per symbol
  • Stop Loss and Take Profit in pips
  • Runs on any symbol/timeframe you attach it to

1.1. High-Level Roadmap

StepWhat You DoResult
1Install / open MetaTrader 5 and MetaEditorEnvironment ready
2Create a new EA templateBasic skeleton with OnInit() and OnTick()
3Define input parametersUser-configurable settings (MA periods, risk)
4Write a simple signal functionDetect BUY/SELL based on MA crossover
5Use CTrade to open and close positionsEA can place trades automatically
6Compile, attach to chart, and backtestYou see your EA in action

2. Prerequisites

You need:

  • MetaTrader 5 installed (desktop version)
  • Basic comfort with:
    • Opening a chart
    • Switching timeframes
    • Using Tabs in MT5 (Terminal, Strategy Tester, etc.)

No prior coding experience is required. We’ll explain the important pieces of MQL5 as we go.

3. EA Lifecycle in MQL5: OnInit, OnDeinit, OnTick

Every Expert Advisor in MQL5 is basically a program with event handlers. You don’t call these functions; MT5 calls them for you.

The key ones:

FunctionWhen It RunsTypical Use
OnInit()When EA is attached to chart or recompiledInitialize variables, check inputs, set handles
OnDeinit()When EA is removed / chart closed / terminal exitRelease resources, close files, etc.
OnTick()On every new tick (price change)Main trading logic (signals, orders, updates)

In this tutorial, we’ll focus mainly on OnInit() and OnTick().

4. The Strategy: Simple Moving Average Crossover

Let’s formalize what the EA should do. This is critical before you write a single line of code.

4.1. Entry Rules

We’ll use two Simple Moving Averages (SMA):

  • Fast MA (e.g. 20-period)
  • Slow MA (e.g. 50-period)

We detect crossovers using previous bar vs current bar:

  • BUY signal:
    • On previous bar: FastMA_prev < SlowMA_prev
    • On current bar: FastMA_curr > SlowMA_curr
  • SELL signal:
    • On previous bar: FastMA_prev > SlowMA_prev
    • On current bar: FastMA_curr < SlowMA_curr

This avoids reacting to random one-tick noise and ensures a clean crossover.

4.2. Position Management Rules

  • Only one open position at a time on the symbol (either BUY or SELL).
  • If a BUY signal appears while there is an open SELL, we close the SELL and open a BUY.
  • If a SELL signal appears while there is an open BUY, we close the BUY and open a SELL.
  • Each trade has:
    • Fixed Stop Loss in pips (e.g. 100)
    • Fixed Take Profit in pips (e.g. 200)

4.3. EA Input Parameters

We’ll make these user-configurable, so you can tweak them in MT5 without changing code.

Input NameTypeDefaultDescription
InpFastMAPeriodint20Period of the fast Moving Average
InpSlowMAPeriodint50Period of the slow Moving Average
InpLotsdouble0.10Lot size per trade
InpStopLossPipsint100Stop Loss distance in pips
InpTakeProfitPipsint200Take Profit distance in pips
InpSlippageint10Max slippage in points (Broker-dependent)
InpMagicNumberint123456Unique ID for this EA’s trades
InpTradeCommentstring“MA_EA”Comment attached to trades

5. Creating the Expert Advisor in MetaEditor

  1. Open MetaTrader 5.
  2. Press F4 or click Tools → MetaQuotes Language Editor to open MetaEditor.
  3. In MetaEditor, click:
    • File → New → Expert Advisor (template).
  4. Name it, e.g. MA_Crossover_EA.
  5. Choose the folder (usually MQL5\Experts).
  6. Click Next → Finish.

MetaEditor will generate a basic EA template with empty OnInit(), OnDeinit(), and OnTick() functions.

6. Designing the Code Structure

We’ll structure our EA into three main parts:

  1. Inputs and Globals
  2. Signal Detection (function that returns BUY/SELL/NO_SIGNAL)
  3. Trading Logic (function that manages orders based on the signal)

6.1. Enumerations for Signal Types

We’ll define a small enum to make code more readable:

enum TradeSignal
  {
   SIGNAL_NONE = 0,
   SIGNAL_BUY  = 1,
   SIGNAL_SELL = -1
  };

This is clearer than using raw integers.

7. Coding the EA Step by Step

Let’s build the EA piece by piece, then we’ll show the full source code.

7.1. Includes, Inputs, and Global Variables

We’ll use the standard CTrade class (from Trade.mqh) to simplify order execution.

#include <Trade\Trade.mqh>

CTrade trade;  // trading object

//--- input parameters
input int      InpFastMAPeriod    = 20;       // Fast MA Period
input int      InpSlowMAPeriod    = 50;       // Slow MA Period
input double   InpLots            = 0.10;     // Lots
input int      InpStopLossPips    = 100;      // Stop Loss (pips)
input int      InpTakeProfitPips  = 200;      // Take Profit (pips)
input int      InpSlippage        = 10;       // Slippage (points)
input int      InpMagicNumber     = 123456;   // Magic Number
input string   InpTradeComment    = "MA_EA";  // Trade Comment

//--- enum for signals
enum TradeSignal
  {
   SIGNAL_NONE = 0,
   SIGNAL_BUY  = 1,
   SIGNAL_SELL = -1
  };

//--- global variables
int fast_ma_handle;
int slow_ma_handle;

The handles will refer to the indicator instances created in OnInit().

7.2. Initializing the Moving Averages in OnInit()

We will create two SMA indicators using iMA() and store their handles.

int OnInit()
  {
   //--- create fast MA
   fast_ma_handle = iMA(_Symbol, _Period, InpFastMAPeriod,
                        0, MODE_SMA, PRICE_CLOSE);

   if(fast_ma_handle == INVALID_HANDLE)
     {
      Print("Failed to create fast MA handle. Error: ", GetLastError());
      return(INIT_FAILED);
     }

   //--- create slow MA
   slow_ma_handle = iMA(_Symbol, _Period, InpSlowMAPeriod,
                        0, MODE_SMA, PRICE_CLOSE);

   if(slow_ma_handle == INVALID_HANDLE)
     {
      Print("Failed to create slow MA handle. Error: ", GetLastError());
      return(INIT_FAILED);
     }

   //--- set magic number for trade object
   trade.SetExpertMagicNumber(InpMagicNumber);

   Print("MA_Crossover_EA initialized successfully.");
   return(INIT_SUCCEEDED);
  }

We return INIT_FAILED if indicator creation fails. This prevents the EA from running in an invalid state.

7.3. Cleaning Up in OnDeinit()

void OnDeinit(const int reason)
  {
   if(fast_ma_handle != INVALID_HANDLE)
      IndicatorRelease(fast_ma_handle);

   if(slow_ma_handle != INVALID_HANDLE)
      IndicatorRelease(slow_ma_handle);

   Print("MA_Crossover_EA deinitialized. Reason: ", reason);
  }

This releases indicator resources when EA is removed.

7.4. Helper: Getting the Moving Average Values

We need current and previous bar values for each MA. We’ll use CopyBuffer().

bool GetMAs(double &fast_prev, double &fast_curr,
            double &slow_prev, double &slow_curr)
  {
   double fast_ma[2];
   double slow_ma[2];

   // Copy last 2 values of each MA (index 0 = current bar)
   if(CopyBuffer(fast_ma_handle, 0, 0, 2, fast_ma) != 2)
     {
      Print("Failed to copy fast MA buffer. Error: ", GetLastError());
      return(false);
     }

   if(CopyBuffer(slow_ma_handle, 0, 0, 2, slow_ma) != 2)
     {
      Print("Failed to copy slow MA buffer. Error: ", GetLastError());
      return(false);
     }

   fast_curr = fast_ma[0];
   fast_prev = fast_ma[1];
   slow_curr = slow_ma[0];
   slow_prev = slow_ma[1];

   return(true);
  }

7.5. Signal Detection Function

Now we use those values to generate a BUY/SELL/NO_SIGNAL.

TradeSignal GetSignal()
  {
   double fast_prev, fast_curr;
   double slow_prev, slow_curr;

   if(!GetMAs(fast_prev, fast_curr, slow_prev, slow_curr))
      return(SIGNAL_NONE);

   //--- BUY crossover
   if(fast_prev < slow_prev && fast_curr > slow_curr)
      return(SIGNAL_BUY);

   //--- SELL crossover
   if(fast_prev > slow_prev && fast_curr < slow_curr)
      return(SIGNAL_SELL);

   return(SIGNAL_NONE);
  }

7.6. Helper: Check Existing Position

We want only one position per symbol and magic number. Let’s create a helper.

int GetCurrentPositionDirection()
  {
   // returns 1 for BUY, -1 for SELL, 0 for none
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(PositionSelectByTicket(ticket))
        {
         string symbol      = PositionGetString(POSITION_SYMBOL);
         long   magic       = PositionGetInteger(POSITION_MAGIC);

         if(symbol == _Symbol && magic == InpMagicNumber)
           {
            long type = PositionGetInteger(POSITION_TYPE);
            if(type == POSITION_TYPE_BUY)
               return(1);
            if(type == POSITION_TYPE_SELL)
               return(-1);
           }
        }
     }

   return(0);
  }

7.7. Calculating Stop Loss and Take Profit Prices

We’ll convert pips to price using SymbolInfoDouble and the tick size.

bool CalculateSLTP(double &sl, double &tp, int direction)
  {
   double price = (direction > 0) ? SymbolInfoDouble(_Symbol, SYMBOL_ASK)
                                  : SymbolInfoDouble(_Symbol, SYMBOL_BID);

   double point      = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   int    digits     = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
   double pip_value  = (digits == 3 || digits == 5) ? (10 * point) : point;

   double sl_distance = InpStopLossPips * pip_value;
   double tp_distance = InpTakeProfitPips * pip_value;

   if(direction > 0) // BUY
     {
      sl = price - sl_distance;
      tp = price + tp_distance;
     }
   else if(direction < 0) // SELL
     {
      sl = price + sl_distance;
      tp = price - tp_distance;
     }
   else
      return(false);

   return(true);
  }

7.8. Main Trading Logic in OnTick()

Now we combine everything:

  1. Get signal
  2. Check existing position
  3. If needed, close opposite and open new trade
void OnTick()
  {
   //--- ignore if not enough bars
   if(Bars(_Symbol, _Period) < MathMax(InpFastMAPeriod, InpSlowMAPeriod) + 10)
      return;

   //--- get signal
   TradeSignal signal = GetSignal();
   if(signal == SIGNAL_NONE)
      return;

   int current_dir = GetCurrentPositionDirection();

   //--- no existing position
   if(current_dir == 0)
     {
      OpenPosition(signal);
     }
   else
     {
      // we have a position
      if((current_dir == 1 && signal == SIGNAL_SELL) ||
         (current_dir == -1 && signal == SIGNAL_BUY))
        {
         // opposite signal -> close and reverse
         CloseCurrentPosition();
         OpenPosition(signal);
        }
      // if signal same direction as current position, do nothing
     }
  }

We’ll implement OpenPosition() and CloseCurrentPosition() next.

7.9. Opening a Position

void OpenPosition(TradeSignal signal)
  {
   int    direction = (signal == SIGNAL_BUY) ? 1 : -1;
   double sl, tp;

   if(!CalculateSLTP(sl, tp, direction))
     {
      Print("Failed to calculate SL/TP");
      return;
     }

   trade.SetDeviationInPoints(InpSlippage);

   bool result = false;

   if(direction > 0)
     {
      result = trade.Buy(InpLots, _Symbol, 0.0, sl, tp, InpTradeComment);
     }
   else
     {
      result = trade.Sell(InpLots, _Symbol, 0.0, sl, tp, InpTradeComment);
     }

   if(!result)
     {
      Print("Order failed. Error: ", GetLastError());
     }
   else
     {
      Print("Opened ", (direction > 0 ? "BUY" : "SELL"),
            " ", DoubleToString(InpLots, 2),
            " lot(s) at ", DoubleToString(trade.ResultPrice(), _Digits),
            ", SL=", DoubleToString(sl, _Digits),
            ", TP=", DoubleToString(tp, _Digits));
     }
  }

7.10. Closing the Current Position

void CloseCurrentPosition()
  {
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(PositionSelectByTicket(ticket))
        {
         string symbol = PositionGetString(POSITION_SYMBOL);
         long   magic  = PositionGetInteger(POSITION_MAGIC);

         if(symbol == _Symbol && magic == InpMagicNumber)
           {
            long type = PositionGetInteger(POSITION_TYPE);

            bool result = false;
            if(type == POSITION_TYPE_BUY)
               result = trade.PositionClose(ticket, InpSlippage);
            else if(type == POSITION_TYPE_SELL)
               result = trade.PositionClose(ticket, InpSlippage);

            if(!result)
               Print("Failed to close position #", ticket,
                     ". Error: ", GetLastError());
            else
               Print("Closed position #", ticket);
           }
        }
     }
  }

8. Full Source Code: MA_Crossover_EA.mq5

Here is the complete EA in one piece.
You can copy–paste it into your MQL5\Experts folder in MetaEditor.

//+------------------------------------------------------------------+
//|                                                MA_Crossover_EA   |
//|                 Simple Moving Average Crossover Expert Advisor   |
//+------------------------------------------------------------------+
#property strict

#include <Trade\Trade.mqh>

CTrade trade;

//--- inputs
input int      InpFastMAPeriod    = 20;       // Fast MA Period
input int      InpSlowMAPeriod    = 50;       // Slow MA Period
input double   InpLots            = 0.10;     // Lots
input int      InpStopLossPips    = 100;      // Stop Loss (pips)
input int      InpTakeProfitPips  = 200;      // Take Profit (pips)
input int      InpSlippage        = 10;       // Slippage (points)
input int      InpMagicNumber     = 123456;   // Magic Number
input string   InpTradeComment    = "MA_EA";  // Trade Comment

//--- signal enum
enum TradeSignal
  {
   SIGNAL_NONE = 0,
   SIGNAL_BUY  = 1,
   SIGNAL_SELL = -1
  };

//--- global indicator handles
int fast_ma_handle;
int slow_ma_handle;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   //--- create fast MA handle
   fast_ma_handle = iMA(_Symbol, _Period, InpFastMAPeriod,
                        0, MODE_SMA, PRICE_CLOSE);
   if(fast_ma_handle == INVALID_HANDLE)
     {
      Print("Failed to create fast MA handle. Error: ", GetLastError());
      return(INIT_FAILED);
     }

   //--- create slow MA handle
   slow_ma_handle = iMA(_Symbol, _Period, InpSlowMAPeriod,
                        0, MODE_SMA, PRICE_CLOSE);
   if(slow_ma_handle == INVALID_HANDLE)
     {
      Print("Failed to create slow MA handle. Error: ", GetLastError());
      return(INIT_FAILED);
     }

   //--- set magic number
   trade.SetExpertMagicNumber(InpMagicNumber);

   Print("MA_Crossover_EA initialized on ", _Symbol,
         " timeframe ", EnumToString(_Period));
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(fast_ma_handle != INVALID_HANDLE)
      IndicatorRelease(fast_ma_handle);

   if(slow_ma_handle != INVALID_HANDLE)
      IndicatorRelease(slow_ma_handle);

   Print("MA_Crossover_EA deinitialized. Reason: ", reason);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   //--- ensure enough bars for MAs
   if(Bars(_Symbol, _Period) < MathMax(InpFastMAPeriod, InpSlowMAPeriod) + 10)
      return;

   //--- get signal
   TradeSignal signal = GetSignal();
   if(signal == SIGNAL_NONE)
      return;

   //--- check current position direction
   int current_dir = GetCurrentPositionDirection();

   //--- no position yet
   if(current_dir == 0)
     {
      OpenPosition(signal);
     }
   else
     {
      // if opposite signal -> close and reverse
      if((current_dir == 1 && signal == SIGNAL_SELL) ||
         (current_dir == -1 && signal == SIGNAL_BUY))
        {
         CloseCurrentPosition();
         OpenPosition(signal);
        }
      // if same direction -> do nothing
     }
  }

//+------------------------------------------------------------------+
//| Get Moving Averages values                                       |
//+------------------------------------------------------------------+
bool GetMAs(double &fast_prev, double &fast_curr,
            double &slow_prev, double &slow_curr)
  {
   double fast_ma[2];
   double slow_ma[2];

   if(CopyBuffer(fast_ma_handle, 0, 0, 2, fast_ma) != 2)
     {
      Print("Failed to copy fast MA buffer. Error: ", GetLastError());
      return(false);
     }

   if(CopyBuffer(slow_ma_handle, 0, 0, 2, slow_ma) != 2)
     {
      Print("Failed to copy slow MA buffer. Error: ", GetLastError());
      return(false);
     }

   fast_curr = fast_ma[0];
   fast_prev = fast_ma[1];
   slow_curr = slow_ma[0];
   slow_prev = slow_ma[1];

   return(true);
  }

//+------------------------------------------------------------------+
//| Determine trading signal                                         |
//+------------------------------------------------------------------+
TradeSignal GetSignal()
  {
   double fast_prev, fast_curr;
   double slow_prev, slow_curr;

   if(!GetMAs(fast_prev, fast_curr, slow_prev, slow_curr))
      return(SIGNAL_NONE);

   //--- BUY crossover
   if(fast_prev < slow_prev && fast_curr > slow_curr)
      return(SIGNAL_BUY);

   //--- SELL crossover
   if(fast_prev > slow_prev && fast_curr < slow_curr)
      return(SIGNAL_SELL);

   return(SIGNAL_NONE);
  }

//+------------------------------------------------------------------+
//| Get current position direction for this EA                       |
//+------------------------------------------------------------------+
int GetCurrentPositionDirection()
  {
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(PositionSelectByTicket(ticket))
        {
         string symbol = PositionGetString(POSITION_SYMBOL);
         long   magic  = PositionGetInteger(POSITION_MAGIC);

         if(symbol == _Symbol && magic == InpMagicNumber)
           {
            long type = PositionGetInteger(POSITION_TYPE);
            if(type == POSITION_TYPE_BUY)
               return(1);
            if(type == POSITION_TYPE_SELL)
               return(-1);
           }
        }
     }
   return(0);
  }

//+------------------------------------------------------------------+
//| Calculate SL and TP prices                                      |
//+------------------------------------------------------------------+
bool CalculateSLTP(double &sl, double &tp, int direction)
  {
   double price = (direction > 0) ? SymbolInfoDouble(_Symbol, SYMBOL_ASK)
                                  : SymbolInfoDouble(_Symbol, SYMBOL_BID);

   double point     = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   int    digits    = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
   double pip_value = (digits == 3 || digits == 5) ? (10 * point) : point;

   double sl_distance = InpStopLossPips * pip_value;
   double tp_distance = InpTakeProfitPips * pip_value;

   if(direction > 0) // BUY
     {
      sl = price - sl_distance;
      tp = price + tp_distance;
     }
   else if(direction < 0) // SELL
     {
      sl = price + sl_distance;
      tp = price - tp_distance;
     }
   else
      return(false);

   return(true);
  }

//+------------------------------------------------------------------+
//| Open a new position                                              |
//+------------------------------------------------------------------+
void OpenPosition(TradeSignal signal)
  {
   int    direction = (signal == SIGNAL_BUY) ? 1 : -1;
   double sl, tp;

   if(!CalculateSLTP(sl, tp, direction))
     {
      Print("Failed to calculate SL/TP.");
      return;
     }

   trade.SetDeviationInPoints(InpSlippage);

   bool result = false;

   if(direction > 0)
     {
      result = trade.Buy(InpLots, _Symbol, 0.0, sl, tp, InpTradeComment);
     }
   else
     {
      result = trade.Sell(InpLots, _Symbol, 0.0, sl, tp, InpTradeComment);
     }

   if(!result)
     {
      Print("Order failed. Error: ", GetLastError());
     }
   else
     {
      Print("Opened ", (direction > 0 ? "BUY" : "SELL"),
            " ", DoubleToString(InpLots, 2),
            " lots at ", DoubleToString(trade.ResultPrice(), _Digits),
            ", SL=", DoubleToString(sl, _Digits),
            ", TP=", DoubleToString(tp, _Digits));
     }
  }

//+------------------------------------------------------------------+
//| Close current position                                           |
//+------------------------------------------------------------------+
void CloseCurrentPosition()
  {
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(PositionSelectByTicket(ticket))
        {
         string symbol = PositionGetString(POSITION_SYMBOL);
         long   magic  = PositionGetInteger(POSITION_MAGIC);

         if(symbol == _Symbol && magic == InpMagicNumber)
           {
            long type = PositionGetInteger(POSITION_TYPE);

            bool result = trade.PositionClose(ticket, InpSlippage);

            if(!result)
               Print("Failed to close position #", ticket,
                     ". Error: ", GetLastError());
            else
               Print("Closed position #", ticket);
           }
        }
     }
  }
//+------------------------------------------------------------------+

9. Compiling and Attaching the EA

  1. Compile:
    • In MetaEditor, click Compile or press F7.
    • Check the Errors and Warnings panel.
    • If there are no errors, your EA is ready.
  2. Attach to Chart in MT5:
    • Go back to MetaTrader 5.
    • In the Navigator window → Expert Advisors.
    • Find MA_Crossover_EA.
    • Drag it onto a chart (e.g., EURUSD H1).
    • In the Inputs tab, you can tweak:
      • MA periods
      • Lots
      • Stop Loss / Take Profit, etc.
    • Make sure AutoTrading is enabled (green button).

10. Quick Backtest in Strategy Tester

You should never trust a robot until you’ve at least backtested it.

10.1. Running a Basic Backtest

  1. Press Ctrl+R or open View → Strategy Tester.
  2. Select:
    • Expert: MA_Crossover_EA
    • Symbol: e.g., EURUSD
    • Period: e.g., H1
    • Model: “Every tick” (for better accuracy)
    • Date range: pick last 6–12 months
  3. Click Start.

10.2. Example Backtest Settings Table

SettingValue
SymbolEURUSD
TimeframeH1
PeriodLast 1 year
Fast MA Period20
Slow MA Period50
Lots0.10
SL / TP (pips)100 / 200

10.3. Sample Interpretation of Results

Look at:

MetricWhat It Tells You
Net profitOverall profit or loss
Maximal drawdownRisk and worst-case drop in equity
Profit factorGross profit / gross loss (>1 is good)
Number of tradesWhether sample size is meaningful

If you see very few trades, try lowering MA periods or testing a longer date range.

11. Common Pitfalls and How to Avoid Them

11.1. EA Not Trading at All

Checklist:

Possible IssueFix
AutoTrading disabledEnable the AutoTrading button
“Algo Trading” not allowed in EACheck EA settings → Common → Allow live trading
Initialization failed (INIT_FAILED)Look in Experts log for MA handle creation errors
Symbol or timeframe too small barsLower MA periods or use longer history

11.2. Wrong SL / TP Values

If your broker uses 5-digit quotes (e.g. 1.12345), a “pip” is often 10 points.
Our CalculateSLTP() function already tries to account for 3/5-digit pricing using:

double pip_value = (digits == 3 || digits == 5) ? (10 * point) : point;

If SL/TP still look off:

  • Check Digits for the symbol (Market Watch → Symbol properties).
  • Print debug info:
Print("Point=", point, " Digits=", digits, " PipValue=", pip_value);

11.3. EA Opens Too Many Trades

In this EA we restrict to one position per symbol. If you clone the EA with different magic numbers or attach it to several charts, you might unintentionally create multiple active copies.

Mitigation:

  • Use a unique MagicNumber per EA instance.
  • Optionally add a time filter, so EA only checks once per bar instead of every tick (advanced improvement: use static datetime last_bar_time;).

12. Where to Go Next: Improving the EA

You now have a fully working MQL5 Expert Advisor that:

  • Creates and uses indicators
  • Generates signals from MA crossovers
  • Opens and closes trades with SL/TP
  • Can be optimized and backtested in MT5

Some ideas for your second generation:

  1. Trade only during specific sessions (e.g., London/NY overlap).
  2. Add spread filter – don’t trade when the spread is too wide.
  3. Replace SMA with EMA or other indicators.
  4. Use multi-timeframe confirmation (e.g., H4 trend, M15 entries).
  5. Add trailing stop or break-even functions.
By Forex Real Trader

Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like