Позволяет ли mql5 написать индикатор, рисующий графики в разных окнах или получать доступ к буферам индикаторов в других окнах?

 

Позволяет ли mql5 написать индикатор, рисующий графики в разных окнах или получать доступ к буферам индикаторов в других окнах?


Во-первых, хочется иметь индикатор, способный рисовать графики одновременно в разных окнах. В идеале — одновременно в indicator_chart_window и indicator_separate_window, хотя вполне устоит и в нескольких indicator_separate_window.


Зачем нужно.

1) Для экономии времени. Проще кинуть один индикатор на график и настроить параметры, чем десяток индикаторов и настраивать для каждого в отдельности на самом деле одинаковые для всех парметры.

2) Для экономии вычислительных ресурсов. Для всей группы индикаторов есть информация, общая для всех. Можно было бы создать несколько общих дополнительных буферов, где эта информация могла бы храниться и повторно использоваться.


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

Документация по MQL5: Операции с графиками / ChartIndicatorAdd
Документация по MQL5: Операции с графиками / ChartIndicatorAdd
  • www.mql5.com
Операции с графиками / ChartIndicatorAdd - Документация по MQL5
 

Первый вопрос решается с помощью  IndicatorAdd.

А второй - с помощью экономичных вспомогательных индикаторов, вызываемых из других индикаторов. По идее, расчет "базового" индикатора будет производиться только один раз.

 
komposter:

Первый вопрос решается с помощью  IndicatorAdd.

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

int OnInit()
{
  hdl = iCustom(NULL,0,"IndicSlave", prm1,p2m2,prm3);
  if( hdl == INVALID_HANDLE )
    return(-1);
  bool f = ChartIndicatorAdd(0,(int)ChartGetInteger(0,CHART_WINDOWS_TOTAL),hdl );
  if(!f)
    return(-1);
  win = (int)ChartGetInteger(0,CHART_WINDOWS_TOTAL)-1;
  return(0);
}
void OnDeinit(const int reason)
{
  if( win ) ChartIndicatorDelete(0,win1,ChartIndicatorName(0,win,0));
  if( hdl != INVALID_HANDLE ) IndicatorRelease( hdl );
}
При изменении параметров основного индикатора видно, что дополнительный индикатор нормально уничтожается и создается с новыми параметрами. А при удалении основного индикатора дополнительный не удаляется с графика.
 

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

Вопрос: Есть ли какая-нибудь иная возможность идентификации индикатора кроме ChartIndicatorName?

Хочется иметь какой-нибудь уникальный идентификатор, который бы не отображался в имени индикатора на графике

 

Отвечаю сам себе. Да, возможность есть. Через IndicatorParameters.


Но возникает другой вопрос. Для вызова IndicatorParameters требуется хэндл индикатора, который можно получить через ChartIndicatorGet. Нужно ли освобождать этот хэндл через IndicatorRelease?

Документация по MQL5: Доступ к таймсериям и индикаторам / IndicatorParameters
Документация по MQL5: Доступ к таймсериям и индикаторам / IndicatorParameters
  • www.mql5.com
Доступ к таймсериям и индикаторам / IndicatorParameters - Документация по MQL5
 
Еще немного поговорю сам с собой. Освобождать в моем случае обязательно.
 

Замечательная беседа получилась ;)

Спасибо, что делитесь этой информацией с публикой, а не оставляете у себя в закромах. 

 
alxm:
Еще немного поговорю сам с собой. Освобождать в моем случае обязательно.

Поддерживаю предыдущего оратора.  Когда-то шибко ковырялся в этой теме, но тогда ещё не було ни ChartIndicatorGet, ни ChartIndicatorName, ни IndicatorParameters.. и много чего другого ещё не было.  Сейчас эта тема не особо  актуальна, но скоро возможно снова займусь написанием всяких сервисных индикаторов, и тогда эта ветка будет мне весьма полезной. 

Так что спасибо Вам. И продолжайте, пожалуйста.

 

Если есть желающие обсудить эту тему, предлагаю придумать название технологии, чтобы было коротко и понятно. Возможно, уже кто-то придумал, но я не нашел. Пока использую рабочее название «Мультииндикатор», хотя это название скорее подходит для индикатора, сочетающего в себе несколько индикаторов. По факту же это один индикатор, использующий для отображения буферов дополнительные (подчиненные) индикаторы в дополнительных окнах, т. к. линии индикатора могут иметь разный масштаб и зачастую хочется видеть их именно в оригинальном масштабе. Собираюсь использовать для мультивалютного анализа, хотя технология подойдет и в случае некоторых индикаторов с тяжелыми вычислениями. Можно было бы использовать отдельные индикаторы для каждой линии, но мой индикатор имеет следующие преимущества:

1) На график помещается только основной индикатор. Остальные подокна создаются автоматически.

2) Более эффективные вычисления. Например, при решении СЛАУ конечным результатом является вектор, значения которого нужно разнести по разным буферам. Дублировать такие вычисления в десятке индикаторов слишком накладно. Мой индикатор произведет их только один раз, а требования к объему памяти возрастают всего лишь в два раза.

3) Удобно отлаживать и дорабатывать связанные одной ТС индикаторы, достаточно перекомпилирвать всего один файл, чтобы увидеть результат сразу во всех подокнах.


Правильно было бы назвать индикатор мультиподоконным, но звучит еще более дико, чем слово "подокно".

 

В виду интереса к теме, опишу результаты своих поисков более подробно.

Начну с проблемы определения свой-чужой. «Свои» в данном случае — индикаторы, работающие в одной связке: один ведущий и несколько ведомых или в другой терминологии один основной и несколько дополнительных.

Как я уже сказал выше, нет смысла запоминать индекс подокна своих индикаторов. Поэтому нужно иметь возможность динамически находить свои индикаторы. Нужна какая-то метка, уникальная в пределах текущего окна.

Первое, что приходит в голову — метка в ChartIndicatorName. Недостаток подхода в том, что отображать эту метку в имени индикатора может быть нежелательным.

Метку можно хранить в параметрах. Но для вызова IndicatorParameters требуется хэндл, получаемый через ChartIndicatorGet. Как программиста, меня напрягают параметры ChartIndicatorGet( chart_id, sub_window, indicator_shortname ). Вопрос: если в одном подокне окажутся два индикатора с одинаковым именем, то хэндл какого из индикаторов будет возвращен из ChartIndicatorGet? Я понимаю, что такая ситуация маловероятна, но программист должен быть готов к любому сценарию. Поэтому я решил использовать метку в имени индикатора. Если есть идеи получше, буду рад услышать.

Теперь расскажу, зачем освобождать хэндл индикатора, и как его освобождать.

При инициализации основного индикатора я создаю дополнительный индикатор и размещаю его в отдельном подокне. При инициализации дополнительного я нахожу основной индикатор и получаю его хэндл для последующего чтения его буферов. Освобождение хэндлов сначала сделал при деинициализации. Но возникла проблема. При удалении основного индикатора с графика его событие OnDeinit не наступает, пока не будут освобождены все связанные с ним хэндлы. А удаление хэндла основного индикатора, сохраненного в подчиненном произойдет только при наступлении OnDeinit для последнего, а оно запускается при удалении его хэндла из основного индикатора в OnDeinit. Замкнутый круг. Проблему решил через событие CHARTEVENT_CHART_CHANGE в подчиненном индикаторе. Если выяснится, что основной индикатор был удален с графика, его хэндл освобождается, после чего срабатывает цепочка событий OnDeinit.

void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)
{
  //изменились какие-то свойства графика
  if( id==CHARTEVENT_CHART_CHANGE )
  { //если основной индикатор инициализирован
    if( mstrHdl != INVALID_HANDLE )
      //но был удален или перемещен в другое подокно
      if( ChartIndicatorName(0,mstrWin,mstrInd) != mstrName )
      { //найти его
        bool fOk=0;
        for( int w=(int)ChartGetInteger(0,CHART_WINDOWS_TOTAL)-1; w>=0 && !fOk; w--)
          for( int i=ChartIndicatorsTotal(0,w)-1; i>=0 && !fOk; i--)
            if( ChartIndicatorName(0,w,i) == mstrName )
            { mstrWin = w; mstrInd = i; fOk=1; }
        //если не найден, удалить хэндл
        if(!fOk)
        { IndicatorRelease( mstrHdl );
          mstrHdl = INVALID_HANDLE;
        }
    }
  }
}
 

Интересный код по теме 

On the Strategy Tester, I need to read the values of one Indicator inside another Indicator, both loaded within an Expert Advisor
On the Strategy Tester, I need to read the values of one Indicator inside another Indicator, both loaded within an Expert Advisor
  • www.mql5.com
Hello again folks. I have one Expert Advisor (EA) which loads 2 indicators...