Новая версия платформы MetaTrader 5 build 2980: Push-уведомления о торговых операциях - страница 23

 

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

В данном случае записал анимацию на b3010.


Другие символы в порядке. На записанном - смена ТФ не помогает. Открытие нового чарта - аналогично. RAM/SSD в достатке. Перезагрузка терминала вылечила.


ЗЫ На анимации видно, что Bid/Ask-линии на чарте тоже не изменяются. Тиковая история обновляется, проблемы только с барами/чартами.

 
fxsaber:
b3010, просьба исправить поведение на прежнее (b2958).

А зачем возвращаться к старой неэффективной системе?

Т.е. если раньше для каждого советника нужно было поддерживать свой порядок в истории: при загрузке советника - сортировка по времени установки ордера, далее дозапись в конец (сколько советников столько и историй), то теперь для всех советников единый порядок (одна история) - налицо экономия ресурса

 

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

Пример и описание показал тут - https://www.mql5.com/ru/forum/373462/page3#comment_23849403

В целом я там накидываю периодически идеи по дизайну, считаю этот момент очень важным. Упаковка (считай дизайн) - 80% успеха любого продукта.

Дизайн терминала Metatrader
Дизайн терминала Metatrader
  • 2021.07.25
  • www.mql5.com
Делимся наблюдениями исключительно по визуалу и дизайну. Начну с первого наблюдения и посвящен он иконками и общему стилю. Иконки устарели...
 

Индикатор утилита, для обработки событий, цепляет свои копии на другие графики. 

События отказываются работать.

Что ожидалось: Полноценная работа индикатора так как будто он установлен в ручную.

Как проявляется баг и как воспроизвести: Положить индикатор в папку Market, Открыть 2 или больше окна графиков, кинуть индикатор на один график и кликнуть мышью по графику. Индикатор прицепит свои копии на другие окна и в комменте напишет свой ЧартИД

При проверке в ручную на других графиках будет прицеплен индикатор. Баг проявляется: Не срабатывает OnInit - на других чартах не выводиться ID графика а при клике на других графиках принт выведет ChartID родного графика на который был кинут первый индикатор руками.

Хотел на самом деле показать другой баг, но по пути наткнулся на этот, думаю это одна проблема...

Код для воспроизведения:

//+------------------------------------------------------------------+
//|                                                         Test.mq5 |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots   0
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
struct CHART
  {
   long              id;
   string            sy;
   ENUM_TIMEFRAMES   tf;
   int               nu;
  };
CHART window[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   ChartSetInteger(0, CHART_EVENT_OBJECT_CREATE, true);
   ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE,    true);
   ChartSetInteger(0, CHART_EVENT_OBJECT_DELETE, true);
   Print("OnInit");
   Comment("ObjectsTotal(m_chart_id) = " + (string)ObjectsTotal(ChartID()) + "  \nChartID() = " + (string)ChartID());
   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[])
  {
//---

//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
   if(id == CHARTEVENT_CLICK)
     {

      WindowUpdate();

      for(int i = 0; i < ArraySize(window); i++)
        {

         string name_ind = MQLInfoString(MQL_PROGRAM_NAME);

         if(ChartWindowFind(window[i].id, name_ind) < 0)
           {
            Print("Добавляем");
            int handle = iCustom(window[i].sy, window[i].tf, "Market" + "\\" + name_ind);
            if(!ChartIndicatorAdd(window[i].id, 0, handle))
               PrintFormat("Не удалось добавить индикатор " + name_ind + " на окно %d графика. Код ошибки  %d",0, GetLastError());
               else
               ChartRedraw(window[i].id);
           }
        }

      Print("Клик на графике " + (string)ChartID() + " x = " + (string)lparam + " y = " + (string)dparam);
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void WindowUpdate()
  {
   long currChart = ChartFirst();
   int i = 0;
   while(i < CHARTS_MAX)
     {
      ArrayResize(window, i + 1);
      window[i].id = currChart;
      window[i].sy = ChartSymbol(currChart);
      window[i].tf = ChartPeriod(currChart);
      currChart = ChartNext(currChart);
      if(currChart == -1)
         break;
      i++;
     }
  }
//+------------------------------------------------------------------+

Результат: Кликнул по разу в каждом из трех окон 

2021.08.05 13:24:49.084 Клик на графике 128968168864101567 x = 517 y = 540.0
2021.08.05 13:24:59.449 Клик на графике 128968168864101567 x = 295 y = 375.0
2021.08.05 13:25:02.845 Клик на графике 128968168864101567 x = 281 y = 442.0
 
A100:

А зачем возвращаться к старой неэффективной системе?

Т.е. если раньше для каждого советника нужно было поддерживать свой порядок в истории: при загрузке советника - сортировка по времени установки ордера, далее дозапись в конец (сколько советников столько и историй), то теперь для всех советников единый порядок (одна история) - налицо экономия ресурса

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

Что касается попадания только что удаленного ордера в конец таблицы, а не в середину, то это неоднократно обсуждалось. 

 
fxsaber:

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

Так может уже отпала необходимость в исторических кешах для каждого советника. Иначе непонятно зачем тогда вообще что-то менять было

 
A100:

Так может уже отпала необходимость в исторических кешах для каждого советника. Иначе непонятно зачем тогда вообще что-то менять было

Разработчики не комментируют.

Добавление в конец обязано быть. Как в Тестере.
 
A100:

Это был не пример для воспроизведения указанной ошибки, а обоснованный ответ на сообщение пользователя, что он якобы что то там непонятное у себя проверил и неуместный совет по поиску ошибки (искать там где ее заведомо нет)

Представьте в сервисдеск или личку код для воспроизведения, пожалуйста.

Если ошибка есть, её нужно исправить.

 
Rashid Umarov:

Представьте в сервисдеск или личку код для воспроизведения, пожалуйста.

Да, сделаю, пока сходу не получилось сделать в компактном виде. Возможно 

Vladimir Pastushak сможет сделать это быстрее - насколько я понял там у него всего один файл
 

b3013, просьба исправить поведение на прежнее (b2958).

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Новая версия платформы MetaTrader 5 build 2940: Перенос витрин MQL5-сервисов в рабочую область и обновление дизайна

fxsaber, 2021.06.19 14:39

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

#property script_show_inputs

input bool inFlag = true;  // Проверка истории с открытием ордеров
input datetime inFrom = 0; // Не ноль приведет к ошибке и с новыми ордерами

#include <MT4Orders.mqh> // https://www.mql5.com/ru/code/16006

void OnTick()
{    
  MqlTick Tick;
  
  if (SymbolInfoTick(_Symbol, Tick) && Tick.ask)
  {
    Print("------------\n" + (string)inFlag); // Отделили строки разных запусков скрипта.
  
    if (inFlag) // Проверка на новых ордерах.
    {
      // Попытка сформировать кеш на случай, если начальная дата будет всегда постоянной, но ненулевой.
      HistorySelect(inFrom, INT_MAX);
      
      Print("Create/Delete orders.");
      
      // Создали первый ордер.
      const TICKET_TYPE Ticket1 = OrderSend(_Symbol, OP_BUYLIMIT, 0.1, Tick.ask - 1000 * _Point, 0, 0, 0);
      
      Sleep(2000); // Подождали и создали второй ордер.
      const TICKET_TYPE Ticket2 = OrderSend(_Symbol, OP_BUYLIMIT, 0.1, Tick.ask - 1000 * _Point, 0, 0, 0);
      
      Print(Ticket1); // Тикет первого.
      Print(Ticket2); // Тикет второго.
      
      OrderDelete(Ticket2); // Удалили второй - попал в историю.
      
      Sleep(2000); // Подождали и удалили первый - попал в историю.
      OrderDelete(Ticket1);
    
      // Проверка последовательности ордеров в истории - последних двух.
      if (HistorySelect(inFrom, INT_MAX))
      {
        Print("Check the History. inFrom = " + (string)inFrom);
        
        const int Total = HistoryOrdersTotal();
        
        for (int i = Total - 2; i < Total; i++)
          Print(HistoryOrderGetTicket(i)); // Распечатываем тикеты в конце таблицы. 
      }
  
      ExpertRemove();  
    }  
  }  
}


Результат Тестера.

2021.06.19 15:30:46.582 Core 1  EURUSD,M1: testing of Experts\Test9.ex5 from 2021.06.18 00:00 to 2021.06.19 00:00 started with inputs:
2021.06.19 15:30:46.582 Core 1    inFlag=true
2021.06.19 15:30:46.582 Core 1    inFrom=0
2021.06.19 15:30:46.582 Core 1  EURUSD : real ticks begin from 2021.03.15 00:00:00
2021.06.19 15:30:46.582 Core 1  2021.06.18 00:00:00   ------------
2021.06.19 15:30:46.582 Core 1  2021.06.18 00:00:00   true
2021.06.19 15:30:46.582 Core 1  2021.06.18 00:00:00   Create/Delete orders.
2021.06.19 15:30:46.582 Core 1  2021.06.18 00:00:00   buy limit 0.1 EURUSD at 1.18097 (1.19057 / 1.19097)
2021.06.19 15:30:46.582 Core 1  2021.06.18 00:00:02   buy limit 0.1 EURUSD at 1.18097 (1.19057 / 1.19069)
2021.06.19 15:30:46.582 Core 1  2021.06.18 00:00:02   2
2021.06.19 15:30:46.582 Core 1  2021.06.18 00:00:02   3
2021.06.19 15:30:46.582 Core 1  2021.06.18 00:00:02   order canceled [#3 buy limit 0.1 EURUSD at 1.18097]
2021.06.19 15:30:46.582 Core 1  2021.06.18 00:00:04   order canceled [#2 buy limit 0.1 EURUSD at 1.18097]
2021.06.19 15:30:46.582 Core 1  2021.06.18 00:00:04   Check the History. inFrom = 1970.01.01 00:00:00
2021.06.19 15:30:46.582 Core 1  2021.06.18 00:00:04   3
2021.06.19 15:30:46.582 Core 1  2021.06.18 00:00:04   2
2021.06.19 15:30:46.582 Core 1  2021.06.18 00:00:04   ExpertRemove() function called

Все четко и правильно в Тестере! Это не повод ломать Тестер. Это повод вернуть хотя бы поведение Терминала к тому, что было еще в b2958. Там работало только для inFrom = 0, но работало. В Тестере работает для любого inFrom правильно. Это абсолютно логично.


Что имеем на данный момент. HistorySelect в Терминале и в Тестере работают разными алгоритмами. При этом в Тестере этот алгоритм удобный и логичный, да еще и супер-быстрый - дозапись всего, что приходит в историю, в конец таблицы. В Терминале же - нет.


Заметьте, не упоминаю сортировку по какому-либо признаку во время работы советника. Просто говорю о дозаписи в конец (а не в середину) новых элементов истории.

Если же говорить о сортировке, то она нужна только один раз - при запуске советника. И сортировка должна быть по ORDER_TIME_DONE_MSC (при совпадающих значениях - по тикету). Тогда будет полная однозначность HistorySelect-таблицы во время работы и сразу после запуска.