Новая версия платформы MetaTrader 5 build 2085: Интеграция с Python и массовые улучшения в тестере стратегий - страница 10

 
Alexey Kozitsyn:

Средствами MQL5 я занимался расчетом дельты. Можете посмотреть статью на эту тему. Дак вот. Дельта не рассчитывается "одной строкой". Ее нужно потиково собирать. То, что Вы указали:

это вообще некорректная формула, т.к. дельта = сумма покупок + сумма продаж. За определенный период. Тиковые данные (по которым можно рассчитать дельту) идут в терминал отдельным потоком. А тот объем, что Вы видите в окне данных - это данные с биржи (другой поток). Терминал объем не рассчитывает. Соответственно и добавление "одной строки дельты" - это доп. серьезная нагрузка на терминал. Разработчики этого точно делать не будут.

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

кстати у вас ошибка, дельта считается как раз из ask-bid, а не сумма

 
Konstantin:

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

кстати у вас ошибка, дельта считается как раз из ask-bid, а не сумма

Да, конечно, знаки перепутал. Просто я отмечал, что для расчета дельты нужно брать сумму покупок - сумму продаж, а не дельта += объем покупок-объем продаж.  

 

В продолжение темы Access Violation.  Вот такой код тоже приводит к краху:

struct B
{
  char _a[];
  B()         { Print(__FUNCSIG__); }
  B(const B&) { Print(__FUNCSIG__); }
 ~B()         { Print(__FUNCSIG__);  ZeroMemory(_a); } 
};

B GetB() { Print(__FUNCSIG__);  B b;  ArrayResize(b._a,1); return b; }

int f(B&) { Print(__FUNCSIG__);  return -1; }

void OnStart()
{
  for (int i=0;  i<2 || (0 && f(GetB()));  i++)
    Print(true ? i : f(GetB()));
}

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

 
Konstantin:

кстати у вас ошибка, дельта считается как раз из ask-bid, а не сумма

Alexey Kozitsyn:

Ну раз вы считаете что расчет дельты займет 100500 человекочасов, то спорить с вами не буду - пусть терминал стагнирует.
Надеюсь разработчики насчитают поменьше.

 
Alexey Navoykov:

В общем баги с временными объектами, находящимися в игнорируемой ветке условного оператора

И в switch

void OnStart()
{
        switch ( 0 ) {
        case  0: break;
        default: f(GetB());
        }
}

и в for

void OnStart()
{
        for (int i = 0; false; i+=f(GetB()));
}

также ошибка при выполнении (вызывается деструктор, а не должен)

 

Версия 2085.

Вывожу на график меню:

Если индикатор удаляю с графика, меню также удаляется. Деструктор удаляет меню.

Если закрываю терминал, а потом снова загружаю терминал, то меню выводится на график.

То есть деструктор:

   ~cMenuCommon(void)
     {
      delete_menuCommon();    // отключаем меню Common
     };

не срабатывает.

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

В МТ4 все работает. И данной ошибки там нет.

 

    Функции

    • MT5Initialize — устанавливает соединение с терминалом MetaTrader 5
    • MT5Shutdown — закрывает ранее установленное подключение к терминалу MetaTrader 5
    • MT5TerminalInfo — получает состояние и параметры подключенного терминала MetaTrader 5
    • MT5Version — возвращает версию терминала MetaTrader 5
    • MT5WaitForTerminal — ждет пока терминал MetaTrader 5 подключится к торговому серверу
    • MT5CopyRatesFrom — получает бары из терминала MetaTrader 5, начиная с указанной даты
    • MT5CopyRatesFromPos — получает бары из терминала MetaTrader 5, начиная с указанного индекса
    • MT5CopyRatesRange — получает бары в указанном диапазоне дат из терминала MetaTrader 5
    • MT5CopyTicksFrom — получает тики из терминала MetaTrader 5, начиная с указанной даты
    • MT5CopyTicksRange — получает тики за указанный диапазон дат из терминала MetaTrader 5



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

 
Eugeni Neumoin:

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

а разве массивы char передавать нельзя? делайте сериализацию/десериализацию данных и передавайте байтовые массивы данных

 
Konstantin:

а разве массивы char передавать нельзя? делайте сериализацию/десериализацию данных и передавайте байтовые массивы данных

А пример кода покажите.

 
Eugeni Neumoin:

А пример кода покажите.

да там все просто, массив char представляете как

#ifndef BYTE
   #define BYTE   uchar
#endif 

затем создаете динамический массив BYTE и передаете в соответствующие методы -  BYTE &a_byte[]

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

   /*!
      \brief   Структура приема данных COrdPos
   */
   struct InOP
     {
      double               cur_vol;    // 8 byte
      double               init_vol;   // 8 byte
      double               open;       // 8 byte
      double               close;      // 8 byte
      double               lev_tp;     // 8 byte
      double               lev_sl;     // 8 byte
      double               profit;     // 8 byte
      double               commission; // 8 byte
      double               swap;       // 8 byte
      double               profit_old; // 8 byte
      ulong                ticket;     // 8 byte
      ulong                pos_id;     // 8 byte
      ulong                time_msc;   // 8 byte
      uint                 level;      // 4 byte
      uint                 speed_ms;   // 4 byte
      ENUM_ORDER_TYPE      type_order; // 4 byte
      ENUM_POSITION_TYPE   type_pos;   // 4 byte
      int                  code;       // 4 byte
      int                  total_dp;   // 4 byte
      bool                 open_close; // 1 byte
      BYTE                 symbol[21]; // 21 byte
     };
   /*!
      \brief   Байтовое представление InLR
   */
   struct ByteOP { BYTE byte[sizeof(InOP)]; };  // 150 byte
   /*!
      \brief   Объединение конвертации данных byte to struct | struct to byte
   */
   union ConvOP { InOP data; ByteOP b; };

все это оборачиваете в union, вот пример кода отработки в одну сторону

/*!
   \brief   Копирование COrdPos в BYTE
   \param   CList &a_data - указатель на список торговых заявок
   \param   BYTE &a_byte[] - массив приемник
*/
void CSerializeData::OpToByte(CList &a_data,BYTE &a_byte[]) {
   int _offset = 0;

   //--- посчитаем размер в байтах
   int _total_byte = 0;
   for(COrdPos *_unit = a_data.GetFirstNode(); _unit != NULL; _unit = a_data.GetNextNode())
      _total_byte += size_dp * ArraySize(_unit.old_ticket) + size_op;

   ArrayResize(a_byte, _total_byte);

   //--- копирование данных COrdPos
   for(COrdPos *_unit = a_data.GetFirstNode(); _unit != NULL; _unit = a_data.GetNextNode()) {
      ConvOP _conv;
      BYTE _byte_op[];
      ArrayResize(_byte_op, size_op);
      _conv.data.cur_vol    = _unit.cur_vol;
      _conv.data.init_vol   = _unit.init_vol;
      _conv.data.open       = _unit.open;
      _conv.data.close      = _unit.close;
      _conv.data.lev_tp     = _unit.lev_tp;
      _conv.data.lev_sl     = _unit.lev_sl;
      _conv.data.profit     = _unit.profit;
      _conv.data.commission = _unit.commission;
      _conv.data.swap       = _unit.swap;
      _conv.data.profit_old = _unit.profit_old;
      _conv.data.ticket     = _unit.ticket;
      _conv.data.pos_id     = _unit.pos_id;
      _conv.data.time_msc   = _unit.time_msc;
      _conv.data.level      = _unit.level;
      _conv.data.speed_ms   = _unit.speed_ms;
      _conv.data.type_order = _unit.type_order;
      _conv.data.type_pos   = _unit.type_pos;
      _conv.data.code       = _unit.code;
      _conv.data.total_dp   = ArraySize(_unit.old_ticket);
      _conv.data.open_close = _unit.open_close;
      StringToCharArray(_unit.symbol, _conv.data.symbol, 0, WHOLE_ARRAY, CP_ACP);   // преобразуем string в массив BYTE

      //--- копируем данные элемента COrdPos
      ArrayCopy(_byte_op, _conv.b.byte, 0, 0, WHOLE_ARRAY);
      ArrayCopy(a_byte, _byte_op, _offset, 0, WHOLE_ARRAY);

      //--- копирование данных old_ticket
      BYTE _byte_dp[];
      DpToByte(_unit.old_ticket, _byte_dp, size_dp);
      ArrayCopy(a_byte, _byte_dp, _offset + size_op, 0, WHOLE_ARRAY);

      _offset += size_op + size_dp * ArraySize(_unit.old_ticket);
   }
}

это в другую сторону

/*!
   \brief   Копирование BYTE в COrdPos
   \param   CList &a_data - указатель на список торговых заявок
   \param   BYTE &a_byte[] - массив источник
*/
void CSerializeData::ByteToOp(CList &a_data,BYTE &a_byte[]) {
   if(a_data.Total() > 0)
      a_data.Clear();

   int _offset = 0;
   int _size = ArraySize(a_byte);
   
   while(_size > 0) {
      COrdPos *_unit = new COrdPos();
      ConvOP _conv;
      BYTE _byte_op[];
      ArrayResize(_byte_op, size_op);

      ArrayCopy(_byte_op, a_byte, 0, _offset, size_op);
      ArrayCopy(_conv.b.byte, _byte_op, 0, 0, WHOLE_ARRAY);
      _unit.cur_vol     = _conv.data.cur_vol;
      _unit.init_vol    = _conv.data.init_vol;
      _unit.open        = _conv.data.open;
      _unit.close       = _conv.data.close;
      _unit.lev_tp      = _conv.data.lev_tp;
      _unit.lev_sl      = _conv.data.lev_sl;
      _unit.profit      = _conv.data.profit;
      _unit.commission  = _conv.data.commission;
      _unit.swap        = _conv.data.swap;
      _unit.profit_old  = _conv.data.profit_old;
      _unit.ticket      = _conv.data.ticket;
      _unit.pos_id      = _conv.data.pos_id;
      _unit.time_msc    = _conv.data.time_msc;
      _unit.level       = _conv.data.level;
      _unit.speed_ms    = _conv.data.speed_ms;
      _unit.type_order  = _conv.data.type_order;
      _unit.type_pos    = _conv.data.type_pos;
      _unit.code        = _conv.data.code;
      _unit.open_close  = _conv.data.open_close;
      _unit.symbol      = CharArrayToString(_conv.data.symbol, 0, WHOLE_ARRAY, CP_ACP);

      //--- копирование данных old_ticket
      BYTE _byte_dp[];
      ArrayCopy(_byte_dp, a_byte, 0, _offset + size_op, size_dp * _conv.data.total_dp);
      ByteToDp(_unit.old_ticket, _byte_dp, size_dp);

      a_data.Add((CObject *)_unit);
      _offset += size_op + size_dp * _conv.data.total_dp;
      _size -= size_op + size_dp * _conv.data.total_dp;
   }
}

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

по сути стандартная ситуация в программировании сериализыции и десериализации данных, не хватает конечно рефлексии в mql5 по типу как в C++17, тогда можно было бы не создавать под каждый тип свои структуры и объединения для сериализации-десериализации, а написать единый механизм для этого ))

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