Using objects to change the extern variable

 

Hi friends,

I usually need to change my indicator extern variable's value in order to change my indicator setting and redraw the indicator with the newly set variables. Now for the purpose of saving my time, I'd like to use the objects to change my extern variable's value by only a simple click on the object. I'd appreciate if anyone could guide me if it is possible to do so ? I mean is it possible to change the indicator extern variable's and reinitialize the indicator to redraw the indicator with the new setting.

Thanking in advance for your kind help,

 
parham.trader:

Hi friends,

I usually need to change my indicator extern variable's value in order to change my indicator setting and redraw the indicator with the newly set variables. Now for the purpose of saving my time, I'd like to use the objects to change my extern variable's value by only a simple click on the object. I'd appreciate if anyone could guide me if it is possible to do so ? I mean is it possible to change the indicator extern variable's and reinitialize the indicator to redraw the indicator with the new setting.

Thanking in advance for your kind help,

1. You cannot change an input. Think of them as constants.

2. But you -can- change local copies of inputs. So, for example:

input int InpAtrPeriod=20; // ATR period
int periodATR;

void OnInit()
{
    periodATR = InpAtrPeriod;
    . . . 
}

3. Have a global boolean called something like:

bool g_recalculate = false;

4. During a push-button even, e.g. CHARTEVENT_OBJECT_CLICK, in addition to changing your local copy of an extern, you set g_recalculate = true;. You might also want an ChartRedraw() in there.

5. In OnCalculate(), do something like this:

if ( g_recalculate )
{
    g_recalculate = false;   // reset flag
    myPrevCalculated = 0;    // causes indicator to refresh
}
else
{
    myPrevCalculated = prev_calculated;
}

Note the use of "myPrevCalculated, which is a local copy of prev_calculated, because you cannot change prev_calculated.

 

Here's a simple example:

click the text once, right-click change value, and click again.

#property strict
#property indicator_chart_window
//--- input parameters
extern int      Value=20;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   if(ObjectFind(ChartID(),"Value")==-1)
      if(!ObjectCreate(ChartID(),"Value",OBJ_TEXT,0,0,0))
         return(INIT_FAILED);
   Print(Value);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   if(rates_total!=prev_calculated)
     {
      ObjectSetInteger(ChartID(),"Value",OBJPROP_TIME,time[0]);
      ObjectSetDouble(ChartID(),"Value",OBJPROP_PRICE,close[0]-200*_Point);
      ObjectSetString(ChartID(),"Value",OBJPROP_TEXT,(string)Value);
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---
   static bool clicked=false;
   if(id==CHARTEVENT_OBJECT_CLICK && sparam=="Value")
     {
      if(clicked)
        { 
         Print(Value=(int)ObjectGetString(ChartID(),"Value",OBJPROP_TEXT));
         ObjectSetInteger(ChartID(),"Value",OBJPROP_SELECTED,false);
         OnInit();
         clicked=false;
        }
      else
        { 
         ObjectSetInteger(ChartID(),"Value",OBJPROP_SELECTED,true);
         clicked=true;
        }
     } 
  }
//+------------------------------------------------------------------+

2018.09.03 17:37:38.313 Change ExternVar EURUSD,H1: 22
2018.09.03 17:37:38.313 Change ExternVar EURUSD,H1: 22
2018.09.03 17:37:22.424 Change ExternVar EURUSD,H1: 20
 
Anthony Garot:

1. You cannot change an input. Think of them as constants.

2. But you -can- change local copies of inputs. So, for example:

3. Have a global boolean called something like:

4. During a push-button even, e.g. CHARTEVENT_OBJECT_CLICK, in addition to changing your local copy of an extern, you set g_recalculate = true;. You might also want an ChartRedraw() in there.

5. In OnCalculate(), do something like this:

Note the use of "myPrevCalculated, which is a local copy of prev_calculated, because you cannot change prev_calculated.

Thank you so much @Anthony Garot for your kind guidance.

But I actually didn't get about the "myPrevCalculated" variable and its operation. what does it do in your code ?

Ernst Van Der Merwe:

Here's a simple example:

click the text once, right-click change value, and click again.

Such a great help ! Thank you very much.
Indeed I would like to change my current Indicator extern variables so that the indicator redraw with my newly set extern variables.

suppose that I'm using MACD with the following setting on my chart its window is shown at the bottom of the chart:

Fast EMA Period : 12

Slow EMA Period : 26

Signal SMA Period : 9

Now I want to change the MACD setting to the following setting and to redraw the MACD with the newly settings simply by clicking on a predefined object on the chart (e.g. Rectangle).

Fast EMA Period : 24

Slow EMA Period : 52

Signal SMA Period : 9

Is it possible or not to redraw the MACD by clicking on the predefined object?

Thanking in advance

 
parham.trader:

Thank you so much @Anthony Garot for your kind guidance.

But I actually didn't get about the "myPrevCalculated" variable and its operation. what does it do in your code ?

Such a great help ! Thank you very much.
Indeed I would like to change my current Indicator extern variables so that the indicator redraw with my newly set extern variables.

suppose that I'm using MACD with the following setting on my chart its window is shown at the bottom of the chart:

Fast EMA Period : 12

Slow EMA Period : 26

Signal SMA Period : 9

Now I want to change the MACD setting to the following setting and to redraw the MACD with the newly settings simply by clicking on a predefined object on the chart (e.g. Rectangle).

Fast EMA Period : 24

Slow EMA Period : 52

Signal SMA Period : 9

Is it possible or not to redraw the MACD by clicking on the predefined object?

Thanking in advance

Yes, it's possible.

macd

Files:
MACD_1.1.mq4  6 kb
 
parham.trader:

Thank you so much @Anthony Garot for your kind guidance.

But I actually didn't get about the "myPrevCalculated" variable and its operation. what does it do in your code ?

That's how you get the indicator to refresh it's values, i.e. to re-calculate all buffer values with the new values you provided. Once the values are re-calculated, the plots update visually on the chart.

 
Ernst Van Der Merwe:

Yes, it's possible.


What an amazing solution ! You made my day man. Thank you very very much !

Anthony Garot:

That's how you get the indicator to refresh it's values, i.e. to re-calculate all buffer values with the new values you provided. Once the values are re-calculated, the plots update visually on the chart.

In general I got what you mean but I think I need to read about it more to find it out precisely. Thank you so much for your time.

 
Ernst Van Der Merwe:

Yes, it's possible.


There is only one shortage about this code that I found today!

it only works on the working days when the OnCalculate function is called continuously but during the days that the market is closed and the OnCalculate function is not called, it doesn't work.

Any idea regarding the matter ?

 
parham.trader:

There is only one shortage about this code that I found today!

it only works on the working days when the OnCalculate function is called continuously but during the days that the market is closed and the OnCalculate function is not called, it doesn't work.

Any idea regarding the matter ?

You'd have to give it a tick when the market is closed.

         OnInit();
         if(!prevCalculated)
           {
            long volume[1];
            int spread[1];
            OnCalculate(Bars,0,Time,Open,High,Low,Close,Volume,volume,spread);
           }
Files:
MACD_1.1.mq4  6 kb
 
Anthony Garot:

1. You cannot change an input. Think of them as constants.

2. But you -can- change local copies of inputs. So, for example:

While this (what I wrote) is true, that you cannot change an input, the OP mentioned externs, and those can be changed during run-time.

https://www.mql5.com/en/forum/281544#comment_8856941

So my enumerated #2 is moot if you are using externs.

 
Anthony Garot:

1. You cannot change an input. Think of them as constants.

#property strict

extern int i1 = 0;
input int i2 = 0;

void OnStart()
{
  i1 = 1; // OK
  i2 = 1; // 'i2' - constant cannot be modified
}


PS Read this topic.

Изменение входных параметров индикатора на ходу
Изменение входных параметров индикатора на ходу
  • 2014.10.10
  • www.mql5.com
Хочу написать универсальный модуль, который бы можно было в несколько нажатий подключить к любому индикатору...
Reason: