Discussão do artigo "Aprendendo a construindo um EA que opera de forma automática (Parte 08): OnTradeTransaction"
Tenho um problema que me confunde.
Obrigado por dedicar um artigo tão maravilhoso. Tenho um problema que me confunde. Escrevi um código para abrir uma posição.
Ele pode retornar o valor correto quando executado em uma conta demo, mas retorna 0 quando executado em uma conta real.
//+------------------------------------------------------------------+ //|& nbsp;   Test1.mq5 //|& nbsp; Copyright 2023, MetaQuotes Ltd. //|& nbsp;   ; https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #include <Trade\Trade.mqh> CTrade m_trade; CDealInfo m_deal; //+------------------------------------------------------------------+ //| Funções de inicialização de comércio da EA & nbsp;   ; | //+------------------------------------------------------------------+ int OnInit() { //--- EventSetMillisecondTimer(1); OpenPosition(ORDER_TYPE_BUY, 0.01, 123456); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //|& nbsp;   nbsp;   nbsp;   //+------------------------------------------------------------------+ void OnDeinit(const int reason) { EventKillTimer(); } //+------------------------------------------------------------------+ //| EA Quotation Function & nbsp;   ; || //+------------------------------------------------------------------+ void OnTick() { //--- } //+------------------------------------------------------------------+ //|& nbsp;   nbsp;   nbsp;   //+------------------------------------------------------------------+ void OnTimer() { } //+------------------------------------------------------------------+ //|& nbsp;   nbsp;   nbsp;   //+------------------------------------------------------------------+ ulong OpenPosition(const ENUM_ORDER_TYPE type, const double lot, const long magic) { double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); m_trade.SetExpertMagicNumber(magic); if(m_trade.PositionOpen(_Symbol, type, lot, (type == ORDER_TYPE_BUY) ? ask : bid, 0, 0)) { ulong deal_ticket = m_trade.ResultDeal(); if(HistoryDealSelect(deal_ticket)) m_deal.Ticket(deal_ticket); string flag = (m_deal.DealType() == DEAL_TYPE_BUY) ? "buy" : "sell"; printf(StringFormat("open deal ticket= #%%d order ticket= #%%d %%s %%.2f %%s at %%.%df", _Digits), deal_ticket, m_deal.Order(), flag, m_deal.Volume(), _Symbol, m_deal.Price()); return(deal_ticket); } return(0); }
Olá, Daniel José
Obrigado por dedicar um artigo tão maravilhoso. Estou com um problema que me confunde. Eu escrevi um código para abrir uma posição.
Ele pode retornar o valor correto quando é executado em conta demo, mas retorna 0 quando é executado em uma conta real, você pode me ajudar a informar onde está o problema? á o problema?
Tente verificar o erro que está sendo retornado, adicionando a linha destacada logo abaixo.
ulong OpenPosition( const ENUM_ORDER_TYPE type, const double lot, const long magic) { double ask = SymbolInfoDouble ( _Symbol , SYMBOL_ASK ); double bid = SymbolInfoDouble ( _Symbol , SYMBOL_BID ); m_trade.SetExpertMagicNumber(magic); if (m_trade.PositionOpen( _Symbol , type, lot, (type == ORDER_TYPE_BUY ) ? ask : bid, 0 , 0 )) { ulong deal_ticket = m_trade.ResultDeal(); if ( HistoryDealSelect (deal_ticket)) m_deal.Ticket(deal_ticket); string flag = (m_deal.DealType() == DEAL_TYPE_BUY ) ? "buy" : "sell" ; printf ( StringFormat ( "open deal ticket= #%%d order ticket= #%%d %%s %%.2f %%s at %%.%df" , _Digits ), deal_ticket, m_deal.Order(), flag, m_deal.Volume(), _Symbol , m_deal.Price()); return (deal_ticket); } Print("Error: ", m_trade.ResultRetcode()); return ( 0 ); }
Tente verificar o erro que está sendo retornado, adicionando a linha destacada logo abaixo.
Não, meu objetivo é retornar um ticket de transação
Ele pode retornar o ticket de transação da posição na conta Demo, mas retorna valor zero na conta Real.
ulong OpenPosition(const ENUM_ORDER_TYPE type, const double lot, const long magic) { double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); m_trade.SetExpertMagicNumber(magic); if(m_trade.PositionOpen(_Symbol, type, lot, (type == ORDER_TYPE_BUY) ? ask : bid, 0, 0)) return(m_trade.ResultDeal()); return(0); }
Não, meu objetivo é devolver um bilhete de acordo
ele pode retornar ticket de negociação da posição na conta Demo, mas retornar valor zero na conta Real, isso é para quê?
A linha que mandei você adicionar NÃO É... vou repetir. NÃO É para retornar nenhum valor ... ELA SERVE PARA VERIFICAR O ERRO que está dando ao tentar abrir uma posição ... você nÃO deve usar o valor retornado... você deve verificar o ERRO na tabela de erros... Veja a DOCUMENTAÇÃO
Olá, estou acompanhando esta série de artigos. Meus respeitos. É realmente útil.
Estou testando o resultado e, depois de criar uma ordem, eu a excluo. Mas a EA não permite mais criar nenhuma nova ordem.
Este trecho de código:
case TRADE_TRANSACTION_ORDER_DELETE : if (trans.order == trans.position) (*manager).PendingToPosition(); else (*manager).UpdatePosition(trans.position); // ORDER? break ;
Ele usa trans.position que, no caso de exclusão da ordem, é sempre 0. Portanto, esse é o valor passado para UpdatePosition. Sua primeira condição o envia diretamente para a instrução return.
Tentei passar o ticket trans.order, mas o código o ignora porque m_position tem dados zero, portanto o ticket é 0 (! = m_Position.Ticket):
Depois dessa. Quando tento criar um novo pedido, m_ticketPending tem o valor do primeiro pedido, portanto, ele não é criado.
EraseTicketPending não é chamado porque quando TRADE_ACTION_REMOVE chega, essa condição é sempre falsa, porque request .request.TRADE_ACTION_REMOVE é sempre falsa.
if ((request.symbol == _Symbol ) && (result.retcode == TRADE_RETCODE_DONE ) && (request.magic == def_MAGIC_NUMBER))
é sempre falsa, pois request.magic é 0.
Investigarei se isso foi corrigido nos próximos capítulos.
Atenciosamente
Acho que encontrei o problema.
Quando a exclusão da ordem é feita na interface do usuário do MT5, o número mágico é 0. Então, modifiquei a condição para
if ((request.symbol == _Symbol ) && (result.retcode == TRADE_RETCODE_DONE ) && ((request.magic == def_MAGIC_NUMBER) || request.magic == 0 ))
e ela parece funcionar como esperado.
Oi, Daniel José.
Obrigado por dedicar um artigo tão maravilhoso. Tenho um problema que me confunde. Escrevi um código para abrir uma posição.
Ele pode retornar o valor correto quando executado em uma conta demo, mas retorna 0 quando executado em uma conta real.
Essa função abre a posição e retorna o DEAL TICKET:
//+------------------------------------------------------------------+ //|& nbsp;   Test1.mq5 //|& nbsp; Copyright 2023, MetaQuotes Ltd. //|& nbsp;   ; https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #include <Trade\Trade.mqh> #include <Trade\SymbolInfo.mqh> CTrade m_trade; CDealInfo m_deal; CSymbolInfo m_symbol; input double TakeProfit = 0; input double StopLoss = 0; input string PositionComment = ""; double m_point; //+------------------------------------------------------------------+ //| Funções de inicialização de comércio da EA & nbsp;   ; | //+------------------------------------------------------------------+ int OnInit() { //--- EventSetMillisecondTimer(1); if(!m_symbol.Name(_Symbol)) // define o nome do símbolo return(INIT_FAILED); RefreshRates(); m_trade.SetMarginMode(); m_trade.SetTypeFillingBySymbol(m_symbol.Name()); m_trade.SetDeviationInPoints(INT_MAX); int adjust = (m_symbol.Digits() == 3 || m_symbol.Digits() == 5) ? 10 : 1; m_point = m_symbol.Point() * adjust; //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //|& nbsp;   nbsp;   nbsp;   //+------------------------------------------------------------------+ void OnDeinit(const int reason) { EventKillTimer(); } //+------------------------------------------------------------------+ //| EA Quotation Function & nbsp;   ; || //+------------------------------------------------------------------+ void OnTick() { //--- } //+------------------------------------------------------------------+ //|& nbsp;   nbsp;   nbsp;   //+------------------------------------------------------------------+ void OnTimer() { } //+------------------------------------------------------------------+ //|& nbsp;   nbsp;   nbsp;   //+------------------------------------------------------------------+ bool RefreshRates(void) { //--- taxas de atualização if(!m_symbol.RefreshRates()) { Print("RefreshRates error"); return(false); } //--- proteção contra o valor de retorno "zero" if(m_symbol.Ask() == 0 || m_symbol.Bid() == 0) return(false); //--- return(true); } //+------------------------------------------------------------------+ //|& nbsp;   nbsp;   nbsp;   //+------------------------------------------------------------------+ ulong OpenPosition(const ENUM_ORDER_TYPE type, const double volume, const long magic) { ulong deal_ticket = 0; double sl = 0; double tp = 0; m_trade.SetExpertMagicNumber(magic); RefreshRates(); double ask = m_symbol.Ask(); double bid = m_symbol.Bid(); switch(type) { case ORDER_TYPE_BUY: if(TakeProfit > 0) tp = m_symbol.NormalizePrice(ask + TakeProfit * m_point); if(StopLoss > 0) sl = m_symbol.NormalizePrice(bid - StopLoss * m_point); break; case ORDER_TYPE_SELL: if(TakeProfit > 0) tp = m_symbol.NormalizePrice(bid - TakeProfit * m_point); if(StopLoss > 0) sl = m_symbol.NormalizePrice(ask + StopLoss * m_point); break; } static datetime from_date = iTime(m_symbol.Name(), PERIOD_D1, 0); ulong time = GetTickCount64(); if(m_trade.PositionOpen(m_symbol.Name(), type, volume, (type == ORDER_TYPE_BUY) ? ask : bid, sl, tp, PositionComment)) { ulong open_execution = GetTickCount64() - time; do { ulong order_ticket = m_trade.ResultOrder(); HistorySelect(from_date, TimeTradeServer()); int total = HistoryDealsTotal(); for(int i = total - 1; i >= 0; i--) { if(!m_deal.SelectByIndex(i)) continue; if(m_deal.Symbol() != m_symbol.Name()) continue; if(m_deal.Entry() != DEAL_ENTRY_IN) continue; if(m_deal.Order() != order_ticket) continue; printf(StringFormat("open #%%I64u %%s %%.2f %%s at %%.%df done in %%I64u ms", m_symbol.Digits()), m_deal.Order(), (type == ORDER_TYPE_BUY) ? "buy" : "sell", m_deal.Volume(), m_deal.Symbol(), m_deal.Price(), open_execution); from_date = m_deal.Time(); deal_ticket = m_deal.Ticket(); break; } } while(deal_ticket == 0); } return(deal_ticket); } //+------------------------------------------------------------------+
Comecei a usá-lo para capturar eventos (abrir uma posição, fechar, modificar) como fazia antes no MT4 (verificando constantemente as posições para adivinhar o que aconteceu). Nesse aspecto, a abordagem do MT5 é muito limpa.
MAS O QUE ACONTECE SE O EA estiver PARADO ou DESLIGADO DURANTE UMA HORA: ele não receberá nenhum evento, é claro, mas quando for reiniciado, não receberá os eventos que foram bagunçados durante uma hora. Portanto, para adivinhar o que aconteceu, ele precisará fazer como no antigo MT4, analisando as posições para adivinhar o que aconteceu. Para resolver esse problema, preciso manter as duas formas de detectar eventos: a forma MT5 e a forma MT4 como backup.
Para posições de mercado, é imediato.
Concordo... é por isso que, durante a inicialização do Expert Advisor, é feita uma verificação das posições ou ordens pendentes. Mas isso é visto em um artigo um pouco mais adiante nesta mesma sequência.
Tradução automatizada aplicada pelo moderador
- 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 Aprendendo a construindo um EA que opera de forma automática (Parte 08): OnTradeTransaction foi publicado:
Neste artigo, mostrei como você pode usar o sistema de tratamento de eventos, a fim de conseguir lidar com mais agilidade, e de uma forma melhor com questões envolvendo o sistema de ordens, a fim de deixar o EA mais rápido. Assim ele não precisará, ficar procurando informações a todo o momento.
Mas agora, de uma forma bem mais completa, temos finalmente a classe C_Manager e o EA, sendo amistosos um com o outro. A ponto que ambos consigam trabalhar, e garantir que não sejam agressivos, ou pouco cordiais. Desta forma, o fluxo de mensagens entre o EA e a classe C_Manager, passa a ser da seguinte maneira, vista na figura 02:
Figura 02: Fluxo de mensagens com as novas rotinas implementadas.
Você pode achar que este fluxo de mensagens, é muito complicado, ou não é nada funcional. Mas no entanto, ele é exatamente o que esta sendo implementado.
Mas então com base na figura 02, você deve estar pensando que o código do EA deve ser muito complicado. Mas no entanto, ele é bem mais simples do que muitos consideram ser um código necessário, para de fato ser usado em um EA. Ainda mais um que estará sendo automatizado. Lembre-se do seguinte: O EA, não gera de fato nenhuma operação. Ele apenas é um meio, ou ferramenta para se comunicar com o servidor de negociação. Então ele na verdade, apenas reage aos gatilhos que são aplicados a ele.
Autor: Daniel Jose