CopyBuffer и использование в индикаторе данных индикатора с другого таймфрейма

 

вопрос в первую очередь к поддержке метаквотов 

но может ктото уже нашел решение этой проблемы в рамках существующих инструментов.

понадобилось использовать в индикаторе другой индикатор с другого таймфрейма того же инструмента

чтото типа того что используется в этом примере из справки по mql5

https://www.mql5.com/ru/docs/series/copybuffer

но только вместо

ma_handle=iMA(Symbol(),0,period,shift,smootMode,price); 

я написал 

ma_handle=iMA(Symbol(),PERIOD_M5,period,shift,smootMode,price);

после этого данный индикатор, текст которого представлю ниже, перестал рисоваться при инициализации, а только после прихода очередного тика, или после внесения каких либо изменений в окно графика (например добавления другого индикатора). то есть только после повторного вызова функции OnCalculate. первый вызов функции натыкается на то что BarsCalculated и CopyBuffer выдают ошибки о неготовности данных (4806). при этом ошибка не исчезает даже если я ставлю проверку BarsCalculated в бесконечный цикл - то есть со временем данные не становятся готовыми (Sleep как известно в индикаторе нельзя использовать). второй же вызов функции OnCalculate приводит к положительному результату.

все вышеописанное приводит к тому что индикатор не рисуется в оффлайне. это очень неудобно.


итого вопрос. как данную проблему можно решить.  самое очевидно что приходит в голову инициировать както перезапуск функции OnCalculate. но я не нашел возможно ли это сделать. возвращать 0 из OnCalculate не помогает.

какие будут идеи. 


текст кода (немного измененный стандартный пример отсюда https://www.mql5.com/ru/docs/series/copybuffer) 

//+------------------------------------------------------------------+
//|                                              TestCopyBuffer3.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
 
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//---- plot MA
#property indicator_label1  "MA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- input parameters
input bool               AsSeries=true;
input int                period=15;
input ENUM_MA_METHOD     smootMode=MODE_EMA;
input ENUM_APPLIED_PRICE price=PRICE_CLOSE;
input int                shift=0;
//--- indicator buffers
double                   MABuffer[];
int                      ma_handle;
int key=0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,MABuffer,INDICATOR_DATA);
   Print("Параметр AsSeries = ",AsSeries);
   Print("Индикаторный буфер после SetIndexBuffer() является таймсерией = ",
         ArrayGetAsSeries(MABuffer));
//--- set short indicator name
   IndicatorSetString(INDICATOR_SHORTNAME,"MA("+period+")"+AsSeries);
//--- set AsSeries(dependes from input parameter)
   ArraySetAsSeries(MABuffer,AsSeries);
   Print("Индикаторный буфер после ArraySetAsSeries(MABuffer,true); является таймсерией = ",
         ArrayGetAsSeries(MABuffer));
//---
   ma_handle=iMA(Symbol(),PERIOD_M5,period,shift,smootMode,price);
   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[])
  {
  Print("OnCalculate");
//--- check if all data calculated
   
   if(BarsCalculated(ma_handle)<rates_total) { Print("BarsCalculated ", GetLastError()); return(0);}
//--- we can copy not all data
   int to_copy;
   if(prev_calculated>rates_total || prev_calculated<=0) to_copy=rates_total;
   else
     {
      to_copy=rates_total-prev_calculated;
      //--- last value is always copied
      to_copy++;
     }
//--- try to copy
   if(CopyBuffer(ma_handle,0,0,to_copy,MABuffer)<=0) { Print("CopyBuffer ", GetLastError()); return(0);}
//--- return value of prev_calculated for next call
   Print("OnCalculate end");
   return(rates_total);
  }
//+------------------------------------------------------------------+

Документация по MQL5: Доступ к таймсериям и индикаторам / CopyBuffer
Документация по MQL5: Доступ к таймсериям и индикаторам / CopyBuffer
  • www.mql5.com
Доступ к таймсериям и индикаторам / CopyBuffer - справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 

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

Sleep()

то проверку готовности нужно проводить на следующем тике. Если это выходные и тиков нет - то простой выход - вручную правый клик на графике и "Обновить".

 
Karputov Vladimir:

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

то проверку готовности нужно проводить на следующем тике. Если это выходные и тиков нет - то простой выход - вручную правый клик на графике и "Обновить".

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

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

 
viktor lubimov:

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

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

Я читал и указал на необходимость проверки готовности данных: Организация доступа к данным. И ещё раз: в индикаторе не работает Sleep(), так как задержки в индикаторе могут вызвать остановку терминала.
 
viktor lubimov:


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

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

поправьте если я не правильно понял.

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

 
viktor lubimov:

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

поправьте если я не правильно понял.

2) Тогда вопрос: "Почему же индикатор для данного таймфрейма считается сразу а для другого нет. Это очень неудобно. Можно ли это как нибудь исправить или обойти?"

  1. Здесь ответ в самом вопросе.
  2. Только проверять готовность данных.
 
Karputov Vladimir:
  1. Здесь ответ в самом вопросе.
  2. Только проверять готовность данных.

проверять  то я могу. но как мне ждать готовности если они не готовы. вопрос то изначально состоял именно в этом. ждать следующего тика не устраивает так как его нет.

 
viktor lubimov:

ждать следующего тика не устраивает так как его нет.

Завести таймер и эмулировать OnCalculate
 
Комбинатор:
Завести таймер и эмулировать OnCalculate
такая мысль одна из первых приходила. но я не знаю как эмулировать событие OnCalculate. не подскажете?
 
viktor lubimov:
такая мысль одна из первых приходила. но я не знаю как эмулировать событие OnCalculate. не подскажете?

Вот здесь есть пример: Рецепты MQL5 - Разработка мультивалютного индикатора волатильности на MQL5 >>>

 
как не странно, но перезапуск OnCalculate вместе с ChartRedraw() не помогает. OnCalculate  в цикле выполняется но данные для отрисовки не появляеются. а вот добавление на график какого либо другого индикатора приводит к прорисовке и этого. очень странно. я уже не понимаю как это работает.