Обсуждение статьи "Библиотека для простого и быстрого создания программ для MetaTrader (Часть I). Концепция, организация данных, первые результаты" - страница 4

 
fxsaber:

Спасибо, понятно разъяснено. Но все же остался вопрос - понятно что быстрее в МТ4, но если про 5-ку - быстрее ли выполнить все методы отдельно, чем вызвать один CopyRates? Если да, то имеет смысл создать свою структуру/класс бара вместо MQLRates, которая бы записывала не все поля, а только нужные в нашем случае, по маске например.

 
alex_all:

Спасибо, понятно разъяснено. Но все же остался вопрос - понятно что быстрее в МТ4, но если про 5-ку - быстрее ли выполнить все методы отдельно, чем вызвать один CopyRates? Если да, то имеет смысл создать свою структуру/класс бара вместо MQLRates, которая бы записывала не все поля, а только нужные в нашем случае, по маске например.

Попробуйте.

 
Никаких обновлений?
 
soldadoraso21:
Вы не хотите обновить?

Не понял вопроса.

Я не понял вопроса.

 

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

Однако я заметил 2 потенциальные проблемные ситуации в этой первой части:

Во-первых.

Sometimes, you may want to get the number of decimal places in a symbol lot. Let's enter this function to our file of service functions:

//+------------------------------------------------------------------+
//| Возвращает количество десятичных знаков в символьном множестве |
//+------------------------------------------------------------------+
uint DigitsLots(conststring symbol_name) 
  { 
   return (int)ceil(fabs(log(SymbolInfoDouble(symbol_name,SYMBOL_VOLUME_STEP))/log(10)));
  }

1.a Предложенное решение с использованием log не является универсальным. На каком-то символе вы можете прекрасно иметь шаг по объему, например, 0.25, и DigitsLots() в таком случае вернет неверный ответ.

1.b Зачем вам нужно "количество знаков после запятой в лоте символа"? Я не вижу для этого никакого реального применения.

1.c Если вы действительно хотите использовать функцию log и будете разбираться с особыми случаями в другом месте, вам следует использовать log10, а не натуральный логарифм.

return (int)ceil(fabs(log10(SymbolInfoDouble(symbol_name,SYMBOL_VOLUME_STEP))));

1.d Предоставление такой функции в публичном интерфейсе может привести к неэффективным результатам, она использует 5 вызовов функций и может быть вызвана несколько раз на каждом тике.


Во-вторых.

intOnInit()
  {
//---
   list_all_orders.Sort();
   list_all_orders.Clear();
   if(!HistorySelect(0,TimeCurrent()))
     {
      Print(DFUN,TextByLanguage(": Не удалось получить историю сделок и ордеров".,": Failed to get history of deals and orders"));
      returnINIT_FAILED;
     }
   ...

2.a Это неправильный способ вызова HistorySelect(), вы можете пропустить некоторую информацию об истории, так как TimeCurrent() возвращает последнюю известную дату тика с сервера брокера. Обоснование отсюда и из опыта.

2.b Это плохой пример использования TimeCurrent() в функции OnInit(), когда у вас нет гарантии наличия соединения с брокером. Вообще, это плохая идея - делать любой запрос данных в OnInit().

 

Спасибо за комментарии, но это всего лишь тест.

  1. Я рассмотрю возможность изменения функции на другую - полностью универсальную
  2. количество знаков после запятой для лота каждого отдельного символа необходимо для безошибочной отправки торговых приказов
  3. Ваша функция с log10 не имеет озвученной Вами проблемы с шагом лота 0.25?
  4. Данные о количестве знаков после запятой записываются один раз в объект класса-символа. Подробнее об этом - в последующих статьях.

Тестовая проверка в OnInit () нужна именно для проверки. И только там я получаю историю ордеров таким образом. В коллекциях ордеров, сделок и позиций - иначе.

Обо всем этом - в следующих статьях.

-------------

Спасибо за комментарии, но это всего лишь тест.

  1. Я рассмотрю возможность изменения функций на иную - полностью универсальную
  2. Количество знаков после запятой для лота каждого отдельного символа нужно для безошибочной отправки торговых приказов
  3. Ваша функция с log10 не имеет озвученной вами проблемы с шагом лота 0.25 ?
  4. Данные о количестве знаков после запятой записываются единожды в объект класса-символ. Это будет далее - в последующих статьях

Тестовая проверка в OnInit() нужна всего лишь лишь для проверки. И только там историю ордеров получаю таким образом. В коллекциях ордеров, сделок и позиций - иначе.

Всё это в последующих статьях.
 
Artyom Trishkin:

Спасибо за комментарии, но это всего лишь тест.

  1. Я рассмотрю возможность изменения функции на другую - полностью универсальную
  2. количество знаков после запятой для лота каждого отдельного символа необходимо для безошибочной отправки торговых приказов
  3. Ваша функция с log10 не имеет озвученной Вами проблемы с шагом лота 0.25?
  4. Данные о количестве знаков после запятой записываются один раз в объект класса-символа. Об этом подробнее - в последующих статьях.

Тестовая проверка в OnInit () нужна именно для проверки. И только там я получаю историю ордеров таким образом. В коллекциях ордеров, сделок и позиций - иначе.

Обо всем этом - в следующих статьях.


1. Хорошо.

2. Это не нужно, если вы правильно нормализуете лот, что-то вроде :

 double lotStep=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
 lots=MathRound(lots/lotStep)*lotStep;

Использование цифр лота может привести только к проблемам.

3. У log10 та же проблема, он не универсален. Это было сделано, чтобы избежать бесполезного вызова log(10).

4. Хорошо.

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

Я прочитаю другие статьи.

 
Alain Verleyen:

1. Хорошо.

2. Он не нужен, если вы правильно нормализуете ваш лот, что-то вроде :

Использование цифр лота может привести только к проблемам.

3. У log10 та же проблема, он не универсален. Это просто для того, чтобы избежать бесполезного вызова log(10).

4. Хорошо.

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

Я прочитаю другие статьи.

ХОРОШО. Спасибо
 

Здравствуйте 

Можете считать меня вашим абитуриентом или студентом  так сказать

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

дошел до пункта  Реализация метода сравнения двух ордеров между собой по заданному свойству:

//+------------------------------------------------------------------+
//| Сравнивает объекты COrder между собой по всем возможным свойствам|
//+------------------------------------------------------------------+
int COrder::Compare(const CObject *node,const int mode=0) const
  {
   const COrder *order_compared=node;
//--- сравнение целочисленных свойств двух ордеров
   if(mode<ORDER_PROP_INTEGER_TOTAL)
     {
      long value_compared=order_compared.GetProperty((ENUM_ORDER_PROP_INTEGER)mode);
      long value_current=this.GetProperty((ENUM_ORDER_PROP_INTEGER)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
//--- сравнение вещественных свойств двух ордеров
   else if(mode<ORDER_PROP_DOUBLE_TOTAL+ORDER_PROP_INTEGER_TOTAL)
     {
      double value_compared=order_compared.GetProperty((ENUM_ORDER_PROP_DOUBLE)mode);
      double value_current=this.GetProperty((ENUM_ORDER_PROP_DOUBLE)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
//--- сравнение строковых свойств двух ордеров
   else if(mode<ORDER_PROP_DOUBLE_TOTAL+ORDER_PROP_INTEGER_TOTAL+ORDER_PROP_STRING_TOTAL)
     {
      string value_compared=order_compared.GetProperty((ENUM_ORDER_PROP_STRING)mode);
      string value_current=this.GetProperty((ENUM_ORDER_PROP_STRING)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
   return 0;
  }
//+------------------------------------------------------------------+

Вот этот код в библиотеке где прописывать 

после

   //--- Сравнивает объекты COrder между собой по всем возможным свойствам
   virtual int       Compare(const CObject *node,const int mode=0) const;

или в защищенном классе абстрактного ордера

protected:
   //--- Защищённый параметрический конструктор
                     COrder(ENUM_ORDER_STATUS order_status,const ulong ticket);
                     
   //--- Получает и возвращает целочисленные свойства выбранного ордера из его параметров
   long              OrderMagicNumber(void)        const;
   long              OrderTicket(void)             const;
   long              OrderTicketFrom(void)         const;
   long              OrderTicketTo(void)           const;
   long              OrderPositionID(void)         const;
   long              OrderPositionByID(void)       const;
   long              OrderOpenTimeMSC(void)        const;
   long              OrderCloseTimeMSC(void)       const;
   long              OrderType(void)               const;
   long              OrderTypeByDirection(void)    const;
   long              OrderTypeFilling(void)        const;
   long              OrderTypeTime(void)           const;
   long              OrderReason(void)             const;
   long              DealOrder(void)               const;
   long              DealEntry(void)               const;
   bool              OrderCloseByStopLoss(void)    const;
   bool              OrderCloseByTakeProfit(void)  const;
   datetime          OrderOpenTime(void)           const;
   datetime          OrderCloseTime(void)          const;
   datetime          OrderExpiration(void)         const;
   datetime          PositionTimeUpdate(void)      const;
   datetime          PositionTimeUpdateMSC(void)   const;
   
   //--- Получает и возвращает вещественные свойства выбранного ордера из его параметров: (1) цену открытия, (2) цену закрытия, (3) профит,
   //---  (4) комиссию, (5) своп, (6) объём, (7) невыполненный объём (8) цену StopLoss, (9) цену TakeProfit (10) цену установки StopLimit-ордера
   double            OrderOpenPrice(void)          const;
   double            OrderClosePrice(void)         const;
   double            OrderProfit(void)             const;
   double            OrderCommission(void)         const;
   double            OrderSwap(void)               const;
   double            OrderVolume(void)             const;
   double            OrderVolumeCurrent(void)      const;
   double            OrderStopLoss(void)           const;
   double            OrderTakeProfit(void)         const;
   double            OrderPriceStopLimit(void)     const;
   
   //--- Получает и возвращает строковые свойства выбранного ордера из его параметров: (1) символ, (2) комментарий, (3) идентификатор на бирже
   string            OrderSymbol(void)             const;
   string            OrderComment(void)            const;
   string            OrderExternalID(void)         const;
   
public:
   //--- Возвращает из массива свойств (1) целочисленное, (2) вещественное и (3) строковое свойство ордера
   long              GetProperty(ENUM_ORDER_PROP_INTEGER property)      const { return m_long_prop[property];                    }
   double            GetProperty(ENUM_ORDER_PROP_DOUBLE property)       const { return m_double_prop[this.IndexProp(property)];  }
   string            GetProperty(ENUM_ORDER_PROP_STRING property)       const { return m_string_prop[this.IndexProp(property)];  }
   
   //--- Возвращает флаг поддержания ордером данного свойства
   virtual bool      SupportProperty(ENUM_ORDER_PROP_INTEGER property)        { return true; }
   virtual bool      SupportProperty(ENUM_ORDER_PROP_DOUBLE property)         { return true; }
   virtual bool      SupportProperty(ENUM_ORDER_PROP_STRING property)         { return true; }

Прошу отнестись с пониманием я уже не молод это молодые схватывают на лету. 

И еще я открыл тему на форуме в Статьи и техническая библиотека по автоматическому трейдингу (12560)  Я Студент там я продублирую эту тему хотелось бы ответ от вас по подробнее про структуру,

работая пошагово по статье . можно ошибаться и не понимать.

Форум трейдеров - MQL5.community: Статьи и техническая библиотека по автоматическому трейдингу
Форум трейдеров - MQL5.community: Статьи и техническая библиотека по автоматическому трейдингу
  • www.mql5.com
Обсуждение статей по трейдингу и примеров на языках MQL4/MQL5
 
Vladimir Andreev:

Здравствуйте 

Можете считать меня вашим абитуриентом или студентом  так сказать

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

дошел до пункта  Реализация метода сравнения двух ордеров между собой по заданному свойству:

Вот этот код в библиотеке где прописывать 

после

или в защищенном классе абстрактного ордера

Прошу отнестись с пониманием я уже не молод это молодые схватывают на лету. 

И еще я открыл тему на форуме в Статьи и техническая библиотека по автоматическому трейдингу (12560)  Я Студент там я продублирую эту тему хотелось бы ответ от вас по подробнее про структуру,

работая пошагово по статье . можно ошибаться и не понимать.

Есть два способа создать метод класса - это прямо в теле класса:

class CMyClass
  {
   bool Flag(void) { return false; }
  }

и за пределами тела класса:

class CMyClass
  {
   bool Flag(void);
  }
//--- метод, реализованный за пределами тела класса
bool CMyClass::Flag(void) { return false; }

В первом случае метод определяется и реализовывается прямо в теле класса - так удобно делать для коротких методов, которые не занимают много строк. Но если метод объёмный, то удобнее объявить его в теле класса, а саму реализацию вынести за пределы тела класса - как во втором примере.

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

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