MT4 relies on the MQL4 execution model. This code handles OrderSend execution, point/pip conversions for 5-digit brokers, MTF calculations via direct runtime functions, and manual ticket-by-ticket position iteration.
Code: Select all
//+------------------------------------------------------------------+
//| EliteScalper_MT4.mq4 |
//| London / New York Overlap Engine|
//+------------------------------------------------------------------+
#property copyright "Elite Scalper Systems"
#property link "https://www.mql5.com"
#property version "2.00"
#property strict
//--- Input Parameters
input string RiskHeader = "--- Risk & Account Management ---";
input double InpRiskPercent = 1.0; // Risk Per Trade (% of Equity)
input double InpMaxDailyLossPct = 3.0; // Circuit Breaker: Max Daily Loss (%)
input double InpMaxDailyProfitPct = 5.0; // Circuit Breaker: Max Daily Profit (%)
input double InpStopLossPips = 5.0; // Stop Loss (Pips)
input double InpTakeProfitPips = 8.0; // Take Profit (Pips)
input int InpMagicNumber = 109202; // Magic Number
input string SessionHeader = "--- Session Filter (Server Time) ---";
input int InpStartHour = 15; // Session Start Hour
input int InpStartMinute = 0; // Session Start Minute
input int InpEndHour = 19; // Session End Hour
input int InpEndMinute = 0; // Session End Minute
input bool InpCloseOnSessionEnd = true; // Liquidate at Session End
input string FilterHeader = "--- Technical Parameters ---";
input int InpMacroTf = 15; // Macro Trend Timeframe (Minutes)
input int InpMacroEmaPeriod = 200; // Macro EMA Period
input int InpFastEmaPeriod = 9; // Micro Fast EMA (M1)
input int InpSlowEmaPeriod = 21; // Micro Slow EMA (M1)
input double InpMinAtrPips = 2.0; // Min ATR Volatility (Pips)
input int InpAtrPeriod = 14; // ATR Period
//--- Internal State
double pipSize;
datetime currentDay;
double dayStartBalance;
bool circuitBreakerHit;
//+------------------------------------------------------------------+
//| Expert Initialization |
//+------------------------------------------------------------------+
int OnInit()
{
pipSize = (_Digits == 3 || _Digits == 5) ? _Point * 10.0 : _Point;
currentDay = 0;
dayStartBalance = AccountBalance();
circuitBreakerHit = false;
return INIT_SUCCEEDED;
}
void OnDeinit(const int reason)
{
Comment("");
}
//+------------------------------------------------------------------+
//| Dynamic Lot Size Calculation |
//+------------------------------------------------------------------+
double CalculateLotSize(double slPips)
{
double equity = AccountEquity();
double riskAmount = equity * (InpRiskPercent / 100.0);
double tickValue = MarketInfo(_Symbol, MODE_TICKVALUE);
double tickSize = MarketInfo(_Symbol, MODE_TICKSIZE);
if(tickSize <= 0 || tickValue <= 0) return 0.0;
double slPriceDist = slPips * pipSize;
double riskPerLot = (slPriceDist / tickSize) * tickValue;
if(riskPerLot <= 0) return 0.0;
double calculatedLot = riskAmount / riskPerLot;
double minLot = MarketInfo(_Symbol, MODE_MINLOT);
double maxLot = MarketInfo(_Symbol, MODE_MAXLOT);
double stepLot = MarketInfo(_Symbol, MODE_LOTSTEP);
calculatedLot = MathFloor(calculatedLot / stepLot) * stepLot;
return MathMin(MathMax(calculatedLot, minLot), maxLot);
}
//+------------------------------------------------------------------+
//| Execution State Utilities |
//+------------------------------------------------------------------+
bool IsInSession()
{
int curMin = TimeHour(TimeCurrent()) * 60 + TimeMinute(TimeCurrent());
int startMin = InpStartHour * 60 + InpStartMinute;
int endMin = InpEndHour * 60 + InpEndMinute;
return (startMin <= endMin) ? (curMin >= startMin && curMin < endMin)
: (curMin >= startMin || curMin < endMin);
}
int CountOpenPositions()
{
int count = 0;
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == _Symbol && OrderMagicNumber() == InpMagicNumber)
count++;
}
}
return count;
}
void CloseAllPositions(string reason)
{
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == _Symbol && OrderMagicNumber() == InpMagicNumber)
{
int ticket = OrderTicket();
double closePrice = (OrderType() == OP_BUY) ? Bid : Ask;
bool res = OrderClose(ticket, OrderLots(), closePrice, 3, clrRed);
if(res) Print("Closed Order #", ticket, " Reason: ", reason);
}
}
}
}
//+------------------------------------------------------------------+
//| Expert Tick Function |
//+------------------------------------------------------------------+
void OnTick()
{
// Daily Circuit Breaker Tracking
datetime today = iTime(_Symbol, PERIOD_D1, 0);
if(today != currentDay)
{
currentDay = today;
dayStartBalance = AccountBalance();
circuitBreakerHit = false;
}
double equity = AccountEquity();
double pnlPct = ((equity - dayStartBalance) / dayStartBalance) * 100.0;
if(!circuitBreakerHit && (pnlPct <= -InpMaxDailyLossPct || pnlPct >= InpMaxDailyProfitPct))
{
circuitBreakerHit = true;
CloseAllPositions("Circuit Breaker Tripped");
}
bool sessionActive = IsInSession();
// End-of-Session Liquidation
if(!sessionActive && InpCloseOnSessionEnd && CountOpenPositions() > 0)
{
CloseAllPositions("End of Trading Session");
}
// Technical Calculations
double fastCurrent = iMA(_Symbol, PERIOD_M1, InpFastEmaPeriod, 0, MODE_EMA, PRICE_CLOSE, 0);
double fastPrev = iMA(_Symbol, PERIOD_M1, InpFastEmaPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
double slowCurrent = iMA(_Symbol, PERIOD_M1, InpSlowEmaPeriod, 0, MODE_EMA, PRICE_CLOSE, 0);
double slowPrev = iMA(_Symbol, PERIOD_M1, InpSlowEmaPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
// MTF Higher Timeframe Read (15m Macro Trend)
double macroEma = iMA(_Symbol, InpMacroTf, InpMacroEmaPeriod, 0, MODE_EMA, PRICE_CLOSE, 0);
// Volatility Filter
double atrValue = iATR(_Symbol, PERIOD_M1, InpAtrPeriod, 0);
double currentAtrPips = atrValue / pipSize;
bool volatilityOk = (currentAtrPips >= InpMinAtrPips);
bool macroBull = (Bid > macroEma);
bool macroBear = (Ask < macroEma);
// On-Chart HUD
string hud = StringFormat(
"=== ELITE SCALPER HUD (MT4) ===\n" +
"Session Status: %s\n" +
"Circuit Breaker: %s (Daily PnL: %.2f%%)\n" +
"Volatility: %.2f Pips (Min: %.1f)\n" +
"Macro Trend (15M): %s\n" +
"Open Positions: %d",
sessionActive ? "ACTIVE" : "CLOSED",
circuitBreakerHit ? "LOCKED" : "CLEAR", pnlPct,
currentAtrPips, InpMinAtrPips,
macroBull ? "BULLISH" : macroBear ? "BEARISH" : "FLAT",
CountOpenPositions()
);
Comment(hud);
// Gate Checks
if(!sessionActive || circuitBreakerHit || CountOpenPositions() > 0 || !volatilityOk)
return;
// Micro Crossovers
bool buySignal = (fastPrev <= slowPrev && fastCurrent > slowCurrent) && macroBull;
bool sellSignal = (fastPrev >= slowPrev && fastCurrent < slowCurrent) && macroBear;
if(buySignal)
{
double lot = CalculateLotSize(InpStopLossPips);
double sl = NormalizeDouble(Ask - (InpStopLossPips * pipSize), _Digits);
double tp = NormalizeDouble(Ask + (InpTakeProfitPips * pipSize), _Digits);
int ticket = OrderSend(_Symbol, OP_BUY, lot, Ask, 3, sl, tp, "Elite Scalper", InpMagicNumber, 0, clrBlue);
}
else if(sellSignal)
{
double lot = CalculateLotSize(InpStopLossPips);
double sl = NormalizeDouble(Bid + (InpStopLossPips * pipSize), _Digits);
double tp = NormalizeDouble(Bid - (InpTakeProfitPips * pipSize), _Digits);
int ticket = OrderSend(_Symbol, OP_SELL, lot, Bid, 3, sl, tp, "Elite Scalper", InpMagicNumber, 0, clrRed);
}
}