Global variable being reset to zero after function call. why?

 

I'll start by saying, I'm very new to programming and mql4 with limited experience, but am doing my best to read through documentation and practice implementing simple strategies to improve.

Unfortunately, I've run into a snag with an EA that I have written. I declare a global variable outside of any functions (not local machine global, just program global). The main program start() then calls a function that I have written to open an order (type void). Within that function, I utilize the global variable declared before, as it calculates a value that I want to later use for a trailing stop. The problem is that as soon as the program returns to the main from the function, the global variable is reset to zero. I have printed the variable just before returning and also just after returning and the value changes from what it should be before, to zero after.

Any ideas? I have done this in other programs without any problem, but for some reason this one is acting differently and I can't pinpoint why.

I think I know of a workaround...I could change the function from void to double and return the value that I need that way. What is confusing me, is the fact that I actually use and change other global variables within the same function and they are not reverting to zero in the same manner. I'm more asking, why one variable would do that and another would not, so I can avoid making this mistake in the future and have a better understanding.

Thanks in advance.

 
irvinfitness:

I'll start by saying, I'm very new to programming and mql4 with limited experience, but am doing my best to read through documentation and practice implementing simple strategies to improve.

Unfortunately, I've run into a snag with an EA that I have written. I declare a global variable outside of any functions (not local machine global, just program global). The main program start() then calls a function that I have written to open an order (type void). Within that function, I utilize the global variable declared before, as it calculates a value that I want to later use for a trailing stop. The problem is that as soon as the program returns to the main from the function, the global variable is reset to zero. I have printed the variable just before returning and also just after returning and the value changes from what it should be before, to zero after.

Please don't call them global variables, these are Global Variables . . . you are talking about "variables with global scope" or "globally declared variables" . . .

Show your code . . . do you have a variable with local scope with the same variable name ?

 
  1. I'd prefer calling them common variables.
  2. Likely local variable, same name.
  3. Show your code.
 

My apologies for the incorrect name and title to this topic. I guess I picked up on that nomenclature based on a different code that I saw when I was first getting started. Good to know that it shouldn't be called that. Thanks

Now, for the code...I do realize that the code is most certainly very inefficient. Please do not "bash" what I have written for the simple fact that it is not the "best" way to do things. I realize this and admit that I still have some learning to do. Right now, I don't necessarily know that best ways to accomplish things. If you have constructive criticism, feel free to comment or suggest something as that is always appreciated. Here is the way that the code was when it was doing what I described in the first post (I did work around it by changing the function type to double and returning the variable that was giving me trouble in an updated version not included here)

I also do realize that this strategy is not necessarily profitable and was simply using it as a way to practice coding. I have since fixed all of the iMA calls to be variables instead of re-calling them each time and made some other minor changes, but could not get diff to return to start() properly out of either OpenLong() or OpenShort().

#property copyright "Nathan Irvin"

extern int SMA_Margin = 0;
extern double Risk = 2.0;
extern int wick_max = 30;
extern int sl_factor = 1;
extern int tp_factor = 3;
extern int MagicNumber = 123456;
extern string EA_Comments="TLP EA";
 
double points;
double TotalLots;
double diff;
double sl;
double newstop;
int ticket = 0;
int order_price;
int per = 0;
int multiplier;

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//---- Allows for any broker setup
  if (Digits==3 || Digits==5) points = Point*10;
  else points = Point;
  if (Digits==3) multiplier = 100;
  else if (Digits==4) multiplier = 1000;
  else if (Digits==5) multiplier = 10000;
  
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
  
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//----
   if ( per != Time[0] ) //To ensure one trade per candle
   {
      if ( WorkingOrder()) //Checks for an open position
      {
         if( OrderSelect(ticket,SELECT_BY_TICKET) && OrderCloseTime()==0 ) //Trailing Stop manipulation 
         { 
            if( OrderType()==OP_BUY ) 
            {
               if ( (iMA(NULL,PERIOD_H4,34,0,MODE_SMA,PRICE_CLOSE,0)-(diff*points)) > sl )
               {
                  newstop = iMA(NULL,PERIOD_H4,34,0,MODE_SMA,PRICE_CLOSE,0)-(diff*points);
                  OrderModify(OrderTicket(),OrderOpenPrice(),newstop,OrderTakeProfit(),0);
               }
            }
            else if( OrderType()==OP_SELL ) 
            {
               if ( (iMA(NULL,PERIOD_H4,34,0,MODE_SMA,PRICE_CLOSE,0)+(diff*points)) < sl)
               {
                  newstop = iMA(NULL,PERIOD_H4,34,0,MODE_SMA,PRICE_CLOSE,0)+(diff*points);
                  OrderModify(OrderTicket(),OrderOpenPrice(),newstop,OrderTakeProfit(),0);
                }
            }
         }  
         
         per = Time[0];
         return(0);
      }
      
      //Check if a new short position needs to be opened      
      else if ( (iClose(Symbol(),PERIOD_W1,1) < iMA(NULL,PERIOD_W1,55,0,MODE_SMA,PRICE_CLOSE,1))               //Checks average price of last Year for downtrend
         && (iClose(Symbol(),PERIOD_D1,1) < iMA(NULL,PERIOD_D1,21,0,MODE_SMA,PRICE_CLOSE,1))                   //Checks average price of last Month for downtrend
            && (iClose(Symbol(),PERIOD_H4,1)+SMA_Margin < iMA(NULL,PERIOD_H4,34,0,MODE_SMA,PRICE_CLOSE,1)) )   //Checks last candle closed below average price of Last Week 
      {
         //Need to check for previous candle touching SMA 34 and closing in direction of trend 
         if ( iLow(Symbol(),PERIOD_H4,1) < iMA(NULL,PERIOD_H4,34,0,MODE_SMA,PRICE_CLOSE,1) 
               && iMA(NULL,PERIOD_H4,34,0,MODE_SMA,PRICE_CLOSE,1) < iHigh(Symbol(),PERIOD_H4,1) 
                  && iOpen(Symbol(),PERIOD_H4,1) > iClose(Symbol(),PERIOD_H4,1) 
                     && iLow(Symbol(),PERIOD_H4,1) > iClose(Symbol(),PERIOD_H4,1)-wick_max*points ) 
         {
            OpenShort();
            Print("diff after return to main: ",diff);
         }
      }
      
      //Check if a new long postion needs to be opened
      else if ( (iClose(Symbol(),PERIOD_W1,1) > iMA(NULL,PERIOD_W1,55,0,MODE_SMA,PRICE_CLOSE,1))               //Checks average price of last Year for uptrend
         && (iClose(Symbol(),PERIOD_D1,1) > iMA(NULL,PERIOD_D1,21,0,MODE_SMA,PRICE_CLOSE,1))                   //Checks average price of last Month for uptrend
            && (iClose(Symbol(),PERIOD_H4,1)-SMA_Margin > iMA(NULL,PERIOD_H4,34,0,MODE_SMA,PRICE_CLOSE,1)) )   //Checks last candle closed above average price of last Week 
      {
         //Need to check for previous candle touching SMA 34 and closing in direction of trend
        if ( iLow(Symbol(),PERIOD_H4,1) < iMA(NULL,PERIOD_H4,34,0,MODE_SMA,PRICE_CLOSE,1) 
               && iMA(NULL,PERIOD_H4,34,0,MODE_SMA,PRICE_CLOSE,1) < iHigh(Symbol(),PERIOD_H4,1) 
                  && iOpen(Symbol(),PERIOD_H4,1) < iClose(Symbol(),PERIOD_H4,1) 
                     && iHigh(Symbol(),PERIOD_H4,1) < iClose(Symbol(),PERIOD_H4,1)+wick_max*points ) 
        {
            OpenLong();
            Print("diff after return to main: ",diff); 
        }

      }
      
      per = Time[0];
   }     
//----
   return(0);
  }

//+------------------------------------------------------------------+
// WorkingOrder - Check to see if any orders are opened              |
//+------------------------------------------------------------------+
bool WorkingOrder()
{
   int total = OrdersTotal();
   for(int cnt = 0; cnt < total; cnt++)
   {
      OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
      if((OrderSymbol() == Symbol()) && (OrderMagicNumber() == MagicNumber))
         return(true);
   }
   return (false);
}

//+------------------------------------------------------------------+
//| OpenLong/OpenShort - initiate buy and sell functions             |
//+------------------------------------------------------------------+
void OpenLong()
{
   double amountatrisk = AccountBalance()*(Risk/100);  
   double atrMax = 0.0; 
   double atrMin = 1.0; 
   double atrCheck = 0.0; 
   double diff = 0.0; 
   int p = 30; //4h period per day = 6 * 5 = 30 
   
   for ( int i = 0 ; i < p ; i++) 
   { 
      atrCheck = iATR(Symbol() , PERIOD_H4 , 14 , i); 
      if (atrCheck > atrMax) atrMax = atrCheck; 
      else if (atrCheck < atrMin) atrMin = atrCheck; 
   }
    
   diff = (( atrMax + atrMin ) * multiplier) / sl_factor;  //pip value that needs to be added to the difference between the price and the 34 SMA for the SL  
   double sma34 = iMA(Symbol() , PERIOD_H4 , 34 , 0 , MODE_SMA , 0 , 0 ) / points;  
   double clo = iClose(Symbol(),PERIOD_H4,0)/ points; 
   double takeprofit = (diff + (clo - sma34)) * tp_factor;
   double stoploss = diff + (clo - sma34);    //pip value for stop loss (Lot size should be calculated off of this)

   if (stoploss < 35) 
   {
      Print("ATR too narrow resulting in too much risk, no position will be opened");
      return;
   }
   
   double TotalLots = NormalizeDouble(amountatrisk/stoploss/(MarketInfo(Symbol(), MODE_TICKVALUE))/10,2);   
   ticket = OrderSend(Symbol(),OP_BUY,TotalLots,Ask,3,0,0,EA_Comments,MagicNumber,0,Blue);
   if( ticket < 1 ) return(-1);

   OrderSelect(ticket, SELECT_BY_TICKET);

   double order_price = OrderOpenPrice();
   double tp = order_price + takeprofit*points;
   sl = order_price - stoploss*points;
   OrderModify(ticket, order_price,sl,tp,0,Blue);
   Print("diff before return: ",diff);
   return;
}

void OpenShort()
{
   double amountatrisk = AccountBalance()*(Risk/100);
   double atrMax = 0.0; 
   double atrMin = 1.0; 
   double atrCheck = 0; 
   double diff = 0.0; 
   int p = 30; //4h period per day = 6 * 5 = 30 

   for ( int i = 0 ; i < p ; i++) 
   { 
      atrCheck = iATR(Symbol() , PERIOD_H4 , 14 , i); //ATR 14 pour H4 
      if (atrCheck > atrMax) atrMax = atrCheck; 
      if (atrCheck < atrMin) atrMin = atrCheck; 
   }
    
   diff = (( atrMax + atrMin ) * multiplier) / sl_factor;    //pip value
   double sma34 = iMA(Symbol() , PERIOD_H4 , 34 , 0 , MODE_SMA , 0 , 0 ) / points; 
   double clo = iClose(Symbol(),PERIOD_H4,0) / points; 
   double takeprofit = (diff + (sma34 - clo)) * tp_factor;
   double stoploss = diff + (sma34 - clo);  //pip value for LotSize to be calculated from   
   
   if (stoploss < 35) return(0);
   {
      Print("ATR too narrow resulting in too much risk, no position will be opened");
      return;
   }
   double TotalLots = NormalizeDouble(amountatrisk/stoploss/(MarketInfo(Symbol(), MODE_TICKVALUE))/10,2);
   ticket = OrderSend(Symbol(),OP_SELL,TotalLots,Bid,3,0,0,EA_Comments,MagicNumber,0,Red);
   if( ticket < 1 ) return (-1);

   OrderSelect(ticket, SELECT_BY_TICKET);

   double order_price = OrderOpenPrice();
   double tp = order_price - takeprofit*points;
   sl = order_price + stoploss*points; 
   OrderModify(ticket, order_price,sl,tp,0,Red);
   Print("diff before return: ",diff);
   return;
} 
 

be proud of ur work man.

it does not matter if u chose a mile long path to walk a yard, what is importante is that u get there (ur cpu might not like mutch, but who cares).

i dont know if i get ur point correctly but:

1. it is not a good practice to declare "double diff" as global (as u call it) and then again "double diff" in "OpenLong()" and "OpenShort()". if it is the same variable it's enough to do it as global if it is diferente variables then give it diferent names (raptorUk is a bit blunt but know things).

2. look for static variables in the mql4 refence docs, it might help.

hope u solve ur problem.

 
irvinfitness:

My apologies for the incorrect name and title to this topic. I guess I picked up on that nomenclature based on a different code that I saw when I was first getting started. Good to know that it shouldn't be called that. Thanks

Now, for the code...I do realize that the code is most certainly very inefficient. Please do not "bash" what I have written for the simple fact that it is not the "best" way to do things. I realize this and admit that I still have some learning to do. Right now, I don't necessarily know that best ways to accomplish things. If you have constructive criticism, feel free to comment or suggest something as that is always appreciated. Here is the way that the code was when it was doing what I described in the first post (I did work around it by changing the function type to double and returning the variable that was giving me trouble in an updated version not included here)

I also do realize that this strategy is not necessarily profitable and was simply using it as a way to practice coding. I have since fixed all of the iMA calls to be variables instead of re-calling them each time and made some other minor changes, but could not get diff to return to start() properly out of either OpenLong() or OpenShort().


RaptorUK:

Show your code . . . do you have a variable with local scope with the same variable name ?

Yes you do, the point of declaring a variable with global scope is that it is "visible" globally, to all functions, so then there is no need to declare it locally also, it can already be "seen" from inside all functions. A variable declared locally can only be seen from inside the function where it was declared . . .

Get rid of your local declarations for your globally declared variables . . .

 
SellSu:

be proud of ur work man.

it does not matter if u chose a mile long path to walk a yard, what is importante is that u get there (ur cpu might not like mutch, but who cares).

i dont know if i get ur point correctly but:

1. it is not a good practice to declare "double diff" as global (as u call it) and then again "double diff" in "OpenLong()" and "OpenShort()". if it is the same variable it's enough to do it as global if it is diferente variables then give it diferent names (raptorUk is a bit blunt but know things).

2. look for static variables in the mql4 refence docs, it might help.

hope u solve ur problem.


Thanks for catching it as they already had guessed. For some reason I kept missing it until you guys pointed it out.

 
RaptorUK:

Yes you do, the point of declaring a variable with global scope is that it is "visible" globally, to all functions, so then there is no need to declare it locally also, it can already be "seen" from inside all functions. A variable declared locally can only be seen from inside the function where it was declared . . .

Get rid of your local declarations for your globally declared variables . . .


Ahh...thanks for your help.

Now I know exactly what happened. I was not originally going to use diff outside of the function and that is why I declared it locally. Then, when I did change my mind, I quickly scanned through the code and missed the local declaration.

I appreciate all of the help from everyone. Still have a long ways to go, but at least I won't be making this mistake again! haha

Reason: