Problem Description
Solution
Here is a complete, robust, and well-commented MQL4 trading strategy based on the Momentum Indicator.
Strategy Logic
This Expert Advisor (EA) uses a classic Momentum crossover strategy filtered by a Moving Average to determine the trend direction.
- Indicator 1 (Signal): Momentum (Period 14).
- Buy Signal: Momentum line crosses above the 100 level.
- Sell Signal: Momentum line crosses below the 100 level.
- Indicator 2 (Trend Filter): Simple Moving Average (SMA 50).
- We only Buy if the price is above the SMA.
- We only Sell if the price is below the SMA.
- Risk Management:
- Fixed Stop Loss and Take Profit.
- Dynamic Trailing Stop to lock in profits.
MQL4 Code
//+------------------------------------------------------------------+
//| MomentumStrategy.mq4 |
//| Copyright 2023, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Quantitative AI"
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
//--- Input Parameters
input string StrategySettings = "--- Strategy Settings ---";
input double LotSize = 0.1; // Fixed Lot Size
input int MomentumPeriod = 14; // Period for Momentum Indicator
input int MAPeriod = 50; // Period for Trend Filter (SMA)
input int StopLoss = 50; // Stop Loss in pips
input int TakeProfit = 100; // Take Profit in pips
input int TrailingStop = 30; // Trailing Stop in pips (0 to disable)
input int MagicNumber = 123456; // Unique ID for this EA
input int Slippage = 3; // Max slippage allowed
//--- Global Variables
double pPoint; // Adjusted point value for 3/5 digit brokers
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Adjust point for 5-digit brokers (0.00001) vs 4-digit (0.0001)
if(Digits == 3 || Digits == 5) pPoint = Point * 10;
else pPoint = Point;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// 1. Check for Open Orders and Manage Trailing Stop
if(OrdersTotal() > 0)
{
ManageTrailingStop();
}
// 2. Check if we already have a position open for this symbol/magic number
if(CountTrades() > 0) return; // We only allow one trade at a time per chart
// 3. Define Indicator Values
// We use shift 1 (previous closed bar) and shift 2 to detect the crossover
// This prevents "repainting" issues on the current forming bar
// Momentum Values
double momCurrent = iMomentum(NULL, 0, MomentumPeriod, PRICE_CLOSE, 1);
double momPrevious = iMomentum(NULL, 0, MomentumPeriod, PRICE_CLOSE, 2);
// Moving Average Value (Trend Filter)
double maValue = iMA(NULL, 0, MAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);
// Previous Close Price (to compare with MA)
double closePrice = iClose(NULL, 0, 1);
// 4. Trading Logic
// --- BUY SIGNAL ---
// Momentum crosses UP over 100 AND Price is ABOVE Moving Average
if(momPrevious < 100 && momCurrent > 100 && closePrice > maValue)
{
double sl = Ask - (StopLoss * pPoint);
double tp = Ask + (TakeProfit * pPoint);
// Send Order
int ticket = OrderSend(Symbol(), OP_BUY, LotSize, Ask, Slippage, sl, tp, "MomBuy", MagicNumber, 0, clrGreen);
if(ticket < 0) Print("OrderSend failed with error #", GetLastError());
}
// --- SELL SIGNAL ---
// Momentum crosses DOWN under 100 AND Price is BELOW Moving Average
if(momPrevious > 100 && momCurrent < 100 && closePrice < maValue)
{
double sl = Bid + (StopLoss * pPoint);
double tp = Bid - (TakeProfit * pPoint);
// Send Order
int ticket = OrderSend(Symbol(), OP_SELL, LotSize, Bid, Slippage, sl, tp, "MomSell", MagicNumber, 0, clrRed);
if(ticket < 0) Print("OrderSend failed with error #", GetLastError());
}
}
//+------------------------------------------------------------------+
//| Helper: Count open trades for this EA |
//+------------------------------------------------------------------+
int CountTrades()
{
int count = 0;
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 || OrderType() == OP_SELL)
count++;
}
}
}
return(count);
}
//+------------------------------------------------------------------+
//| Helper: Manage Trailing Stop |
//+------------------------------------------------------------------+
void ManageTrailingStop()
{
if(TrailingStop == 0) return; // Exit if disabled
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
// Logic for BUY orders
if(OrderType() == OP_BUY)
{
// If price has moved in our favor by TrailingStop amount
if(Bid - OrderOpenPrice() > TrailingStop * pPoint)
{
// If current SL is lower than (Bid - TrailingStop), move it up
if(OrderStopLoss() < Bid - (TrailingStop * pPoint))
{
if(!OrderModify(OrderTicket(), OrderOpenPrice(), Bid - (TrailingStop * pPoint), OrderTakeProfit(), 0, clrBlue))
Print("Error modifying Buy Trailing Stop: ", GetLastError());
}
}
}
// Logic for SELL orders
if(OrderType() == OP_SELL)
{
// If price has moved in our favor by TrailingStop amount
if(OrderOpenPrice() - Ask > TrailingStop * pPoint)
{
// If current SL is higher than (Ask + TrailingStop) or is 0, move it down
if(OrderStopLoss() > Ask + (TrailingStop * pPoint) || OrderStopLoss() == 0)
{
if(!OrderModify(OrderTicket(), OrderOpenPrice(), Ask + (TrailingStop * pPoint), OrderTakeProfit(), 0, clrBlue))
Print("Error modifying Sell Trailing Stop: ", GetLastError());
}
}
}
}
}
}
}
How to Install and Run
- Open MetaTrader 4.
- Press
F4to open the MetaEditor. - In MetaEditor, click New -> Expert Advisor (template) -> Next.
- Name it
MomentumStrategyand click Next/Finish. - Delete everything in the new file and paste the code provided above.
- Press
F7or click Compile. Ensure there are no errors in the "Errors" tab at the bottom. - Go back to the main MetaTrader 4 window.
- Find
MomentumStrategyin the Navigator panel under "Expert Advisors". - Drag it onto a chart (e.g., EURUSD H1).
- Ensure the "AutoTrading" button at the top is Green and check "Allow live trading" in the EA inputs tab.
Key Features of This Code
- Point Adjustment: The code automatically detects if your broker uses 5-digit pricing (e.g., EURUSD 1.12345) or 4-digit pricing and adjusts the Pips calculation accordingly.
- Trend Filter: It uses a 50-period Simple Moving Average (
iMA) to ensure you aren't buying into a downtrend or selling into an uptrend. - Crossover Logic: It compares the Momentum value of the previous bar (
shift 1) against the bar before that (shift 2). This ensures the signal is confirmed by a closed candle, preventing the signal from flickering (repainting). - Trailing Stop: A built-in function moves your Stop Loss automatically as the price moves in your favor, securing profits.
Q&A: Momentum Strategy in MQL4
Q: Why do we use shift 1 and shift 2 instead of shift 0?
A: shift 0 refers to the current candle, which is still forming. The Momentum value can jump above and below 100 multiple times before the candle closes. Using shift 1 ensures we only trade based on confirmed, closed candles.
Q: What is the standard level for the Momentum indicator?
A: The standard centerline for Momentum in MetaTrader 4 is 100. Values above 100 indicate price is higher than it was n periods ago (uptrend momentum), and values below 100 indicate the opposite.
Q: Can I optimize the parameters?
A: Yes. Because we defined the variables (like MomentumPeriod, StopLoss, MAPeriod) as input, you can use the MT4 Strategy Tester to run optimizations and find the best settings for specific currency pairs.
Q: How does the Trailing Stop work in this code?
A: The trailing stop activates immediately. If you set it to 30 pips, once the price moves 31 pips in profit, the Stop Loss will move to +1 pip profit. It will continue to follow the price at a distance of 30 pips.