Problem Description
Solution
Here is a complete, fully functional MQL4 Expert Advisor (EA) based on the DeMarker indicator.
Strategy Logic
This strategy uses a crossover approach rather than simply checking if the value is currently in the zone. This prevents the EA from opening multiple trades continuously while the market remains overbought or oversold.
- Buy Signal: The DeMarker line was below the Oversold Level (0.3) and crosses back above it.
- Sell Signal: The DeMarker line was above the Overbought Level (0.7) and crosses back below it.
- Trade Management: When a signal occurs, the EA will close any opposite positions (e.g., close Sells before Buying) and open a new trade with Stop Loss and Take Profit.
MQL4 Code
//+------------------------------------------------------------------+
//| DeMarkerStrategy.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 int DeMarkerPeriod = 14; // DeMarker Period
input double OverboughtLevel = 0.7; // Overbought Level (Sell Zone)
input double OversoldLevel = 0.3; // Oversold Level (Buy Zone)
input double LotSize = 0.1; // Fixed Lot Size
input int StopLoss = 50; // Stop Loss in points (0 = none)
input int TakeProfit = 100; // Take Profit in points (0 = none)
input int MagicNumber = 123456; // Unique Identifier for this EA
input int Slippage = 3; // Max Slippage in points
//--- Global Variables
double pipMultiplier;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Adjust points for 3 and 5 digit brokers (Jpy pairs vs others)
if(Digits == 3 || Digits == 5)
pipMultiplier = 10;
else
pipMultiplier = 1;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Clean up if necessary
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Check for a new bar to avoid calculating on every tick (optional, but efficient)
// For this strategy, we check every tick but look at closed bars (index 1 and 2)
// to ensure the signal is confirmed and doesn't repaint.
// 1. Get DeMarker values
// Index 1 is the previous closed bar. Index 2 is the bar before that.
double deM_1 = iDeMarker(NULL, 0, DeMarkerPeriod, 1);
double deM_2 = iDeMarker(NULL, 0, DeMarkerPeriod, 2);
// 2. Check for Buy Signal (Cross from below 0.3 to above 0.3)
if(deM_2 < OversoldLevel && deM_1 > OversoldLevel)
{
// Close existing Sell positions first
ClosePositions(OP_SELL);
// Check if we already have a Buy position
if(CountPositions(OP_BUY) == 0)
{
OpenTrade(OP_BUY);
}
}
// 3. Check for Sell Signal (Cross from above 0.7 to below 0.7)
if(deM_2 > OverboughtLevel && deM_1 < OverboughtLevel)
{
// Close existing Buy positions first
ClosePositions(OP_BUY);
// Check if we already have a Sell position
if(CountPositions(OP_SELL) == 0)
{
OpenTrade(OP_SELL);
}
}
}
//+------------------------------------------------------------------+
//| Helper: Open a Trade |
//+------------------------------------------------------------------+
void OpenTrade(int type)
{
double sl = 0, tp = 0;
double price = 0;
color cmdColor = clrNONE;
if(type == OP_BUY)
{
price = Ask;
if(StopLoss > 0) sl = price - (StopLoss * Point * pipMultiplier);
if(TakeProfit > 0) tp = price + (TakeProfit * Point * pipMultiplier);
cmdColor = clrBlue;
}
else if(type == OP_SELL)
{
price = Bid;
if(StopLoss > 0) sl = price + (StopLoss * Point * pipMultiplier);
if(TakeProfit > 0) tp = price - (TakeProfit * Point * pipMultiplier);
cmdColor = clrRed;
}
// Normalize prices
sl = NormalizeDouble(sl, Digits);
tp = NormalizeDouble(tp, Digits);
// Send Order
int ticket = OrderSend(Symbol(), type, LotSize, price, Slippage, sl, tp, "DeMarker EA", MagicNumber, 0, cmdColor);
if(ticket < 0)
{
Print("OrderSend failed with error #", GetLastError());
}
}
//+------------------------------------------------------------------+
//| Helper: Close Positions of a specific type |
//+------------------------------------------------------------------+
void ClosePositions(int type)
{
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
if(OrderType() == type)
{
bool result = false;
if(type == OP_BUY)
result = OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, clrRed);
else if(type == OP_SELL)
result = OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, clrBlue);
if(!result) Print("OrderClose failed: ", GetLastError());
}
}
}
}
}
//+------------------------------------------------------------------+
//| Helper: Count Open Positions of a specific type |
//+------------------------------------------------------------------+
int CountPositions(int type)
{
int count = 0;
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() == type)
{
count++;
}
}
}
return count;
}
//+------------------------------------------------------------------+
How to Install and Use
- Open MetaTrader 4.
- Press
F4to open the MetaEditor. - Click New -> Expert Advisor (template) -> Name it "DeMarkerStrategy".
- Delete everything in the new file and paste the code above.
- Press
F7or click Compile. Ensure there are no errors. - Go back to the main MT4 window.
- Find "DeMarkerStrategy" in the Navigator panel under Expert Advisors.
- Drag it onto a chart (e.g., EURUSD H1).
- Ensure the "AutoTrading" button at the top of MT4 is green.
Key Features of This Code
- 5-Digit Broker Support: Automatically adjusts Stop Loss and Take Profit calculations for brokers using 5 decimal places (points vs pips).
- Signal Confirmation: It uses
iDeMarker(..., 1)andiDeMarker(..., 2). This means it looks at the previous closed bar and the bar before that. This ensures the signal is "locked in" and won't disappear (repaint) while the current candle is still moving. - Risk Management: Includes inputs for Stop Loss and Take Profit.
- Magic Number: Uses a unique ID so this EA won't accidentally close trades opened by you manually or by other EAs.
Q&A
Q: How can I make the strategy more aggressive?
A: You can change the OverboughtLevel to 0.6 and OversoldLevel to 0.4 in the input settings. This will generate signals closer to the center line, resulting in more trades but potentially more false signals.
Q: Why does the EA close opposite trades?
A: This is a reversal strategy. If the indicator says the market is oversold (Buy), it implies the previous downward trend (Sell) is ending. Therefore, it is logical to close any open Sell positions before opening a Buy.
Q: Can I use this on any timeframe?
A: Yes, the code uses 0 in the iDeMarker function, which represents the PERIOD_CURRENT. It will adapt to whatever timeframe (M15, H1, D1) the chart is set to.