Help please, array mangement question. MQL4 vs .Net

 

Hello,


I am bringing some of my indicators over from NinjaTrader which are C# written and have a couple of questions regarding array management I am hoping someone can shed some light on.

 

1.) In c# I use "foreach" to search a double arrray to count how many times a particular double exists in the array. Noticing that foreach is not available, what is the best solution for this? would it be writing a cutom script using arrayBsearch where the last found idx is used to continue the search ? 

I imgine I can make a custom function but dont know if I can pass the array into the function or not? ANy suggestions for this?

  

2 .) I use dictionary to associated text labels with a price double. As in, i can seach the price in the dictionary and bring up all text associatd with this price. Can anyone suggest the best way to compensate for the missing "dictionary" funtion is mql4? Should i be doing this with string arrays and converting back to doubles?

 

Thank you for any guidance. 

 
Marty087:

Hello,


I am bringing some of my indicators over from NinjaTrader which are C# written and have a couple of questions regarding array management I am hoping someone can shed some light on.

 

1.) In c# I use "foreach" to search a double arrray to count how many times a particular double exists in the array. Noticing that foreach is not available, what is the best solution for this? would it be writing a cutom script using arrayBsearch where the last found idx is used to continue the search ? 

I imgine I can make a custom function but dont know if I can pass the array into the function or not? ANy suggestions for this?

  

2 .) I use dictionary to associated text labels with a price double. As in, i can seach the price in the dictionary and bring up all text associatd with this price. Can anyone suggest the best way to compensate for the missing "dictionary" funtion is mql4? Should i be doing this with string arrays and converting back to doubles?

 

Thank you for any guidance. 


int ArrayValCnt(double& array[], double val)
{  
   int cnt = 0;
   for(int z=0;z<ArraySize(array);z++)
   {
      if (val == array[z]) cnt++;
   }
   return(cnt);
}

 

ok, turns out it was easy to solve the array search, i see you can pass arrays into a fuction using &.... just the dictionary questions left if anyone can help.. 


 
Marty087:

.... just the dictionary questions left if anyone can help.. 
See the code associated with this library.
 
Alain Verleyen:
See the code associated with this library.

My personal favourite is https://www.mql5.com/en/code/11117

The attached version updates it to use the templates which became available in MQL4 after the original code was written. 

Files:
 

Brilliant. Thank you Alain and JC, just what i was looking for.

 

For interest sake, before I got your info, i made my own virtual Dict using a 2D string array..... This allowed me to get on with my project straight away... 

 There is some serious processor hogging going on somwhere. I wonder if all this string array searching is causing it.(havnt had a chance to degbug yet) I imagine that the suggested "hash" libary would be alot more efficient? 

 

Thanks for the assistance. 

 

string DictGet(string &theArray[][],double key,int sze)
{
   key = NormalizeDouble(key,myDigits());
  
   for (int x = 0; x< (sze/2);x++)
   {
      if (theArray[x][0] == string(key)) //key exists
         return(theArray[x][1]);
   }
   return("!"); //key not found

}

void DictAdd(string &theArray[][],double key,string info,int sze)
{
   key = NormalizeDouble(key,myDigits());

   if (sze >0)
   {
      for (int x = 0; x< (sze/2);x++)
      {
         if (theArray[x][0] == string(key)) // key exits so add to string and return out
         {
            theArray[x][1] += " , "+info;
            return;
         }
      }
   }

   if (theArray[0][0] == "nil") //first key and val to add to dictionary
   {
      theArray[0][0] = string(key);
      theArray[0][1] = info;
      return;
   }
   else //new key, re-size array and add in key and val
   {
      ArrayResize(theArray,(sze/2)+1,0);
      theArray[(sze/2)][0] = string(key); //as it is a 2 dimensional array the correct index is half the size. should be half size + 1 but cuz indexing starts at 0 it is just half.
      theArray[(sze/2)][1] = info;
   }
}


 

 
Marty087:

There is some serious processor hogging going on somwhere. I wonder if all this string array searching is causing it.(havnt had a chance to degbug yet) I imagine that the suggested "hash" libary would be alot more efficient? 

Yes, repeatedly iterating through the array will be slow. If you are doing lots of DictAdd, then repeatedly resizing the array will be punitive.

The ydrol hashtable is very fast.

I've only found more efficient alternatives to the ydrol hashtable for occasional, very specific purposes. For example: a large dictionary which is almost completely static (few/no new additions after initial fill), with integer keys. Under such circumstances the linked-list approach can be beatable using an array of values plus an array of keys+indexes, and doing ArrayBsearch on the array of keys+indexes.

 
JC:

Yes, repeatedly iterating through the array will be slow. If you are doing lots of DictAdd, then repeatedly resizing the array will be punitive.

The ydrol hashtable is very fast.

I've only found more efficient alternatives to the ydrol hashtable for occasional, very specific purposes. For example: a large dictionary which is almost completely static (few/no new additions after initial fill), with integer keys. Under such circumstances the linked-list approach can be beatable using an array of values plus an array of keys+indexes, and doing ArrayBsearch on the array of keys+indexes.

Replaced my clunky dictionary code with hash library soltion. Super fast now. Time wise, i have seen a reduction from 250ms  to <0ms for my function dealing with the dictionary adding / referencng. I cant beleve how much faster!

Thank you. 

 

Ok, i have run into a little trouble using the Hash class and can't seem to work it out. I am getting the errors below. 

//------------ 

3 14:17:57.164 indicator AUDJPY,H1: 24120 undeleted objects left

3 14:17:57.164 indicator AUDJPY,H1: 24120 objects of type HashString left

3 14:17:57.164 indicator AUDJPY,H1: 15670 leaked strings left

3 14:17:57.164 indicator AUDJPY,H1: 706768 bytes of leaked memory 

//------------ 


This is the structure of how I am using my hash libraries

 

Hash              *testHash = new Hash(true);  //globally declared


void OnDeinit()
{
   delete testHash; //delete upon removal of indicator

}
OnCalculate()
{
   delete testHash; //delete
   testHash = new Hash(true); //re-initiate
  
   //Doing all my adding and key searching etc in fuctions called from here.
  
   Print("The Hash count is = "+testHash.getCount()); //checking my hash count is approriatly re-sizing on every run (which it is)
  
  
}

 

 How it is possible that I have undeleted hash objects and memory leaks upon DEINIT?

 

Thanks in advance for any help.  

 
Martin Asher:

Ok, i have run into a little trouble using the Hash class and can't seem to work it out. I am getting the errors below. 

//------------ 

3 14:17:57.164 indicator AUDJPY,H1: 24120 undeleted objects left

3 14:17:57.164 indicator AUDJPY,H1: 24120 objects of type HashString left

3 14:17:57.164 indicator AUDJPY,H1: 15670 leaked strings left

3 14:17:57.164 indicator AUDJPY,H1: 706768 bytes of leaked memory 


 How it is possible that I have undeleted hash objects and memory leaks upon DEINIT?

 

Thanks in advance for any help.  

You should provide a code that reproduces your issue if you want help.
 
Martin Asher:

Ok, i have run into a little trouble using the Hash class and can't seem to work it out. I am getting the errors below.  

I'd suggest that you use the modified, templated version which I posted above, rather than the original code. It keeps all the excellence of the original while adding in convenient templating which was not available when the original code was written.

The code as originally posted does have a memory leak if you replace an existing entry with a new value. See the comment at https://www.mql5.com/en/forum/28938#comment_1751819. There's a section of the original code which is commented-out for no obvious reason, and which generates this memory leak.

Libraries: HashMap implementation
Libraries: HashMap implementation
  • www.mql5.com
MQL5 programming forum
 
JC:

I'd suggest that you use the modified, templated version which I posted above, rather than the original code. It keeps all the excellence of the original while adding in convenient templating which was not available when the original code was written.

The code as originally posted does have a memory leak if you replace an existing entry with a new value. See the comment at https://www.mql5.com/en/forum/28938#comment_1751819. There's a section of the original code which is commented-out for no obvious reason, and which generates this memory leak.

I am face palming now.. I read the comment about the mysterious commented-out section yesterday and did attempt a trouble shoot by uncommenting but it didnt resolve the memory leak at the time so I moved on..... I have just tried again and no memory leaks now. In my haste, yesterday I must have rushed the process and maybe had an unoticed compile error or something which caused me to overlook this as the issue.

Anyway, all working perfectly now. Thank you again JC. 

Reason: