//+------------------------------------------------------------------+
//| Gold Scalper M1.mq4 |
//| Optimized for XAU/USD 1-Minute Scalping |
//+------------------------------------------------------------------+
#property strict
//--- Input Parameters
input double LotSize = 0.1; // Base lot size
input int StopLoss = 150; // SL in points (15 pips for gold)
input int TakeProfit = 300; // TP in points (30 pips for gold)
input int TrailingStop = 100; // Trailing stop in points
input int MagicNumber = 202311; // EA identifier
input int MaxSpread = 15; // Max allowed spread (1.5 pips)
input int ATR_Period = 14; // ATR period for volatility filter
input double ATR_Multiplier = 1.5; // ATR multiplier for dynamic SL/TP
input int MaxTradesPerDay = 30; // Daily trade limit
input string TradeTimeStart = "00:00"; // Trading window start
input string TradeTimeEnd = "23:59"; // Trading window end
input int Slippage = 3; // Maximum allowed slippage
//--- Global Variables
datetime lastTradeTime;
int dailyTradeCount = 0;
datetime lastBarTime;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Check for gold symbol
if(Symbol() != "XAUUSD" && Symbol() != "XAUUSD.")
{
Alert("This EA is designed for XAUUSD only!");
return(INIT_FAILED);
}
// Initialize daily trade counter
CheckNewDay();
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//--- Check for new bar (1-minute)
datetime currentBarTime = iTime(NULL, PERIOD_M1, 0);
if(lastBarTime == currentBarTime) return;
lastBarTime = currentBarTime;
//--- Check for new day
CheckNewDay();
//--- Trade time filter
if(!IsTradeTime()) return;
//--- Spread check
if(MarketInfo(Symbol(), MODE_SPREAD) > MaxSpread) return;
//--- Check existing trades
if(CountTrades() >= 1)
{
TrailingStopCheck();
return;
}
//--- Check daily trade limit
if(dailyTradeCount >= MaxTradesPerDay) return;
//--- Volatility filter using ATR
double atr = iATR(NULL, 0, ATR_Period, 0);
if(atr < 0.5 || atr > 5.0) return; // Filter for gold's typical M1 volatility
//--- Trading signals (example: MACD + Stochastic)
double macd = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 0);
double macdPrev = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 1);
double stoch = iStochastic(NULL, 0, 14, 3, 3, MODE_SMA, 0, MODE_MAIN, 0);
// Dynamic SL/TP based on ATR
int dynSL = (int)(atr * ATR_Multiplier * 100);
int dynTP = dynSL * 2;
// Use whichever is smaller - fixed or dynamic SL/TP
int finalSL = MathMin(StopLoss, dynSL);
int finalTP = MathMin(TakeProfit, dynTP);
//--- Buy Signal
if(macd > 0 && macdPrev <= 0 && stoch < 20)
{
double sl = NormalizeDouble(Bid - finalSL * Point, Digits);
double tp = NormalizeDouble(Ask + finalTP * Point, Digits);
if(OrderSend(Symbol(), OP_BUY, LotSize, Ask, Slippage, sl, tp, "GoldScalper", MagicNumber, 0, clrGreen) > 0)
dailyTradeCount++;
}
//--- Sell Signal
if(macd < 0 && macdPrev >= 0 && stoch > 80)
{
double sl = NormalizeDouble(Ask + finalSL * Point, Digits);
double tp = NormalizeDouble(Bid - finalTP * Point, Digits);
if(OrderSend(Symbol(), OP_SELL, LotSize, Bid, Slippage, sl, tp, "GoldScalper", MagicNumber, 0, clrRed) > 0)
dailyTradeCount++;
}
}
//+------------------------------------------------------------------+
//| Custom functions |
//+------------------------------------------------------------------+
void CheckNewDay()
{
MqlDateTime today, lastTradeDate;
TimeToStruct(TimeCurrent(), today);
TimeToStruct(lastTradeTime, lastTradeDate);
if(today.day != lastTradeDate.day || today.mon != lastTradeDate.mon || today.year != lastTradeDate.year)
{
dailyTradeCount = 0;
lastTradeTime = TimeCurrent();
}
}
bool IsTradeTime()
{
datetime start = StringToTime(TradeTimeStart);
datetime end = StringToTime(TradeTimeEnd);
datetime now = TimeCurrent();
return (now >= start && now <= end);
}
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)
count++;
}
return count;
}
void TrailingStopCheck()
{
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)
{
if(Bid - OrderOpenPrice() > TrailingStop * Point)
if(OrderStopLoss() < Bid - TrailingStop * Point)
OrderModify(OrderTicket(), OrderOpenPrice(),
NormalizeDouble(Bid - TrailingStop * Point, Digits),
OrderTakeProfit(), 0, clrBlue);
}
else if(OrderType() == OP_SELL)
{
if(OrderOpenPrice() - Ask > TrailingStop * Point)
if(OrderStopLoss() > Ask + TrailingStop * Point)
OrderModify(OrderTicket(), OrderOpenPrice(),
NormalizeDouble(Ask + TrailingStop * Point, Digits),
OrderTakeProfit(), 0, clrRed);
}
}
}
}
}