Então @feliperamos,
Fez a função e não testou? Porque não sabe se esta certa homem!?
Fato é que você enviou false
if(!VerificarOrdensRejeitadas(ORDER_TYPE_BUY, false)
e verifica dentro da função se é true.
if(gravar)
Observe também que determinou como valor padrão para este parâmetro false
bool VerificarOrdensRejeitadas( ENUM_ORDER_TYPE tipo, bool gravar = false)
Não vai entrar...
Sugiro inicialmente coletar dados para entender porque suas ordens foram rejeitadas.
Foi o stop com valor errado ou profit?
stop/profit = 0 |
"fora do tick"...tick para win é 5 mandou o valor de 106212
Foi negado/rejeitado devido ao volume?
não tinha contrato disponível para minha ordem BuyStop/SellStop
Assim, para um novo reenvio dessa ordem você teria como tratar o problema e reenviar a ordem com a atualização necessária.
Mas, se desejar prossegui evitando essa parte, a sugestão do @Eduardo Oliveira resolve
if(!PositionSelect() && reenviar_ordem) { //Reenvie sua ordem novamente //Se o seu contador chegar ao limite que você determinou //Ative a flag para reenviar_ordem como o eduardo sugeriu }; //Implemente uma função que, após um dado período ou candle reset o valor para o reenviar_ordem
Agora, se deseja ter alguns dados sobre as operações que tem ou não sido realizado enquanto sua EA esta rodando, trabalha com uma struct coletando estes dados, vai facilitar em tudo sua vida, apesar de algum trabalho que terá para implementar.
Sucesso por aí
O MQL5 é uma m* para tratamento de eventos. Não tem Hooks suficientes para tratar as inúmeras falhas que podem ocorrer durante um trade.
No seu caso eu sugir aguardar o retorno no OnTradeTransaction().
Não adianta aguardar X segundos.
Os eventos de retorno e ocorrências de uma conta DEMO são diferentes na conta REAL.
Uma coisa é tratar uma exceção, a outra é tentar conviver com corretora ruim. Mude de corretora também.
;)
O MQL5 é uma m* para tratamento de eventos. Não tem Hooks suficientes para tratar as inúmeras falhas que podem ocorrer durante um trade.
No seu caso eu sugir aguardar o retorno no OnTradeTransaction().
Não adianta aguardar X segundos.
Os eventos de retorno e ocorrências de uma conta DEMO são diferentes na conta REAL.
Uma coisa é tratar uma exceção, a outra é tentar conviver com corretora ruim. Mude de corretora também.
;)
eu fiz dessa forma com essa função no OnTradeTransaction(). Agradeço Flavio e sucesso pra ti.
//+------------------------------------------------------------------+ //| TradeTransaction function | //+------------------------------------------------------------------+ void OnTradeTransaction(const MqlTradeTransaction &trans, const MqlTradeRequest &request, const MqlTradeResult &result) { B.Encrypt(); //--- get transaction type as enumeration value ENUM_TRADE_TRANSACTION_TYPE type = trans.type; ENUM_ORDER_TYPE lastOrderType = trans.order_type; ENUM_ORDER_STATE lastOrderState = trans.order_state; string trans_symbol = trans.symbol; //VARIAVEIS DO ONTRADETRANSACTION bool m_need_delete_buy_stop = false; bool m_need_delete_sell_stop = false; bool m_need_place_buy_stop = false; bool m_need_place_sell_stop = false; double ExtLot = 0.0; if(trans_symbol != _Symbol) { return; } if(lastOrderState == ORDER_STATE_REJECTED) {//========================================================== VerificarOrdensRejeitadas(lastOrderType, true);//========================================================== } //--- if transaction is result of addition of the transaction in history if(type == TRADE_TRANSACTION_DEAL_ADD) { long deal_ticket = 0; long deal_order = 0; long deal_time = 0; long deal_time_msc = 0; long deal_type = -1; long deal_entry = -1; long deal_magic = 0; long deal_reason = -1; long deal_position_id = 0; double deal_volume = 0.0; double deal_price = 0.0; double deal_commission = 0.0; double deal_swap = 0.0; double deal_profit = 0.0; string deal_symbol = ""; string deal_comment = ""; string deal_external_id = ""; if(HistoryDealSelect(trans.deal)) { deal_ticket = HistoryDealGetInteger(trans.deal, DEAL_TICKET); deal_order = HistoryDealGetInteger(trans.deal, DEAL_ORDER); deal_time = HistoryDealGetInteger(trans.deal, DEAL_TIME); deal_time_msc = HistoryDealGetInteger(trans.deal, DEAL_TIME_MSC); deal_type = HistoryDealGetInteger(trans.deal, DEAL_TYPE); deal_entry = HistoryDealGetInteger(trans.deal, DEAL_ENTRY); deal_magic = HistoryDealGetInteger(trans.deal, DEAL_MAGIC); deal_reason = HistoryDealGetInteger(trans.deal, DEAL_REASON); deal_position_id = HistoryDealGetInteger(trans.deal, DEAL_POSITION_ID); deal_volume = HistoryDealGetDouble(trans.deal, DEAL_VOLUME); deal_price = HistoryDealGetDouble(trans.deal, DEAL_PRICE); deal_commission = HistoryDealGetDouble(trans.deal, DEAL_COMMISSION); deal_swap = HistoryDealGetDouble(trans.deal, DEAL_SWAP); deal_profit = HistoryDealGetDouble(trans.deal, DEAL_PROFIT); deal_symbol = HistoryDealGetString(trans.deal, DEAL_SYMBOL); deal_comment = HistoryDealGetString(trans.deal, DEAL_COMMENT); deal_external_id = HistoryDealGetString(trans.deal, DEAL_EXTERNAL_ID); } else return; if(deal_symbol == simbolo.Name() && deal_magic == in_magic) { if(deal_entry == DEAL_ENTRY_IN) { if(deal_type == DEAL_TYPE_BUY || deal_volume == DEAL_TYPE_SELL) { m_need_delete_buy_stop = true; m_need_delete_sell_stop = true; ExtLot = in_volume * 2.0; m_need_place_buy_stop = true; m_need_place_sell_stop = true; } } } } }
Então @feliperamos,
Fez a função e não testou? Porque não sabe se esta certa homem!?
Fato é que você enviou false
e verifica dentro da função se é true.
Observe também que determinou como valor padrão para este parâmetro false
Não vai entrar...
Sugiro inicialmente coletar dados para entender porque suas ordens foram rejeitadas.
Foi o stop com valor errado ou profit?
stop/profit = 0 |
"fora do tick"...tick para win é 5 mandou o valor de 106212
Foi negado/rejeitado devido ao volume?
não tinha contrato disponível para minha ordem BuyStop/SellStop
Assim, para um novo reenvio dessa ordem você teria como tratar o problema e reenviar a ordem com a atualização necessária.
Mas, se desejar prossegui evitando essa parte, a sugestão do @Eduardo Oliveira resolve
Agora, se deseja ter alguns dados sobre as operações que tem ou não sido realizado enquanto sua EA esta rodando, trabalha com uma struct coletando estes dados, vai facilitar em tudo sua vida, apesar de algum trabalho que terá para implementar.
Sucesso por aí
Ok guerreiro, agradeço por ajudar irei testar essas opções. Grato sucesso
Não sei se estou viajando na maionese, mais será que tem alguma função que evite algum bug vindo da corretora que possa fazer o robô entrar em um loop de envios de ordens?
Olá Felipe,
o MT5 é um bicho de sete cabeças no tocante a travamentos. Depois de sofrer alguns prejuízos e brigar com as corretoras, escrevi a função que estou compartilhando. O objetivo da função é abortar o EA em caso de travamento de uma ordem por mais de 60 segundos.
Ela é chamada imediatamente após ao OrderSend().
Também é chamada no OnTimer(), porque também ocorre travamento nas ordens emitidas pelos gatilhos de SL/TP da posição.
void ToDoTravamentoOrdem() { int contOrderState = 0; bool flagOrdemTravada = false; do { for(int i = OrdersTotal() - 1; i >= 0; i--) { if(OrderSelect(OrderGetTicket(i))) { if(OrderGetString(ORDER_SYMBOL) == ativoOper && OrderGetInteger(ORDER_MAGIC) == inpMagicNumber && (OrderGetInteger(ORDER_STATE) == ORDER_STATE_STARTED || OrderGetInteger(ORDER_STATE) == ORDER_STATE_REQUEST_ADD)) { Sleep(100); flagOrdemTravada = true; contOrderState++; break; } } } } while(contOrderState < 600 && flagOrdemTravada == true); if(contOrderState >= 600) { string txt = strNomeEA + " Requer sua atenção, ordem travada: " + (string) OrderGetInteger(ORDER_TICKET) + " " + EnumToString((ENUM_ORDER_STATE) OrderGetInteger(ORDER_STATE)) ; Alert(txt); SendNotification(txt); ExpertRemove(); } }
Olá Felipe,
o MT5 é um bicho de sete cabeças no tocante a travamentos. Depois de sofrer alguns prejuízos e brigar com as corretoras, escrevi a função que estou compartilhando. O objetivo da função é abortar o EA em caso de travamento de uma ordem por mais de 60 segundos.
Ela é chamada imediatamente após ao OrderSend().
Também é chamada no OnTimer(), porque também ocorre travamento nas ordens emitidas pelos gatilhos de SL/TP da posição.
Obrigado Rogerio por compartilhar sua ideia , irei utilizar em meu projeto . Todas as ideias de sistemas de segurança e bem vinda. Agradeço!
Olá Felipe,
o MT5 é um bicho de sete cabeças no tocante a travamentos. Depois de sofrer alguns prejuízos e brigar com as corretoras, escrevi a função que estou compartilhando. O objetivo da função é abortar o EA em caso de travamento de uma ordem por mais de 60 segundos.
Ela é chamada imediatamente após ao OrderSend().
Também é chamada no OnTimer(), porque também ocorre travamento nas ordens emitidas pelos gatilhos de SL/TP da posição.
Eu fiz assim.
// Se bem sucessedida a verificação a ordem é enviada if(!OrderSend(request, result)) { // Mensagem exibida em caso de falha no envio da ordem printf(__FUNCTION__, "[%s] Erro %d no envio da ordem. Código %d (%s)", in_nome, GetLastError(), result.retcode, result.comment); PrintResultTrade(trade, simbolo); ToDoTravamentoOrdem(); return(false); } else printf(__FUNCTION__, "[%s] Sucesso no negócio [%d]. Código %d (%s)", in_nome, result.order, result.retcode, result.comment); PrintResultTrade(trade, simbolo); return(true); }
Na questão de atraso de ordem e entre outros similares, eu fiz isso para "simular" esse B.O, mais não sei se e útil.
//+------------------------------------------------------------------+ //| ProjectName | //| Copyright 2020, CompanyName | //| http://www.companyname.net | //+------------------------------------------------------------------+ #include <Trade/Trade.mqh> #include <Trade/Trade.mqh> #include <Trade\PositionInfo.mqh> #include <Trade\AccountInfo.mqh> //--- Load the class CTrade trade; CPositionInfo m_Position; struct s_posicoes { double volume; // Lot double lucro; // Lucro real da posição aberta, referente ao verdadeiro preço de saída datetime abertura; // Horário que se inicio a posição ulong ticket_compra; // Bilhete da posição se for de compra ulong ticket_venda; // Bilhete da posição de venda se existir ambas simultanemanetes, são fechadas entre si }; enum e_sn { nao = 0, // Não sim = 1 // Sim }; input double LotSize = 1.0; input int MagicNumber = 65262; input int Slippage = 10; input double ValorStop = 100.00; input double RelacaoGainStop = 3; input int HoraInicioOper = 09; input int MinInicioOper = 10; input int HoraFimOper = 17; input int MinFimOper = 30; input int HoraFechOper = 17; input int MinFechOper = 30; input bool DebugAtivo = true; input group "[■ slippeges BACKTEST ■]" input int slippeges = 100;//[■ slippeges BACKTEST/500=5MS ■] sinput e_sn in_hab_slippeges = true; //[■Habilitar slippeges BACKTEST ■] double Gain = 0; double Stop = 0; double TamanhoLote = 1; int Horario_Proxima_Verificacao = 0; ulong ticketCorrente = 0; MqlDateTime DataHoraAtu; double bid, ask, High[], Low[], Close[], Open[]; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnInit() { // parte efetivamente escrita para o trading: trade.SetExpertMagicNumber(MagicNumber); trade.SetDeviationInPoints(Slippage); trade.SetAsyncMode(false); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnTick() { s_posicoes posicao = posicionamento(); // Contabilizando posições abertas // obtem data e hora corrente TimeToStruct(TimeCurrent(), DataHoraAtu); // Verifica se está fora do horário de negociação definido em parâmetro if(RestringeHoraNegociacao()) return; ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK); bid = SymbolInfoDouble(Symbol(), SYMBOL_BID); if(TimeCurrent() > Horario_Proxima_Verificacao ) { if(!TemTradeAberto()) { VerificarEntradas(); } else { VerificarSaidas(); }}} //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool TemTradeAberto() { if(m_Position.Select(Symbol())) return true; else return false; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void VerificarEntradas() { int Numero = rand(); if(MathMod(Numero, 2) == 0.00) { Gain = ask + (ValorStop * RelacaoGainStop); Stop = ask - ValorStop; iniciar_SLIP();//========================================================================/////aqui if(!trade.Buy(TamanhoLote, Symbol())) { Print("Buy falhou: Cod. retorno= ", trade.ResultRetcode(), " Tamanho lote: ", TamanhoLote, "descricao: ", trade.ResultRetcodeDescription()); } Horario_Proxima_Verificacao = int(TimeLocal()) + 2; } else { Gain = bid - (ValorStop * RelacaoGainStop); Stop = bid + ValorStop; iniciar_SLIP();//========================================================================/////aqui if(!trade.Sell(TamanhoLote, Symbol())) { Print("Sell falhou: Cod. retorno= ", trade.ResultRetcode(), " Tamanho lote: ", TamanhoLote, "descricao: ", trade.ResultRetcodeDescription()); } Horario_Proxima_Verificacao = int(TimeLocal()) + 2; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void VerificarSaidas() { int pt = PositionsTotal(); for(int i = 0; i < pt; i++) { //Print("verificar saidas: ", PositionGetInteger(POSITION_MAGIC), " ", PositionGetInteger(POSITION_TYPE) ); if(PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetSymbol(i) == _Symbol) { if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { if(bid >= Gain || bid <= Stop) { ulong esteticket = trade.PositionClose(Symbol()); Horario_Proxima_Verificacao = int(TimeLocal()) + 2; } } else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) { if(ask <= Gain || ask >= Stop) { ulong esteticket = trade.PositionClose(Symbol()); Horario_Proxima_Verificacao = int(TimeLocal()) + 2 ; } } } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool RestringeHoraNegociacao() { int DtHrAtu = (DataHoraAtu.hour * 100) + DataHoraAtu.min; int DtHrIni = (HoraInicioOper * 100) + MinInicioOper; int DtHrFim = (HoraFimOper * 100) + MinFimOper; // se horário está entre hora ini e fim definidos, seguir com o EA // senão, verificar se tem posição aberta e encerrar o trade if(DtHrAtu >= DtHrIni && DtHrAtu <= DtHrFim) return false; else { if(TemTradeAberto()) { trade.PositionClose(Symbol()); if(DebugAtivo) Print("Fechou o trade por horário limite. Retcode ", trade.ResultRetcode()); } return true; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool DisplayInfoConta() { //--- objeto criado para carregar informacoes de conta CAccountInfo account; //--- variavel que recebe o numero da conta de trading long login = account.Login(); Print("Login=", login); //--- verifica tipo de conta ENUM_ACCOUNT_TRADE_MODE account_type = account.TradeMode(); //--- if the account is real, the Expert Advisor is stopped immediately! /* if(account_type==ACCOUNT_TRADE_MODE_REAL) { MessageBox("Trading on a real account is forbidden, disabling","The Expert Advisor has been launched on a real account!"); return(false); } */ //--- mostra o tipo de conta Print("Account type: ", EnumToString(account_type)); //--- emite aviso se o tipo de conta permite o trade: if(account.TradeAllowed()) Print("Trading on this account is allowed"); else Print("Trading on this account is forbidden: you may have entered using the Investor password"); //--- verifica se a conta permite expert advisors (robo trader) if(account.TradeExpert()) Print("Automated trading on this account is allowed"); else Print("Automated trading using Expert Advisors and scripts on this account is forbidden"); //--- verifica numero máximo de ordens pendentes int orders_limit = account.LimitOrders(); if(orders_limit != 0) Print("Maximum permissible amount of active pending orders: ", orders_limit); //--- mostra a corretora e o servidor Print(account.Company(), ": server ", account.Server()); //--- Mostra o saldo e o lucro no final Print("Balance=", account.Balance(), " Profit=", account.Profit(), " Equity=", account.Equity()); Print(__FUNCTION__, " completed"); //--- return true; } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //======================================================================== //======================================================================== //==FUNÇAO Posicionamento | //======================================================================== //======================================================================== s_posicoes posicionamento(void) { // Estrutura para armazenar os dados de ordens executadas s_posicoes posicao; ZeroMemory(posicao); string err_text = ""; for(int i = PositionsTotal() - 1; i >= 0; i--) { ulong ticket = PositionGetTicket(i); if(!PositionSelectByTicket(ticket)) continue; if(PositionGetInteger(POSITION_MAGIC) != 1344) continue; if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue; ENUM_POSITION_TYPE tipo = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); double vol = PositionGetDouble(POSITION_VOLUME); double price = PositionGetDouble(POSITION_PRICE_OPEN); if(posicao.abertura == 0) posicao.abertura = (datetime)PositionGetInteger(POSITION_TIME); if(tipo == POSITION_TYPE_BUY) { posicao.volume += vol; // Verifica o volume aberto, positivo para compras posicao.ticket_compra = ticket; // Verifica o lucro real da posição com base no preço verdadeiro de saída e não pelo último negócio if(!OrderCalcProfit(ORDER_TYPE_BUY, _Symbol, vol, price, SymbolInfoDouble(_Symbol, SYMBOL_BID), posicao.lucro)) printf(__FUNCTION__, "[%s] Falha no cálculo de lucro da posição comprada %d" , "", (string)ticket, err_text); } else { posicao.volume -= vol; // Verifica o volume aberto, negativo para vendas posicao.ticket_venda = ticket; if(!OrderCalcProfit(ORDER_TYPE_SELL, _Symbol, vol, price, SymbolInfoDouble(_Symbol, SYMBOL_ASK), posicao.lucro)) printf(__FUNCTION__, "[%s] Falha no cálculo de lucro da posição vendida %d", "", (string)ticket, err_text); } } return posicao; } //+------------------------------------------------------------------+ //____________________________________________________________________________ //____________________________________________________________________________ // //slippaggen SIMULADOR //____________________________________________________________________________ bool iniciar_SLIP(void) {//=======================================aqui funcao if(!in_hab_slippeges) { return false ; } Sleep(slippeges); return true; }
- 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
Não sei se estou viajando na maionese, mais será que tem alguma função que evite algum bug vindo da corretora que possa fazer o robô entrar em um loop de envios de ordens?
Eu me deparei com esses daqui:
ORDER_STATE_STARTED
Ordem verificada, mas ainda não aceita pela corretora (broker)
ORDER_STATE_REJECTED
Ordem rejeitada
eu consigo fazer isso com eles?
da pra testar em uma conta demo ?
fiz uma função aqui, mais não sei se esta certo.
espero que possam me orientar.