Скачать MetaTrader 5

Принудительная остановка индикаторов и скриптов

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Привык пользоваться стандартной библиотекой? В MQL5 она тоже есть!
Sergey Eremin
4362
Sergey Eremin 2015.08.15 12:53 
Подскажите, пожалуйста, есть ли возможность принудительного прекращения работы индикаторов и скриптов из самих себя?
Интересует нечто вроде ExpertRemove() для экспертов.

Для индикаторов, пожалуй, можно даже иначе вопрос поставить. Есть ли программный способ узнать короткое имя? Что-то вроде "IndicatorGetString(INDICATOR_SHORTNAME)"?

А то есть функция ChartIndicatorDelete(), но для работы с ней нужно знать короткое имя индикатора. Это, конечно, не проблема в частном случае - можно захардкодить. Но в общем случае (универсальный рецепт) уже не очень применимо.

Про жёсткие методы вроде вызова деления на ноль пока не хочется думать.
Vitalie Postolache
12135
Vitalie Postolache 2015.08.15 14:20  

Скрипт сам выгружается, если не зациклен, а если зациклен, то никто не мешает сделать на нужном условии выход из цикла.

Что касается короткого имени, то хардкодить ничего не надо, надо читать справку:

string name=MQLInfoString(MQL_PROGRAM_NAME);
Sergey Eremin
4362
Sergey Eremin 2015.08.15 14:53  
Vitalie Postolache:

Скрипт сам выгружается, если не зациклен, а если зациклен, то никто не мешает сделать на нужном условии выход из цикла.

Что касается короткого имени, то хардкодить ничего не надо, надо читать справку:

Эхх! Ну вот, обозвали не читающим справку... а может всё же Вы поспешили с этими словами? Всего, конечно, из неё и не знаю (отсюда и вопросы этой ветки), но что б прямо не читать...


Повторюсь: для ChartIndicatorDelete нужно короткое имя индикатора. Это чётко сказано в справке, которую, как Вы считаете, я не читаю.

MQLInfoString(MQL_PROGRAM_NAME); не годится, т.к. возвращает не короткое имя индикатора, а имя запущенной программы.

Например, для MACD(12, 26, 9):

MQLInfoString(MQL_PROGRAM_NAME) = MACD

Короткое имя (оцените иронию, оно длиннее имени запущенной программы) = MACD(12,26,9).

Они будут совпадать только если короткое имя никак явно не задано в коде: " Если короткое наименование индикатора не задается явным образом, то при компиляции в нем указывается имя файла с исходным кодом индикатора.". Но надеяться на это, по понятным причинам, нельзя.


Раскрою карты: пишу статью про утверждения (assertion). Как, надеюсь, всем известно одна из функций механизма утверждений - завершать работу программы, если выражение, переданное в утверждение, оказывается ложным. Так что ни слова о том, что скрипт сам выгружается, ни полное имя запущенной программы для индикатора не очень помогают в моей задумке. Пока макрос у меня получается таким:

#define DEBUG

#ifdef DEBUG  
   #define assert(condition, message) \
      if(!(condition)) \
        { \
         string fullMessage= \
                            #condition+", " \
                            +__FILE__+", " \
                            +__FUNCSIG__+", " \
                            +"line: "+(string)__LINE__ \
                            +(message=="" ? "" : ", "+message); \
         \
         string title="Assertion failed!"; \
         \
         if(MQLInfoInteger(MQL_PROGRAM_TYPE)==PROGRAM_EXPERT) \
           { \
            if(MessageBox(fullMessage+"\r\n\r\n"+"Continue?",title,MB_ICONWARNING|MB_YESNO)==IDNO) \
              { \
               ExpertRemove(); \
              } \
           } else { \
            Alert(title+" "+fullMessage); \
           } \
        }
#else 
   #define assert(condition, message) ;
#endif 

Т.е. для индикаторов и скриптов пока используется Alert, в моей работе мне этого хватает, но для статьи немного уныло, вот и думаю - а есть ли пути сделать правильно и красиво?

Vitalie Postolache
12135
Vitalie Postolache 2015.08.15 17:06  
Sergey Eremin:

Эхх! Ну вот, обозвали не читающим справку... а может всё же Вы поспешили с этими словами? Всего, конечно, из неё и не знаю (отсюда и вопросы этой ветки), но что б прямо не читать...


Повторюсь: для ChartIndicatorDelete нужно короткое имя индикатора. Это чётко сказано в справке, которую, как Вы считаете, я не читаю.

...

Ошибся, виноват, тогда почитайте ещё справку про ChartIndicatorName ;)

А про скрипты так и не понял я, что мешает сделать выход из цикла по требованию, если скрипт зациклен?

Sergey Eremin
4362
Sergey Eremin 2015.08.15 17:21  
Vitalie Postolache:

Ошибся, виноват, тогда почитайте ещё справку про ChartIndicatorName ;)

А про скрипты так и не понял я, что мешает сделать выход из цикла по требованию, если скрипт зациклен?

И про это я читал, конечно :)

Думаю, что не подходит и ChartIndicatorName мне. Для этой функции нужен уже индекс индикатора. А я не знаю его, и не знаю, как его узнать . Хотя может я действительно чего-то не понимаю? Тогда, пожалуйста, покажите, как применить ChartIndicatorName для моей задачи - получить своё же короткое имя изнутри абстрактного индикатора.

Только, пожалуйста, не посылайте к ChartIndicatorsTotal и перебору всех индексов в ChartIndicatorName, я ведь не буду знать где остановиться (фактически, мне тогда уже нужно знать короткое имя у моего индикатора) :)


Насчёт выхода из цикла. Вы наверно не совсем поняли мою задачу. Моя задача реализовать механизм утверждений (если тема не знакома, то настоятельно рекомендую, к примеру запрос assert C++ в гугле). Попробую кратко объяснить то, что мне нужно: представим, что некий скрипт состоит из функций А, Б, В, которые поочерёдно выполняются. И в А я проверяю некое условие (к примеру, что x > y). Если оно не выполняется, то мне нужно выдать сообщение и прервать выполнение программы. И всё это сделать в виде макроса, унифицировать стало быть.

Нельзя городить проверки состояний, нельзя выходить из какого-то цикла, нужно просто немедленно (ну или максимально близко к этому) выдать сообщение и закончить выполнение программы. Нет смысла доходить ни до конца функции А, ни тем более доходить до Б и В - программа работает неправильно, она сказала в каком конкретно месте и на этом она должна закончить свою работу. Всё это не должно добавлять в код никаких return'ов, break'ов, только строчку вида assert(x > y, "my message") в том месте, где мне нужно проверить, не стал ли x меньше или равен y.

Mikhail Filimonov
5931
Mikhail Filimonov 2015.08.16 01:29  
Sergey Eremin:
Подскажите, пожалуйста, есть ли возможность принудительного прекращения работы индикаторов и скриптов из самих себя?
Интересует нечто вроде ExpertRemove() для экспертов.

Для индикаторов, пожалуй, можно даже иначе вопрос поставить. Есть ли программный способ узнать короткое имя? Что-то вроде "IndicatorGetString(INDICATOR_SHORTNAME)"?

А то есть функция ChartIndicatorDelete(), но для работы с ней нужно знать короткое имя индикатора. Это, конечно, не проблема в частном случае - можно захардкодить. Но в общем случае (универсальный рецепт) уже не очень применимо.

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

Есть очень простой способ:

Объявляем глобальную переменную н-р: stop_trading;

При инициализации присваиваем ей значение false

А в OnTick() пишем:

void OnTick()
{
  if ( stop_trading ) return;

  //You code here.....
}

 А в любом месте кода ( когда Вам нужно остановить работу советника),

присваиваете переменной значение true 

Sergey Eremin
4362
Sergey Eremin 2015.08.16 08:44  
Михаил:

Есть очень простой способ:

Объявляем глобальную переменную н-р: stop_trading;

При инициализации присваиваем ей значение false

А в OnTick() пишем:

 А в любом месте кода ( когда Вам нужно остановить работу советника),

присваиваете переменной значение true 

Спасибо за отклик!

Правда (вот же я капризный, да?) немного не подойдёт для поставленной задачи - реализация утверждений :)

Вот скажем, у меня 100 классов и в каждом по 20 методов, и утверждения находятся во всех из них (да ещё и не по одному на метод). Т.е. потенциально программа может найти в себе ошибку в любом из 2000 методов. Неужели нужно во всех городить работу с одной общей глобальной переменной? По мне так уж лучше вызвать деление на ноль, если нет более изящного выхода.

Опять же, не ясно как организовать принудительный выход из методов всех возможных типов (в макросе прописать return для всех возможных типов данных, возвращаемых методом, включая пользовательские). А если метод А, вызывает метод Б, метод Б вызывает метод В, и в методе В сработало утверждение - как с таким подходом сделать так, чтобы остановился метод В (ладно, могу представить принудительный return), а Б и А не стали выполняться далее?


P.S. пока склоняюсь к алертам для скриптов/индикаторов. Либо пойти жёстко и использовать деление на ноль - по идее концепции утверждений столь радикальный метод остановки приложения не сильно противоречит.

Mikhail Filimonov
5931
Mikhail Filimonov 2015.08.16 14:08  
Sergey Eremin:

Спасибо за отклик!

Правда (вот же я капризный, да?) немного не подойдёт для поставленной задачи - реализация утверждений :)

Вот скажем, у меня 100 классов и в каждом по 20 методов, и утверждения находятся во всех из них (да ещё и не по одному на метод). Т.е. потенциально программа может найти в себе ошибку в любом из 2000 методов. Неужели нужно во всех городить работу с одной общей глобальной переменной? По мне так уж лучше вызвать деление на ноль, если нет более изящного выхода.

Опять же, не ясно как организовать принудительный выход из методов всех возможных типов (в макросе прописать return для всех возможных типов данных, возвращаемых методом, включая пользовательские). А если метод А, вызывает метод Б, метод Б вызывает метод В, и в методе В сработало утверждение - как с таким подходом сделать так, чтобы остановился метод В (ладно, могу представить принудительный return), а Б и А не стали выполняться далее?


P.S. пока склоняюсь к алертам для скриптов/индикаторов. Либо пойти жёстко и использовать деление на ноль - по идее концепции утверждений столь радикальный метод остановки приложения не сильно противоречит.

Сергей, Вы задали вопрос:

Как остановить? Вам ответили.

Причём тут классы и проч....?

Пусть всё работает как работало одно другому совсем не мешает. 

Sergey Eremin
4362
Sergey Eremin 2015.08.16 15:02  
Михаил:

Сергей, Вы задали вопрос:

Как остановить? Вам ответили.

Причём тут классы и проч....?

Пусть всё работает как работало одно другому совсем не мешает. 

Сейчас у меня возникло лёгкое ощущение, что Вы не ознакомились с веткой перед ответом, либо сделали это недостаточно внимательно (включая моё же первое сообщение, где я говорю, что мне нужно нечто вроде ExpertRemove). Надеюсь оно ложно, но дальнейшее сообщение будет на всякий случай основано именно на этом ощущении.

Строго говоря, я объяснил уже в своём втором сообщении "причём тут классы и проч", сообщив, что моя цель - механизм утверждений. Они и предполагают немедленное, или близко к тому, завершение программы из любого места программы (как пример - один из 2000 методов). На тот момент я предполагал, что читающие ветку понимают о чём я говорю, ну или перед последующими ответами вникнут хотя бы поверхностно в понятие "утверждений", т.е. в мою задачу (наивный, но привык к такому общению). Затем, подумав, что далеко не все пойдут по такому пути сами по себе, в третьем сообщении постарался акцентировать внимание на эту мысль (предлагая ознакомиться, если вещь незнакомая) и даже немного показать, что мне нужно. И вот опять нужно объяснять зачем?

Окей: так нужно для моей задачи - реализация механизма утверждений.

Если уж не обращать внимание на последующие, кроме первого, мои сообщения, и если не смотреть на мою ключевую фразу из первого сообщения про "нечто вроде ExpertRemove" - то позвольте задать контр-вопрос в духе "причём тут классы и проч...?": какое отношение OnTick имеет к индикаторам/скриптам? ;)

Увы, раз Ваше решение не годится для моей задачи, то и "Пусть всё работает как работало одно другому совсем не мешает" не будет верным для меня. Для Ваших целей да, возможно, для моих - нет. Я ни в коем случае не умаляю корректности решения (хотя глобальная переменная меня немножко коробит), но оно не годится для моей задачи.


Надеюсь, не обидел резкостью ответа. И надеюсь уж теперь недопонимание будет устранено. Если нет, то я могу попробовать прямо тут попытаться объяснить, что такое утверждения и почему там так сильно желательно прибивать программу максимально быстро. Но это уводит от поставленной в первом же сообщении проблемы - принудительно завершить индикатор или скрипт (не эксперт, с ним понятно) из самого себя наподобие ExpertRemove. Именно завершить, а не сделать так, чтобы перестал что-то считать. Да, мой косяк, что я вместо "завершить" в первом сообщении применил слово "остановить", но неужели поведение ExpertRemove не приводит к мыслям о нужном поведении?


Кстати, отдельное спасибо evillive за его ответы.

Stanislav Korotky
17925
Stanislav Korotky 2015.08.16 15:13  
Sergey Eremin:

Кстати, отдельное спасибо evillive за его ответы.

В свое время я исследовал данный вопрос с ассеротом (после того как МК напрочь отмели идею о том, что в нормальном ООП языке должен быть механизм исключений).

Так вот единственный выход - действительно принудительно вызвать ошибку выполнения.

void Halt(bool Condition, string Message)
{
  int x = 0;
  if(Condition)
  {
    Print(Message);
    x++;
    x--;
    x = 1 / x;
  }
}
Или MathSqrt(-1); например.
Sergey Eremin
4362
Sergey Eremin 2015.08.16 15:17  
Stanislav Korotky:

В свое время я исследовал данный вопрос с ассеротом (после того как МК напрочь отмели идею о том, что в нормальном ООП языке должен быть механизм исключений).

Так вот единственный выход - действительно принудительно вызвать ошибку выполнения.

Спасибо за ответ и понимание! Если я не ошибаюсь, то когда-то в одной из статей я видел Ваше решение. Если так, то, надеюсь, Вы не будете сильно возражать, если я в своей статье про утверждения сделаю ссылку на Вас, как на пример применения оных (и если не будете против, то очень прошу скинуть сюда или в личку ссылку на ту статью)?


Ну и как человеку, понимающему мою задачу, отдельная просьба - оцените сам мой макрос (третье сообщение ветки), как оно Вам? Может что-то режет глаз?

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