Сброс глобальных переменных при смене периода графика

 

Приветствую всех! 

Есть индикатор.

//+------------------------------------------------------------------+
//|                                                  Example-359.mq4 |
//|                                                  Vitaly Gorbunov |
//|                           https://www.mql5.com/ru/users/faust-gp |
//+------------------------------------------------------------------+
#property copyright "Vitaly Gorbunov"
#property link      "https://www.mql5.com/ru/users/faust-gp"
#property version   "1.00"
#property strict
#property indicator_chart_window
extern long X=10; //Смещение меню по Х
extern long Y=10; //Смещение меню по Y
string Prefix="Example-359_";//Префикс для объектов на чарте
long X1,X2,Y1,Y2; //Координаты меню
bool ShowMenu=false;//Есть или нет меню на чарте
int Widht=80;//Ширина элемента меню
int Height=20;//Высота элемента меню
string FontName="Arial";//Имя шрифта для меню
int FontSize=10;//Размер шрифта
color clrMain=clrSteelBlue;//Основной цвет для меню
color clrFont=clrWhite;//Цвет шрифта
bool SwMenu1;//Состояние переключателя меню 1
bool SwMenu2;//Состояние переключателя меню 2
bool SwMenu3;//Состояние переключателя меню 3
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   IndicatorShortName("Example-359");//Имя индикатора
   ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,1);//Устанавливаем отслеживание координат мышки на чарте
                                               //Создадим панельку на которую будем реагировать разворачиванием меню
   EditCreate(0,Prefix+"MM",0,X,Y,Widht,Height,CORNER_LEFT_UPPER,"Main menu",FontName,FontSize,ALIGN_LEFT,true,clrFont,clrMain,clrMain,false,false);
//Пересчитаем координаты для реагирования
   X1=X; Y1=Y; X2=X+Widht; Y2=Y+Height;
   SwMenu1=false;//Состояние переключателя меню 1
   SwMenu2=false;//Состояние переключателя меню 2
   SwMenu3=false;//Состояние переключателя меню 3
   
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinit function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   DeleteMenu();
   ObjectDelete(0,Prefix+"MM");
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---

//--- 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)
  {
//Если мышка в границах реагирования то реагируем
   if(id==CHARTEVENT_MOUSE_MOVE && lparam>=X1 && lparam<=X2 && dparam>=Y1 && dparam<=Y2)
     {
      if(!ShowMenu){CreateMenu();}//Если меню нет на чарте то создаём его
     }
//Если мышка вне границ реагирования то проверяем
   if(id==CHARTEVENT_MOUSE_MOVE && (lparam<X1 || lparam>X2 || dparam<Y1 || dparam>Y2))
     {
      if(ShowMenu){DeleteMenu();}//Если меню есть на чарте то удаляем
     }
//Реагируем на нажатие на объекты     
   if(id==CHARTEVENT_OBJECT_CLICK && sparam==Prefix+"M1")
     {
      ChangeMenu(sparam);
     }
   if(id==CHARTEVENT_OBJECT_CLICK && sparam==Prefix+"M2")
     {
      ChangeMenu(sparam);
     }
   if(id==CHARTEVENT_OBJECT_CLICK && sparam==Prefix+"M3")
     {
      ChangeMenu(sparam);
     }
  }
//+------------------------------------------------------------------+
//| Function create object text                                      |
//+------------------------------------------------------------------+
bool EditCreate(const long             chart_ID=0,
                const string           name="Edit",
                const int              sub_window=0,
                const long             x=0,
                const long             y=0,
                const int              width=50,
                const int              height=18,
                const ENUM_BASE_CORNER corner=CORNER_LEFT_UPPER,
                const string           text="Text",
                const string           font="Arial",
                const int              font_size=10,
                const ENUM_ALIGN_MODE  align=ALIGN_CENTER,
                const bool             read_only=false,
                const color            clr=clrWhite,
                const color            back_clr=clrWhite,
                const color            border_clr=clrSteelBlue,
                const bool             back=false,
                const bool             selection=false,
                const bool             hidden=true,
                const long             z_order=0)
  {

   ResetLastError();

   if(!ObjectCreate(chart_ID,name,OBJ_EDIT,sub_window,0,0))
     {
      Print(__FUNCTION__,
            "Code ERROR: ",GetLastError());
      return(false);
     }

   ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x);
   ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y);
   ObjectSetInteger(chart_ID,name,OBJPROP_XSIZE,width);
   ObjectSetInteger(chart_ID,name,OBJPROP_YSIZE,height);
   ObjectSetString(chart_ID,name,OBJPROP_TEXT,text);
   ObjectSetString(chart_ID,name,OBJPROP_FONT,font);
   ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,font_size);
   ObjectSetInteger(chart_ID,name,OBJPROP_ALIGN,align);
   ObjectSetInteger(chart_ID,name,OBJPROP_READONLY,read_only);
   ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner);
   ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
   ObjectSetInteger(chart_ID,name,OBJPROP_BGCOLOR,back_clr);
   ObjectSetInteger(chart_ID,name,OBJPROP_BORDER_COLOR,border_clr);
   ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
   ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
   ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
   return(true);
  }
//+------------------------------------------------------------------+
//|Function create menu                                              |
//+------------------------------------------------------------------+
void DeleteMenu()
  {
   ObjectDelete(0,Prefix+"M1");
   ObjectDelete(0,Prefix+"M2");
   ObjectDelete(0,Prefix+"M3");
//Пересчитаем координаты реагирования
   Y2=Y+Height;
   ShowMenu=false;
  }
//+------------------------------------------------------------------+
//|Function delete menu                                              |
//+------------------------------------------------------------------+
void CreateMenu()
  {
   string tmpStr="";
   if(SwMenu1){tmpStr="ON 1";}else{tmpStr="OFF 1";}//Выставляем состояние переключателя 1
   EditCreate(0,Prefix+"M1",0,X,Y+21,Widht,Height,CORNER_LEFT_UPPER,tmpStr,FontName,FontSize,ALIGN_LEFT,true,clrFont,clrMain,clrMain,false,false);
   if(SwMenu2){tmpStr="ON 1";}else{tmpStr="OFF 1";}//Выставляем состояние переключателя 2
   EditCreate(0,Prefix+"M2",0,X,Y+42,Widht,Height,CORNER_LEFT_UPPER,tmpStr,FontName,FontSize,ALIGN_LEFT,true,clrFont,clrMain,clrMain,false,false);
   if(SwMenu3){tmpStr="ON 1";}else{tmpStr="OFF 1";}//Выставляем состояние переключателя 3
   EditCreate(0,Prefix+"M3",0,X,Y+63,Widht,Height,CORNER_LEFT_UPPER,tmpStr,FontName,FontSize,ALIGN_LEFT,true,clrFont,clrMain,clrMain,false,false);
//Пересчитаем координаты реагирования
   Y2=Y+63+Height;
   ShowMenu=true;
  }
//+------------------------------------------------------------------+
//|Change menu                                                       |
//+------------------------------------------------------------------+
void ChangeMenu(string PMenu)
  {
   if(PMenu==Prefix+"M1")
     {
      if(SwMenu1)
        {
         ObjectSetString(0,PMenu,OBJPROP_TEXT,"OFF 1");
         SwMenu1=false;
        }
      else
        {
         ObjectSetString(0,PMenu,OBJPROP_TEXT,"ON 1");
         SwMenu1=true;
        }
     }
   if(PMenu==Prefix+"M2")
     {
      if(SwMenu2)
        {
         ObjectSetString(0,PMenu,OBJPROP_TEXT,"OFF 1");
         SwMenu2=false;
        }
      else
        {
         ObjectSetString(0,PMenu,OBJPROP_TEXT,"ON 1");
         SwMenu2=true;
        }
     }
   if(PMenu==Prefix+"M3")
     {
      if(SwMenu3)
        {
         ObjectSetString(0,PMenu,OBJPROP_TEXT,"OFF 1");
         SwMenu3=false;
        }
      else
        {
         ObjectSetString(0,PMenu,OBJPROP_TEXT,"ON 1");
         SwMenu3=true;
        }
     }
  }
//+------------------------------------------------------------------+

 

В нем при смене ТФ сбрасываются переменные:

bool SwMenu1=false;//Состояние переключателя меню 1
bool SwMenu2=false;//Состояние переключателя меню 2
bool SwMenu3=false;//Состояние переключателя меню 3


Пробовал переделать согласно примеру:

//+------------------------------------------------------------------+
//|                                    exTextInitGlobalVariables.mq5 |
//|              Copyright 2015, Artem A. Trishkin, Skype artmedia70 |
//|                       https://login.mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Artem A. Trishkin, Skype artmedia70"
#property link      "https://login.mql5.com/ru/users/artmedia70"
#property version   "1.00"
//--- input parameters
input int      TestInput=0;            // Внешняя переменная
int testInputGlobal=TestInput;         // Значение внешней переменной, присвоенное на глобальном уровне
int testInputInit;                     // Значение внешней переменной, присвоенное в OnInit()

//--- global variables
int   TestValueGlobalNoInitNo;         // Не инициализирована значением нигде
int   TestValueGlobalYesInitNo=0;      // Инициализирована значением 0 при объявлении, не инициализирована в OnInit()
//---
int   TestValueGlobalNoInitYes;        // Не инициализирована значением при объявлении, инициализирована в OnInit() нулём
int   TestValueGlobalYesInitYes=0;     // Инициализирована нулём и при объявлении, и в OnInit()
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   testInputInit=TestInput;
   TestValueGlobalNoInitYes=0;
   TestValueGlobalYesInitYes=0;
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   testInputInit++;
   testInputGlobal++;
   TestValueGlobalNoInitNo++;
   TestValueGlobalNoInitYes++;
   TestValueGlobalYesInitNo++;
   TestValueGlobalYesInitYes++;
   Comment
         (
         "\n"+"============================================="+
         "\n"+"Значение внешней переменной TestInput(",TestInput,"), присвоенное в OnInit(): ",(string)testInputGlobal+
         "\n"+"Значение внешней переменной TestInput(",TestInput,"), присвоенное на глобальном уровне: ",(string)testInputGlobal+
         //---
         "\n"+"============================================="+
         "\n"+"Не инициализирована значением нигде (неявная инициализация нулём): ",(string)TestValueGlobalNoInitNo+
         "\n"+"Инициализирована значением 0 при объявлении, не инициализирована в OnInit(): "+(string)TestValueGlobalYesInitNo+
         //---
         "\n"+"============================================="+
        "\n"+"Не инициализирована значением при объявлении, инициализирована в OnInit() нулём: "+(string)TestValueGlobalNoInitYes+
         "\n"+"Инициализирована нулём и при объявлении, и в OnInit(): "+(string)TestValueGlobalYesInitYes
         );
  }
//+------------------------------------------------------------------+


Вариант 1. Не инициализированная нигде:

bool SwMenu1;//Состояние переключателя меню 1
bool SwMenu2;//Состояние переключателя меню 2
bool SwMenu3;//Состояние переключателя меню 3


Вариант 2. Значение внешней переменной, присвоенное на глобальном уровне:

...
input bool TestInput=false;  // Внешняя переменная
...

bool SwMenu1=TestInput;//Состояние переключателя меню 1
bool SwMenu2=TestInput;//Состояние переключателя меню 2
bool SwMenu3=TestInput;//Состояние переключателя меню 3


Вариант 3. Глобальные переменные без инициализации, но инициализированы в ините:

...
bool SwMenu1;//Состояние переключателя меню 1
bool SwMenu2;//Состояние переключателя меню 2
bool SwMenu3;//Состояние переключателя меню 3
...

int OnInit()
  {
   SwMenu1=false;//Состояние переключателя меню 1
   SwMenu2=false;//Состояние переключателя меню 2
   SwMenu3=false;//Состояние переключателя меню 3
   
   return(INIT_SUCCEEDED);
  }


В примере все работает. В моем случае нет. Подскажите пожалуйста где искать причину?

 
Andrey Kornishkin:

Приветствую всех! 

Есть индикатор.

 

В нем при смене ТФ сбрасываются переменные:


Пробовал переделать согласно примеру:


Вариант 1. Значение внешней переменной, присвоенное на глобальном уровне:


Вариант 2. Глобальные переменные без инициализации, но инициализированы в ините:

Инициализация глобальных переменных программы и другие полезные знания.
Инициализация глобальных переменных программы и другие полезные знания.
  • 2016.11.29
  • www.mql5.com
Встал на форуме недавно вопрос по поводу верной/неверной инициализации глобальных переменных в программах...
 
Artyom Trishkin:

Прочитал ветку внимательно. По индикаторам вопрос остался открытым?

 
Andrey Kornishkin:

В примере все работает. В моем случае нет. Подскажите пожалуйста где искать причину?

Ну так пример который Вы юзаете это советник, а у Вас индикатор. Поведение советника и индикатора при смене таймфрейма будет разное. Как выход из положения, это использовать глобальные терминала.

 
Sergey Kolemanov:

Ну так пример который Вы юзаете это советник, а у Вас индикатор. Поведение советника и индикатора при смене таймфрейма будет разное. Как выход из положения, это использовать глобальные терминала.

Что значит использовать глобальные переменные терминала? как решить проблему для индикатора?

 
vebster005:

Что значит использовать глобальные переменные терминала? как решить проблему для индикатора?

https://www.mql5.com/ru/docs/globals

Документация по MQL5: Глобальные переменные терминала
Документация по MQL5: Глобальные переменные терминала
  • www.mql5.com
Глобальные переменные существуют в клиентском терминале 4 недели с момента последнего обращения, после этого автоматически уничтожаются. Обращением к глобальной переменной считается не только установка нового значения, но и чтение значения глобальной переменной.
 

Проблема в общем случае нерешаема, потому что два одинаковых индикатора на одном чарте неразличимы между собой, разве что разным значением параметров. И идентифицировать, к какому индикатору какая глобальная переменная относится, невозможно.

Ситуацию спасло бы наличие некоторой встроенной MQL функции типа long GetUniqueProgId(), которая возвращала бы одно и то же уникальное значение внутри каждого экземпляра эксперта и индикатора при смене параметров, тайфреймов или аккаунта.

Документация по MQL5: Основы языка / Переменные / Глобальные переменные
Документация по MQL5: Основы языка / Переменные / Глобальные переменные
  • www.mql5.com
Глобальные переменные создаются путем размещения их объявлений вне описания какой-либо функции. Глобальные переменные определяются на том же уровне, что и функции, т. е. не локальны ни в каком блоке. Область видимости глобальных переменных - вся программа, глобальные переменные доступны из всех функций, определенных в программе...
 
RickD:

Проблема в общем случае нерешаема

Если код деинициализации равен смене таймфрейма, то через любой механизм передачи данных отправить нужные значения другой копии индикатора.

 
fxsaber:

Если код деинициализации равен смене таймфрейма, то через любой механизм передачи данных отправить нужные значения другой копии индикатора.

Чавой?

Пример. На чарте запущено 2 инстанции одного индикатора: А и B. Каждый из них произвел какие-то длительные действия (например загрузил новости с новостного сайта).

Если бы каждая инстанция могла возвращать некий уникальный ID (по аналогии с HINSTANCE в Виндовс), который бы не менялся при смене таймфрейма, то выгрузка и загрузка данных при деинициализации проблем бы не составила. Сейчас же кто есть кто - непонятно. Отличия толко в символе, таймфрейме и значениях параметров.

Еще раз повторю свою мнение, что несохранение глобальных переменных при переинициализации индикатора есть неправильное решение от разработчиков.

Правильно было бы сохранять их и дать возможность занулять их самому программисту по необходимости в OnDeinit в зависимости от причины деинициализации.

 
RickD:

...Если бы каждая инстанция могла возвращать некий уникальный ID (по аналогии с HINSTANCE в Виндовс), который бы не менялся при смене таймфрейма...

1) каждый индикатор имеет параметры, если параметры одинаковы - индикатор делает одно и тоже
2) при старте, собираем все параметры в стринг, считаем crc32, устанавливаем shortname = crc32.
3) вот вам постоянный, уникальный айди.

 
Andrey Kornishkin:

Приветствую всех! 

Есть индикатор.

 

В нем при смене ТФ сбрасываются переменные:


Пробовал переделать согласно примеру:


Вариант 1. Не инициализированная нигде:


Вариант 2. Значение внешней переменной, присвоенное на глобальном уровне:


Вариант 3. Глобальные переменные без инициализации, но инициализированы в ините:


В примере все работает. В моем случае нет. Подскажите пожалуйста где искать причину?

Вы какое отношение к Виталию Горбунову имеете? 

Причина обращения: