В справочнике MQL5 ошибка или как это следует понимать?

 

Вот описание структуры торгового запроса из справочника:

struct MqlTradeRequest 
  { 
   ENUM_TRADE_REQUEST_ACTIONS    action;           // Тип выполняемого действия 
   ulong                         magic;            // Штамп эксперта (идентификатор magic number) 
   ulong                         order;            // Тикет ордера 
   string                        symbol;           // Имя торгового инструмента 
   double                        volume;           // Запрашиваемый объем сделки в лотах 
   double                        price;            // Цена  
   double                        stoplimit;        // Уровень StopLimit ордера 
   double                        sl;               // Уровень Stop Loss ордера 
   double                        tp;               // Уровень Take Profit ордера 
   ulong                         deviation;        // Максимально приемлемое отклонение от запрашиваемой цены 
   ENUM_ORDER_TYPE               type;             // Тип ордера 
   ENUM_ORDER_TYPE_FILLING       type_filling;     // Тип ордера по исполнению 
   ENUM_ORDER_TYPE_TIME          type_time;        // Тип ордера по времени действия 
   datetime                      expiration;       // Срок истечения ордера (для ордеров типа ORDER_TIME_SPECIFIED) 
   string                        comment;          // Комментарий к ордеру 
   ulong                         position;         // Тикет позиции 
   ulong                         position_by;      // Тикет встречной позиции 
  };

Видно, что поля: magic, order, position, position_by, - имеют тип ulong.

Для того чтобы запросить целочисленную информацию об выделенном размещённом ордере или позиции, запрашиваем значения с помощью функций: OrderGetInteger(), PositionGetInteger(). Обе функции имеют тип возвращаемого значения long и принимают идентификатор запрашиваемого свойства тоже типа long. Диапазоны значений long и ulong не совпадают.

Получается, я как минимум могу задать для ордера магик, который влезает в тип ulong, но тип long уже будет переполнен и при запросе такого магика я должен получить неправильное значение.

 
Oleg Remizov:

Вот описание структуры торгового запроса из справочника:

Видно, что поля: magic, order, position, position_by, - имеют тип ulong.

Для того чтобы запросить целочисленную информацию об выделенном размещённом ордере или позиции, запрашиваем значения с помощью функций: OrderGetInteger(), PositionGetInteger(). Обе функции имеют тип возвращаемого значения long и принимают идентификатор запрашиваемого свойства тоже типа long. Диапазоны значений long и ulong не совпадают.

Получается, я как минимум могу задать для ордера магик, который влезает в тип ulong, но тип long уже будет переполнен и при запросе такого магика я должен получить неправильное значение.

Так спроектировали разработчики.

Наверное потому, чтобы не плодить функции ( Н-р OrderGetUlong(), OrderGetlong() )

Проверим

Код

//+------------------------------------------------------------------+
//|                                                         Time.mq5 |
//|                                      Copyright 2021 prostotrader |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
//
ulong ticket;

void OrdSet(const double price, const ulong magic)
{
  ResetLastError();
  MqlTradeRequest request = {0};
  MqlTradeResult  result  = {0};
  //--- Fill structure
  request.action = TRADE_ACTION_PENDING;
  request.magic  = magic;
  request.symbol = Symbol();
  request.volume = 1;
  request.price  = price;
  request.type = ORDER_TYPE_BUY_LIMIT;
  request.comment = "Отложенный ордер...";      
  request.type_filling = ORDER_FILLING_RETURN;
  request.type_time = ORDER_TIME_DAY;
  if(OrderSend(request, result) == true)
  {
    if((result.retcode == TRADE_RETCODE_PLACED) || (result.retcode == TRADE_RETCODE_DONE)) 
    {
      ticket = result.order;
      if(OrderSelect(ticket) == true)
      {
        ulong cur_magic = ulong(OrderGetInteger(ORDER_MAGIC));
        Print("Cur magic is: ", cur_magic);
      }  
    } else Print(__FUNCTION__, ": Error: ", GetLastError());
  }
  else Print(__FUNCTION__, ": Order not send! Error: ", GetLastError());
}

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
  ulong a_magic = 18446744073709551615; //Максимальное число ULONG
  double low_price = SymbolInfoDouble(Symbol(), SYMBOL_SESSION_PRICE_LIMIT_MIN);
  OrdSet(low_price, a_magic);
  return(INIT_SUCCEEDED);
}

      

Результат

2021.01.21 16:00:18.347 Test (Si-3.21,M1)       Cur magic is: 18446744073709551615
Значение magic правильное.
 
prostotrader:

Так спроектировали разработчики.

Наверное потому, чтобы не плодить лишние функции ( Н-р OrderGetUlong() )

Проверим

Код

Результат

Значение magic правильное.

Странно.

Я посмотрел список свойств, которые может вернуть функция. Там для всех свойств можно обойтись только нулём и положительными числами. И тогда можно было бы указать, что тип возвращаемого значения ulong. И не возникло бы такого вопроса. В структуре все целые поля имеют тип ulong и функция запроса целых свойств тоже возвращает ulong.

 
long и ulong имеют один и тот же размер (8 байт). Да, диапазоны указываемых значений разные, т. к. в long старший бит отведен под знак. Но если значение ulong записать в long, а потом прочитать его, то значение не претерпит никаких изменений. Так что все нормально. Главное, не производить математических операций со значением long между записью и чтением ulong.
 
Ihor Herasko:
long и ulong имеют один и тот же размер. Да, диапазоны указываемых значений разные, т. к. в long старший бит отведен под знак. Но если значение ulong записать в long, а потом прочитать его, то значение не претерпит никаких изменений. Так что все нормально. Главное, не производить математических операций со значением между записью и чтением.

Нет, не все правильно

Код

int OnInit()
{
  ulong a_magic = 18446744073709551615; //Максимальное число ULONG
  long l_magic =  a_magic;
  Print("Long magic is: ", l_magic);
  double low_price = SymbolInfoDouble(Symbol(), SYMBOL_SESSION_PRICE_LIMIT_MIN);
  //OrdSet(low_price, a_magic);
  return(INIT_SUCCEEDED);
}

Результат

2021.01.21 16:35:22.423 Test (Si-3.21,M1)       Long magic is: -1

Такой вариант тоже дает не правильный результат

long l_magic =  long(a_magic);
 
prostotrader:

Нет, не все правильно

Код

Результат

Такой вариант тоже дает не правильный результат

Это вы сами делаете приведение, а в наших функциях мы без преобразований записываем и отдаем сырые 64 битные данные.

Поэтому у нас ничего не портится.
 

Всё же ошибка получается. Если следовать справочнику, для хранения значения, которое вернут функции: OrderGetInteger(), PositionGetInteger(), - я могу объявить переменную long и рассчитывать на корректный результат без всяких преобразований типов. Функция должна вернуть long, переменная для хранения значения тоже long. А вот структура, в которую я передавал магик, принимала ulong. В структуру передавал магик 18446744073709551615, получил -1.

Код:

//+------------------------------------------------------------------+
//|                                                         Time.mq5 |
//|                                      Copyright 2021 prostotrader |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
ulong ticket;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OrdSet(const double price, const ulong magic)
  {
   ResetLastError();
   MqlTradeRequest request = {0};
   MqlTradeResult  result  = {0};
//--- Fill structure
   request.action = TRADE_ACTION_PENDING;
   request.magic  = magic;
   request.symbol = Symbol();
   request.volume = 1;
   request.price  = price;
   request.type = ORDER_TYPE_BUY_LIMIT;
   request.comment = "Отложенный ордер...";
   request.type_filling = ORDER_FILLING_FOK;
   request.type_time = ORDER_TIME_DAY;
   if(OrderSend(request, result) == true)
     {
      if((result.retcode == TRADE_RETCODE_PLACED) || (result.retcode == TRADE_RETCODE_DONE))
        {
         ticket = result.order;
         if(OrderSelect(ticket) == true)
           {
            long cur_magic = OrderGetInteger(ORDER_MAGIC);
            Print("Cur magic is: ", cur_magic);
           }
        }
      else
         Print(__FUNCTION__, ": Error: ", GetLastError());
     }
   else
      Print(__FUNCTION__, ": Order not send! Error: ", GetLastError());
  }

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   ulong a_magic = 18446744073709551615; //Максимальное число ULONG
   double low_price = SymbolInfoDouble(Symbol(), SYMBOL_BIDLOW);
   OrdSet(low_price, a_magic);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
 
Oleg Remizov:

Всё же ошибка получается. Если следовать справочнику, для хранения значения, которое вернут функции: OrderGetInteger(), PositionGetInteger(), - я могу объявить переменную long и рассчитывать на корректный результат без всяких преобразований типов. Функция должна вернуть long, переменная для хранения значения тоже long. А вот структура, в которую я передавал магик, принимала ulong. В структуру передавал магик 18446744073709551615, получил -1.

Код:

И будет ошибка.

Вы в long "запихиваете" макcимальный ulong

Но будут ли исправлять справочник?

Вместо long 64-битные данные

 
Oleg Remizov:

Всё же ошибка получается. Если следовать справочнику, для хранения значения, которое вернут функции: OrderGetInteger(), PositionGetInteger(), - я могу объявить переменную long и рассчитывать на корректный результат без всяких преобразований типов. Функция должна вернуть long, переменная для хранения значения тоже long. А вот структура, в которую я передавал магик, принимала ulong. В структуру передавал магик 18446744073709551615, получил -1.

Код:

Раз уж Вы записали ulong, то и читайте в ulong

            ulong cur_magic = (ulong) OrderGetInteger(ORDER_MAGIC);
            Print("Cur magic is: ", cur_magic);


ulong и long - это x64 битовые целые числа ничем не отличающиеся, пока хранятся в памяти или на диске

Разница возникает лишь при использовании, для операций над знаковым long используются одни инструкции CPU, для беззнакового - другие

 
Напоминает анекдот про аптеку: "простите сэр, я вам испортила такую ночь!"
 
Ilyas:

Раз уж Вы записали ulong, то и читайте в ulong

Он записал long (как в справочнике)

ORDER_MAGIC
 
Идентификатор эксперта выставившего ордер (предназначен для того, чтобы каждый эксперт выставлял свой собственный уникальный номер)
 
long
 
long cur_magic = OrderGetInteger(ORDER_MAGIC);
Причина обращения: