2 вопроса МТ5 - страница 4

 
Только вот, если оставить индикаторы на графиках, то после перезагрузки терминала они слетают...
 
Сергей Таболин:

Как этот мусор чистить?

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

  if(rates_total - prev_calculated > 1)
   {
    ArrayInitialize(bufOpen, EMPTY_VALUE);
    ArrayInitialize(bufHigh, EMPTY_VALUE);
    ArrayInitialize(bufLow, EMPTY_VALUE);
    ArrayInitialize(bufClose, EMPTY_VALUE);
    ArrayInitialize(arr, 0);
// и дальше ...
 
Сергей Таболин:
Только вот, если оставить индикаторы на графиках, то после перезагрузки терминала они слетают...

Ну поставьте условие, если данных по какому-то символу нет, то return(0); вместо return(rates_total); и тогда при следующем тике и повторном обращении к данным символа они будут доступны.

 
Alexey Viktorov:

Ну поставьте условие, если данных по какому-то символу нет, то return(0); вместо return(rates_total); и тогда при следующем тике и повторном обращении к данным символа они будут доступны.

Спасибо.

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

 
Сергей Таболин:

Спасибо.

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

Ждёт первый тик. Без него не запустится. Нужно обновить график.

 
Artyom Trishkin:

Ждёт первый тик. Без него не запустится. Нужно обновить график.

Да нет.

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

Во-вторых, индикатор ошибку не выдаёт.

2020.01.14 14:37:49.226 ICTMP_2.01 (EURUSD,H8)  "EURUSD" "EURNZD" "EURJPY" "EURGBP" "EURCHF" "EURCAD" "EURAUD" "EURTRY"
2020.01.14 14:37:49.227 ICTMP_2.01 (EURUSD,H8)  ======= EURUSD INIT_SUCCEEDED ======= bars_calc = 9936
2020.01.14 14:37:49.227 ICTMP_2.01 (EURUSD,H8)  EURUSD ~~~ Start OnCalculate ~~~ Try 10
2020.01.14 14:37:49.900 ICTMP_2.01 (EURUSD,H8)  EURUSD / EURNZD [1] ~~~ (доступно 9978) bars_calc = 9936
2020.01.14 14:37:49.900 ICTMP_2.01 (EURUSD,H8)  EURUSD / EURJPY [2] ~~~ (доступно 10095) bars_calc = 9936
2020.01.14 14:37:49.900 ICTMP_2.01 (EURUSD,H8)  EURUSD / EURGBP [3] ~~~ (доступно 13971) bars_calc = 9936
2020.01.14 14:37:49.900 ICTMP_2.01 (EURUSD,H8)  EURUSD / EURCHF [4] ~~~ (доступно 9993) bars_calc = 9936
2020.01.14 14:37:49.900 ICTMP_2.01 (EURUSD,H8)  EURUSD / EURCAD [5] ~~~ (доступно 10093) bars_calc = 9936
2020.01.14 14:37:49.900 ICTMP_2.01 (EURUSD,H8)  EURUSD / EURAUD [6] ~~~ (доступно 10095) bars_calc = 9936
2020.01.14 14:37:49.900 ICTMP_2.01 (EURUSD,H8)  EURUSD / EURTRY [7] ~~~ (доступно 7137) bars_calc = 7137


Покурил, снял индикатор с графика, опять накинул его - работает...

2020.01.14 14:37:49.226 ICTMP_2.01 (EURUSD,H8)  "EURUSD" "EURNZD" "EURJPY" "EURGBP" "EURCHF" "EURCAD" "EURAUD" "EURTRY"
2020.01.14 14:37:49.227 ICTMP_2.01 (EURUSD,H8)  ======= EURUSD INIT_SUCCEEDED ======= bars_calc = 9936
2020.01.14 14:37:49.227 ICTMP_2.01 (EURUSD,H8)  EURUSD ~~~ Start OnCalculate ~~~ Try 10
2020.01.14 14:37:49.900 ICTMP_2.01 (EURUSD,H8)  EURUSD / EURNZD [1] ~~~ (доступно 9978) bars_calc = 9936
2020.01.14 14:37:49.900 ICTMP_2.01 (EURUSD,H8)  EURUSD / EURJPY [2] ~~~ (доступно 10095) bars_calc = 9936
2020.01.14 14:37:49.900 ICTMP_2.01 (EURUSD,H8)  EURUSD / EURGBP [3] ~~~ (доступно 13971) bars_calc = 9936
2020.01.14 14:37:49.900 ICTMP_2.01 (EURUSD,H8)  EURUSD / EURCHF [4] ~~~ (доступно 9993) bars_calc = 9936
2020.01.14 14:37:49.900 ICTMP_2.01 (EURUSD,H8)  EURUSD / EURCAD [5] ~~~ (доступно 10093) bars_calc = 9936
2020.01.14 14:37:49.900 ICTMP_2.01 (EURUSD,H8)  EURUSD / EURAUD [6] ~~~ (доступно 10095) bars_calc = 9936
2020.01.14 14:37:49.900 ICTMP_2.01 (EURUSD,H8)  EURUSD / EURTRY [7] ~~~ (доступно 7137) bars_calc = 7137
2020.01.14 14:49:05.085 ICTMP_2.01 (EURUSD,H8)  "EURUSD" "EURNZD" "EURJPY" "EURGBP" "EURCHF" "EURCAD" "EURAUD" "EURTRY"
2020.01.14 14:49:05.085 ICTMP_2.01 (EURUSD,H8)  ======= EURUSD INIT_SUCCEEDED ======= bars_calc = 9936
2020.01.14 14:49:05.085 ICTMP_2.01 (EURUSD,H8)  EURUSD ~~~ Start OnCalculate ~~~ Try 10
2020.01.14 14:49:05.550 ICTMP_2.01 (EURUSD,H8)  EURUSD / EURNZD [1] ~~~ (доступно 9978) bars_calc = 9936
2020.01.14 14:49:05.550 ICTMP_2.01 (EURUSD,H8)  EURUSD / EURJPY [2] ~~~ (доступно 10095) bars_calc = 9936
2020.01.14 14:49:05.550 ICTMP_2.01 (EURUSD,H8)  EURUSD / EURGBP [3] ~~~ (доступно 13971) bars_calc = 9936
2020.01.14 14:49:05.550 ICTMP_2.01 (EURUSD,H8)  EURUSD / EURCHF [4] ~~~ (доступно 9993) bars_calc = 9936
2020.01.14 14:49:05.550 ICTMP_2.01 (EURUSD,H8)  EURUSD / EURCAD [5] ~~~ (доступно 10093) bars_calc = 9936
2020.01.14 14:49:05.550 ICTMP_2.01 (EURUSD,H8)  EURUSD / EURAUD [6] ~~~ (доступно 10095) bars_calc = 9936
2020.01.14 14:49:05.550 ICTMP_2.01 (EURUSD,H8)  EURUSD / EURTRY [7] ~~~ (доступно 7137) bars_calc = 7137
 
Сергей Таболин:

Да нет.

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

Во-вторых, индикатор ошибку не выдаёт.


Покурил, снял индикатор с графика, опять накинул его - работает...

Тут вот какое дело:

  1. у нас есть символ, на котором установлен индикатор. У этого символа есть его количество баров. (например bars_current, оно равно rates_total)
  2. у нас есть символ, по которому рассчитывается индикатор. У этого символа есть его количество баров. (например bars_symb)
  3. Если мы берём данные с двух символов, то для неродного символа мы их копируем при помощи, например, CopyBuffer(), ну или каким-то иным способом заполняем вспомогательный буфер, хранящий расчёты с неродного символа.
  4. Индикатор может отобразить только то количество данных, которые доступны на текущем символе (на том символе, на котором запущен индикатор). Соответственно, нам нужно брать для расчёта только то количество баров, которое мы в состоянии безошибочно отображать - т.е., минимальное количество баров, доступных по обоим символам:
    int count=fmin(rates_total,bars_symb)
  5. При копировании данных в буфер нужно использовать значение count - это то количество баров, которое однозначно возможно скопировать при удовлетворительной для расчёта доступности данных.
  6. Если скопировано количество баров, не равное count - то выполнять return(0) - это даст возможность индикатору дождаться следующего тика (при этом подкачка истории уже запущена автоматически).

В общем, поразбирайтесь в примере расчёта индекса:

Performance_Index
Performance_Index
  • www.mql5.com
Стоит учитывать, что для корректного отображения индикатора, символ, указанный в настройках, должен существовать на сервере, и по нему должна иметься история в требуемом количестве. Если истории по символу не достаточно, то индикатор не будет отображаться до тех пор, пока требуемая история не подгрузится с сервера.
 
Artyom Trishkin:

Тут вот какое дело:

  1. у нас есть символ, на котором установлен индикатор. У этого символа есть его количество баров. (например bars_current, оно равно rates_total)
  2. у нас есть символ, по которому рассчитывается индикатор. У этого символа есть его количество баров. (например bars_symb)
  3. Если мы берём данные с двух символов, то для неродного символа мы их копируем при помощи, например, CopyBuffer(), ну или каким-то иным способом заполняем вспомогательный буфер, хранящий расчёты с неродного символа.
  4. Индикатор может отобразить только то количество данных, которые доступны на текущем символе (на том символе, на котором запущен индикатор). Соответственно, нам нужно брать для расчёта только то количество баров, которое мы в состоянии безошибочно отображать - т.е., минимальное количество баров, доступных по обоим символам:
    int count=fmin(rates_total,bars_symb)
  5. При копировании данных в буфер нужно использовать значение count - это то количество баров, которое однозначно возможно скопировать при удовлетворительной для расчёта доступности данных.
  6. Если скопировано количество баров, не равное count - то выполнять return(0) - это даст возможность индикатору дождаться следующего тика (при этом подкачка истории уже запущена автоматически).

В общем, поразбирайтесь в примере расчёта индекса:

Я только ещё хочу разобраться в написании индикаторов, поэтому он написан "не так". Не так, как в примерах и в других индикаторах. Но об этом я хотел спросить несколько позже.

А пока, всё Вами сказанное я понимаю. Наверняка реализовано у меня не правильно, топорно, но оно работает. Проблема сейчас именно с перезапуском терминала.

В общем, вот распечатка после последнего перезапуска

MF      0       15:37:23.840    ICTMP_2.01 (NZDUSD,H8)  "NZDUSD" "GBPNZD" "EURNZD" "AUDNZD" "NZDJPY"
OS      0       15:37:23.840    ICTMP_2.01 (NZDUSD,H8)  ======= NZDUSD INIT_SUCCEEDED ======= bars_calc = 3343
HE      0       15:37:23.840    ICTMP_2.01 (NZDUSD,H8)  NZDUSD ~~~ Start OnCalculate ~~~ Try 1
IK      0       15:37:24.339    ICTMP_2.01 (NZDUSD,H8)  NZDUSD / 1 / GBPNZD [1] ~~~ (доступно 7197) bars_calc = 3343
LN      0       15:37:24.339    ICTMP_2.01 (NZDUSD,H8)  NZDUSD Не удалось получить количество баров из EURNZD
KP      0       15:37:24.353    ICTMP_2.01 (NZDUSD,H8)  NZDUSD ~~~ Start OnCalculate ~~~ Try 2
NO      0       15:37:24.735    ICTMP_2.01 (NZDUSD,H8)  NZDUSD / 2 / GBPNZD [1] ~~~ (доступно 7197) bars_calc = 3343
QQ      0       15:37:24.735    ICTMP_2.01 (NZDUSD,H8)  NZDUSD / 2 / EURNZD [2] ~~~ (доступно 9978) bars_calc = 3343
DE      0       15:37:24.735    ICTMP_2.01 (NZDUSD,H8)  NZDUSD / 2 / AUDNZD [3] ~~~ (доступно 4959) bars_calc = 3343
OD      0       15:37:24.735    ICTMP_2.01 (NZDUSD,H8)  NZDUSD / 2 / NZDJPY [4] ~~~ (доступно 10007) bars_calc = 3343
LK      0       15:37:24.746    ICTMP_2.01 (NZDUSD,H8)  NZDUSD Начальный расчёт индикатора.
PQ      0       15:37:24.755    ICTMP_2.01 (NZDUSD,H8)  NZDUSD Начальный расчёт индикатора завершён.
NJ      0       15:37:24.755    ICTMP_2.01 (NZDUSD,H8)  NZDUSD Обработка новых данных.
EO      0       15:37:24.755    ICTMP_2.01 (NZDUSD,H8)  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Как видно, все бары на каждом инструменте получены, для расчёта (bars_calc) выбрано наименьшее количество. Начальный расчёт успешно завершён и тут индикатор зависает. Хочу подчеркнуть - зависает не на всех графиках (из 4-х завис на одном) и не всегда. Вот только что перегрузил терминал - на всех 4-х графиках индикатор нормально запустился...

 

Вот первый сегодня запуск терминала

Из-за чего могут появляться такие, извините, "сопли"?

Я думаю, где-то в построении индикатора прокол. Чуть позже выложу схему построения. Ну и будут вопросы. Куда ж без них? )))))))

 

Уважаемые, у меня уже совсем лыжи не едут... (((

Решил я тут маленько ускорить синхронизацию. Подправил чуток.

            Print(Symbol()," ~~~ Start OnCalculate ~~~ Try ",++it);
            
            ArrayResize(chID,ArraySize(symbols_name));
            
            for(int n = 0, c = 0; n < ArraySize(symbols_name); n++)
            {
               if(symbols_name[n] != Symbol()) chID[c++] = myChart.Open(symbols_name[n],Period());
               Sleep(150);
            }
            
            for(int n = 1; n < ArraySize(symbols_name); n++)
            {
               if(symbols_name[n] == Symbol()) continue;
               
               int bc = Bars(symbols_name[n],Period());
               if(bc <= 0)
               {
                  //--- видимо, данные по символу не синхронизированы с данными на сервере
                  bool synchronized = false;
                  //--- счетчик цикла
                  int attempts = 0;
                  // сделаем x попыток дождаться синхронизации
                  while(attempts < init_try)
                  {
                     bc = Bars(symbols_name[n],Period());
                     Sleep(100);
                     if(SeriesInfoInteger(symbols_name[n],PERIOD_M1,SERIES_SYNCHRONIZED))
                     {
                        //--- есть синхронизация, выходим
                        synchronized = true;
                        break;
                     }
                     //--- увеличим счетчик
                     attempts++;
                     //--- подождем 300 миллисекунд до следующей итерации
                     Sleep(300);
                  }
                  //--- вышли из цикла по факту синхронизации
                  if(!synchronized)
                  {
                     Print(Symbol()," Не удалось получить количество баров из ",symbols_name[n]);
                     for(int c = 0; c < ArraySize(chID); c++) ChartClose(chID[c]);
                     if(it >= init_try)
                     {
                        Print(Symbol()," Снимаем индикатор с графика.");
                        ChartIndicatorDelete(0,0,indicatorSHORTNAME);
                     }
                     else return(0);
                  }
               }
               
               if(bars_calc > bc)   bars_calc = bc;
               Print(Symbol()," / ",it," / ",symbols_name[n]," [",n,"] ~~~ (доступно ",bc,") bars_calc = ",bars_calc);
            }
            
            for(int n = 0; n < ArraySize(chID); n++) ChartClose(chID[n]);
            
            if(bars_calc > TerminalInfoInteger(TERMINAL_MAXBARS)) bars_calc = TerminalInfoInteger(TERMINAL_MAXBARS);
            
            if(bars_calc < odds_bars + in_smoothing + 1)
            {
               Print(Symbol()," Баров для рассчётов меньше необходимого");
               if(it >= init_try)
               {
                  Print(Symbol()," Снимаем индикатор с графика.");
                  ChartIndicatorDelete(0,0,indicatorSHORTNAME);
               }
               return(0);
            }
            Print(Symbol()," ~~~ Start OnCalculate ~~~ Try ",++it);
            
            ArrayResize(chID,ArraySize(symbols_name));
            
            for(int n = 0, c = 0; n < ArraySize(symbols_name); n++)
            {
               if(symbols_name[n] != Symbol()) chID[c++] = myChart.Open(symbols_name[n],Period());
               Sleep(150);
            }
            
            for(int n = 1; n < ArraySize(symbols_name); n++)
            {
               if(symbols_name[n] == Symbol()) bars_calc_arr[n] = bars_calc_arr[0];
               
               if(bars_calc_arr[n] > 0) continue;
               
               bars_calc_arr[n] = Bars(symbols_name[n],Period());
               if(bars_calc_arr[n] <= 0)
               {
                  //--- видимо, данные по символу не синхронизированы с данными на сервере
                  bool synchronized = false;
                  //--- счетчик цикла
                  int attempts = 0;
                  // сделаем x попыток дождаться синхронизации
                  while(attempts < init_try)
                  {
                     bars_calc_arr[n] = Bars(symbols_name[n],Period());
                     Sleep(100);
                     if(SeriesInfoInteger(symbols_name[n],PERIOD_M1,SERIES_SYNCHRONIZED))
                     {
                        //--- есть синхронизация, выходим
                        synchronized = true;
                        break;
                     }
                     //--- увеличим счетчик
                     attempts++;
                     //--- подождем 300 миллисекунд до следующей итерации
                     Sleep(300);
                  }
                  //--- вышли из цикла по факту синхронизации
                  if(!synchronized)
                  {
                     Print(Symbol()," Не удалось получить количество баров из ",symbols_name[n]);
                     for(int c = 0; c < ArraySize(chID); c++) ChartClose(chID[c]);
                     if(it >= init_try)
                     {
                        Print(Symbol()," Снимаем индикатор с графика.");
                        ChartIndicatorDelete(0,0,indicatorSHORTNAME);
                     }
                     else return(0);
                  }
               }
               
               Print(Symbol()," / ",it," / ",symbols_name[n]," [",n,"] ~~~ доступно ",bars_calc_arr[n]);
            }
            
            bars_calc = bars_calc_arr[ArrayMinimum(bars_calc_arr)];
            Print(Symbol()," / ",it," / ",symbols_name[0]," [0] ~~~ доступно ",bars_calc_arr[0]);
            Print("=== bars_calc = ",bars_calc);
            
            for(int n = 0; n < ArraySize(chID); n++) ChartClose(chID[n]);
            
            if(bars_calc > TerminalInfoInteger(TERMINAL_MAXBARS)) bars_calc = TerminalInfoInteger(TERMINAL_MAXBARS);
            
            if(bars_calc < odds_bars + in_smoothing + 1)
            {
               Print(Symbol()," Баров для рассчётов меньше необходимого");
               if(it >= init_try)
               {
                  Print(Symbol()," Снимаем индикатор с графика.");
                  ChartIndicatorDelete(0,0,indicatorSHORTNAME);
               }
               return(0);
            }

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

Но как только бросаю индикатор с изменённым кодом на график, он начинает работать, а потом график закрывается....

А самое непонятное это то, что если сначала не график бросаю индикатор с не изменённым кодом, а затем с изменённым - то всё нормально и график не пропадает.

Что не так?


Хотя распринтовка говорит, что всё ОК....

2020.01.16 00:15:31.331 ICTMP_2.05 (AUDNZD,M15) "AUDNZD" "AUDCHF" "AUDCAD" "GBPAUD" "EURAUD" "AUDUSD" "AUDJPY"
2020.01.16 00:15:31.331 ICTMP_2.05 (AUDNZD,M15) ======= AUDNZD INIT_SUCCEEDED ======= bars_calc = 317619
2020.01.16 00:15:31.331 ICTMP_2.05 (AUDNZD,M15) AUDNZD ~~~ Start OnCalculate ~~~ Try 1
2020.01.16 00:15:31.742 ICTMP_2.05 (AUDNZD,M15) AUDNZD / 1 / AUDCHF [1] ~~~ доступно 318522
2020.01.16 00:15:31.742 ICTMP_2.05 (AUDNZD,M15) AUDNZD / 1 / AUDCAD [2] ~~~ доступно 318611
2020.01.16 00:15:31.742 ICTMP_2.05 (AUDNZD,M15) AUDNZD / 1 / GBPAUD [3] ~~~ доступно 305704
2020.01.16 00:15:31.742 ICTMP_2.05 (AUDNZD,M15) AUDNZD / 1 / EURAUD [4] ~~~ доступно 383569
2020.01.16 00:15:31.742 ICTMP_2.05 (AUDNZD,M15) AUDNZD / 1 / AUDUSD [5] ~~~ доступно 516889
2020.01.16 00:15:31.742 ICTMP_2.05 (AUDNZD,M15) AUDNZD / 1 / AUDJPY [6] ~~~ доступно 513277
2020.01.16 00:15:31.742 ICTMP_2.05 (AUDNZD,M15) AUDNZD / 1 / AUDNZD [0] ~~~ доступно 317619
2020.01.16 00:15:31.742 ICTMP_2.05 (AUDNZD,M15) === bars_calc = 305704
2020.01.16 00:15:31.760 ICTMP_2.05 (AUDNZD,M15) AUDNZD Начальный расчёт индикатора.
2020.01.16 00:15:32.842 ICTMP_2.05 (AUDNZD,M15) AUDNZD Начальный расчёт индикатора завершён.
2020.01.16 00:15:32.842 ICTMP_2.05 (AUDNZD,M15) AUDNZD Обработка новых данных.
2020.01.16 00:15:32.842 ICTMP_2.05 (AUDNZD,M15) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Причина обращения: