Do I need to use a three-dimensional array?

 

Hi,

I use a scanner in a dashboard-style like you can see in the attached image. It scans for Pinbars in all currency pairs in all timeframes. A red dash means that the last bar was a "Short-Pinbar" (long upper shadow), green means a long lower shadow. Now I would like to replace the Pinbar-Check with an EMA-Check. For example when EMA 50 is above or below EMA 100. But now I would like to print more than just a red or green dot.

The dashboard should show the numbers since the EMA cross has happened. For example, when the EMA 50 crossed the EMA 100 to the upside 5 bars ago there should be displayed a green 5.

Right now I use a two-dimensional array (currency pairs x timeframe). When I would like to add these numbers, do I have to initialize a three-dimensional array? I think it works like this:

When I would address the AUDCHF in H4 I use Array(1, 5) and when I need the number, I address it this way: Array(1,5,1). Is that correct?

I have never worked with a three-dimensional array, therefore I read the documentation about it but I found nothing in the forum. Therefore I want to know if this could be the solution for my issue or is there a more simple and effective way to do that?


 
mar: I use a scanner in a dashboard-style like you can see in the attached image. It scans for Pinbars in all currency pairs in all timeframes. A red dash means that the last bar was a "Short-Pinbar" (long upper shadow), green means a long lower shadow. Now I would like to replace the Pinbar-Check with an EMA-Check. For example when EMA 50 is above or below EMA 100. But now I would like to print more than just a red or green dot.

The dashboard should show the numbers since the EMA cross has happened. For example, when the EMA 50 crossed the EMA 100 to the upside 5 bars ago there should be displayed a green 5.

Right now I use a two-dimensional array (currency pairs x timeframe). When I would like to add these numbers, do I have to initialize a three-dimensional array? I think it works like this:

When I would address the AUDCHF in H4 I use Array(1, 5) and when I need the number, I address it this way: Array(1,5,1). Is that correct?

I have never worked with a three-dimensional array, therefore I read the documentation about it but I found nothing in the forum. Therefore I want to know if this could be the solution for my issue or is there a more simple and effective way to do that?

I usually do-not go past one-dimensional arrays ... it just simply get confusing above 2-dimensions. So no, think of another way to do it with 2-dimensional array or less.

Maybe this'll help you visualize 3d arrays: https://book.mql4.com/variables/arrays.

Since all symbols needs this every piece of information, I'll do my 1d arrays as follows.

String Symbols_Array[ myTotalSymbols ] {where total symbols equals array size}

Integer PeriodM1_Array[ myTotalSymbols ]

Integer PeriodM5_Array[ myTotalSymbols ] >>> On and On to PeriodW1 then

Double Indicator_Array[ myTotalSymbols ]

This way I know every thing in the 0 Index belongs to the symbol in the 0 index. Hope this makes sense.

 
Or something else you could do is add another column to your 2d_table/array above for the value of the indicator.
 
mar:

Hi,

I use a scanner in a dashboard-style like you can see in the attached image. It scans for Pinbars in all currency pairs in all timeframes. A red dash means that the last bar was a "Short-Pinbar" (long upper shadow), green means a long lower shadow. Now I would like to replace the Pinbar-Check with an EMA-Check. For example when EMA 50 is above or below EMA 100. But now I would like to print more than just a red or green dot.

The dashboard should show the numbers since the EMA cross has happened. For example, when the EMA 50 crossed the EMA 100 to the upside 5 bars ago there should be displayed a green 5.

Right now I use a two-dimensional array (currency pairs x timeframe). When I would like to add these numbers, do I have to initialize a three-dimensional array? I think it works like this:

When I would address the AUDCHF in H4 I use Array(1, 5) and when I need the number, I address it this way: Array(1,5,1). Is that correct?

I have never worked with a three-dimensional array, therefore I read the documentation about it but I found nothing in the forum. Therefore I want to know if this could be the solution for my issue or is there a more simple and effective way to do that?


You can do it this way (3D), but in my opinion it's more logical to create a second 2D array, similar to your first, but to store your EMA's cross value.
 

Hey guys,

I put the idea of creating a three-dim array aside.

For me it seems to be the best to create this second 2D array. I would like to show you how I think about it. Unfortunately I only get compilation errors because I don't know the correct syntax.

I want to do it this way but I don't think that the variable BarsFromCross can be used this way. Therefore I would be thankful if someone helped me with that:

         if (Bar1_Long)                                  // Bar1_Long means that all three EMAs are in the correct "long" order at Bar 1
         {
            col=Lime;
            if (Bar2_Long==false)                        // Bar2_Long checks the same as Bar1_Long, but only for Bar 2. If it is false, there was a new cross at Bar 1
            {
               BarsFromCross = 1;                        // 1 Bar back was the cross
            }
            else
            {
               BarsFromCross = BarsFromCross + 1;        // Still Bar1_Long = true but also Bar2_Long=true and so the EMAs are still in "long" order but cross was somewhere before
                                                         // therefore 1 is added to BarsFromCross
            }
         }
         else if (Bar1_Short)                            // the same as above, only for shorts
         {
            col=Red;
            if (Bar2_Short==false)
            {
               BarsFromCross = 1;
            }
            else
            {
               BarsFromCross = BarsFromCross + 1;
            }

         }
         else                                            // the EMAs are mixed and not in long or short order
         {
            col=Gray;
            BarsFromCross = 0;                           // 0 means no cross
         }
         
//-- Dot Matrix --
         ObjectSetText(CurrPair[i]+Timeframe[j], BarsFromCross, 9, "Calibri", col);  
 
  1. mar: Right now I use a two-dimensional array (currency pairs x timeframe). When I would like to add these numbers, do I have to initialize a three-dimensional array?
    When I would address the AUDCHF in H4 I use Array(1, 5) and when I need the number, I address it this way: Array(1,5,1). Is that correct?
    Your dimensions are pair and TF which I assume you map into indexes (iPair and iTF.) What are you storing in the array are your values. Keep the two separate in you mind.
    You need to go to 3D IFF you need to store multiple values AND need to loop through them. If you don't need to loop through them use multiple 2D arrays. (Easier naming and allows different data types for different values.)
    #define iSYM_AUDCHF 1  // Symbols
    :
       #define iSYM_COUNT ..
    
    #define iTF_M1 0
    :
    #define iTF_H4 5      // TimeFrames
       #define  iTF_COUNT 8
    
    #define iVAL_1     0  // Values
    #define iVAL_BAR   1
       #define iVAL_COUNT 2
    
    double Arr[iSYM_COUNT][iTF_COUNT][iVAL_COUNT];
    
    :
    for(iVal=iVAL_1; iVal < iVAL_COUNT; iVAL++){
       double  value = Arr[iSYM_AUDCHF][iTF_H4][iVal];
    #define iSYM_AUDCHF 1  // Symbols
    :
       #define iSYM_COUNT ..
    :
    #define iTF_M1 0
    :
    #define iTF_H4 5      // TimeFrames
       #define  iTF_COUNT 8
    
    
    
    
    
    double   Values[iSYM_COUNT, iTF_COUNT];
    datetime Ages  [iSYM_COUNT, iTF_COUNT];
    :
    double age = Ages[iSYM_AUDCHF, iTF_H4];

    I wouldn't store bar numbers at all but the datetime.


  2. Array(1,5,1). Is that correct?
    Function calls use parentheses. Array references use square brackets either Array[a][b] or Array[a,b]. See above left and right examples. You can use either form but keep your declaration and use consistent.
 

Hello William,

no, I don't need to loop the stored values through. It is just to store them. When I think about an array, I have an Excelsheet in mind. The currency pairs are stored on the y-axis and the timeframes on the x-axis. And the cells should be filled with the numbers showing the bars back to the last cross. When the EMAs are not in order, it should show a zero.

But I forgot something in my example above. That requires that the metatrader is running 24/5 because I assume that my indicator is running everytime there is a cross. But the indicator should count back to find the cross. So my idea is rubbish...

Edit: No, have not indexed the pairs and timeframe. I use it this way:

         ObjectSet(CurrPair[i]+Timeframe[j], OBJPROP_XDISTANCE, dist_X);
         ObjectSet(CurrPair[i]+Timeframe[j], OBJPROP_YDISTANCE, dist_Y);
 
I found one part of the solution: during the initialization I check all pairs and the selected timeframes for the last EMA cross. Then I populate an array with the numbers and print them. Then I could use the idea I had before. So I avoid unnecessary loops in the int start().
 

The first part is almost completed. In the init() I count the bars until the last EMA cross happens. I hope, the code is correct. But now the array should be initialized with the counted data. And this is my problem, I have no clue how to do that.

Maybe you have a look?

//+------------------------------------------------------------------+
//|                                                3 EMA-Scanner.mq4 |
//|                                               Copyright 2013, MR |
//|                                                                  |
//+------------------------------------------------------------------+
//|                                                                  |
//|                                                  17th Dec 2013   |
//|                                                                  |
//|    Modified by RaptorUK,  only process on a new bar              |
//|                                                                  |
//|    All mods marked RaptorUK                                      |
//|                                                                  |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2013, MR"
#property link      ""

#property indicator_chart_window

extern int FastMA = 30;
extern int MidMA  = 50;
extern int SlowMA = 100;
extern bool M1  = true;
extern bool M5  = true;
extern bool M15 = true;
extern bool M30 = true;
extern bool H1  = true;
extern bool H4  = true;
extern bool D1  = true;
extern bool W1  = true;

string Timeframe[];
int TimeframeNo[];
int TimeframeNo2[];
string CurrPair[] = {"AUDCAD", "AUDCHF", "AUDJPY", "AUDNZD", "AUDUSD", "CADCHF", "CHFJPY", "EURAUD",
                     "EURCAD", "EURCHF", "EURGBP", "EURJPY", "EURNZD", "EURUSD", "GBPAUD", "GBPCAD",
                     "GBPCHF", "GBPJPY", "GBPNZD", "GBPUSD", "NZDJPY", "NZDUSD", "USDCAD", "USDCHF",
                     "USDJPY"};
string CurrPair2[] = {"AUDCAD", "AUDCHF", "AUDJPY", "AUDNZD", "AUDUSD", "CADCHF", "CHFJPY", "EURAUD",
                     "EURCAD", "EURCHF", "EURGBP", "EURJPY", "EURNZD", "EURUSD", "GBPAUD", "GBPCAD",
                     "GBPCHF", "GBPJPY", "GBPNZD", "GBPUSD", "NZDJPY", "NZDUSD", "USDCAD", "USDCHF",
                     "USDJPY"};
color col;
bool LongMode, ShortMode, Bar1_Long, Bar2_Long, Bar1_Short, Bar2_Short;
double FastMA_1, FastMA_2, MidMA_1, MidMA_2, SlowMA_1, SlowMA_2;
int dist_X, dist_Y, i, j, count, k;

// datetime variables added by RaptorUK
datetime M1Bar1Time, M5Bar1Time, M15Bar1Time, M30Bar1Time, H1Bar1Time, H4Bar1Time, D1Bar1Time, W1Bar1Time;


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
  
//---- Arrays population ----
   if (M1)
   {
      ArrayResize(Timeframe, ArraySize(Timeframe)+1);
      Timeframe[ArraySize(Timeframe)-1]="M1";
      ArrayResize(TimeframeNo, ArraySize(TimeframeNo)+1);
      TimeframeNo[ArraySize(TimeframeNo)-1]=PERIOD_M1;
      ArrayResize(TimeframeNo2, ArraySize(TimeframeNo2)+1);
      TimeframeNo2[ArraySize(TimeframeNo2)-1]=PERIOD_M1;
   }
   if (M5)
   {
      ArrayResize(Timeframe, ArraySize(Timeframe)+1);
      Timeframe[ArraySize(Timeframe)-1]="M5";
      ArrayResize(TimeframeNo, ArraySize(TimeframeNo)+1);
      TimeframeNo[ArraySize(TimeframeNo)-1]=PERIOD_M5;
      ArrayResize(TimeframeNo2, ArraySize(TimeframeNo2)+1);
      TimeframeNo2[ArraySize(TimeframeNo2)-1]=PERIOD_M5;
   }
   if (M15)
   {
      ArrayResize(Timeframe, ArraySize(Timeframe)+1);
      Timeframe[ArraySize(Timeframe)-1]="M15";
      ArrayResize(TimeframeNo, ArraySize(TimeframeNo)+1);
      TimeframeNo[ArraySize(TimeframeNo)-1]=PERIOD_M15;
      ArrayResize(TimeframeNo2, ArraySize(TimeframeNo2)+1);
      TimeframeNo2[ArraySize(TimeframeNo2)-1]=PERIOD_M15;
   }
   if (M30)
   {
      ArrayResize(Timeframe, ArraySize(Timeframe)+1);
      Timeframe[ArraySize(Timeframe)-1]="M30";
      ArrayResize(TimeframeNo, ArraySize(TimeframeNo)+1);
      TimeframeNo[ArraySize(TimeframeNo)-1]=PERIOD_M30;
      ArrayResize(TimeframeNo2, ArraySize(TimeframeNo2)+1);
      TimeframeNo2[ArraySize(TimeframeNo2)-1]=PERIOD_M30;
   }
   if (H1)
   {
      ArrayResize(Timeframe, ArraySize(Timeframe)+1);
      Timeframe[ArraySize(Timeframe)-1]="H1";
      ArrayResize(TimeframeNo, ArraySize(TimeframeNo)+1);
      TimeframeNo[ArraySize(TimeframeNo)-1]=PERIOD_H1;
      ArrayResize(TimeframeNo2, ArraySize(TimeframeNo2)+1);
      TimeframeNo2[ArraySize(TimeframeNo2)-1]=PERIOD_H1;
   }
   if (H4)
   {
      ArrayResize(Timeframe, ArraySize(Timeframe)+1);
      Timeframe[ArraySize(Timeframe)-1]="H4";
      ArrayResize(TimeframeNo, ArraySize(TimeframeNo)+1);
      TimeframeNo[ArraySize(TimeframeNo)-1]=PERIOD_H4;
      ArrayResize(TimeframeNo2, ArraySize(TimeframeNo2)+1);
      TimeframeNo2[ArraySize(TimeframeNo2)-1]=PERIOD_H4;
   }
   if (D1)
   {
      ArrayResize(Timeframe, ArraySize(Timeframe)+1);
      Timeframe[ArraySize(Timeframe)-1]="D1";
      ArrayResize(TimeframeNo, ArraySize(TimeframeNo)+1);
      TimeframeNo[ArraySize(TimeframeNo)-1]=PERIOD_D1;
      ArrayResize(TimeframeNo2, ArraySize(TimeframeNo2)+1);
      TimeframeNo2[ArraySize(TimeframeNo2)-1]=PERIOD_D1;
   }
   if (W1)
   {
      ArrayResize(Timeframe, ArraySize(Timeframe)+1);
      Timeframe[ArraySize(Timeframe)-1]="W1";
      ArrayResize(TimeframeNo, ArraySize(TimeframeNo)+1);
      TimeframeNo[ArraySize(TimeframeNo)-1]=PERIOD_W1;
      ArrayResize(TimeframeNo2, ArraySize(TimeframeNo2)+1);
      TimeframeNo2[ArraySize(TimeframeNo2)-1]=PERIOD_W1;
   }

//---- Title Object ----
         ObjectCreate("Title", OBJ_LABEL, 0, 0, 0);
         ObjectSet("Title", OBJPROP_CORNER, 0);
         ObjectSet("Title", OBJPROP_XDISTANCE, 1);
         ObjectSet("Title", OBJPROP_YDISTANCE, 10);
         ObjectSetText("Title", "3 EMA", 12, "Verdana", Yellow);

//---- Timeframe Objects ----
   dist_X = 80;
   for(i=0; i<=ArrayRange(Timeframe,0)-1; i++)
   {
      if (ObjectFind(Timeframe[i]+"txt") == -1)
      {
         ObjectCreate(Timeframe[i]+"txt", OBJ_LABEL, 0, 0, 0);
         ObjectSet(Timeframe[i]+"txt", OBJPROP_CORNER, 0);
         ObjectSet(Timeframe[i]+"txt", OBJPROP_XDISTANCE, dist_X);
         ObjectSet(Timeframe[i]+"txt", OBJPROP_YDISTANCE, 12);
         ObjectSetText(Timeframe[i]+"txt", Timeframe[i], 9, "Calibri", White);
         dist_X = dist_X+40;     
      }
   }
   
//---- Currency pairs objects ----
   dist_Y = 35;
   for(i=0; i<=ArrayRange(CurrPair,0)-1; i++)
   {
      if (ObjectFind(CurrPair[i]+"txt") == -1)
      {
         ObjectCreate(CurrPair[i]+"txt", OBJ_LABEL, 0, 0, 0);
         ObjectSet(CurrPair[i]+"txt", OBJPROP_CORNER, 0);
         ObjectSet(CurrPair[i]+"txt", OBJPROP_XDISTANCE, 0);
         ObjectSet(CurrPair[i]+"txt", OBJPROP_YDISTANCE, dist_Y);
         ObjectSetText(CurrPair[i]+"txt", CurrPair[i], 9, "Calibri", White);
         dist_Y = dist_Y+17;     
      }
   }
   
//---- Counting bars since last cross ----   
   for(j=0; j<=ArrayRange(TimeframeNo2,0)-1; j++)
   {
      for(i=0; i<=ArrayRange(CurrPair2,0)-1; i++)
      {
         FastMA_1 = iMA(CurrPair[i], TimeframeNo[j], FastMA, 0, MODE_EMA, PRICE_CLOSE, 1);
         MidMA_1  = iMA(CurrPair[i], TimeframeNo[j], MidMA, 0, MODE_EMA, PRICE_CLOSE, 1);
         SlowMA_1 = iMA(CurrPair[i], TimeframeNo[j], SlowMA, 0, MODE_EMA, PRICE_CLOSE, 1);
         Bar1_Long   = SlowMA_1 < MidMA_1 && MidMA_1 < FastMA_1;
         Bar1_Short  = SlowMA_1 > MidMA_1 && MidMA_1 > FastMA_1;
         count = 0;
         k = 1;
         if (Bar1_Long)                                  // EMAs in long order at bar 1
         {
            while (Bar1_Long)
            {
               FastMA_1 = iMA(CurrPair[i], TimeframeNo[j], FastMA, 0, MODE_EMA, PRICE_CLOSE, k+1);
               MidMA_1  = iMA(CurrPair[i], TimeframeNo[j], MidMA, 0, MODE_EMA, PRICE_CLOSE, k+1);
               SlowMA_1 = iMA(CurrPair[i], TimeframeNo[j], SlowMA, 0, MODE_EMA, PRICE_CLOSE, k+1);
               k++;
               count++;
               Bar1_Long   = SlowMA_1 < MidMA_1 && MidMA_1 < FastMA_1;
            }
            // here the variable count represents the bar shift from current bar to the last EMA long cross
            // i don't know how to populate the array with that value so it can be printed later in the dashboard
         }
         else if (Bar1_Short)
         {
            while (Bar1_Short)
            {
               FastMA_1 = iMA(CurrPair[i], TimeframeNo[j], FastMA, 0, MODE_EMA, PRICE_CLOSE, k+1);
               MidMA_1  = iMA(CurrPair[i], TimeframeNo[j], MidMA, 0, MODE_EMA, PRICE_CLOSE, k+1);
               SlowMA_1 = iMA(CurrPair[i], TimeframeNo[j], SlowMA, 0, MODE_EMA, PRICE_CLOSE, k+1);
               k++;
               count++;
               Bar1_Short  = SlowMA_1 > MidMA_1 && MidMA_1 > FastMA_1;
            }
            // here the variable count represents the bar shift from current bar to the last EMA short cross
            // i don't know how to populate the array with that value so it can be printed later in the dashboard
         }
         else
         {
         // here the variable count is 0 because the EMAs are in no order at bar 1
         // i don't know how to populate the array with that value so it can be printed later in the dashboard         
         }
      }
   }
//----
   return(0);
  }  
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   ObjectsDeleteAll();
//----
   return(0);
  }
Reason: