361 lines
No EOL
9.5 KiB
MQL4
361 lines
No EOL
9.5 KiB
MQL4
//+------------------------------------------------------------------+
|
|
//| AITradingBot.mq4 |
|
|
//| MT4 Automated Trading Bot - Starter Version |
|
|
//| Strategy: EMA Crossover + RSI + Risk Management |
|
|
//+------------------------------------------------------------------+
|
|
#property strict
|
|
|
|
//---------------------- INPUT SETTINGS -----------------------------//
|
|
input double RiskPercent = 1.0;
|
|
input double FixedLot = 0.01;
|
|
input bool UseFixedLot = true;
|
|
|
|
input int FastEMA = 9;
|
|
input int SlowEMA = 21;
|
|
input int RSIPeriod = 14;
|
|
|
|
input double BuyRSIMin = 55.0;
|
|
input double SellRSIMax = 45.0;
|
|
|
|
input int StopLossPips = 30;
|
|
input int TakeProfitPips = 60;
|
|
input int TrailingStopPips = 20;
|
|
|
|
input int MaxSpreadPips = 3;
|
|
input int Slippage = 5;
|
|
input int MagicNumber = 20260826;
|
|
|
|
input bool EnableBuy = true;
|
|
input bool EnableSell = true;
|
|
input bool EnableTrailing = true;
|
|
|
|
//---------------------- GLOBAL VARIABLES ---------------------------//
|
|
datetime LastBarTime = 0;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert initialization |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
Print("AITradingBot MT4 started successfully.");
|
|
return(INIT_SUCCEEDED);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert deinitialization |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
Print("AITradingBot MT4 stopped.");
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Main Tick Function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick()
|
|
{
|
|
ManageTrailingStop();
|
|
|
|
if(!IsNewBar())
|
|
return;
|
|
|
|
if(!TradingAllowed())
|
|
return;
|
|
|
|
if(CountOpenTrades() > 0)
|
|
return;
|
|
|
|
double fastEMA1 = iMA(Symbol(), PERIOD_CURRENT, FastEMA, 0, MODE_EMA, PRICE_CLOSE, 1);
|
|
double fastEMA2 = iMA(Symbol(), PERIOD_CURRENT, FastEMA, 0, MODE_EMA, PRICE_CLOSE, 2);
|
|
|
|
double slowEMA1 = iMA(Symbol(), PERIOD_CURRENT, SlowEMA, 0, MODE_EMA, PRICE_CLOSE, 1);
|
|
double slowEMA2 = iMA(Symbol(), PERIOD_CURRENT, SlowEMA, 0, MODE_EMA, PRICE_CLOSE, 2);
|
|
|
|
double rsi = iRSI(Symbol(), PERIOD_CURRENT, RSIPeriod, PRICE_CLOSE, 1);
|
|
|
|
// BUY SIGNAL
|
|
bool buySignal =
|
|
EnableBuy &&
|
|
fastEMA2 <= slowEMA2 &&
|
|
fastEMA1 > slowEMA1 &&
|
|
rsi >= BuyRSIMin;
|
|
|
|
// SELL SIGNAL
|
|
bool sellSignal =
|
|
EnableSell &&
|
|
fastEMA2 >= slowEMA2 &&
|
|
fastEMA1 < slowEMA1 &&
|
|
rsi <= SellRSIMax;
|
|
|
|
if(buySignal)
|
|
{
|
|
OpenBuy();
|
|
return;
|
|
}
|
|
|
|
if(sellSignal)
|
|
{
|
|
OpenSell();
|
|
return;
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Check for new candle |
|
|
//+------------------------------------------------------------------+
|
|
bool IsNewBar()
|
|
{
|
|
datetime currentBar = iTime(Symbol(), PERIOD_CURRENT, 0);
|
|
|
|
if(currentBar != LastBarTime)
|
|
{
|
|
LastBarTime = currentBar;
|
|
return(true);
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Check trading conditions |
|
|
//+------------------------------------------------------------------+
|
|
bool TradingAllowed()
|
|
{
|
|
if(!IsTradeAllowed())
|
|
{
|
|
Print("Trading is not allowed.");
|
|
return(false);
|
|
}
|
|
|
|
double spreadPips = (Ask - Bid) / PipSize();
|
|
|
|
if(spreadPips > MaxSpreadPips)
|
|
{
|
|
Print("Spread too high: ", DoubleToString(spreadPips, 1), " pips");
|
|
return(false);
|
|
}
|
|
|
|
return(true);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Open Buy |
|
|
//+------------------------------------------------------------------+
|
|
void OpenBuy()
|
|
{
|
|
RefreshRates();
|
|
|
|
double pip = PipSize();
|
|
double lots = CalculateLotSize();
|
|
|
|
double price = Ask;
|
|
double sl = NormalizeDouble(price - StopLossPips * pip, Digits);
|
|
double tp = NormalizeDouble(price + TakeProfitPips * pip, Digits);
|
|
|
|
int ticket = OrderSend(
|
|
Symbol(),
|
|
OP_BUY,
|
|
lots,
|
|
price,
|
|
Slippage,
|
|
sl,
|
|
tp,
|
|
"AITradingBot BUY",
|
|
MagicNumber,
|
|
0,
|
|
clrBlue
|
|
);
|
|
|
|
if(ticket < 0)
|
|
Print("BUY failed. Error: ", GetLastError());
|
|
else
|
|
Print("BUY opened successfully. Ticket: ", ticket);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Open Sell |
|
|
//+------------------------------------------------------------------+
|
|
void OpenSell()
|
|
{
|
|
RefreshRates();
|
|
|
|
double pip = PipSize();
|
|
double lots = CalculateLotSize();
|
|
|
|
double price = Bid;
|
|
double sl = NormalizeDouble(price + StopLossPips * pip, Digits);
|
|
double tp = NormalizeDouble(price - TakeProfitPips * pip, Digits);
|
|
|
|
int ticket = OrderSend(
|
|
Symbol(),
|
|
OP_SELL,
|
|
lots,
|
|
price,
|
|
Slippage,
|
|
sl,
|
|
tp,
|
|
"AITradingBot SELL",
|
|
MagicNumber,
|
|
0,
|
|
clrRed
|
|
);
|
|
|
|
if(ticket < 0)
|
|
Print("SELL failed. Error: ", GetLastError());
|
|
else
|
|
Print("SELL opened successfully. Ticket: ", ticket);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Calculate lot size |
|
|
//+------------------------------------------------------------------+
|
|
double CalculateLotSize()
|
|
{
|
|
if(UseFixedLot)
|
|
return(NormalizeLot(FixedLot));
|
|
|
|
double riskMoney = AccountBalance() * RiskPercent / 100.0;
|
|
|
|
double pipValuePerLot =
|
|
MarketInfo(Symbol(), MODE_TICKVALUE) /
|
|
MarketInfo(Symbol(), MODE_TICKSIZE) *
|
|
PipSize();
|
|
|
|
if(pipValuePerLot <= 0)
|
|
return(NormalizeLot(FixedLot));
|
|
|
|
double lots = riskMoney / (StopLossPips * pipValuePerLot);
|
|
|
|
return(NormalizeLot(lots));
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Normalize lot size |
|
|
//+------------------------------------------------------------------+
|
|
double NormalizeLot(double lots)
|
|
{
|
|
double minLot = MarketInfo(Symbol(), MODE_MINLOT);
|
|
double maxLot = MarketInfo(Symbol(), MODE_MAXLOT);
|
|
double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
|
|
|
|
if(lots < minLot)
|
|
lots = minLot;
|
|
|
|
if(lots > maxLot)
|
|
lots = maxLot;
|
|
|
|
lots = MathFloor(lots / lotStep) * lotStep;
|
|
|
|
return(NormalizeDouble(lots, 2));
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Pip size |
|
|
//+------------------------------------------------------------------+
|
|
double PipSize()
|
|
{
|
|
if(Digits == 3 || Digits == 5)
|
|
return(Point * 10);
|
|
|
|
return(Point);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Count current bot trades |
|
|
//+------------------------------------------------------------------+
|
|
int CountOpenTrades()
|
|
{
|
|
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);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Trailing Stop |
|
|
//+------------------------------------------------------------------+
|
|
void ManageTrailingStop()
|
|
{
|
|
if(!EnableTrailing)
|
|
return;
|
|
|
|
double pip = PipSize();
|
|
|
|
for(int i = OrdersTotal() - 1; i >= 0; i--)
|
|
{
|
|
if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
|
|
continue;
|
|
|
|
if(OrderSymbol() != Symbol())
|
|
continue;
|
|
|
|
if(OrderMagicNumber() != MagicNumber)
|
|
continue;
|
|
|
|
// BUY TRAILING
|
|
if(OrderType() == OP_BUY)
|
|
{
|
|
double newSL = NormalizeDouble(
|
|
Bid - TrailingStopPips * pip,
|
|
Digits
|
|
);
|
|
|
|
if(Bid - OrderOpenPrice() >= TrailingStopPips * pip)
|
|
{
|
|
if(OrderStopLoss() < newSL)
|
|
{
|
|
bool modified = OrderModify(
|
|
OrderTicket(),
|
|
OrderOpenPrice(),
|
|
newSL,
|
|
OrderTakeProfit(),
|
|
0,
|
|
clrBlue
|
|
);
|
|
|
|
if(!modified)
|
|
Print("BUY trailing error: ", GetLastError());
|
|
}
|
|
}
|
|
}
|
|
|
|
// SELL TRAILING
|
|
if(OrderType() == OP_SELL)
|
|
{
|
|
double newSL = NormalizeDouble(
|
|
Ask + TrailingStopPips * pip,
|
|
Digits
|
|
);
|
|
|
|
if(OrderOpenPrice() - Ask >= TrailingStopPips * pip)
|
|
{
|
|
if(OrderStopLoss() == 0 || OrderStopLoss() > newSL)
|
|
{
|
|
bool modified = OrderModify(
|
|
OrderTicket(),
|
|
OrderOpenPrice(),
|
|
newSL,
|
|
OrderTakeProfit(),
|
|
0,
|
|
clrRed
|
|
);
|
|
|
|
if(!modified)
|
|
Print("SELL trailing error: ", GetLastError());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+ |