Discussão do artigo "Biblioteca para desenvolvimento fácil e rápido de programas para a MetaTrader (parte I). Conceito, gerenciamento de dados e primeiros resultados" - página 4

 
fxsaber:

Obrigado, a explicação está clara. Mas ainda há uma pergunta - está claro que é mais rápido no MT4, mas se estivermos falando de 5 - é mais rápido executar todos os métodos separadamente do que chamar um CopyRates? Se sim, então faz sentido criar uma estrutura/classe de barra em vez de MQLRates, que escreveria não todos os campos, mas apenas os necessários em nosso caso, por máscara, por exemplo.

 
alex_all:

Obrigado, a explicação está clara. Mas ainda há uma pergunta - está claro que é mais rápido no MT4, mas se estivermos falando de 5 - é mais rápido executar todos os métodos separadamente do que chamar um CopyRates? Se sim, faz sentido criar sua própria estrutura/classe de barra em vez de MQLRates, que escreveria não todos os campos, mas apenas os necessários em nosso caso, por máscara, por exemplo.

Tente fazer isso.

 
Nenhuma atualização?
 
soldadoraso21:
Você não vai atualizar?

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

Não estou entendendo a pergunta.

 

Como se trata de uma biblioteca em desenvolvimento, aguardarei mais artigos antes de fazer qualquer comentário global.

No entanto, notei duas situações problemáticas em potencial nessa primeira parte:

Em primeiro 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:

//+------------------------------------------------------------------+
//| Retorna o número de casas decimais em um lote de símbolos
//+------------------------------------------------------------------+
uint DigitsLots(conststring symbol_name) 
  { 
   return (int)ceil(fabs(log(SymbolInfoDouble(symbol_name,SYMBOL_VOLUME_STEP))/log(10)));
  }

1.a A solução proposta usando log não é universal. Em alguns símbolos, você pode perfeitamente ter uma etapa de volume de 0,25, por exemplo, e o DigitsLots() retornará uma resposta errada nesse caso.

1.b Por que você quer o "número de casas decimais em um lote de símbolo"? Não vejo nenhum caso de uso real para isso.

1.c Se você realmente quiser usar a função log e for lidar com casos especiais em outro lugar, deverá usar log10, em vez de logaritmo natural.

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

1.d Fornecer essa função na interface pública pode levar a resultados ineficientes, pois ela usa 5 chamadas de função e pode ser chamada várias vezes em cada tick.


Em 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 Essa não é a maneira correta de chamar HistorySelect(), pois você pode perder algumas informações do histórico, já que TimeCurrent() retorna a última data de tick conhecida do servidor do corretor. Justificativa aqui e por experiência própria.

2.b É um mau exemplo usar TimeCurrent() na função OnInit() quando não há garantia de conexão com o corretor. Em geral, é uma má ideia fazer qualquer solicitação de dados em OnInit().

 

Obrigado pelos comentários, mas este é apenas um teste.

  1. Considerarei a possibilidade de alterar a função para outra - completamente universal
  2. O número de casas decimais para o lote de cada símbolo individual é necessário para o envio inequívoco de ordens de negociação
  3. Sua função com log10 não tem o problema mencionado por você com uma etapa de lote de 0,25?
  4. Os dados sobre o número de casas decimais são gravados uma vez no objeto da classe-símbolo. Isso será aprofundado em artigos posteriores.

Uma verificação de teste em OnInit () é necessária apenas para verificação. E somente lá eu obtenho o histórico de ordens dessa forma. Em coleções de ordens, negócios e posições - caso contrário.

Tudo isso em artigos posteriores.

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

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

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

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

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

Obrigado pelos comentários, mas este é apenas um teste.

  1. Considerarei a possibilidade de alterar a função para outra - completamente universal
  2. O número de casas decimais para o lote de cada símbolo individual é necessário para o envio inequívoco de ordens de negociação
  3. Sua função com log10 não tem o problema mencionado por você com uma etapa de lote de 0,25?
  4. Os dados sobre o número de casas decimais são gravados uma vez no objeto da classe-símbolo. Isso será abordado em artigos posteriores.

Uma verificação de teste em OnInit () é necessária apenas para verificação. E somente lá eu obtenho o histórico de ordens dessa forma. Em coleções de ordens, negócios e posições - caso contrário.

Tudo isso em artigos posteriores.


1. Bom.

2. Isso não é necessário se você normalizar seu lote corretamente, algo como :

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

Usar os dígitos do lote só pode levar a problemas.

3. log10 tem o mesmo problema, não é universal. Foi apenas para evitar a chamada inútil para log(10).

4. Bom.

Sei que é apenas para verificar, mas mesmo com o código de teste disponível publicamente, acho que temos a responsabilidade de mostrar e usar boas práticas.

Lerei outros artigos.

 
Alain Verleyen:

1. Bom.

2. Não é necessário se você normalizar seu lote corretamente, algo como :

Usar os dígitos do lote só pode causar problemas.

3. log10 tem o mesmo problema, não é universal. Foi apenas para evitar a chamada inútil para log(10).

4. Bom.

Sei que é apenas para verificar, mas mesmo com o código de teste disponível publicamente, acho que temos a responsabilidade de mostrar e usar boas práticas.

Lerei outros artigos.

OK. Obrigado pela atenção
 

Olá

Você pode me considerar seu participante ou aluno, por assim dizer.

Decidi estudar sua biblioteca, mas é difícil para mim, embora eu saiba algumas coisas em MQL, mas tropecei na primeira etapa.

Cheguei ao ponto Implementação do método de comparação de duas ordens entre si por uma determinada propriedade:

//+------------------------------------------------------------------+
//|| Compara os objetos COrder entre si em todas as propriedades possíveis
//+------------------------------------------------------------------+
int COrder::Compare(const CObject *node,const int mode=0) const
  {
   const COrder *order_compared=node;
//--- comparação de propriedades inteiras de duas ordens
   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);
     }
//--- comparação de propriedades reais de duas ordens
   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);
     }
//--- comparação de propriedades de string de duas ordens
   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 é o código na biblioteca, onde escrevê-lo

depois de

   //--- Compara os objetos COrder entre si em todas as propriedades possíveis
   virtual int       Compare(const CObject *node,const int mode=0) const;

ou na classe protegida da ordem abstrata.

protected:
   //--- Construtor paramétrico protegido
                     COrder(ENUM_ORDER_STATUS order_status,const ulong ticket);
                     
   //--- Obtém e retorna propriedades inteiras do pedido selecionado a partir de seus 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;
   
   //--- Obtém e retorna propriedades reais da ordem selecionada a partir de seus parâmetros: (1) preço de abertura, (2) preço de fechamento, (3) lucro,
   //--- (4) comissão, (5) swap, (6) volume, (7) volume pendente (8) preço StopLoss, (9) preço TakeProfit (10) preço de configuração da ordem 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;
   
   //--- Obtém e retorna propriedades de cadeia de caracteres da ordem selecionada a partir de seus parâmetros: (1) símbolo, (2) comentário, (3) identificador de troca
   string            OrderSymbol(void)             const;
   string            OrderComment(void)            const;
   string            OrderExternalID(void)         const;
   
public:
   //--- Retorna as propriedades (1) integer, (2) real e (3) string da ordem a partir da matriz de propriedades
   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)];  }
   
   //--- Retorna o sinalizador de que a ordem mantém a propriedade fornecida
   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; }

Entenda que não sou mais jovem, os jovens conseguem entender isso na hora.

E também abri um tópico no fórum em Artigos e biblioteca técnica sobre negociação automatizada (12560), sou um estudante lá e vou duplicar este tópico,

trabalhando passo a passo de acordo com o artigo. Você pode estar errado e não entender.

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

Olá

Você pode me considerar seu candidato ou aluno, por assim dizer.

Decidi estudar sua biblioteca, mas é difícil para mim, embora eu saiba alguma coisa sobre MQL, mas tropecei na primeira etapa.

Cheguei ao ponto Realização do método de comparação de duas ordens entre si por uma determinada propriedade:

Este é o código na biblioteca, onde escrevê-lo

depois de

ou na classe protegida da ordem abstrata

Entenda que não sou mais jovem, mas os jovens conseguem entender isso rapidamente.

E também abri um tópico no fórum em Artigos e biblioteca técnica sobre negociação automatizada (12560) Sou um estudante lá e vou duplicar este tópico Gostaria de uma resposta detalhada de vocês sobre a estrutura,

trabalhando passo a passo de acordo com o artigo. Você pode estar errado e não entender.

Há duas maneiras de criar um método de classe - diretamente no corpo da classe:

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

e fora do corpo da classe:

class CMyClass
  {
   bool Flag(void);
  }
//--- método implementado fora do corpo da classe
bool CMyClass::Flag(void) { return false; }

No primeiro caso, o método é definido e implementado diretamente no corpo da classe - é conveniente fazer isso para métodos curtos que não ocupam muitas linhas. Mas se o método for grande, é mais conveniente declará-lo no corpo da classe e colocar a implementação fora do corpo da classe, como no segundo exemplo.

Está claro que é mais conveniente escrever o método dentro do corpo da classe. Mas o método sobre o qual você está perguntando é mais conveniente escrevê-lo separadamente do corpo da classe.

No entanto, você pode fazer download de todos os arquivos anexados ao artigo - eles já contêm tudo, estão prontos para uso - e usá-los para estudar o que está descrito no artigo.