//+------------------------------------------------------------------+
//| Smart_Scalping_Bot.mq5 |
//| Professional Automated Scalper |
//+------------------------------------------------------------------+
#property copyright "Smart Scalping Bot"
#property version "2.00"
#property strict
//--- Input Parameters
input group "=== Account & Risk ==="
input double RiskPercent = 1.0; // Risk per trade (%)
input double FixedLotSize = 0.0; // Fixed lot (0 = auto-calculate)
input group "=== Profit Targets ==="
input int QuickProfitPips = 3; // Quick profit target (pips)
input int StopLossPips = 15; // Stop loss (pips)
input int TrailingStartPips = 5; // Start trailing at (pips)
input int TrailingStopPips = 3; // Trailing stop distance (pips)
input group "=== Trading Settings ==="
input int MaxPositions = 3; // Max positions per direction
input int MinDistancePips = 10; // Min distance between positions
input bool CloseOnOpposite = true; // Close on opposite signal
input group "=== Indicators ==="
input int FastEMA = 9; // Fast EMA period
input int SlowEMA = 21; // Slow EMA period
input int RSI_Period = 14; // RSI period
input int Stoch_K = 5; // Stochastic K
input int Stoch_D = 3; // Stochastic D
input double SAR_Step = 0.02; // SAR step
input double SAR_Max = 0.2; // SAR maximum
input group "=== Advanced ==="
input int MagicNumber = 777777; // Magic number
input string TradeComment = "SmartScalp"; // Trade comment
//--- Global Variables
int h_FastEMA, h_SlowEMA, h_RSI, h_Stoch, h_SAR;
double fastEMA[], slowEMA[], rsi[], stochK[], stochD[], sar[];
datetime lastBar = 0;
bool initSuccess = false;
//+------------------------------------------------------------------+
//| Expert initialization |
//+------------------------------------------------------------------+
int OnInit()
{
Print("═══════════════════════════════════════════");
Print(" SMART SCALPING BOT - INITIALIZING");
Print("═══════════════════════════════════════════");
// Create indicators
h_FastEMA = iMA(_Symbol, 0, FastEMA, 0, MODE_EMA, PRICE_CLOSE);
h_SlowEMA = iMA(_Symbol, 0, SlowEMA, 0, MODE_EMA, PRICE_CLOSE);
h_RSI = iRSI(_Symbol, 0, RSI_Period, PRICE_CLOSE);
h_Stoch = iStochastic(_Symbol, 0, Stoch_K, Stoch_D, 3, MODE_SMA, STO_LOWHIGH);
h_SAR = iSAR(_Symbol, 0, SAR_Step, SAR_Max);
if(h_FastEMA == INVALID_HANDLE || h_SlowEMA == INVALID_HANDLE ||
h_RSI == INVALID_HANDLE || h_Stoch == INVALID_HANDLE || h_SAR ==
INVALID_HANDLE)
{
Print("ERROR: Failed to create indicators!");
return INIT_FAILED;
}
ArraySetAsSeries(fastEMA, true);
ArraySetAsSeries(slowEMA, true);
ArraySetAsSeries(rsi, true);
ArraySetAsSeries(stochK, true);
ArraySetAsSeries(stochD, true);
ArraySetAsSeries(sar, true);
// Display settings
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
Print("Account Balance: $", balance);
Print("Risk per Trade: ", RiskPercent, "1%");
Print("Quick Profit Target: ", QuickProfitPips, " pips");
Print("Stop Loss: ", StopLossPips, " pips");
Print("Max Positions: ", MaxPositions);
Print("═══════════════════════════════════════════");
// Check trading permissions
if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
{
Alert("WARNING: AutoTrading is OFF! Enable it in MT5 toolbar.");
}
initSuccess = true;
Print("✅ Initialization successful - Ready to trade!");
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Expert deinitialization |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(h_FastEMA != INVALID_HANDLE) IndicatorRelease(h_FastEMA);
if(h_SlowEMA != INVALID_HANDLE) IndicatorRelease(h_SlowEMA);
if(h_RSI != INVALID_HANDLE) IndicatorRelease(h_RSI);
if(h_Stoch != INVALID_HANDLE) IndicatorRelease(h_Stoch);
if(h_SAR != INVALID_HANDLE) IndicatorRelease(h_SAR);
Print("Smart Scalping Bot stopped");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
if(!initSuccess) return;
// Manage existing positions every tick
ManagePositions();
// Check for new bar
datetime currentBar = iTime(_Symbol, 0, 0);
if(currentBar == lastBar) return;
lastBar = currentBar;
// Load indicators
if(!LoadIndicators()) return;
// Analyze market
int signal = AnalyzeMarket();
if(signal == 0) return; // No signal
// Execute trades
if(signal == 1) // BUY
{
int buyCount = CountPositions(POSITION_TYPE_BUY);
int sellCount = CountPositions(POSITION_TYPE_SELL);
if(CloseOnOpposite && sellCount > 0)
CloseAll(POSITION_TYPE_SELL);
if(buyCount < MaxPositions && CanOpenPosition(POSITION_TYPE_BUY))
{
OpenTrade(ORDER_TYPE_BUY);
}
}
else if(signal == -1) // SELL
{
int buyCount = CountPositions(POSITION_TYPE_BUY);
int sellCount = CountPositions(POSITION_TYPE_SELL);
if(CloseOnOpposite && buyCount > 0)
CloseAll(POSITION_TYPE_BUY);
if(sellCount < MaxPositions && CanOpenPosition(POSITION_TYPE_SELL))
{
OpenTrade(ORDER_TYPE_SELL);
}
}
}
//+------------------------------------------------------------------+
//| Load all indicators |
//+------------------------------------------------------------------+
bool LoadIndicators()
{
if(CopyBuffer(h_FastEMA, 0, 0, 3, fastEMA) < 3) return false;
if(CopyBuffer(h_SlowEMA, 0, 0, 3, slowEMA) < 3) return false;
if(CopyBuffer(h_RSI, 0, 0, 2, rsi) < 2) return false;
if(CopyBuffer(h_Stoch, 0, 0, 2, stochK) < 2) return false;
if(CopyBuffer(h_Stoch, 1, 0, 2, stochD) < 2) return false;
if(CopyBuffer(h_SAR, 0, 0, 2, sar) < 2) return false;
return true;
}
//+------------------------------------------------------------------+
//| Analyze market and return signal |
//+------------------------------------------------------------------+
int AnalyzeMarket()
{
int buyPoints = 0;
int sellPoints = 0;
double price = iClose(_Symbol, 0, 1);
// EMA Analysis (40 points)
if(fastEMA[1] > slowEMA[1] && fastEMA[2] <= slowEMA[2])
buyPoints += 40; // Bullish cross
else if(fastEMA[1] < slowEMA[1] && fastEMA[2] >= slowEMA[2])
sellPoints += 40; // Bearish cross
else if(fastEMA[1] > slowEMA[1])
buyPoints += 20; // Bullish trend
else if(fastEMA[1] < slowEMA[1])
sellPoints += 20; // Bearish trend
// RSI Analysis (30 points)
if(rsi[1] < 30)
buyPoints += 30; // Oversold
else if(rsi[1] > 70)
sellPoints += 30; // Overbought
else if(rsi[1] < 50 && rsi[1] > rsi[2])
buyPoints += 15; // Rising
else if(rsi[1] > 50 && rsi[1] < rsi[2])
sellPoints += 15; // Falling
// Stochastic Analysis (30 points)
if(stochK[1] < 20 && stochK[1] > stochD[1])
buyPoints += 30; // Oversold cross up
else if(stochK[1] > 80 && stochK[1] < stochD[1])
sellPoints += 30; // Overbought cross down
// SAR Analysis (30 points)
if(sar[1] < price && sar[2] >= iClose(_Symbol, 0, 2))
buyPoints += 30; // SAR flip bullish
else if(sar[1] > price && sar[2] <= iClose(_Symbol, 0, 2))
sellPoints += 30; // SAR flip bearish
else if(sar[1] < price)
buyPoints += 10; // SAR bullish
else if(sar[1] > price)
sellPoints += 10; // SAR bearish
// Return signal if strong enough (70+ points)
if(buyPoints >= 70 && buyPoints > sellPoints)
return 1; // BUY
else if(sellPoints >= 70 && sellPoints > buyPoints)
return -1; // SELL
return 0; // NEUTRAL
}
//+------------------------------------------------------------------+
//| Calculate lot size |
//+------------------------------------------------------------------+
double GetLotSize()
{
if(FixedLotSize > 0)
return FixedLotSize;
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
double riskMoney = balance * RiskPercent / 100.0;
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
double pipValue = (digits == 5 || digits == 3) ? point * 10 : point;
double moneyPerPip = (pipValue / tickSize) * tickValue;
double lots = riskMoney / (StopLossPips * moneyPerPip);
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
lots = MathFloor(lots / lotStep) * lotStep;
if(lots < minLot) lots = minLot;
if(lots > maxLot) lots = maxLot;
return NormalizeDouble(lots, 2);
}
//+------------------------------------------------------------------+
//| Open trade |
//+------------------------------------------------------------------+
void OpenTrade(ENUM_ORDER_TYPE type)
{
double lots = GetLotSize();
if(lots <= 0) return;
double price = (type == ORDER_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_ASK) :
SymbolInfoDouble(_Symbol, SYMBOL_BID);
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
double pipValue = (digits == 5 || digits == 3) ? point * 10 : point;
double sl, tp;
if(type == ORDER_TYPE_BUY)
{
sl = price - StopLossPips * pipValue;
tp = price + QuickProfitPips * pipValue;
}
else
{
sl = price + StopLossPips * pipValue;
tp = price - QuickProfitPips * pipValue;
}
MqlTradeRequest req = {};
MqlTradeResult res = {};
[Link] = TRADE_ACTION_DEAL;
[Link] = _Symbol;
[Link] = lots;
[Link] = type;
[Link] = price;
[Link] = NormalizeDouble(sl, digits);
[Link] = NormalizeDouble(tp, digits);
[Link] = MagicNumber;
[Link] = TradeComment;
req.type_filling = ORDER_FILLING_IOC;
if(!OrderSend(req, res))
{
req.type_filling = ORDER_FILLING_FOK;
if(!OrderSend(req, res))
{
req.type_filling = ORDER_FILLING_RETURN;
OrderSend(req, res);
}
}
if([Link] == 10009 || [Link] == 10008)
{
Print("✅ ", (type == ORDER_TYPE_BUY ? "BUY" : "SELL"), " opened | Lot: ", lots, " | Price:
", price);
}
else
{
Print("❌ Order failed | Code: ", [Link]);
}
}
//+------------------------------------------------------------------+
//| Manage positions (trailing, quick profit) |
//+------------------------------------------------------------------+
void ManagePositions()
{
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
double pipValue = (digits == 5 || digits == 3) ? point * 10 : point;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) continue;
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double currentSL = PositionGetDouble(POSITION_SL);
ENUM_POSITION_TYPE posType =
(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double profitPips = (posType == POSITION_TYPE_BUY) ?
(bid - openPrice) / pipValue :
(openPrice - ask) / pipValue;
// Quick profit close
if(profitPips >= QuickProfitPips)
{
CloseTrade(ticket);
Print("💰 Profit taken: ", NormalizeDouble(profitPips, 1), " pips");
continue;
}
// Trailing stop
if(profitPips >= TrailingStartPips)
{
double newSL = 0;
if(posType == POSITION_TYPE_BUY)
{
newSL = bid - TrailingStopPips * pipValue;
if(newSL > currentSL)
ModifySL(ticket, NormalizeDouble(newSL, digits));
}
else
{
newSL = ask + TrailingStopPips * pipValue;
if(newSL < currentSL || currentSL == 0)
ModifySL(ticket, NormalizeDouble(newSL, digits));
}
}
}
}
//+------------------------------------------------------------------+
//| Close trade |
//+------------------------------------------------------------------+
void CloseTrade(ulong ticket)
{
MqlTradeRequest req = {};
MqlTradeResult res = {};
if(!PositionSelectByTicket(ticket)) return;
[Link] = TRADE_ACTION_DEAL;
[Link] = ticket;
[Link] = _Symbol;
[Link] = PositionGetDouble(POSITION_VOLUME);
[Link] = MagicNumber;
req.type_filling = ORDER_FILLING_RETURN;
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
[Link] = ORDER_TYPE_SELL;
[Link] = SymbolInfoDouble(_Symbol, SYMBOL_BID);
}
else
{
[Link] = ORDER_TYPE_BUY;
[Link] = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
}
OrderSend(req, res);
}
//+------------------------------------------------------------------+
//| Modify stop loss |
//+------------------------------------------------------------------+
void ModifySL(ulong ticket, double sl)
{
MqlTradeRequest req = {};
MqlTradeResult res = {};
[Link] = TRADE_ACTION_SLTP;
[Link] = ticket;
[Link] = _Symbol;
[Link] = sl;
[Link] = PositionGetDouble(POSITION_TP);
OrderSend(req, res);
}
//+------------------------------------------------------------------+
//| Count positions |
//+------------------------------------------------------------------+
int CountPositions(ENUM_POSITION_TYPE type)
{
int count = 0;
for(int i = 0; i < PositionsTotal(); i++)
{
if(PositionGetTicket(i) <= 0) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) continue;
if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == type)
count++;
}
return count;
}
//+------------------------------------------------------------------+
//| Check if can open position |
//+------------------------------------------------------------------+
bool CanOpenPosition(ENUM_POSITION_TYPE type)
{
double price = (type == POSITION_TYPE_BUY) ?
SymbolInfoDouble(_Symbol, SYMBOL_ASK) :
SymbolInfoDouble(_Symbol, SYMBOL_BID);
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
double pipValue = (digits == 5 || digits == 3) ? point * 10 : point;
double minDist = MinDistancePips * pipValue;
for(int i = 0; i < PositionsTotal(); i++)
{
if(PositionGetTicket(i) <= 0) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) continue;
if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) != type) continue;
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
if(MathAbs(price - openPrice) < minDist)
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Close all positions of type |
//+------------------------------------------------------------------+
void CloseAll(ENUM_POSITION_TYPE type)
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) continue;
if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == type)
CloseTrade(ticket);
}
}
//+------------------------------------------------------------------+