Switch-case statement issue...

 

I'm writing an indicator with a switch-case statement and it's behaving in a way that I can't understand.  I'm wondering if someone might have some insight?  This switch-case runs a state machine. Once in the upwardTrend or downwardTrend state, it should only be able to go back to the noTrend state if the dirMult variable is a certain value (3 or -3).  However, if you look at the indicator window below, you can see that the value of dirMult (the red histogram) skips directly from -1 to -4, or 1 to 4, without first going to -3 or 3  as would be expected from the state machine.  It also goes from 0 to -3 or 0 to 3, without first going to -4 or 4 as would be expected from the state machine.  I am completely stumped as to how this is happening.


 



#include <jtCommonFunctions.mqh>

#property copyright "Copyright 2022, John Turner"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_minimum -5
#property indicator_maximum 5
#property indicator_buffers 9
#property indicator_plots   5

#property indicator_label1  "dirTF1"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrWhiteSmoke
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2

#property indicator_label2  "dirTF2"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrYellow
#property indicator_style2  STYLE_SOLID
#property indicator_width2  2

#property indicator_label3  "dirTF3"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrCyan
#property indicator_style3  STYLE_SOLID
#property indicator_width3  2

#property indicator_label4  "dirTF4"
#property indicator_type4   DRAW_LINE
#property indicator_color4  clrOrange
#property indicator_style4  STYLE_SOLID
#property indicator_width4  2

#property indicator_label5  "dirMult"
#property indicator_type5   DRAW_HISTOGRAM
#property indicator_color5  clrOrangeRed
#property indicator_style5  STYLE_SOLID
#property indicator_width5  3

//--- indicator buffers
double         trendTF1[];
double         trendTF2[];
double         trendTF3[];
double         trendTF4[];
double         dirMult[];     // 0 = down, 1 = up
double         dirTF1[];
double         dirTF2[];
double         dirTF3[];
double         dirTF4[];

double dirSum;
double TF1prev;
double TF2prev;
double TF3prev;
double TF4prev;

//--- variables
input ENUM_TIMEFRAMES TimeFrame1 = 60; // Lowest Time Frame
input ENUM_TIMEFRAMES TimeFrame2 = 240;
input ENUM_TIMEFRAMES TimeFrame3 = 240;
input ENUM_TIMEFRAMES TimeFrame4 = 1440;  // Highest Time Frame
input double TF1_Period = 25;
input double TF2_Period = 25;
input double TF3_Period = 25;
input double TF4_Period = 10;
input ENUM_MA_METHOD TF1_MA_Method = 1; //0 = Simple MA, 1 = Exponential MA, 2 = Smoothed MA, 3 = Linear-weighted MA
input ENUM_MA_METHOD TF2_MA_Method = 1;
input ENUM_MA_METHOD TF3_MA_Method = 2;
input ENUM_MA_METHOD TF4_MA_Method = 1;
input int run = 28;  // Number of TF4 bars to use for slope calculation
input int scalingSet = 500;   // Number of Bars to scale slope against

#define UP (1)
#define DOWN (-1)

enum trend
{
   noTrend,
   upwardTrend,
   downwardTrend
};

trend trendDir;

#define enPrice (0)

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping

   SetIndexBuffer(0,dirTF1);
   SetIndexBuffer(1,dirTF2);
   SetIndexBuffer(2,dirTF3);
   SetIndexBuffer(3,dirTF4);
   SetIndexBuffer(4,dirMult);
   SetIndexBuffer(5,trendTF1);
   SetIndexBuffer(6,trendTF2);
   SetIndexBuffer(7,trendTF3);
   SetIndexBuffer(8,trendTF4);
   
   ArraySetAsSeries(trendTF1,true);
   ArraySetAsSeries(trendTF2,true);
   ArraySetAsSeries(trendTF3,true);
   ArraySetAsSeries(trendTF4,true);
   ArraySetAsSeries(dirMult,true);     
   ArraySetAsSeries(dirTF1,true);
   ArraySetAsSeries(dirTF2,true);
   ArraySetAsSeries(dirTF3,true);
   ArraySetAsSeries(dirTF4,true);
   
   ObjectsDeleteAll();
   
   trendDir = noTrend;
   
//---
   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[])
  {
//---
   int i;
   static int limit;
   int shift = 0; 
   static bool upTrend = false;
   static bool downTrend = false;
   
   if((rates_total <= run) || (rates_total <= shift))
      return 0; 
        
   //--- last counted bar will be recounted
   limit=rates_total-prev_calculated;
   if(prev_calculated>0)
      limit++;     
   
   if(limit <= 1)
      shift = 1;
   else shift = 0;  
    
   for(i=0; i<limit; i++)   
   {
   
      trendTF1[i] = iCustom(NULL, 0, "Super smoothed average trend 1.2", TimeFrame1, TF1_Period, enPrice, TF1_MA_Method, false, false, true, true, false, false, false, clrLimeGreen, clrOrangeRed, clrDimGray, 3, true, 4, i); // Mode 4 indicates direction 
      trendTF2[i] = iCustom(NULL, 0, "Super smoothed average trend 1.2", TimeFrame2, TF2_Period, enPrice, TF2_MA_Method, false, false, true, true, false, false, false, clrLimeGreen, clrOrangeRed, clrDimGray, 3, true, 4, i); // 1 = UP
      trendTF3[i] = iCustom(NULL, 0, "Super smoothed average trend 1.2", TimeFrame3, TF3_Period, enPrice, TF3_MA_Method, false, false, true, true, false, false, false, clrLimeGreen, clrOrangeRed, clrDimGray, 3, true, 4, i); // -1 = DOWN
      trendTF4[i] = iCustom(NULL, 0, "Super smoothed average trend 1.2", TimeFrame4, TF4_Period, enPrice, TF4_MA_Method, false, false, true, true, false, false, false, clrLimeGreen, clrOrangeRed, clrDimGray, 3, true, 4, i); 

      TF1prev = iCustom(NULL, 0, "Super smoothed average trend 1.2", TimeFrame1, TF1_Period, enPrice, TF1_MA_Method, false, false, true, true, false, false, false, clrLimeGreen, clrOrangeRed, clrDimGray, 3, true, 4, i+1); // Mode 4 indicates direction 
      TF2prev = iCustom(NULL, 0, "Super smoothed average trend 1.2", TimeFrame2, TF2_Period, enPrice, TF2_MA_Method, false, false, true, true, false, false, false, clrLimeGreen, clrOrangeRed, clrDimGray, 3, true, 4, i+1); // 1 = UP
      TF3prev = iCustom(NULL, 0, "Super smoothed average trend 1.2", TimeFrame3, TF3_Period, enPrice, TF3_MA_Method, false, false, true, true, false, false, false, clrLimeGreen, clrOrangeRed, clrDimGray, 3, true, 4, i+1); // -1 = DOWN
      TF4prev = iCustom(NULL, 0, "Super smoothed average trend 1.2", TimeFrame4, TF4_Period, enPrice, TF4_MA_Method, false, false, true, true, false, false, false, clrLimeGreen, clrOrangeRed, clrDimGray, 3, true, 4, i+1); 

      if(trendTF1[i] == UP){
         dirTF1[i] = 2;}
      else {dirTF1[i] = -2;}
      
      if(trendTF2[i] == UP){
         dirTF2[i] = 2.5;}
      else {dirTF2[i] = -2.5;}
      
      if(trendTF3[i] == UP){
         dirTF3[i] = 3;}
      else {dirTF3[i] = -3;}
      
      if(trendTF4[i] == UP){
         dirTF4[i] = 3.5;}
      else {dirTF4[i] = -3.5;}
      
      dirSum = dirTF1[i] + dirTF2[i] + dirTF3[i] + dirTF4[i];


      switch(trendDir)
      {
         case noTrend:
         
            //if((trendTF1[i] == UP) && (trendTF2[i+shift] == UP) && (trendTF3[i+shift] == UP)) // UP
            if(dirSum == 11)
            {
               trendDir = upwardTrend;
               dirMult[i] = 4; // 1
            }
            //else if((trendTF1[i] == DOWN) && (trendTF2[i+shift] == DOWN) && (trendTF3[i+shift] == DOWN)) // DOWN
            else if(dirSum == -11)
            {
               trendDir = downwardTrend;
               dirMult[i] = -4;
            }
            else
            {
               dirMult[i] = 0; // 0
            }
         
         break;
         
         case upwardTrend:
            if(trendTF3[i] == DOWN) // DOWN
            {
               dirMult[i] = -3; // 0
               trendDir = noTrend;
            }
            else
            {
               dirMult[i] = 1; 
            } 
         
         break;
         
         case downwardTrend:
            if(trendTF3[i] == UP) // UP
            {
               dirMult[i] = 3; // 0
               trendDir = noTrend;
            }
            else
            {
               dirMult[i] = -1;  // -1 
            } 
         
         break;
         
         default:
            dirMult[i] = 5;
            trendDir = noTrend;   
         break;
      }
   
   }


  
//--- return value of prev_calculated for next call
   return(rates_total);
  }
 

Because your indicator is build in the wrong direction (from present to past) :

   for(i=0; i<limit; i++)  

...directly from -1 to -4, or 1 to 4, without first going to -3 or 3  as would be expected from the state machine.  It also goes from 0 to -3 or 0 to 3, without first going to -4 or 4 as would be expected from the state machine.

It doesn't go from -1 to -4 ... but from -4 to -1, from 4 to 1, from -3 to 0 and from 3 to 0. Which is what you coded.

Reason: