Please review my code of EA I have created

 
I have 2 issues with the code - 
1. There are no profitable trades in bullish side in past 1 year according to this code , which is not particularly possible . 
2. There is issue with fib object creation as well .....

#include <Trade\Trade.mqh>
CTrade trade;

#define FIBO_OBJ "FIB_RETRACEMENT"

input ENUM_TIMEFRAMES Timeframe = PERIOD_D1;
input double CandleSizeMin = 2.0;
input double EntryLevelTP = -0.236;
input double StopLossPercent = 2.0;
input double TakeProfitPercent = 5.0;
input double TrailingStartPercent = 1.0;
input double TradeVolume = 1.0;
const int FiboLevelCount = 12;
double FiboLevels[];
double PrevFiboLevels[];
bool FiboCreated = false;
datetime LastTradeDay = 0;
bool TradeTaken = false;
double Tolerance = 0.1;
int BarsTotal = 0;

struct FiboEntry {
   double EntryLevel;
   double TpLevel;
   double EntryPrice;
   bool IsBullish;
};

FiboEntry EntryData;

int OnInit()
{
   ArrayResize(FiboLevels, FiboLevelCount);
   double levels[] = {-1.618, -1.272, -0.382, -0.236, 0.0, 0.236, 0.382, 0.5, 0.618, 0.786, 1.0, 1.272};
   ArrayCopy(FiboLevels, levels);

   ArrayResize(PrevFiboLevels, FiboLevelCount);
   ArrayInitialize(PrevFiboLevels, 0.0);
   OnTick();
   return INIT_SUCCEEDED;
}

double GetFibEntryLevel(double candleSize, bool isBullish)
{
   if (isBullish) {
      if (candleSize >= 2 && candleSize < 4) return 0.5;
      if (candleSize >= 4 && candleSize < 6) return 0.382;
      return candleSize >= 6 ? 0.236 : -1;
   }
   if (candleSize >= 2 && candleSize < 4) return 0.382;
   if (candleSize >= 4 && candleSize < 6) return 0.5;
   return candleSize >= 6 ? 0.382 : -1;
}

int FindLevelIndex(double level)
{
   for (int i = 0; i < FiboLevelCount; i++)
      if (MathAbs(FiboLevels[i] - level) < 0.0001) return i;
   return -1;
}

bool CreateFiboLevels(double high, double low, datetime timeStart, datetime timeEnd, bool isBullish, double &levels[])
{
   ArrayResize(levels, FiboLevelCount);

   bool created = isBullish ?
      ObjectCreate(0, FIBO_OBJ, OBJ_FIBO, 0, timeEnd, low, timeStart, high) :
      ObjectCreate(0, FIBO_OBJ, OBJ_FIBO, 0, timeStart, high, timeEnd, low);

   if (!created) return false;

   ObjectSetInteger(0, FIBO_OBJ, OBJPROP_COLOR, clrRed);
   ObjectSetInteger(0, FIBO_OBJ, OBJPROP_STYLE, STYLE_DASHDOT);
   ObjectSetInteger(0, FIBO_OBJ, OBJPROP_WIDTH, 2);
   ObjectSetInteger(0, FIBO_OBJ, OBJPROP_BACK, true);
   ObjectSetInteger(0, FIBO_OBJ, OBJPROP_RAY_RIGHT, true);
   ObjectSetInteger(0, FIBO_OBJ, OBJPROP_LEVELS, FiboLevelCount);

   double fiboHigh = isBullish ? high : low;
   double fiboLow = isBullish ? low : high;
   for (int i = 0; i < FiboLevelCount; i++) {
      ObjectSetDouble(0, FIBO_OBJ, OBJPROP_LEVELVALUE, i, FiboLevels[i]);
      ObjectSetInteger(0, FIBO_OBJ, OBJPROP_LEVELCOLOR, i, clrYellow);
      ObjectSetInteger(0, FIBO_OBJ, OBJPROP_LEVELSTYLE, i, STYLE_DASHDOT);
      ObjectSetInteger(0, FIBO_OBJ, OBJPROP_LEVELWIDTH, i, 2);
      ObjectSetString(0, FIBO_OBJ, OBJPROP_LEVELTEXT, i, StringFormat("%.3f", FiboLevels[i]));
      levels[i] = isBullish ? fiboLow + (fiboHigh - fiboLow) * FiboLevels[i] : fiboHigh - (fiboHigh - fiboLow) * FiboLevels[i];
   }

   return true;
}

void OpenTrade(double entryLevel, double tpLevel, bool isBullish, double &fiboLevels[])
{
   int entryIdx = FindLevelIndex(entryLevel);
   int tpIdx = FindLevelIndex(isBullish ? -tpLevel : tpLevel);
   if (entryIdx == -1 || tpIdx == -1) return;

   double entryPrice = fiboLevels[entryIdx];
   double tpPrice = fiboLevels[tpIdx];
   double slPrice = entryPrice * (isBullish ? (1 - StopLossPercent/100) : (1 + StopLossPercent/100));
   double tpsPrice = entryPrice * (isBullish ? (1 + TakeProfitPercent/100) : (1 - TakeProfitPercent/100));
   int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
   double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   NormalizePrices(slPrice, tpPrice, entryPrice, digits);

   if (!SymbolInfoInteger(_Symbol, SYMBOL_TRADE_MODE) == SYMBOL_TRADE_MODE_FULL) {
      Print("Market is closed. Cannot open trade.");
      return;
   }

   datetime currentDay = iTime(_Symbol, Timeframe, 0);
   if (!TradeTaken && PositionsTotal() == 0) {
      double currentPrice = isBullish ? SymbolInfoDouble(_Symbol, SYMBOL_ASK) : SymbolInfoDouble(_Symbol, SYMBOL_BID);
      if (MathAbs(currentPrice - entryPrice) <= Tolerance) {
      Print(isBullish);
         if (isBullish ? trade.Buy(TradeVolume, _Symbol, entryPrice, slPrice, tpsPrice, "Fibo Buy") :
                        trade.Sell(TradeVolume, _Symbol, entryPrice, slPrice, tpsPrice, "Fibo Sell")) {
            PrintFormat("Trade opened: %s at %.5f | SL: %.5f | TP: %.5f", 
                        isBullish ? "Buy" : "Sell", entryPrice, slPrice, tpPrice);
            TradeTaken = true;
            LastTradeDay = currentDay;
         } else {
            Print("Trade failed: ", GetLastError());
         }
      }
   }
}

void TrailStop(bool isBullish)
{
   for (int i = PositionsTotal() - 1; i >= 0; i--) {
      if (PositionSelectByTicket(PositionGetTicket(i)) && PositionGetString(POSITION_SYMBOL) == _Symbol) {
         double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
         double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
         double sl = PositionGetDouble(POSITION_SL);
         double tp = PositionGetDouble(POSITION_TP);
         long type = PositionGetInteger(POSITION_TYPE);

         int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
         double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
         double minStop = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * point;

         bool isBuy = type == POSITION_TYPE_BUY;
         bool isPriceAboveEntry = (isBuy && currentPrice > EntryData.EntryPrice) || (!isBuy && currentPrice < EntryData.EntryPrice);

         if (!isPriceAboveEntry) continue;

         int newSlIdx = -1;
         for (int j = 0; j < FiboLevelCount; j++) {
            double fiboPrice = PrevFiboLevels[j];
            if ((isBuy && currentPrice >= fiboPrice) || (!isBuy && currentPrice <= fiboPrice)) {
               newSlIdx = j;
            }
         }

         if (newSlIdx != -1) {
            double newSL = PrevFiboLevels[newSlIdx];
            newSL = NormalizeDouble(newSL, digits);

            if ((isBuy && newSL > sl && currentPrice - newSL >= minStop) ||
                (!isBuy && newSL < sl && newSL - currentPrice >= minStop)) {
               if (trade.PositionModify(PositionGetTicket(i), newSL, tp)) {
                  PrintFormat("%s SL trailed to Fibonacci level %.3f at %.5f", 
                              isBuy ? "Buy" : "Sell", FiboLevels[newSlIdx], newSL);
               } else {
                  Print("Trailing failed: ", GetLastError());
               }
            }
         }
      }
   }
}

void CheckPriceForEntry(double entryLevel, double tpLevel, bool isBullish)
{
   double currentPrice = isBullish ? SymbolInfoDouble(_Symbol, SYMBOL_ASK) : SymbolInfoDouble(_Symbol, SYMBOL_BID);
   int entryIdx = FindLevelIndex(entryLevel);
   if (entryIdx != -1 && MathAbs(currentPrice - PrevFiboLevels[entryIdx]) <= Tolerance)
      OpenTrade(entryLevel, tpLevel, isBullish, PrevFiboLevels);
}

void OnTick()
{
   if (iBars(_Symbol, Timeframe) != BarsTotal) {
      BarsTotal = iBars(_Symbol, Timeframe);
      
      for (int i = PositionsTotal() - 1; i >= 0; i--) {
         if (PositionSelectByTicket(PositionGetTicket(i)) && PositionGetString(POSITION_SYMBOL) == _Symbol) {
            if (trade.PositionClose(PositionGetTicket(i))) {
               PrintFormat("Position closed at new candle: Ticket %d", PositionGetTicket(i));
            } else {
               Print("Failed to close position: ", GetLastError());
            }
         }
      }
      
      TradeTaken = false;

      MqlRates rate[];
      if (CopyRates(_Symbol, Timeframe, 1, 2, rate) == 2) {
         bool isBullish = rate[1].close > rate[1].open;
         double candleSize = MathAbs(rate[1].open - rate[1].close) / SymbolInfoDouble(_Symbol, SYMBOL_POINT);
         double wickSize = (MathMax(rate[1].high - MathMax(rate[1].open, rate[1].close), 
                                    MathMin(rate[1].open, rate[1].close) - rate[1].low)) / SymbolInfoDouble(_Symbol, SYMBOL_POINT);

         if (wickSize <= candleSize * 0.8 && candleSize > CandleSizeMin) {
            if (CreateFiboLevels(rate[1].high, rate[1].low, rate[1].time, rate[0].time - 1, isBullish, PrevFiboLevels)) {
               FiboCreated = true;
               double entryLevel = GetFibEntryLevel(candleSize, isBullish);
               if (entryLevel != -1) {
                  EntryData.EntryLevel = entryLevel;
                  
                  EntryData.TpLevel = EntryLevelTP;
                  EntryData.IsBullish = isBullish;
                  EntryData.EntryPrice = PrevFiboLevels[FindLevelIndex(entryLevel)];
                  OpenTrade(entryLevel, EntryLevelTP, isBullish, PrevFiboLevels);
               }
               Comment(entryLevel);
            }
         } else {
            FiboCreated = false;
         }
      }
   }

   if (FiboCreated && !TradeTaken)
      CheckPriceForEntry(EntryData.EntryLevel, EntryData.TpLevel, EntryData.IsBullish);

   if (FiboCreated)
      TrailStop(EntryData.IsBullish);
}

void OnDeinit(const int reason)
{
   ObjectDelete(0, FIBO_OBJ);
}

void NormalizePrices(double &sl, double &tp, double &price, int digits)
{
   sl = NormalizeDouble(sl, digits);
   tp = NormalizeDouble(tp, digits);
   price = NormalizeDouble(price, digits);
}
Documentation on MQL5: Constants, Enumerations and Structures / Trade Constants / Position Properties
Documentation on MQL5: Constants, Enumerations and Structures / Trade Constants / Position Properties
  • www.mql5.com
Execution of trade operations results in the opening of a position, changing of its volume and/or direction, or its disappearance. Trade operations...
Files:
 
Code-Debugging - Programme entwickeln - MetaEditor Hilfe
Code-Debugging - Programme entwickeln - MetaEditor Hilfe
  • www.metatrader5.com
MetaEditor hat einen eingebauten Debugger, mit dem Sie die Programmausführung Schritt für Schritt (durch einzelne Funktionen) ü...