Discussão do artigo "Biblioteca para desenvolvimento fácil e rápido de programas para a MetaTrader (parte XI). Compatibilidade com a MQL4 - Eventos de encerramento de posição"
Tenho algumas observações relacionadas ao efeito das variáveis de tempo de milissegundos e, particularmente, sobre afunção CHistoryCollection::GetListByTime(...) em relação à versão MQL5.
Elas são (em ordem decrescente de relevância):
1) Tanto as variáveis datetime quanto as variáveis de tempo de milissegundos longos representam o tempo decorrido desde 01/01/1970. No entanto, há um fator de 1000 entre os valores efetivamente armazenados. Portanto, os dois tipos não podem ser atribuídos diretamente um ao outro. Como consequência, o GetListByTime(...) parou de funcionar após a alteração, pois armazena diretamente os parâmetros de data e hora na propriedade time millisecond do COrder m_order_instance. Uma possível solução poderia ser incluir duas novas funções de conversão (provavelmente em delib.mqh) para cuidar desse fator 1000:
//+------------------------------------------------------------------+ //| Converte o tempo em milissegundos para datetime //+------------------------------------------------------------------+ datetime TimeMSCtoDate(const long time_msc) { return datetime(time_msc/1000); } //+------------------------------------------------------------------+ //| Converte datetime em tempo em milissegundos //+------------------------------------------------------------------+ long DatetoTimeMSC(const datetime time_sec) { return long(time_sec * 1000); }
Esse tipo de problema não aconteceria se a MetaQuotes tivesse definido desde o início as variáveis datetime como o tempo decorrido em milissegundos, ou mesmo em microssegundos (quem disse que em dez anos os robôs não estarão negociando em menos de milissegundos?).
De qualquer forma, o problema também está presente pelo menos nas funções GetListByTime(...) nas classes CEventsCollection e CMarketCollection, talvez em outros lugares...
2) A coleção History é um objeto que sabe se está classificada ou não e, se estiver, qual é a propriedade de classificação (funçãoSortMode() ), enquanto a função GetListByTime(...) pressupõe que a coleção já esteja classificada pelas propriedades ORDER_PROP_TIME_OPEN ou ORDER_PROP_TIME_CLOSE (apenas ORDER_PROP_TIME_OPEN nas versões CEventsCollection e CMarketCollection ). Seguindo a filosofia OOP, GetListByTime(...) deve verificar se a coleção está classificada corretamente antes de continuar.
De fato, o exemplo de programa TestDoEasyPart03_1.mq5 criou uma coleção de histórico ordenada por ORDER_PROP_TIME_OPEN (o padrão no MT5) e, em seguida, chamou GetListByTime(...,SELECT_BY_TIME_CLOSE). Com essa verificação, isso teria aparecido!
3) Não é grande coisa, mas como o MT5 deve ser o novo padrão, por que não deixar que SELECT_BY_TIME_OPEN seja o valor padrão do parâmetro select_time_mode da função CHistoryCollection::GetListByTime(...)?
Seguindo as sugestões anteriores, este seria o código da função CHistoryCollection::GetListByTime(...):
public: ....... //--- Selecione os pedidos da coleção com o tempo de begin_time a end_time CArrayObj *GetListByTime(const datetime begin_time=0,const datetime end_time=0, const ENUM_SELECT_BY_TIME select_time_mode=SELECT_BY_TIME_OPEN); ....... //+------------------------------------------------------------------+ //| Selecionar ordens da coleção com tempo //| do begin_time ao end_time| //+------------------------------------------------------------------+ CArrayObj *CHistoryCollection::GetListByTime(const datetime begin_time=0,const datetime end_time=0, const ENUM_SELECT_BY_TIME select_time_mode=SELECT_BY_TIME_OPEN) { ENUM_ORDER_PROP_INTEGER property=(select_time_mode==SELECT_BY_TIME_CLOSE ? ORDER_PROP_TIME_CLOSE : ORDER_PROP_TIME_OPEN); if(property != (ENUM_ORDER_PROP_INTEGER)m_list_all_orders.SortMode()) { ::Print(DFUN+"History list not prpperly sorted"); //Talvez uma mensagem para adicionar ao ENUM_MESSAGES_LIB return NULL; } CArrayObj *list=new CArrayObj(); if(list==NULL) { ::Print(DFUN+CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_TEMP_LIST)); return NULL; } datetime begin=begin_time,end=(end_time==0 ? END_TIME : end_time); if(begin_time>end_time) begin=0; list.FreeMode(false); ListStorage.Add(list); //--- this.m_order_instance.SetProperty(property,DatetoTimeMSC(begin)); int index_begin=this.m_list_all_orders.SearchGreatOrEqual(&m_order_instance); if(index_begin==WRONG_VALUE) return list; this.m_order_instance.SetProperty(property,DatetoTimeMSC(end)); int index_end=this.m_list_all_orders.SearchLessOrEqual(&m_order_instance); if(index_end==WRONG_VALUE) return list; for(int i=index_begin; i<=index_end; i++) list.Add(this.m_list_all_orders.At(i)); return list; }
Tenho algumas observações relacionadas ao efeito das variáveis de tempo de milissegundos e, particularmente, sobre a função CHistoryCollection::GetListByTime(...) em relação à versão MQL5.
Elas são (em ordem decrescente de relevância):
1) As variáveis datetime e long millisecond time representam o tempo decorrido desde 01/01/1970. No entanto, há um fator de 1000 entre os valores efetivamente armazenados. Portanto, os dois tipos não podem ser atribuídos diretamente um ao outro. Como consequência, o GetListByTime(...) parou de funcionar após a alteração, pois armazena diretamente os parâmetros de data e hora na propriedade time millisecond do COrder m_order_instance. Uma possível solução poderia ser incluir duas novas funções de conversão (provavelmente no delib.mqh ) para cuidar desse fator 1000:
Esse tipo de problema não aconteceria se o MetaQuotes tivesse definido desde o início as variáveis datetime como sendo o tempo decorrido em milissegundos, ou mesmo em microssegundos (quem disse que em dez anos os robôs não estarão negociando em menos de milissegundos?)
De qualquer forma, o problema também está presente pelo menos nas funções GetListByTime(...) nas classes CEventsCollection e CMarketCollection, talvez em outros lugares...
2) A coleção History é um objeto que sabe se está classificada ou não e, se estiver, qual é a propriedade de classificação (. SortMode() ), enquanto a função GetListByTime(...) pressupõe que a coleção já esteja classificada pelas propriedades ORDER_PROP_TIME_OPEN ou ORDER_PROP_TIME_CLOSE (apenas ORDER_PROP_TIME_OPEN nas versões CEventsCollection e CMarketCollection ). Seguindo a filosofia OOP, GetListByTime(...) deve verificar se a coleção está classificada corretamente antes de continuar.
De fato, o exemplo de programa TestDoEasyPart03_1.mq5 criou uma coleção de histórico ordenada por ORDER_PROP_TIME_OPEN (o padrão no MT5) e, em seguida, chamou GetListByTime(...,SELECT_BY_TIME_CLOSE). Com essa verificação, isso teria aparecido!
3) Não é grande coisa, mas como o MT5 deve ser o novo padrão, por que não deixar que SELECT_BY_TIME_OPEN seja o valor padrão do parâmetro select_time_mode da função CHistoryCollection::GetListByTime(...)?
Seguindo as sugestões anteriores, este seria o código da função CHistoryCollection::GetListByTime(...):
Obrigado. Nas versões posteriores da biblioteca (nos artigos acima do XI), parece que a conversão de tempo já é usada (geralmente deixo o datetime - tudo está em long).
Eu não entendi um pouco sobre coleções - por favor, mostre um exemplo de classificação errada. Desejável no artigo mais recente disponível (já que os artigos descrevem a sequência de criação de uma biblioteca, e tudo muda)
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso
Novo artigo Biblioteca para desenvolvimento fácil e rápido de programas para a MetaTrader (parte XI). Compatibilidade com a MQL4 - Eventos de encerramento de posição foi publicado:
Nós continuamos com o desenvolvimento de uma grande biblioteca multi-plataforma, simplificando o desenvolvimento de programas para as plataformas MetaTrader 5 e MetaTrader 4. Na décima parte, nós retomamos nosso trabalho sobre a compatibilidade da biblioteca com a MQL4 e definimos os eventos de abertura de posições e ativação de ordens pendentes. Neste artigo, nós definiremos os eventos de encerramento de posições e nos livraremos das propriedades de ordem não utilizadas.
Agora, os eventos de encerramento parcial e remoção de ordem pendente são definidos como eventos separados.
Inicie o EA novamente e clique nos botões observando as definição de eventos:
Como nós podemos ver, os eventos estão definidos corretamente. Um evento de encerramento é definido, modificações nos níveis de stop e preços de ordens pendentes também são rastreados.
Autor: Artyom Trishkin