Discusión sobre el artículo "Biblioteca para el desarrollo rápido y sencillo de programas para MetaTrader (Parte I): Concepto, organización de datos y primeros resultados" - página 4

 
fxsaber:

Gracias, está claramente explicado. Pero todavía hay una pregunta - está claro que es más rápido en MT4, pero si estamos hablando de 5 - ¿es más rápido ejecutar todos los métodos por separado que llamar a un CopyRates? Si es así, entonces tiene sentido crear una estructura/clase de barra en lugar de MQLRates, que escribiría no todos los campos, sino sólo los necesarios en nuestro caso, por máscara, por ejemplo.

 
alex_all:

Gracias, está claramente explicado. Pero todavía hay una pregunta - está claro que es más rápido en MT4, pero si estamos hablando de 5 - ¿es más rápido para ejecutar todos los métodos por separado que llamar a un CopyRates? Si es así, tiene sentido crear tu propia estructura/clase de barra en lugar de MQLRates, que escribiría no todos los campos, sino sólo los necesarios en nuestro caso, por máscara, por ejemplo.

Pruebe esto.

 
¿No actualizara?
 
soldadoraso21:
¿No actualizara?

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

I do not understand the question.

 

Como se trata de una librería en desarrollo esperaré más artículos antes de hacer cualquier comentario global.

Sin embargo, me di cuenta de 2 posibles situaciones problemáticas en esta primera parte:

En primer lugar

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:

//+------------------------------------------------------------------+
//| Devuelve el número de decimales en un lote de símbolos ||
//+------------------------------------------------------------------+
uint DigitsLots(conststring symbol_name) 
  { 
   return (int)ceil(fabs(log(SymbolInfoDouble(symbol_name,SYMBOL_VOLUME_STEP))/log(10)));
  }

1.a La solución propuesta usando log no es universal. En algún símbolo se puede tener perfectamente un paso de volumen de 0.25 por ejemplo y DigitsLots() devolverá una respuesta errónea en tal caso.

1.b ¿Para qué quieres el "número de decimales de un lote de símbolo"? No veo ningún caso de uso real para eso.

1.c Si realmente quieres usar la función log y vas a tratar casos especiales en otro lugar, deberías usar log10, en lugar de logaritmo natural.

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

1.d Proporcionar dicha función en la interfaz pública podría conducir a resultados ineficientes, utiliza 5 llamadas a funciones y podría ser llamada varias veces en cada tick.


En segundo lugar.

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 Esta no es una forma correcta de llamar a HistorySelect(), podría perderse alguna información histórica ya que TimeCurrent() devuelve la última fecha de tick conocida del servidor del broker. Razonamiento desde aquí y desde la experiencia.

2.b Es un mal ejemplo usar TimeCurrent() en la función OnInit() donde no se tiene garantía de tener una conexión con el broker. En general es una mala idea hacer cualquier petición de datos en OnInit().

 

Gracias por los comentarios, pero esto es sólo una prueba.

  1. Voy a considerar la posibilidad de cambiar la función a otra - completamente universal
  2. el número de decimales para el lote de cada símbolo individual es necesario para el envío inequívoco de órdenes comerciales
  3. Su función con log10 no tiene un problema expresado por usted con un paso de lote de 0,25?
  4. los datos sobre el número de decimales se escriben una vez en el objeto de la clase-símbolo. Esto será más - en artículos posteriores.

Una comprobación de prueba en OnInit () es necesaria sólo para comprobar. Y sólo allí obtengo la historia de las órdenes de esta manera. En colecciones de órdenes, tratos y posiciones - de otra manera.

Todo esto en artículos posteriores.

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

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

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

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

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

Gracias por los comentarios, pero esto es sólo una prueba.

  1. Voy a considerar la posibilidad de cambiar la función a otra - completamente universal
  2. el número de decimales para el lote de cada símbolo individual es necesario para el envío inequívoco de órdenes comerciales
  3. Su función con log10 no tiene un problema expresado por usted con un paso de lote de 0,25?
  4. los datos sobre el número de decimales se escriben una vez en el objeto de la clase-símbolo. Esto será más - en artículos posteriores.

Una comprobación de prueba en OnInit () es necesaria sólo para comprobar. Y sólo allí obtengo la historia de las órdenes de esta manera. En colecciones de órdenes, tratos y posiciones - de otra manera.

Todo esto en artículos posteriores.


1. Bien.

2. No es necesario si normaliza su lote correctamente, algo como :

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

Usar dígitos de lote sólo puede traer problemas.

3. log10 tiene el mismo problema, no es universal. Era sólo para evitar la inútil llamada a log(10).

4. Bien.

Sé que es sólo para comprobar, pero incluso con el código de prueba a disposición del público, creo que tenemos la responsabilidad de mostrar y utilizar las buenas prácticas.

Leeré otros artículos.

 
Alain Verleyen:

1. Bien.

2. No es necesario si normaliza su lote correctamente, algo así como :

Usar dígitos de lote sólo puede traer problemas.

3. log10 tiene el mismo problema, no es universal. Era sólo para evitar la inútil llamada a log(10).

4. Bien.

Sé que es sólo para comprobar, pero incluso con el código de prueba a disposición del público, creo que tenemos la responsabilidad de mostrar y utilizar las buenas prácticas.

Leeré otros artículos.

DE ACUERDO. Gracias
 

Hola

Puedes considerarme tu entrante o alumno por así decirlo.

Decidí estudiar su biblioteca, pero es difícil para mí, aunque sé algo en MQL, pero me tropecé en el primer paso.

Llegué al punto Implementación del método de comparación de dos órdenes entre sí por una propiedad dada:

//+------------------------------------------------------------------+
//|| Compara los objetos COrder entre sí en todas las propiedades posibles||
//+------------------------------------------------------------------+
int COrder::Compare(const CObject *node,const int mode=0) const
  {
   const COrder *order_compared=node;
//--- comparación de propiedades enteras de dos órdenes
   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);
     }
//--- comparación de propiedades reales de dos órdenes
   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);
     }
//--- comparación de propiedades de cadena de dos órdenes
   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;
  }
//+------------------------------------------------------------------+

Este es el código en la biblioteca, donde escribirlo

después de

   //--- Compara los objetos COrder entre sí en todas las propiedades posibles
   virtual int       Compare(const CObject *node,const int mode=0) const;

o en la clase protegida del orden abstracto.

protected:
   //--- Constructor paramétrico protegido
                     COrder(ENUM_ORDER_STATUS order_status,const ulong ticket);
                     
   //--- Obtiene y devuelve propiedades enteras de la orden seleccionada a partir de sus parámetros
   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;
   
   //--- Obtiene y devuelve propiedades reales de la orden seleccionada a partir de sus parámetros: (1) precio de apertura, (2) precio de cierre, (3) beneficio,
   //--- (4) comisión, (5) swap, (6) volumen, (7) volumen pendiente (8) precio StopLoss, (9) precio TakeProfit (10) precio de ajuste de la orden 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;
   
   //--- Obtiene y devuelve propiedades de cadena de la orden seleccionada a partir de sus parámetros: (1) símbolo, (2) comentario, (3) identificador de bolsa
   string            OrderSymbol(void)             const;
   string            OrderComment(void)            const;
   string            OrderExternalID(void)         const;
   
public:
   //--- Devuelve las propiedades (1) integer, (2) real y (3) string de la orden desde el array de propiedades
   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)];  }
   
   //--- Devuelve la bandera de que la orden mantiene la propiedad dada
   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; }

Por favor, comprended que ya no soy joven, los jóvenes pueden captar esto al vuelo.

Y también he abierto un tema en el foro en Artículos y biblioteca técnica en el comercio automatizado (12560) Soy un estudiante allí voy a duplicar este tema me gustaría una respuesta de usted en detalle acerca de la estructura,

trabajando paso a paso de acuerdo con el artículo . Usted puede estar equivocado y no entiendo.

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

Hola

Puedes considerarme tu aspirante o alumno por así decirlo.

He decidido estudiar su biblioteca, pero es difícil para mí, aunque sé algo en MQL, pero me tropecé en el primer paso.

Llegué al punto Realización del método de comparación de dos órdenes entre sí por una propiedad dada:

Este es el código en la biblioteca, donde escribirlo

después de

o en la clase protegida del orden abstracto

Por favor, comprenda que ya no soy joven, pero los jóvenes pueden entenderlo al vuelo.

Y también he abierto un tema en el foro en Artículos y biblioteca técnica sobre el comercio automatizado (12560) Soy un estudiante allí voy a duplicar este tema me gustaría una respuesta detallada de usted acerca de la estructura,

trabajando paso a paso de acuerdo con el artículo . Usted puede estar equivocado y no entiendo.

Hay dos maneras de crear un método de clase - es directamente en el cuerpo de la clase:

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

y fuera del cuerpo de la clase:

class CMyClass
  {
   bool Flag(void);
  }
//--- método implementado fuera del cuerpo de la clase
bool CMyClass::Flag(void) { return false; }

En el primer caso, el método se define e implementa directamente en el cuerpo de la clase - es conveniente hacerlo para métodos cortos que no ocupan muchas líneas. Pero si el método es grande, es más conveniente declararlo en el cuerpo de la clase, y poner la implementación fuera del cuerpo de la clase - como en el segundo ejemplo.

Está claro que es más conveniente escribir el método dentro del cuerpo de la clase. Pero el método sobre el que preguntas es más conveniente escribirlo separado del cuerpo de la clase.

No obstante, puede descargar todos los archivos adjuntos al artículo - ya contienen todo, están listos para usar - y utilizarlos para estudiar lo que se describe en el artículo.