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

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Andrey Kornishkin
9930
Andrey Kornishkin  

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

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

//+------------------------------------------------------------------+
//|                                                  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);
  }


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

Artyom Trishkin
Модератор
56584
Artyom Trishkin  
Andrey Kornishkin:

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

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

 

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


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


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


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

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

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

Sergey Kolemanov
1020
Sergey Kolemanov  
Andrey Kornishkin:

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

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

vebster005
457
vebster005  
Sergey Kolemanov:

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

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

Sergey Kolemanov
1020
Sergey Kolemanov  
vebster005:

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

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

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

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

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

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

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

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

RickD
1225
RickD  
fxsaber:

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

Чавой?

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

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

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

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

Taras Slobodyanik
38275
Taras Slobodyanik  
RickD:

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

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

Алексей Тарабанов
10044
Алексей Тарабанов  
Andrey Kornishkin:

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

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

 

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


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


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


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


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


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

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

12
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий