Help Needed: My indicator print the cloud in the wrong place

 

Hello Friends!

I tried to convert an indicator from MQL4 to MQL5. the indicator named: Swing Cloud and I don't know what is wrong with MQL5 code.

In uptrend the cloud should be below the price and in downtrend the cloud should be above the price.

Here is on MT4 it print the cloud in the correct position.

MT4 screenshot of Swing Cloud

But the cloud printed on MT5 is not in the correct position.

Indicator on MT5

here is the code

//+------------------------------------------------------------------+
//|                                                      SwingCloud.mq5 |
//|                        Copyright 2025, SOPHEAK KHMER TRADER      |
//|                                  https://t.me/sopheak_khmer_trader |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, by SOPHEAK KHMER TRADER"
#property link      "https://t.me/sopheak_khmer_trader"
#property version   "1.0"
#property description ""

#property indicator_chart_window
#property indicator_buffers 7  // Increased to 7 for all buffers
#property indicator_plots 3    // Only 4 visible plots

// Plot 1: Stop Line
#property indicator_label1  "Stop Line"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Blue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

// Plot 2: Swing Line
#property indicator_label2  "Swing Line"
#property indicator_type2   DRAW_LINE
#property indicator_color2  Red
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1

// Plot 3: Cloud
#property indicator_label3  "Bullish Cloud"
#property indicator_type3   DRAW_FILLING
#property indicator_color3  clrLightPink,clrLightCyan
#property indicator_style3  STYLE_DOT
#property indicator_width3  1


// Input parameters
input int TrendPeriod = 200;
input int SwingPeriod = 120;

// Indicator buffers
double buff_Stop[];        // Stop line
double buff_Swing[];       // Swing line
double buff_CloudUp[];     // Bullish cloud
double buff_CloudDown[];   // Bearish cloud

// Calculation buffers (not displayed)
double buff_LowerBand[];
double buff_UpperBand[];
double buff_Trend[];

double trend100;
double swing100;
bool swing;

// ATR handle
int atrHandle;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   // Validate inputs
   if(TrendPeriod <= 0 || SwingPeriod <= 0)
   {
      Print("Error: Periods must be greater than 0");
      return INIT_PARAMETERS_INCORRECT;
   }
   
   // Calculate coefficients
   trend100 = TrendPeriod / 100.0;
   swing100 = SwingPeriod / 100.0;
   
   // Set indicator properties
   IndicatorSetString(INDICATOR_SHORTNAME, "Swing Cloud(" + IntegerToString(TrendPeriod) + "," + IntegerToString(SwingPeriod) + ")");
   IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
   
   // Set buffers for visible plots
   SetIndexBuffer(0, buff_Stop, INDICATOR_DATA);
   SetIndexBuffer(1, buff_Swing, INDICATOR_DATA);
   SetIndexBuffer(2, buff_CloudUp, INDICATOR_DATA);
   SetIndexBuffer(3, buff_CloudDown, INDICATOR_DATA);
   
   // Set buffers for calculation (not displayed)
   SetIndexBuffer(4, buff_LowerBand, INDICATOR_CALCULATIONS);
   SetIndexBuffer(5, buff_UpperBand, INDICATOR_CALCULATIONS);
   SetIndexBuffer(6, buff_Trend, INDICATOR_CALCULATIONS);
   
   // Set plot properties
   PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   
   // Initialize ATR indicator handle
   atrHandle = iATR(_Symbol, _Period, 100);
   if(atrHandle == INVALID_HANDLE)
   {
      Print("Failed to create ATR handle");
      return INIT_FAILED;
   }
   
   return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
   // Check if we have enough data
   if(rates_total < MathMax(TrendPeriod, SwingPeriod) + 100)
      return 0;
   
   // Calculate start position
   int start;
   if(prev_calculated == 0)
   {
      // First calculation
      start = rates_total - 1;
      
      // Initialize buffers with EMPTY_VALUE
      ArrayInitialize(buff_Stop, EMPTY_VALUE);
      ArrayInitialize(buff_Swing, EMPTY_VALUE);
      ArrayInitialize(buff_CloudUp, EMPTY_VALUE);
      ArrayInitialize(buff_CloudDown, EMPTY_VALUE);
      ArrayInitialize(buff_LowerBand, EMPTY_VALUE);
      ArrayInitialize(buff_UpperBand, EMPTY_VALUE);
      ArrayInitialize(buff_Trend, EMPTY_VALUE);
      
      // Initialize trend from the first bar
      buff_Trend[start] = 0.0;
   }
   else
   {
      // Calculate from the last bar
      start = prev_calculated - 1;
   }
   
   // Copy ATR values
   double atrValues[];
   if(CopyBuffer(atrHandle, 0, 0, rates_total, atrValues) <= 0)
   {
      Print("Failed to copy ATR values");
      return 0;
   }
   
   // Main calculation loop
   for(int i = start; i >= 0; i--)
   {
      double atr = atrValues[i];
      
      // Skip if ATR is not valid
      if(atr <= 0 || atr == EMPTY_VALUE)
      {
         if(i < rates_total - 1)
         {
            buff_Stop[i] = buff_Stop[i+1];
            buff_Swing[i] = buff_Swing[i+1];
            buff_CloudUp[i] = buff_CloudUp[i+1];
            buff_CloudDown[i] = buff_CloudDown[i+1];
            buff_LowerBand[i] = buff_LowerBand[i+1];
            buff_UpperBand[i] = buff_UpperBand[i+1];
            buff_Trend[i] = buff_Trend[i+1];
         }
         continue;
      }
      
      // Calculate ATR-based levels
      double atrHigh = high[i] + atr * trend100;
      double atrLow = low[i] - atr * trend100;
      
      // Adjust based on previous values
      if(i < rates_total - 1)
      {
         if(buff_LowerBand[i+1] != EMPTY_VALUE && atrLow < buff_LowerBand[i+1])
            atrLow = buff_LowerBand[i+1];
         
         if(buff_UpperBand[i+1] != EMPTY_VALUE && atrHigh > buff_UpperBand[i+1])
            atrHigh = buff_UpperBand[i+1];
         
         // Copy trend from previous bar
         buff_Trend[i] = buff_Trend[i+1];
      }
      
      // Reset bands
      buff_LowerBand[i] = EMPTY_VALUE;
      buff_UpperBand[i] = EMPTY_VALUE;
      
      // Determine trend direction
      if(close[i] > atrHigh && (i == rates_total - 1 || buff_Trend[i+1] != 0.0))
      {
         buff_Trend[i] = 0.0;
      }
      else if(close[i] < atrLow && (i == rates_total - 1 || buff_Trend[i+1] != 1.0))
      {
         buff_Trend[i] = 1.0;
      }
      else if(i < rates_total - 1)
      {
         buff_Trend[i] = buff_Trend[i+1];
      }
      
      // Set values based on trend direction
      if(buff_Trend[i] == 0.0)  // Bullish trend
      {
         buff_LowerBand[i] = atrLow;
         buff_Stop[i] = atrLow;
         buff_Swing[i] = atrLow + atr * swing100;
         buff_CloudUp[i] = buff_Swing[i];
         buff_CloudDown[i] = buff_Stop[i];
      }
      else  // Bearish trend
      {
         buff_UpperBand[i] = atrHigh;
         buff_Stop[i] = atrHigh;
         buff_Swing[i] = atrHigh - atr * swing100;
         buff_CloudUp[i] = buff_Swing[i];
         buff_CloudDown[i] = buff_Stop[i];
      }
   }
   
   return rates_total;
}

//+------------------------------------------------------------------+
//| Deinitialization function                                        |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   // Release indicator handle
   if(atrHandle != INVALID_HANDLE)
   {
      IndicatorRelease(atrHandle);
   }
}
 
Sopheak Khlot:

Hello Friends!

I tried to convert an indicator from MQL4 to MQL5. the indicator named: Swing Cloud and I don't know what is wrong with MQL5 code.

In uptrend the cloud should be below the price and in downtrend the cloud should be above the price.

Here is on MT4 it print the cloud in the correct position.

But the cloud printed on MT5 is not in the correct position.

here is the code

Traders and coders are working for free:

  • if it is interesting for them personally, or
  • if it is interesting for many members on this forum.

Freelance section of the forum should be used in most of the cases.

Trading applications for MetaTrader 5 to order
Trading applications for MetaTrader 5 to order
  • 2026.02.10
  • www.mql5.com
The largest freelance service with MQL5 application developers
 

1. Count up.

2. Make atrValues[] a buffer and only copy what is necessary.

   // Calculate start position
   int start=(rates_total==prev_calculated)?rates_total-1:prev_calculated;
   
   if(prev_calculated == 0)
   {
      // First calculation
      
      // Initialize buffers with EMPTY_VALUE
      ArrayInitialize(buff_Stop, EMPTY_VALUE);
      ArrayInitialize(buff_Swing, EMPTY_VALUE);
      ArrayInitialize(buff_CloudUp, EMPTY_VALUE);
      ArrayInitialize(buff_CloudDown, EMPTY_VALUE);
      ArrayInitialize(buff_LowerBand, EMPTY_VALUE);
      ArrayInitialize(buff_UpperBand, EMPTY_VALUE);
      ArrayInitialize(buff_Trend, EMPTY_VALUE);
      
      // Initialize trend from the first bar
      buff_Trend[start++] = 0.0;
   }
   
   // Copy ATR values
   //double atrValues[];
   int toCopy=(rates_total==prev_calculated)?1:rates_total-prev_calculated;
   
   if(CopyBuffer(atrHandle, 0, 0, toCopy, atr_Values) <= 0)
   {
      Print("Failed to copy ATR values");
      return 0;
   }
   
   // Main calculation loop
   for(int i = start; i < rates_total; i++)
   {
      double atr = atr_Values[i];
      
      // Skip if ATR is not valid
      if(atr <= 0 || atr == EMPTY_VALUE)
      {
         buff_Stop[i] = buff_Stop[i-1];
         buff_Swing[i] = buff_Swing[i-1];
 
Sopheak Khlot:

Hello Friends!

I tried to convert an indicator from MQL4 to MQL5. the indicator named: Swing Cloud and I don't know what is wrong with MQL5 code.

In uptrend the cloud should be below the price and in downtrend the cloud should be above the price.

Here is on MT4 it print the cloud in the correct position.

But the cloud printed on MT5 is not in the correct position.

here is the code

Hey boss, how can two different time frames produce the same result?
 
Nguyen Chung #:
Hey boss, how can two different time frames produce the same result?
It's not about the timeframe, it's about the the position of the cloud.