GlobalVariables for Client Terminal

 

My question is based on this lesson in the MQL4 book. https://book.mql4.com/variables/globals

The code used in the example is reproduced for convenience

//--------------------------------------------------------------------
// globalvar.mq4
// The code should be used for educational purpose only.
//--------------------------------------------------------------------
int    Experts;                                 // Amount of EAs
double Depo=10000.0,                            // Set deposit
       Persent=30,                              // Set percentage     
       Money;                                   // Desired money
string Quantity="GV_Quantity";                  // GV name
//--------------------------------------------------------------------
int init()                                      // Special funct. init()
  {
   Experts=GlobalVariableGet(Quantity);         // Getting current value
   Experts=Experts+1;                           // Amount of EAs
   GlobalVariableSet(Quantity, Experts);        // New value
   Money=Depo*Persent/100/Experts;                // Money for EAs
   Alert("For EA in window ", Symbol()," allocated ",Money);
   return;                                      // Exit init()
  }
//--------------------------------------------------------------------
int start()                                     // Special funct. start()
  {
   int New_Experts= GlobalVariableGet(Quantity);// New amount of EAs
   if (Experts!=New_Experts)                    // If changed
     {
      Experts=New_Experts;                      // Now current
      Money=Depo*Persent/100/Experts;             // New money value 
      Alert("New value for EA ",Symbol(),": ",Money);
     }
   /*
   ...
   Here the main EA code should be indicated.
   The value of the variable Money is used in it.
   ...
   */
   return;                                      // Exit start()
  }
//--------------------------------------------------------------------
int deinit()                                    // Special funct. deinit()
  {
   if (Experts ==1)                             // If one EA..
      GlobalVariableDel(Quantity);              //..delete GV
   else                                         // Otherwise..
      GlobalVariableSet(Quantity, Experts-1);   //..diminish by 1
   Alert("EA detached from window ",Symbol());  // Alert about detachment
   return;                                      // Exit deinit()
  }
//--------------------------------------------------------------------

My question is that (at least the first time this EA executes) it seems after init(), 

 Experts=GlobalVariableGet(Quantity);

will be casting an int variable type to a string value since Quantity is a global variable string? 
Then Experts is incremented but does it not need to be explicitly cast back to an int in order to do this math operation?

GlobalVariables - Variables - MQL4 Tutorial
GlobalVariables - Variables - MQL4 Tutorial
  • book.mql4.com
GlobalVariables - Variables - MQL4 Tutorial
 
clemmo:

My question is based on this lesson in the MQL4 book. https://book.mql4.com/variables/globals

The code used in the example is reproduced for convenience

My question is that (at least the first time this EA executes) it seems after init(), 

will be casting an int variable type to a string value since Quantity is a global variable string? 
Then Experts is incremented but does it not need to be explicitly cast back to an int in order to do this math operation?

Not a good article or example IMO.

The line you refer to will get the double value of the global variable Quantity (Quantity is a string that holds the name of the GV)

It will then store the value in the integer variable called Experts.

It will automatically cast from double to integer but you would lose data in the process because Experts is not a double.

Experts should therefore be a double.

You can get away with this if you are sure that you are storing only an integer value in the GV in the first place... 

 
Paul Anscombe:

Not a good article or example IMO.

The line you refer to will get the double value of the global variable Quantity (Quantity is a string that holds the name of the GV)


It will automatically cast from double to interger but you would lose data in the process because Experts.

Experts should therefore be a double.

You can get away with this if you are sure that you are storing only an integer value in the GV in the first place... 

Thanks Paul.

Note that this comes directly from the official MetaQuotes docs (book). Do you know a better example?
>>"The line you refer to will get the double value of the global variable Quantity (Quantity is a string that holds the name of the GV)"
So if it is initialized without a double value (as in the example) the double at initialization is equal to zero?


>> It will then store the value in the integer variable called Experts.
So is the value stored in 'int Experts' the value zero or the string with the GV name?

>>Experts should therefore be a double. 
That is my thinking too. 

>> You can get away with this if you are sure that you are storing only an integer value in the GV in the first place... 
It seems clear in this example that is the case, but can you clarify how we 'get away with this'? Are the values being typecast as I thought or is it that the int Experts is somehow only taking the numeric value part of the GV?

 
clemmo:

Thanks Paul.

Note that this comes directly from the official MetaQuotes docs (book). Do you know a better example?
>>"The line you refer to will get the double value of the global variable Quantity (Quantity is a string that holds the name of the GV)"
So if it is initialized without a double value (as in the example) the double at initialization is equal to zero?


>> It will then store the value in the integer variable called Experts.
So is the value stored in 'int Experts' the value zero or the string with the GV name?

>>Experts should therefore be a double. 
That is my thinking too. 

>> You can get away with this if you are sure that you are storing only an integer value in the GV in the first place... 
It seems clear in this example that is the case, but can you clarify how we 'get away with this'? Are the values being typecast as I thought or is it that the int Experts is somehow only taking the numeric value part of the GV?

When Experts is used in the example it is receiving the value from the GV.  Only the integer part will be stored in Experts and decimal places will be lost

SO you can get away with it if you only store integer values in the GV 

examples:

store  55   in GV   stores as 55.0    will store 55 in Experts when recalled from the GV.

store  55.123   in GV   stores as 55.123    will store 55 in Experts when recalled from the GV.

store  0.5   in GV   stores as 0.5    will store 0 in Experts when recalled from the GV.

try it for yourself

 
Paul Anscombe:

When Experts is used in the example it is receiving the value from the GV.  Only the integer part will be stored in Experts and decimal places will be lost

SO you can get away with it if you only store integer values in the GV 

examples:

store  55   in GV   stores as 55.0    will store 55 in Experts when recalled from the GV.

store  55.123   in GV   stores as 55.123    will store 55 in Experts when recalled from the GV.

store  0.5   in GV   stores as 0.5    will store 0 in Experts when recalled from the GV.

try it for yourself

>> Only the integer part will be stored in Experts

Ok thanks. That's the part that seems mysterious to me because 

Experts = GlobalVariableGet(Quantity); seems like it should be fetching the string as
string Quantity = "GV_Quantity"; contains only string data. 

 
clemmo:

>> Only the integer part will be stored in Experts

Ok thanks. That's the part that seems mysterious to me because 

Experts = GlobalVariableGet(Quantity); seems like it should be fetching the string as
string Quantity = "GV_Quantity"; contains only string data. 

Also, just as deinit decrements the number of experts in one step while setting the GV couldn't I combine these two lines

Experts=Experts+1;                           // Amount of EAs
   GlobalVariableSet(Quantity, Experts);        // New value

into one line?

GlobalVariableSet(Quantity, Experts+1);
 

My last concern is that for each of the special functions (init, start, deinit) I get a warning. I assume this would be an error if strict compilation was enforced.

"function must return a value"

I have tried changing return operator to return init(); return start(); return deinit(); which compiles but causes the EA to freeze.

 
clemmo:

Also, just as deinit decrements the number of experts in one step while setting the GV couldn't I combine these two lines

into one line?

To answer my own question, no you cannot do this. It creates a bug where the previous EA will be detached when a new one is added. I will have to ponder why this is so.

 
clemmo:

My last concern is that for each of the special functions (init, start, deinit) I get a warning. I assume this would be an error if strict compilation was enforced.

"function must return a value"

I have tried changing return operator to return init(); return start(); return deinit(); which compiles but causes the EA to freeze.

The solution is to use return(0);

 

completed and corrected code for globalvar.mq4 follows.

//--------------------------------------------------------------------
// globalvar.mq4
//--------------------------------------------------------------------
double Experts;                                 // holds the # of running EAs
double Depo=10000.0,                            // initial deposit size
       Percent=30,                              // Percentage to be divided among the EAs
       Money;                                   // cash value to be divided among the EAs
string Quantity="GV_Quantity";                  // global var name initial string value
//--------------------------------------------------------------------
#property strict;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int init()                                      // special function init start
  {
   Experts=GlobalVariableGet(Quantity);         // Get the value of the global var -
   Experts=Experts+1;                           // increment the number of running EAs by this one
   GlobalVariableSet(Quantity, Experts);        // Update the global var so that it can be accessed by other EAs
   Money=Depo*Percent/100/Experts;              // Formula for money sharing.
   Alert("For EA in window ", Symbol()," allocated ",Money);
   return(0);                                   // exit special function init()
  }
//--------------------------------------------------------------------
int start()                                     // begin special func start()
  {
   double New_Experts= GlobalVariableGet(Quantity);// every tick update the status of the number of running EAs
   if(Experts!=New_Experts)                     // check if the number of running EAs has changed
     {
      Experts=New_Experts;                      // if it has update the number of running EAs
      Money=Depo*Percent/100/Experts;           // and update the money sharing scheme
      Alert("New value for EA ",Symbol(),": ",Money);
     }
   /*
   ...
   The main EA code would go here. The value of the variable Money is used for the
   max trade volume.
   ...
   */
//Sleep(100000);
   return(0);                                   // exit special func start()
  }
//--------------------------------------------------------------------
int deinit()                                    // begin specil func deinit
  {
   Experts=GlobalVariableGet(Quantity);         //update the running EA status
//this is necessary to avoid a bug where an incoming tick hasn't yet updated the status via start()
   if(Experts ==1)                              // if this is the sole remaining EA running
      GlobalVariableDel(Quantity);              //delete the global varibable Quantity as it's no longer needed
   else                                         // otherwise
      GlobalVariableSet(Quantity, Experts-1);   //decrement the running EA count by 1
   Alert("EA detached from window ",Symbol());  // Notify of detached EA
   return(0);                                   // exit special func deinit()
  }
//--------------------------------------------------------------------
//+------------------------------------------------------------------+