Новая версия MetaTrader 4 Client Terminal 387 и MetaTrader 4 Data Center build 387 - страница 4

 
AlexSTAL:

Переписку удалил, но я и без неё прекрасно понимаю, что такое оптимизация...

Чётко с помощью минимального кода сформулируйте то, чего Вы боитесь, но что не воспроизвели в реалии...

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

Вот я и пытаюсь понять о чём речь идёт....


to Zhunko: позже попытаюсь вкурить написанное


Куда же четче, я писал, что у меня идет расчет только:

1) когда появляется новый бар

2) когда цена выходит за пределы уже посчитанной части бара (за хай или лоу)

3) рассчитывается три-четыре последних луча.

Об этом было в нашей переписке. Ты сказал, что это понятно.... или я зря писал?

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

Этого мало?

 
nen:

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

А где такое написано? Можно ведь сначала проверить, и только потом пугаться.
 
nen:


Куда же четче, я писал, что у меня идет расчет только:

1) когда появляется новый бар

2) когда цена выходит за пределы уже посчитанной части бара (за хай или лоу)

3) рассчитывается три-четыре последних луча.

Об этом было в нашей переписке. Ты сказал, что это понятно.... или я зря писал?

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

Этого мало?

Если бы, да ка бы... Нету этой проблемы! У Zhunko совершенно другая проблема. Прежде чем поднимать панику нужно самому проверить. Я проверил несколькими постами выше и даже код выложил
 
Rosh:
А где такое написано? Можно ведь сначала проверить, и только потом пугаться.

+10000

В каждом деле должен быть профессиональный подход....

 
start()
 {
  if(glowBar<=iLow(NULL, gtf, 0) && ghighBar>=iHigh(NULL, gtf, 0) && gtimelast==iTime(NULL, gtf, 0)) return (0);

  glowBar=iLow(NULL, gtf, 0); ghighBar=iHigh(NULL, gtf, 0);                  // обновляем сразу, а не после длительного расчета
...// здесь код основного расчета.

  gcurrentBars=iBars(NULL, gtf);       // обновляем в конце, чтобы не накапливались непосчитанные бары за время расчета
                                        // и не срабатывал полный пересчет на следующем тике в случае длительного расчета
 }

Полный код секции старт


//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int i, j;

   gtf=Period();
   gRecalculation=1;

   while(gRecalculation>0)
     {
      if(gcurrentBars<iBars(NULL, gtf)-1)
        {
         Print("Время полного пересчета = ",TimeToStr(Time[0],TIME_DATE|TIME_MINUTES));
         glowBar=0; ghighBar=0; gtimelast=0; gsave_wr0=0;
         ArrayInitialize(gsave_tLast,0);ArrayInitialize(gsave_hl,0);ArrayInitialize(gsave_lastlow,0);ArrayInitialize(gsave_lasthigh,0);
         ArrayInitialize(gt_hi,0);ArrayInitialize(gt_li,0);ArrayInitialize(gt_end,0);

         gTheExternalBar=false; 
         history=true;
//      if(_PrimarySelectionOfExtremums==2 || _PrimarySelectionOfExtremums==3) delete_objects();
         delete_objects();
         g_addnewextremum=true;
         gbar=iBars(NULL, gtf);

         ArrayInitialize(gtime_gbar,0); ArrayInitialize(gL2LTime,0); ArrayInitialize(gL2HTime,0); 

         ArrayInitialize(LowestBuffer1,0);ArrayInitialize(HighestBuffer1,0);
         ArrayInitialize(LowestBuffer2,0);ArrayInitialize(HighestBuffer2,0); 
         ArrayInitialize(LowestBuffer3,0);ArrayInitialize(HighestBuffer3,0); 
         ArrayInitialize(LowestBuffer4,0);ArrayInitialize(HighestBuffer4,0); 

         ArrayInitialize(last_h,0);ArrayInitialize(last_l,0);ArrayInitialize(last_t,0);

         ArrayInitialize(tL1,0);ArrayInitialize(tL2,0);ArrayInitialize(tL3,0);ArrayInitialize(tL4,0);ArrayInitialize(tL5,0);
         ArrayInitialize(tL6,0);ArrayInitialize(tL7,0);ArrayInitialize(tL8,0);ArrayInitialize(tL9,0);ArrayInitialize(tL10,0);
         ArrayInitialize(tL11,0);

         ArrayInitialize(cL1,0);ArrayInitialize(cL2,0);ArrayInitialize(cL3,0);ArrayInitialize(cL4,0);ArrayInitialize(cL5,0);
         ArrayInitialize(cL6,0);ArrayInitialize(cL7,0);ArrayInitialize(cL8,0);ArrayInitialize(cL9,0);ArrayInitialize(cL10,0);
         ArrayInitialize(cL11,0);
         ArrayInitialize(cH1,0);ArrayInitialize(cH2,0);ArrayInitialize(cH3,0);ArrayInitialize(cH4,0);ArrayInitialize(cH5,0);
         ArrayInitialize(cH6,0);ArrayInitialize(cH7,0);ArrayInitialize(cH8,0);ArrayInitialize(cH9,0);ArrayInitialize(cH10,0);
         ArrayInitialize(cH11,0);
         if(filterZigZag==1)
           {
            ArrayResize(cLz1,gbar);ArrayResize(cHz1,gbar);ArrayResize(tLz1,gbar);

            ArrayInitialize(tLz1,0);ArrayInitialize(tLz2,0);ArrayInitialize(tLz3,0);ArrayInitialize(tLz4,0);ArrayInitialize(tLz5,0);
            ArrayInitialize(tLz6,0);ArrayInitialize(tLz7,0);ArrayInitialize(tLz8,0);ArrayInitialize(tLz9,0);ArrayInitialize(tLz10,0);
            ArrayInitialize(tLz11,0);

            ArrayInitialize(cLz1,0);ArrayInitialize(cLz2,0);ArrayInitialize(cLz3,0);ArrayInitialize(cLz4,0);ArrayInitialize(cLz5,0);
            ArrayInitialize(cLz6,0);ArrayInitialize(cLz7,0);ArrayInitialize(cLz8,0);ArrayInitialize(cLz9,0);ArrayInitialize(cLz10,0);
            ArrayInitialize(cLz11,0);
            ArrayInitialize(cHz1,0);ArrayInitialize(cHz2,0);ArrayInitialize(cHz3,0);ArrayInitialize(cHz4,0);ArrayInitialize(cHz5,0);
            ArrayInitialize(cHz6,0);ArrayInitialize(cHz7,0);ArrayInitialize(cHz8,0);ArrayInitialize(cHz9,0);ArrayInitialize(cHz10,0);
            ArrayInitialize(cHz11,0);
           }
Print("");
        }
      else
        {
         if(_PrimarySelectionOfExtremums<2)
           {
            gbar=iBarShift(NULL, gtf, gtime_gbar[0], true)+2;
           }
        }

      if(_PrimarySelectionOfExtremums==4 && gtimelast==iTime(NULL, gtf, 0)) return(0);
      if(tL1[0]>0)
        {
         if(glowBar<=iLow(NULL, gtf, 0) && ghighBar>=iHigh(NULL, gtf, 0) && gtimelast==iTime(NULL, gtf, 0)) return (0);
         if(gtimelast<iTime(NULL, gtf, 0) &&(_PrimarySelectionOfExtremums==2 || _PrimarySelectionOfExtremums==3))
           {
            gTheExternalBar=false; delete_objects();
           }
        }
      glowBar=iLow(NULL, gtf, 0); ghighBar=iHigh(NULL, gtf, 0);                  // обновляем сразу, а не после длительного расчета

      // Поиск экстремумов для первого уровня
      glevel=0;
      SamplingCreationExtremums();

      if(history)
        {

         if(ShowPrimaryLevel==0)
           {
            VisiblePrimarySelections(cL1, cH1, tL1, cLz1, cHz1, tLz1, LowestBuffer1, HighestBuffer1); // визуализация
           }

         // Создание следующих уровней и визуализация
         SelectionArrayForNextLevels();
         gtimelast=iTime(NULL, gtf, 0); // эта переменная используется в промежуточных расчетах, поэтому ее обновляем после расчетов
         history=false;

//*
         // Обрезка массивов
         if(QuantityExtremums>0)
           {
            for(i=1;i<11;i++)
             {
              int k=ScrapOfArrays(i);
              if(k!=0) Print("размер массива уровня ",i-1," = ",k);
              if(k==0) break;
//              if(ScrapOfArrays(i)==0) break;
             }
          }
//*/
        }
      else
        {
         WriteNewExtremums(cL1, cH1, tL1, cLz1, cHz1, tLz1);

         // Создание следующих уровней и визуализация
         SelectionArrayForNextLevels();

         gtimelast=iTime(NULL, gtf, 0); // эта переменная используется в промежуточных расчетах, поэтому ее обновляем после расчетов
        }
      if(gRecalculation>0) gRecalculation--;
     }

   gcurrentBars=iBars(NULL, gtf);       // обновляем в конце, чтобы не накапливались непосчитанные бары за время расчета
                                        // и не срабатывал полный пересчет на следующем тике в случае длительного расчета

Err(371);

   return(0);
  }
//+------------------------------------------------------------------+

Небольшой кусочек кода. И примерно такое же с некоторыми вариациями у меня во всех индикаторах.

Заметь, у меня достаточно большой участок, где происходит переинициализация буферов. Все функции ArrayInitialize как раз занимаются такой переинициализацией. Но это происходит только по необходимости, а не принудительно.

 

Я еще на первой странице написал, чтобы разработчики объяснили смысл пункта 6

Terminal: Для пользовательских индикаторов добавлена инициализация буферов при повторном чтении исторических данных.

С их стороны пока никаких объяснений не последовало. А мы здесь создаем бурю в стакане воды. Но и не только здесь. Я предупредил всех, кто пользуется моими индикаторами, чтобы повременили с загрузкой 387 билда.

 
Дискуссия закончена.
 
Zhunko:

Разобрался почему не работал комплекс. Прощай оптимизация :-(

Теперь на каждый тик надо заново заполнять буфера. Позаботились называется...

Нет изменений - нет инициализации! Хотя бы это продумайте!

Не читаю исторические данные в буферах. Использую их только для вертикальной развёртки в подокне. Зачем мне постоянно их заполнять? Случаев, когда их надо переписать, всего три (первый запуск, зум, смещение графика). И так МТ4 еле ворочается, а тут ещё один тормоз.


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

2 Terminal: Исправлен расчёт счётчика котировок при расчёте пользовательских индикаторов.

Была ошибка с оценкой количества изменений в исторических данных. При большом количестве изменений ошибочно вызывался досчёт данных, а не пересчёт. Это особенно сказывалось на индикаторе ZigZag, когда данные кардинально менялись, а зигзаг не пересчитывался.

 
VBAG:

Это замечательно! Что разработчики не забили на четверку, а её поддерживают и даже дорабатывают. Об этом просто напросто свидетельствует номер билда - 387!

Последний который я видел был - 229. И сразу - 387(может сопроцессор подключили? Гы...)! Круто!

Главное, чтобы при этом соблюдалась основная заповедь хирурга-программера - "Не навреди!"

Платформа MetaTrader 4 представляет собой совокупность многих компонентов - серверы, дата-центры, фидеры котировок и новостей, клиентский терминал, терминалы менеджера и администратора, АПИ, стандартные надстройки над компонентами, написанные с использованием АПИ и т.п. Эти компоненты развивались по-разному.

Поэтому всем нынешним компонентам присвоили номер 380, уравняв нумерацию билдов. Чисто косметическая операция.

Причина обращения: