Array count elements of the same value and add to object

 

Hi All

I'm hoping someone might be able to help me with this question as so far I've not had a very good experience on this forum so here goes.

I have a couple of arrays that build up support and resistance levels over the lookback period. It seems that some of these levels have the same price level so I would like to associate a count of when the condition has been met multiple times with the label of the object. In other words, I believe multiple elements within each array have the same value but I would like to total the number that are at the same level. "Indicator01" is a Price Channel in the code so far - inserted below.

Hoping someone might help me out this time please.

Thanks

Rob

for(int i=limit-1; i>=0; i--)
     {
      //--- find all previous BUY levels and plot them green
      if(i>=MathMin(Lookback-1,rates_total-1-50)) continue;
      if(iCustom(NULL,PERIOD_CURRENT,"Indicator01",Period_n,price_type,0,i)==iCustom(NULL,PERIOD_CURRENT,"Indicator01",Period_n,price_type,0,Shift+i)
         )
        {
         Buffer1[i]=iCustom(NULL,PERIOD_CURRENT,"Indicator01",Period_n,price_type,0,i);
         ObjectCreate(WindowExpertName()+i,OBJ_HLINE,0,0,iCustom(NULL,PERIOD_CURRENT,"Indicator01",Period_n,price_type,0,clrRed,clrLimeGreen,0,i));
         ObjectSetText(WindowExpertName()+i,Close[i]+"_Buy");
         ObjectSet(WindowExpertName()+i,OBJPROP_STYLE,STYLE_DOT);
         ObjectSet(WindowExpertName()+i,OBJPROP_COLOR,LimeGreen);
         ObjectSet(WindowExpertName()+i,OBJPROP_WIDTH,1);
        }
      //--- find all previous SELL levels and plot them red
      if(iCustom(NULL,PERIOD_CURRENT,"Indicator01",Period_n,price_type,1,i)==iCustom(NULL,PERIOD_CURRENT,"Indicator01",Period_n,price_type,1,Shift+i)
         )
        {
         Buffer2[i]=iCustom(NULL,PERIOD_CURRENT,"Indicator01",Period_n,price_type,1,i);
         ObjectCreate(WindowExpertName()+i,OBJ_HLINE,0,0,iCustom(NULL,PERIOD_CURRENT,"Indicator01",Period_n,price_type,1,clrRed,clrLimeGreen,1,i));
         ObjectSetText(WindowExpertName()+i,Close[i]+"_Sell");
         ObjectSet(WindowExpertName()+i,OBJPROP_STYLE,STYLE_DOT);
         ObjectSet(WindowExpertName()+i,OBJPROP_COLOR,Red);
         ObjectSet(WindowExpertName()+i,OBJPROP_WIDTH,1);
        }
     }
   return(rates_total);
  }
 
  1. I don't see any of the arrays you are talking about therefore I hardly understand what you want.
  2. You need to use delta-values, maximal allowed price difference for the comparison.
  3. I guess you need a lot of loops within loops which can be quite time consuming and if you make a little error you might end up in an endless loop.
  4. I don't think it's a good idea to calculate everything again and again - depends on limit!
 
robdav:

Hi All

I have a couple of arrays that build up support and resistance levels over the lookback period. It seems that some of these levels have the same price level so I would like to associate a count of when the condition has been met multiple times with the label of the object. In other words, I believe multiple elements within each array have the same value but I would like to total the number that are at the same level.

The construct you want is called an "associative array" or a "dictionary" or "hash array."

You basically store pairs of (value,count).

Then you put in some logic that "adds element if new value" or "increments count if exists."

Finally, you have some logic that loops through all elements to dump the value with the total count next to it. Good for building histograms.

I thought I saw somewhere that MQL5 added this in their libraries, but now I don't see it; however, this library looks like it would do the trick.

https://www.mql5.com/en/code/19314

This article describes associative arrays in more detail.

https://www.mql5.com/en/articles/1334

 
Anthony Garot:

The construct you want is called an "associative array" or a "dictionary" or "hash array."

You basically store pairs of (value,count).

Then you put in some logic that "adds element if new value" or "increments count if exists."

Finally, you have some logic that loops through all elements to dump the value with the total count next to it. Good for building histograms.

I thought I saw somewhere that MQL5 added this in their libraries, but now I don't see it; however, this library looks like it would do the trick.

https://www.mql5.com/en/code/19314

This article describes associative arrays in more detail.

https://www.mql5.com/en/articles/1334

Thanks Anthony. I only started learning MQL4 a week ago so this is going to take me a few days/weeks to get my head around. I thought a 'count' of the same values would be relatively easy. I assumed there was a way of looking at an existing array and simply totalling by count all those elements of the same value and outputting the value but clearly this is not going to be as trivial as I thought but thanks for your pointers.
 
robdav:
Thanks Anthony. I only started learning MQL4 a week ago so this is going to take me a few days/weeks to get my head around. I thought a 'count' of the same values would be relatively easy. I assumed there was a way of looking at an existing array and simply totalling by count all those elements of the same value and outputting the value but clearly this is not going to be as trivial as I thought but thanks for your pointers.

As Carl mentioned, the description of your problem and desired outcome are pretty vague. The best I could make of it - is that you want to take a value and find out how many times that value has occurred within an array. If that's the case then this is the easiest way. 

int CountOccurrences(const double condition, const double &array[])
{
   int cnt=0;
   for(int i=ArraySize(array)-1;i>=0;i--)
      if(condition == array[i])
         cnt++
   return cnt;
}
 
nicholishen:

As Carl mentioned, the description of your problem and desired outcome are pretty vague. The best I could make of it - is that you want to take a value and find out how many times that value has occurred within an array. If that's the case then this is the easiest way. 


Thanks, that's exactly what I want to do "take a value and find out how many times that value has occurred within an array"

I'll give it a go.

Thanks again. Rob

 

or...

in the code you posted instead of comparing i to shift+i, compare i to zero

 
nicholishen:

As Carl mentioned, the description of your problem and desired outcome are pretty vague. The best I could make of it - is that you want to take a value and find out how many times that value has occurred within an array. If that's the case then this is the easiest way. 


I'm struggling. nicholishen could you possibly re-post your previous reply that I think you removed with the highest high, lowest low example as I think it may help me. Many thanks.

 
robdav:

I'm struggling. nicholishen could you possibly re-post your previous reply that I think you removed with the highest high, lowest low example as I think it may help me. Many thanks.

You can use the array index itself to reference the data-value and the array element to reference the count. That probably doesn't make sense at this point but follow me here... 


Determine the range of your data. For this example lets say 1-10

Determine the step increment for your data set. For this example lets say 1

Calculate the number of steps in your data range by subtracting the min from the max and dividing by the step plus one.

int n_steps = (10 - 1) / 1 + 1; //10

To add a count for a data-value: subtract the data-value from the max-range-value and divide the sum by the step to get the index. So lets say we wanted to add a count for the data-value of 4

int arr[10];

int value_to_count = 4;

int range_max = 10;

int step = 1;

int index = (range_max-value_to_count) / step; //index = 6

arr[index]++;

Find the element with the highest count

int highest = ArrayMaximum(arr);


//in this case index 6

Reference your data value with the index by subtracting the index * step from the max range value

int data_value = 10 - 6 * 1; // 4

Here is an example script that finds the most common high on the chart by counting highs.


void OnStart()

{

   double res = 0.0;

   if(MostFrequentlyOccuringValueInArray(_Point,High,res))

      Print("The most common high is ",DoubleToString(res,_Digits));

}


template<typename T>

bool MostFrequentlyOccuringValueInArray(double step,const T &arr[],T &result)

{

   double max = (double)arr[ArrayMaximum(arr)];

   double min = (double)arr[ArrayMinimum(arr)];

   int    n_steps = int((max-min)/step) + 1;

   int    resarr[];

   if(ArrayResize(resarr,n_steps)!= n_steps)

      return false;

   for(int i=ArraySize(arr)-1; i >=0; i--)

      resarr[int((max-arr[i])/_Point)]++;

   result = T(max - (double)ArrayMaximum(resarr) * step);

   return true;

}

 
nicholishen:

As Carl mentioned, the description of your problem and desired outcome are pretty vague. The best I could make of it - is that you want to take a value and find out how many times that value has occurred within an array. If that's the case then this is the easiest way. 


Hi

How do I pass the condition into this please? The array just contains price levels I believe but I'm not sure how I can check that.

I've tried printing the values of the array and all I can see is a price value.

Thanks

Rob


int CountOccurrences(const double condition, const double &array[])
{
   int cnt=0;
   for(int i=ArraySize(array)-1;i>=0;i--)
      if(condition == array[i])
         cnt++
   return cnt;
}
 
robdav:

Hi

How do I pass the condition into this please? The array just contains price levels I believe but I'm not sure how I can check that.

I've tried printing the values of the array and all I can see is a price value.

Thanks

Rob



Rob, this was just a generic algo that you will need to tailor to your specific needs.

Reason: