Generate code in 3 minutes
Enter your idea and AI generates runnable code.
Here is a complete, fully functional MQL4 Expert Advisor (EA) based on the DeMarker indicator.
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.
//+------------------------------------------------------------------+
//| 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;
}
//+------------------------------------------------------------------+
F4 to open the MetaEditor.F7 or click Compile. Ensure there are no errors.iDeMarker(..., 1) and iDeMarker(..., 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.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.