So the problem im expiriencing is that when i run the built in mql5 tester, my indicator values dont dynamically change, they keep a constant value, even though i wrote the code so that the indicator values are constantly read on every tick. This results in the bot not making a single trade, and i have tried everything to solve this, even read the documentation of mql5 and as far as i know, i have made no mistakes. any feedback or solutions are welcome.
//+------------------------------------------------------------------+
//| SwingTradeBot.mq5 |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
CTrade trade; // Trade object for order operations
input int SMA_Fast_Period = 50; // Fast SMA period
input int SMA_Slow_Period = 200; // Slow SMA period
input int RSI_Period = 14; // RSI period
input double Risk_Percent = 2.0; // Risk percentage of account balance
input double StopLossFactor = 2.0; // Factor for setting stop loss
input double TakeProfitFactor = 3.0; // Factor for setting take profit
// Global variables for indicator values
double FastMA_Current, SlowMA_Current, RSI_Current;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit() {
Print("Swing Trading Bot Initialized");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Calculate the lot size based on risk management rules |
//+------------------------------------------------------------------+
double CalculateLotSize() {
double riskAmount = AccountInfoDouble(ACCOUNT_BALANCE) * Risk_Percent / 100;
double atr = iATR(_Symbol, PERIOD_D1, 14);
double stopLossPips = atr * StopLossFactor / _Point;
double pipValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE) / SymbolInfoDouble(_Symbol, SYMBOL_TRADE_CONTRACT_SIZE);
double calculatedLotSize = riskAmount / (stopLossPips * pipValue);
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
calculatedLotSize = MathMax(minLot, MathMin(calculatedLotSize, maxLot));
calculatedLotSize = MathRound(calculatedLotSize / lotStep) * lotStep;
Print("Calculated Lot Size: ", calculatedLotSize); // Debugging print
return calculatedLotSize;
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick() {
UpdateIndicators();
double lot = CalculateLotSize();
if (ShouldOpenBuyOrder()) {
Print("Attempting to place buy order."); // Debugging print
PlaceBuyOrder(lot);
} else if (ShouldOpenSellOrder()) {
Print("Attempting to place sell order."); // Debugging print
PlaceSellOrder(lot);
}
}
//+------------------------------------------------------------------+
//| Update indicator values |
//+------------------------------------------------------------------+
void UpdateIndicators() {
FastMA_Current = iMA(_Symbol, PERIOD_D1, SMA_Fast_Period, 0, MODE_SMA, PRICE_CLOSE);
SlowMA_Current = iMA(_Symbol, PERIOD_D1, SMA_Slow_Period, 0, MODE_SMA, PRICE_CLOSE);
RSI_Current = iRSI(_Symbol, PERIOD_H4, RSI_Period, PRICE_CLOSE);
datetime currentBarTime = iTime(_Symbol, PERIOD_D1, 0);
Print("Current Bar Time: ", TimeToString(currentBarTime, TIME_DATE|TIME_MINUTES),
", FastMA: ", FastMA_Current,
", SlowMA: ", SlowMA_Current,
", RSI: ", RSI_Current);
}
//+------------------------------------------------------------------+
//| Check if a buy order should be opened |
//+------------------------------------------------------------------+
bool ShouldOpenBuyOrder() {
Print("Checking Buy Condition - FastMA: ", FastMA_Current, ", SlowMA: ", SlowMA_Current, ", RSI: ", RSI_Current); // Debugging print
return (FastMA_Current > SlowMA_Current && RSI_Current < 50);
}
//+------------------------------------------------------------------+
//| Check if a sell order should be opened |
//+------------------------------------------------------------------+
bool ShouldOpenSellOrder() {
Print("Checking Sell Condition - FastMA: ", FastMA_Current, ", SlowMA: ", SlowMA_Current, ", RSI: ", RSI_Current); // Debugging print
return (FastMA_Current < SlowMA_Current && RSI_Current > 50);
}
//+------------------------------------------------------------------+
//| Place a buy order |
//+------------------------------------------------------------------+
void PlaceBuyOrder(double lot) {
double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double stopLoss = currentPrice - StopLossFactor * SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
double takeProfit = currentPrice + TakeProfitFactor * SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
MqlTradeRequest request;
MqlTradeResult result;
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = lot;
request.type = ORDER_TYPE_BUY;
request.price = currentPrice;
request.sl = stopLoss;
request.tp = takeProfit;
request.deviation = 3;
request.type_filling = ORDER_FILLING_RETURN;
request.comment = "Buy Order";
if (!trade.OrderSend(request, result)) {
Print("Error opening buy order: ", result.comment, ", Error Code: ", GetLastError()); // Debugging print
} else {
Print("Buy order placed successfully."); // Debugging print
}
}
//+------------------------------------------------------------------+
//| Place a sell order |
//+------------------------------------------------------------------+
void PlaceSellOrder(double lot) {
double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double stopLoss = currentPrice + StopLossFactor * SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
double takeProfit = currentPrice - TakeProfitFactor * SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
MqlTradeRequest request;
MqlTradeResult result;
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = lot;
request.type = ORDER_TYPE_SELL;
request.price = currentPrice;
request.sl = stopLoss;
request.tp = takeProfit;
request.deviation = 3;
request.type_filling = ORDER_FILLING_RETURN;
request.comment = "Sell Order";
if (!trade.OrderSend(request, result)) {
Print("Error opening sell order: ", result.comment, ", Error Code: ", GetLastError()); // Debugging print
} else {
Print("Sell order placed successfully."); // Debugging print
}
}
Using an indicator in MQL5 is very different from using them in MQL4.
In MQL4 indicators simply are called and their values are returned.
In MQL5, indicators are defined (returning an indicator handle) and a buffer (in the form of an array) must be defined and prepared to store their values.
Upon a call of the defined indicator (by using its handle) the returned values must be copied into the array.
In your code the indicator handle is returned upon every call your function makes. That's why you don't see any changing values.
You'll also have to set:
#property indicator_buffers 1 // or 2,3...
At first usage this seems intimidating, but when applying similar indicators on multiple timeframes (like iMA 5, 30, D1) it works easy.