//+------------------------------------------------------------------+ //| osc_minion_trade.| //| Copyright 2010,oficina de software.| //| http://www.metaquotes.net/marcoc.| //+------------------------------------------------------------------+ #property copyright "2010, Oficina de Software." #property link "http://www.os.net" //--- //#include #include #include #include #include #define M_TIME_SLEEP_MANY_REQUESTS 50 // estratura usada para guardar ordens enviadas pro mercado bem como seu ultimo status. class TradeOrder : public CObject{ public: MqlTradeRequest req; MqlTradeResult res; }; //class osc_minion_trade : public CExpertTrade{ class osc_minion_trade : public CTrade{ private: CHashMap m_ordens; MqlTradeRequest m_treq ; // To be used for sending our trade requests MqlTradeResult m_tres ; // To be used to get our trade results bool enviarOrdemAMercado(double val, ENUM_ORDER_TYPE tipo); bool enviarOrdemAMercado(double val, ENUM_ORDER_TYPE tipo, string obs); //bool enviarOrdemPendenteStop(ENUM_ORDER_TYPE tipo, int offset, string obs); double m_stp ; double m_tkp ; double m_stpV ; double m_tkpV ; int m_digits ; ulong m_mmagic ; // transforme em parametro int m_desvio ; // transforme em parametro int m_digitos ; double m_point ; double m_volume ; COrderInfo m_order ; CPositionInfo m_position ; bool m_async ; bool m_async_salvo ; CSymbolInfo m_symb ; string m_symb_str ; double m_stops_level_in_price ; //--------------------------------------------------------------- // Administracao de ordens e seus resultados de processamento //--------------------------------------------------------------- void addOrdem(MqlTradeRequest& req, MqlTradeResult &res, ulong ordem=0);// adiciona requisicao e resultado de uma ordem TradeOrder* getOrdem(ulong ordem); // recupera ultima requisicao e resultado de uma ordem bool permiteAlterarOrdem(ulong ordem, double newPrice, double newVol, string newComment); // valida se pode enviar pedido de alteracao de ordem bool permiteCancelarOrdem(ulong ordem); // valida se pode enviar pedido de cancelamento de ordem //--------------------------------------------------------------- bool orderStatePendente(const ENUM_ORDER_STATE order_state); // retorna true se o estado da ordem informado for pendente protected: public: void osc_minion_trade(); void setStopLoss( double stp ){ m_symb.NormalizePrice(stp) ; m_stp = stp; m_stpV = -stp; } void setTakeProf( double tkp ){ m_tkp = tkp; m_tkpV = -tkp; } void setMagic ( ulong mag ){ m_mmagic = mag ; } void setVolLote ( double vol ){ m_volume = vol ; } // tamanho do lote que serah usado nas operacoes; bool vender (MqlTick &tick ){ return enviarOrdemAMercado(tick.bid, ORDER_TYPE_SELL ); } bool vender (MqlTick &tick , string obs){ return enviarOrdemAMercado(tick.bid, ORDER_TYPE_SELL, obs ); } bool comprar (MqlTick &tick ){ return enviarOrdemAMercado(tick.ask, ORDER_TYPE_BUY ); } bool comprar (MqlTick &tick , string obs){ return enviarOrdemAMercado(tick.ask, ORDER_TYPE_BUY , obs ); } bool venderStop (double val, string obs){ return enviarOrdemPendente (ORDER_TYPE_SELL_STOP , val, obs ); } bool comprarStop (double val, string obs){ return enviarOrdemPendente (ORDER_TYPE_BUY_STOP , val, obs ); } bool venderLimit (double val, string obs){ return enviarOrdemPendente (ORDER_TYPE_SELL_LIMIT, val, obs ); } bool comprarLimit(double val, string obs){ return enviarOrdemPendente (ORDER_TYPE_BUY_LIMIT , val, obs ); } // bool venderStop (int offset, string obs){ return enviarOrdemPendenteStop(ORDER_TYPE_SELL_STOP, offset, obs ); } // bool comprarStop(int offset, string obs){ return enviarOrdemPendenteStop(ORDER_TYPE_BUY_STOP , offset, obs ); } void fecharPosicao (string); // fecha posicoes abertas com o magic ulong fecharPosicaoCtaNetting (string symbol, string comentario); // fecha a posico aberta para o simbolo informado. void fecharPosicaoVendida(string symbol, string comentario); //fecha posicoes vendidas abertas com o magic. void fecharPosicaoComprada(string symbol, string comentario);//fecha posicoes compradas abertas com o magic. void fecharQualquerPosicao (string); // fecha posicoes abertas ateh de magic diferentes void trazerOrdensComComentarioNumerico2valorPresente(string symbol, int qtdTicksDeslocamento=0); // tras as ordens de fechamento a valor presente, visando fechar a posicao. bool alterarValorDeOrdensNumericasPara(string symbol,double novoValor, double valorPosicao); bool cancelarOrdem (ulong ticket );//cancela a ordem que tem o ticket informado no parametro. void cancelarOrdensDuplicadas ( ENUM_ORDER_TYPE tipo);//cancela ordens pendentes do tipo informado void cancelarOrdens ( ENUM_ORDER_TYPE tipo);//cancela ordens pendentes do tipo informado void cancelarOrdens ( string comentario);//cancela ordens pendentes void cancelarOrdensComentadas (string symbol, string comentario);//cancela as ordens que tenham o comentario informado bool cancelarOrdensComentadasDeVenda (string symbol, string comentario);//cancela as ordens que tenham o comentario informado e sejam de venda bool cancelarOrdensComentadasDeVenda (string symbol, string comentario, double valor);//cancela as ordens de venda que tenham o comentario e valor informado; bool cancelarOrdensComentadasDeVendaMaioresQue (string symbol, string comentario, double valor);//cancela as ordens de venda que tenham o comentario e valor informado; bool cancelarOrdensComentadasDeCompra (string symbol, string comentario );//cancela as ordens que tenham o comentario informado e sejam de compra bool cancelarOrdensComentadasDeCompra (string symbol, string comentario, double valor);//cancela as ordens de compra que tenham o comentario e valor informado; bool cancelarOrdensComentadasDeCompraMenoresQue(string symbol, string comentario, double valor);//cancela as ordens de compra que tenham o comentario e valor informado; void cancelarOrdensComComentarioNumerico (string symbol );//cancela ordens cujo comentario eh um numero; void cancelarOrdensComComentarioNumerico (string symbol, ENUM_ORDER_TYPE tipo );//cancela ordens cujo comentario eh um numero e o tipo eh igual ao especificado; void cancelarOrdensExcetoComTxt (string txtNaoCancelar, string comentario); void cancelarOrdensDeCompraMenoresQue (double valor); void cancelarOrdensDeVendaMaioresQue (double valor); void cancelarOrdensDoTipo (ENUM_ORDER_TYPE tipo ); // cancela todas as ordens do tipo informado void cancelarOrdensPorTipoEvalor(ENUM_ORDER_TYPE tipo, double valor); // cancela todas as ordens do tipo informado ulong cancelarMaiorOrdemDeVendaComComentarioNumerico (); ulong cancelarMenorOrdemDeCompraComComentarioNumerico(); int contarOrdensLimitadasDeCompra(string symbol, string comment); int contarOrdensLimitadasDeVenda (string symbol, string comment); bool enviarOrdemPendente (ENUM_ORDER_TYPE tipo, double val, string obs); bool enviarOrdemPendente (ENUM_ORDER_TYPE tipo, double val, double volume, string obs); bool enviarOrdemPendente (ENUM_ORDER_TYPE tipo, double val, double volume, string obs, ulong &tkt); // devolve o ticket da ordem bool enviarOrdemPendenteRajada(ENUM_ORDER_TYPE tipo, double _val, double _volume, string obs, double passoVal, double incremVolume, double incremVal, double qtdOrdens, bool stop=false, double porcStop=0, double valSaidaPosicao=0, double passoValAtehSaidaPosicao=0 ); void preencherOrdensLimitadasDeCompraAbaixo(double valIni, int qtdOrdens, string symbol, string comment, double volume, double tickSize); void preencherOrdensLimitadasDeVendaAcima (double valIni, int qtdOrdens, string symbol, string comment, double volume, double tickSize); // a versao 2 destas funcoes inicia o controle mais longe preco atual. void preencherOrdensLimitadasDeCompraAbaixoComLag(double valIni, int qtdOrdens, string symbol, string comment, double volume, double tickSize, int lag); void preencherOrdensLimitadasDeVendaAcimaComLag (double valIni, int qtdOrdens, string symbol, string comment, double volume, double tickSize, int lag); // a versao 2 destas funcoes inicia o controle mais proximo preco atual. void preencherOrdensLimitadasDeCompraAbaixoComLag2(double valIni, int qtdOrdens, string symbol, string comment, double volume, double tickSize, int lag); void preencherOrdensLimitadasDeVendaAcimaComLag2 (double valIni, int qtdOrdens, string symbol, string comment, double volume, double tickSize, int lag); bool alterarOrdem(ENUM_ORDER_TYPE tipo, double price); bool alterarOrdem( double price, double volume); bool alterarOrdem(ENUM_ORDER_TYPE tipo, double price, double volume, ulong order_ticket=0, string newComment=""); bool alterarPrecoOrdem(double price); void colocarStopEmTodasAsOrdens(double stp); bool colocarStopNaOrdem(ulong ticket, double stp); double getPositionVolume(){ return m_position.Volume();} //Volume da posicao. estouComprado ou estouVendido devem ter sido chamados antes. double getPrice(){ return m_treq.price; } // valor do preco da ultima ordem ou da ultima posicao. bool estouVendido(string symbol); bool estouVendido(){return estouVendido(_Symbol);} bool estouComprado(string symbol) ; bool estouComprado(){return estouComprado(_Symbol);} bool tenhoOrdemLimitada(double value, ENUM_ORDER_TYPE type); bool tenhoOrdemLimitadaDeCompra(double value, string symbol, string comment); bool tenhoOrdemLimitadaDeCompra(double value, string symbol, string comment, double volume, bool cancelar, double tolerancia, string newComment=""); bool tenhoOrdemLimitadaDeCompra(double value, string comment){ return tenhoOrdemLimitadaDeCompra(value, m_symb_str, comment); } bool tenhoOrdemLimitadaDeVenda (double value, string symbol, string comment ); bool tenhoOrdemLimitadaDeVenda (double value, string symbol, string comment, double volume, bool cancelar, double tolerancia, string newComment=""); bool tenhoOrdemLimitadaDeVenda (double value, string comment){return tenhoOrdemLimitadaDeVenda (value, m_symb_str, comment);} double tenhoOrdemLimitadaDeCompraMaiorQue(double value, string symbol, string comment, double volume, ulong& ticket); double tenhoOrdemLimitadaDeVendaMenorQue (double value, string symbol, string comment, double volume, ulong& ticket); bool tenhoOrdenComComentarioNumerico(double price, ENUM_ORDER_TYPE tipo); double buscarMenorOrdemLimitadaDeVenda ( string symbol, string comment, double volume, ulong& ticket); double buscarMaiorOrdemLimitadaDeCompra ( string symbol, string comment, double volume, ulong& ticket); double buscarMaiorOrdemLimitadaDeVendaAcimaDe (double value, string symbol, string comment, double volume, ulong& ticket); double buscarMenorOrdemLimitadaDeCompraAbaixoDe(double value, string symbol, string comment, double volume, ulong& ticket); double buscarMaiorOrdemLimitadaDeVendaComComentarioNumerico (ulong& ticket); double buscarMenorOrdemLimitadaDeCompraComComentarioNumerico(ulong& ticket); bool alterarOrdemLimitadaComValorDiferenteDe(double value, string symbol, double volume, string comment, string newComment=""); double getVolUltOrdemVerificada(){ return m_order.VolumeCurrent(); } double getValUltOrdemVerificada(){ return m_order.PriceOpen(); } bool tenhoOrdemPendente(double price); ulong tenhoOrdemPendente(double price, ENUM_ORDER_TYPE tipo, ulong ticketOut);// busca ordem com o mesmo preco, tipo e ticket diferente. bool tenhoOrdemPendenteComComentario( string symbol, string comment);// verifica se tem ordem pendente de execucao para o simbolo informado com o comentario informado double getVolOrdensPendentesDeVenda (string symbol); double getVolOrdensPendentesDeCompra(string symbol); void setAsync(bool newMode){ m_async = newMode;} bool getAsync() { return m_async;} void saveAsync() { m_async_salvo = m_async;} void restoreAsync() { m_async = m_async_salvo;} void osc_minion_trade::setSymbol(string symb_str); }; void osc_minion_trade::osc_minion_trade(){ setStopLoss(40) ; setTakeProf(15) ; m_mmagic = 20191004; // transforme em parametro m_desvio = 0.0 ; // transforme em parametro setSymbol(_Symbol); //m_digitos = _Digits ; //m_point = _Point ; //m_symb.Name(_Symbol); Print(":-| osc_minion_trade:" , __FUNCTION__,": DIGITOS:",m_digitos," POINTS: ",m_point ); } void osc_minion_trade::setSymbol(string symb_str){ m_symb_str = symb_str; m_symb.Name(symb_str); m_point = m_symb.Point(); m_digitos = m_symb.Digits(); m_stops_level_in_price = m_symb.StopsLevel()*m_symb.Point(); } bool osc_minion_trade::enviarOrdemAMercado(double val, ENUM_ORDER_TYPE tipo ){ return enviarOrdemAMercado(val,tipo,""); } bool osc_minion_trade::enviarOrdemAMercado(double val, ENUM_ORDER_TYPE tipo, string obs){ ZeroMemory(m_treq); ZeroMemory(m_tres); double price = val; double point = _Point; double stp = 0; double tkp = 0; m_treq.comment = obs; if(tipo == ORDER_TYPE_SELL) { stp = m_stpV; tkp = m_tkpV; } if(tipo == ORDER_TYPE_BUY ) { stp = m_stp ; tkp = m_tkp ; } m_treq.action = TRADE_ACTION_DEAL; // immediate order execution m_treq.price = m_symb.NormalizePrice(val); // latest ask price if( m_stp != 0.0 ){ m_treq.sl = m_symb.NormalizePrice(price - stp); } // Stop Loss if( m_tkp != 0.0 ){ m_treq.tp = m_symb.NormalizePrice(price + tkp); } // Take Profit m_treq.symbol = _Symbol; // currency pair m_treq.volume = m_volume; // number of lots to trade m_treq.magic = m_mmagic; // Order Magic Number m_treq.type = tipo; // Compra, venda, etc //m_treq.type_filling = ORDER_FILLING_FOK; // Order execution type m_treq.type_filling = ORDER_FILLING_RETURN; // Order execution type m_treq.deviation = m_desvio; // Deviation from current price in points if( m_async ){ if ( OrderSendAsync(m_treq,m_tres) ){ return true; } }else{ if ( OrderSend (m_treq,m_tres) ){ return true; } } Alert(":-( ",__FUNCTION__,"(",val, ",",tipo, ",",obs, ") ERRO SOLIC ORD ",GetLastError(),":",m_tres.retcode,":",m_tres.comment); Print(":-( ",__FUNCTION__,"(",val, ",",tipo, ",",obs, ") retcode=",m_tres.retcode," deal=",m_tres.deal," order=",m_tres.order," comment=",m_tres.comment," EA=", obs); //if( m_tres.retcode == TRADE_RETCODE_TOO_MANY_REQUESTS ){ Print(":-( ",__FUNCTION__,"(",val,",",tipo,",", obs,") Aguardando ",M_TIME_SLEEP_MANY_REQUESTS,"ms..." ); Sleep(M_TIME_SLEEP_MANY_REQUESTS); // consertar e tentar tirar este sleep daqui //} return false; } bool osc_minion_trade::enviarOrdemPendente(ENUM_ORDER_TYPE tipo, double val, string obs){return enviarOrdemPendente(tipo,val,m_volume,obs);} bool osc_minion_trade::enviarOrdemPendente(ENUM_ORDER_TYPE tipo, double val, double volume, string obs, ulong &tkt){ if( enviarOrdemPendente(tipo,val,volume,obs) ){ tkt = m_tres.order; return true; } return false; } bool osc_minion_trade::enviarOrdemPendente(ENUM_ORDER_TYPE tipo, double val, double volume, string obs){ ZeroMemory(m_treq); ZeroMemory(m_tres); double price = val; double stp = 0; double tkp = 0; if (tipo==ORDER_TYPE_BUY_STOP || tipo==ORDER_TYPE_BUY_LIMIT ){ //if( tipo==ORDER_TYPE_BUY_LIMIT ){ // //price = SymbolInfoDouble(_Symbol,SYMBOL_ASK)+offset*point; // preço de abertura da ordem // double bid = SymbolInfoDouble(_Symbol,SYMBOL_ASK)-m_stops_level_in_price; // if( price > bid){ // price = bid; // Print(":-| ",__FUNCTION__,"(",EnumToString(tipo), ",",val,",",volume, ",",obs, ") preco maior que stopLevel! Alterado para ",price); // } //} stp = m_stp ; tkp = m_tkp ; }else if(tipo==ORDER_TYPE_SELL_STOP || tipo==ORDER_TYPE_SELL_LIMIT ){ //if( tipo==ORDER_TYPE_SELL_LIMIT ){ // //price = SymbolInfoDouble(_Symbol,SYMBOL_BID)-offset*point; // preço para abertura // double ask = SymbolInfoDouble(_Symbol,SYMBOL_BID)+m_stops_level_in_price; // if( price < ask){ // price = ask; // Print(":-| ",__FUNCTION__,"(",EnumToString(tipo), ",",val,",",volume, ",",obs, ") preco menor que stopLevel! Alterado para ",price); // } //} stp = m_stpV; tkp = m_tkpV; } m_treq.action = TRADE_ACTION_PENDING; // execucao pendente m_treq.price = m_symb.NormalizePrice(price ); // preco futuro recebido no pedido de negociacao if( m_stp != 0.0 ){ m_treq.sl = m_symb.NormalizePrice(price - stp); } // Stop Loss if( m_tkp != 0.0 ){ m_treq.tp = m_symb.NormalizePrice(price + tkp); } // Take Profit m_treq.symbol = _Symbol; // currency pair m_treq.volume = volume; // number of lots to trade m_treq.magic = m_mmagic; // Order Magic Number m_treq.type = tipo; // Compra, venda, etc //m_treq.type_filling = ORDER_FILLING_FOK; // Order execution type m_treq.type_filling = ORDER_FILLING_RETURN; // Order execution type m_treq.deviation = m_desvio; // Deviation from current price in points m_treq.comment = obs; m_treq.type_time = ORDER_TIME_DAY; //m_treq.expiration = TimeLocal(); if( tipo==ORDER_TYPE_BUY_STOP_LIMIT || tipo==ORDER_TYPE_SELL_STOP_LIMIT ){ m_treq.stoplimit = m_treq.price; if(tipo==ORDER_TYPE_BUY_STOP_LIMIT){ m_treq.price = m_treq.stoplimit + m_symb.TickSize(); }else{ m_treq.price = m_treq.stoplimit - m_symb.TickSize(); } } //Print(":-| osc_minion_trade: Enviando ordem:", m_treq.price); if( m_async ){ if ( OrderSendAsync(m_treq,m_tres) ){ return true; } }else{ if ( OrderSend (m_treq,m_tres) ){ return true; } } Alert(":-( ",__FUNCTION__,"(",EnumToString(tipo), ",",val,",",volume, ",",obs, ") ERRO SOLIC ORD ",GetLastError(),":",m_tres.retcode,":",m_tres.comment); Print(":-( ",__FUNCTION__,"(",EnumToString(tipo), ",",val,",",volume, ",",obs, ") retcode=",m_tres.retcode," deal=",m_tres.deal," order=",m_tres.order," comment=",m_tres.comment," EA=", obs); //if( m_tres.retcode == TRADE_RETCODE_TOO_MANY_REQUESTS ){ Print(__FUNCTION__,"(",EnumToString(tipo),",",val,",", volume,",", obs,")"," :-( Aguardando ",M_TIME_SLEEP_MANY_REQUESTS,"ms..." ); Sleep(M_TIME_SLEEP_MANY_REQUESTS); // consertar e tentar tirar este sleep daqui //} return false; } //------------------------------------------------------------------------------------------------------------ // Monta rajada de ordens usando o valor, volume, passo do valor, passo do volume e quantidade informados. // ENUM_ORDER_TYPE tipo, // double _val , valor da primeira ordem // double _volume , volume da primeira ordem // string obs , comentario a ser usado em todas as ordens da rajada // double passoVal , valor a ser acrescentado ao preco inicial a cada iteracao para definir os niveis de preco // da rajada. Se quiser incrementar o preco pra baixo, passe um numero negativo neste parametro. // double incremVolume, incremento do volume a cada passo. Ex: se quiser dobrar a quantidade de ordens a cada // nivel de preco, informe 2 no passo. // double tamanhoRajada, quantidade de ordens na rajada. // bool stop , se true cria uma ordem de saida contraria as ordens de entrada apos a ultima ordem da rajada. // double porcStop , porcentagem aplicada ao passo da ultima rajada para obter o valor a decrementar ao passo do preco stop. // Se quiser incrementar o passo neste ponto coloque um valor negativo. //------------------------------------------------------------------------------------------------------------ bool osc_minion_trade::enviarOrdemPendenteRajada(ENUM_ORDER_TYPE tipo , double _val ,// valor primeira ordem double _volume ,// volume da primeira ordem string obs ,// cometario das ordens double passoVal ,// distancia entre as ordens double incremVolume ,// multiplica pelo volume a cada ordem double incremVal ,// multiplica pela distancia a cada ordem double tamanhoRajada,// qtd ordens bool stop=false ,// se true, a ultima ordem serah o stop loss double porcStop=0 , // double valSaidaPosicao =0,// double passoValAtehSaidaPosicao=0 ){ double volume = _volume; double val = _val; double volLocal = volume; double volTot = 1; val = m_symb.NormalizePrice(val); while( tamanhoRajada > 0 ){ volTot += volume; if( !enviarOrdemPendente(tipo, val, volume, obs) ){ return false; } // volume da ordem volLocal = volLocal * incremVolume; volume = round(volLocal); // valor da ordem passoVal = passoVal*incremVal; val = m_symb.NormalizePrice(val + passoVal); // controle do laco tamanhoRajada--; } // testando a colocacao do stoploss... if( stop ){ if( tipo == ORDER_TYPE_BUY_LIMIT ){ if( !enviarOrdemPendente(ORDER_TYPE_SELL_STOP_LIMIT, val-passoVal*porcStop, volTot, obs) ){ return false; } }else{ if( !enviarOrdemPendente(ORDER_TYPE_BUY_STOP_LIMIT , val-passoVal*porcStop, volTot, obs) ){ return false; } } } // testando colocacao de ordens a favor da posicao... if(valSaidaPosicao > 0 && passoValAtehSaidaPosicao != 0){ val = _val; if( tipo == ORDER_TYPE_BUY_LIMIT ){ while(val < (valSaidaPosicao-passoValAtehSaidaPosicao*2) ){ val = val+passoValAtehSaidaPosicao; if( val < valSaidaPosicao ){ enviarOrdemPendente(ORDER_TYPE_BUY_STOP_LIMIT , val, _volume, obs); } } }else{ while(val > (valSaidaPosicao+passoValAtehSaidaPosicao*2) ){ val = val-passoValAtehSaidaPosicao; if( val > valSaidaPosicao ){ enviarOrdemPendente(ORDER_TYPE_SELL_STOP_LIMIT, val, _volume, obs); } } } } return true; } //bool osc_minion_trade::alterarPrecoOrdem(int ticket, double price){ // return alterarOrdem( int ticket, price); //} // altera preco da ordem pendente... bool osc_minion_trade::alterarPrecoOrdem(double price){ return alterarOrdem(m_treq.type, price); } // altera ordem pendente... bool osc_minion_trade::alterarOrdem( double price, double volume ){return alterarOrdem(m_treq.type, price, volume);} bool osc_minion_trade::alterarOrdem(ENUM_ORDER_TYPE tipo, double price ){return alterarOrdem(tipo , price, m_volume);} bool osc_minion_trade::alterarOrdem(ENUM_ORDER_TYPE tipo, double price, double volume, ulong order_ticket=0,string newComment="" ){ ZeroMemory(m_treq); ZeroMemory(m_tres); m_treq.action = TRADE_ACTION_MODIFY; // alterar ordem m_treq.type = tipo; m_treq.volume = volume; // number of lots to trade m_treq.order = order_ticket==0?OrderGetTicket(0):order_ticket; // m_treq.price = m_symb.NormalizePrice(price ); // preco futuro recebido no pedido de negociacao // valida se pode enviar pedido de alteracao de ordem if( !permiteAlterarOrdem(m_treq.order,m_treq.price,m_treq.volume,m_treq.comment) ) return false; // configurando stops... double stp = 0; double tkp = 0; if ( m_treq.type==ORDER_TYPE_BUY_STOP || m_treq.type==ORDER_TYPE_BUY_LIMIT ){ stp = m_stp ; tkp = m_tkp ; }else if( m_treq.type==ORDER_TYPE_SELL_STOP || m_treq.type==ORDER_TYPE_SELL_LIMIT ){ stp = m_stpV; tkp = m_tkpV; } if( m_stp != 0.0 ){ m_treq.sl = m_symb.NormalizePrice(price - stp); } // Stop Loss if( m_tkp != 0.0 ){ m_treq.tp = m_symb.NormalizePrice(price + tkp); } // Take Profit m_treq.symbol = _Symbol; // currency pair m_treq.magic = m_mmagic; // Order Magic Number //m_treq.type_filling = ORDER_FILLING_FOK; // Order execution type m_treq.type_filling = ORDER_FILLING_RETURN; // Order execution type m_treq.deviation = m_desvio; // Deviation from current price in points m_treq.type_time = ORDER_TIME_DAY; // m_treq.comment = obs; if( newComment != "" ) m_treq.comment = newComment; // enviando a ordem de alteracao do preco... // 27/12/2019: alteracao de ordem passa a ser assincrona. //if( m_async ){ if ( OrderSendAsync(m_treq,m_tres) ){ addOrdem(m_treq,m_tres); return true; } addOrdem(m_treq,m_tres); //}else{ // if ( OrderSend (m_treq,m_tres) ){ return true; } //} //Alert(":-( osc_minion_trade:ERRO SOLIC ALTER ORD:",GetLastError()); //Alert(":-( ",__FUNCTION__,"(",tipo, ",",price,",",volume, ",",order_ticket,",",newComment,") ERRO SOLIC ORD ",GetLastError(),":",m_tres.retcode,":",m_tres.comment); //Print(":-( ",__FUNCTION__,"(",tipo, ",",price,",",volume, ",",order_ticket,",",newComment,") retcode=",m_tres.retcode," lastError=",GetLastError()," order=",m_treq.order," comment=",m_tres.comment," Aguardando ",M_TIME_SLEEP_MANY_REQUESTS,"ms..."); Print(":-( ",__FUNCTION__,"(",tipo, ",",price,",",volume, ",",order_ticket,",",newComment,") retcode=",m_tres.retcode," lastError=",GetLastError()," order=",m_treq.order," comment=",m_tres.comment); //if( m_tres.retcode == TRADE_RETCODE_TOO_MANY_REQUESTS ){ //Print(__FUNCTION__,"(",tipo,",",price,",", volume, ",", order_ticket,",",newComment,")"," :-( Aguardando ",M_TIME_SLEEP_MANY_REQUESTS,"ms..." ); //Sleep(M_TIME_SLEEP_MANY_REQUESTS); // consertar e tentar tirar este sleep daqui //} //ERRO SOLIC ORD return false; } //+-----------------------------------------------------------+ //| Cancela a ordem do ticket informado | //+-----------------------------------------------------------+ bool osc_minion_trade::cancelarOrdem(ulong ticket){ if( !permiteCancelarOrdem(ticket) ) return false; if( OrderSelect(ticket) ){ MqlTradeResult result ={0}; MqlTradeRequest request={0}; request.order = ticket; request.action = TRADE_ACTION_REMOVE; if(!OrderSendAsync(request,result)){ addOrdem(request,result,ticket); Print(":-( ",__FUNCTION__,"(",ticket,") REMOCAO ERRO OrderSendAsync ",GetLastError(),":",result.retcode,":",result.comment); return false; } addOrdem(request,result,ticket); return true; } Print(":-| ", __FUNCTION__,"(",ticket,") ORDEM NAO ENCONTRADA NA LISTA DE ORDENS PENDENTES :GetLastError():", GetLastError() ); return false; } /* //+-----------------------------------------------------------+ //| Cancela a ordem do ticket informado | //+-----------------------------------------------------------+ bool osc_minion_trade::cancelarOrdem(ulong ticket) { if( OrderSelect(ticket) ){ MqlTradeResult result ={0}; MqlTradeRequest request={0}; request.order = ticket; request.action = TRADE_ACTION_REMOVE; //PrintFormat("ENVIANDO REMOCAO DA ORDEM COM TICKET #%I64d :",ticket); // 27/12/2019: cancelamento de ordens passa a ser assincrono. //if( m_async ){ Print(":-| ",__FUNCTION__ ,"(#",ticket,") :-| Canc #",ticket," asyn"); if(!OrderSendAsync(request,result)){ Print(__FUNCTION__,"(#", ticket,") :-( REMOCAO ERRO OrderSendAsync=",GetLastError(), ":", result.retcode,":",result.comment, " order=", ticket); // se não for possível enviar o pedido, exibir um código de erro //if( result.retcode == TRADE_RETCODE_TOO_MANY_REQUESTS ){ Print(__FUNCTION__,"(",ticket,")"," :-( Aguardando ",M_TIME_SLEEP_MANY_REQUESTS,"ms..." ); Sleep(M_TIME_SLEEP_MANY_REQUESTS); // consertar e tentar tirar este sleep daqui //} return false; } //}else{ // if(!OrderSend(request,result)){ // PrintFormat(":-( osc_minion_trade: REMOCAO ERRO OrderSend %d :",GetLastError()); // se não for possível enviar o pedido, exibir um código de erro // PrintFormat(":-( osc_minion_trade: REMOCAO ERRO retcode=%u deal=%I64u order=%I64u :", result.retcode,result.deal,result.order); // return false; // } //} return true; } Print(__FUNCTION__,"(",ticket,") :-( ERRO REMOCAO ORDEM: NAO ENCONTRADA :GetLastError():", GetLastError() ); return false; } */ //+---------------------------------------------------------------------+ //| Verifica se tenho uma ordem limitada de compra no valor especificado| //+---------------------------------------------------------------------+ bool osc_minion_trade::tenhoOrdemLimitadaDeCompra(double value, string symbol,string comment){ ulong order_ticket; //ENUM_ORDER_STATE order_state; //--- passando por todas as ordens pendentes for(int i=OrdersTotal()-1; i>=0; i--){ if( (order_ticket = OrderGetTicket(i) )>0 ){ //m_order.SelectByIndex(i); // selecionando a ordem para posterior alteracao se necessario... //order_state = (ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE); if( OrderGetString (ORDER_SYMBOL ) == symbol && OrderGetDouble (ORDER_PRICE_OPEN) == value && OrderGetInteger(ORDER_TYPE ) == ORDER_TYPE_BUY_LIMIT && orderStatePendente((ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE)) //order_state != ORDER_STATE_FILLED && // buscamos ordens pendentes //order_state != ORDER_STATE_REJECTED && //order_state != ORDER_STATE_CANCELED && //order_state != ORDER_STATE_EXPIRED ){ return true; } } } return false; } //+--------------------------------------------------------------------------------------------------------------------+ //| Verifica se tenho uma ordem limitada no valor e tipo especificados, e simbolo configurado previamente na instancia.| //+--------------------------------------------------------------------------------------------------------------------+ bool osc_minion_trade::tenhoOrdemLimitada(double value, ENUM_ORDER_TYPE type){ ulong order_ticket; //--- passando por todas as ordens pendentes for(int i=OrdersTotal()-1; i>=0; i--){ if( (order_ticket = OrderGetTicket(i) )>0 ){ if( OrderGetString (ORDER_SYMBOL ) == m_symb_str && OrderGetDouble (ORDER_PRICE_OPEN) == value && OrderGetInteger(ORDER_TYPE ) == type && orderStatePendente((ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE)) ){ return true; } } } return false; } bool osc_minion_trade::orderStatePendente(const ENUM_ORDER_STATE order_state){ return ( order_state == ORDER_STATE_PLACED || order_state == ORDER_STATE_STARTED || order_state == ORDER_STATE_REQUEST_ADD || order_state == ORDER_STATE_REQUEST_MODIFY || order_state == ORDER_STATE_REQUEST_CANCEL || order_state == ORDER_STATE_PARTIAL ); } //+---------------------------------------------------------------------+ //| Verifica se tenho uma ordem limitada de venda no valor especificado | //+---------------------------------------------------------------------+ bool osc_minion_trade::tenhoOrdemLimitadaDeVenda(double value, string symbol, string comment){ ulong order_ticket; //--- passaANDO por todas as ordens pendentes for(int i=OrdersTotal()-1; i>=0; i--){ if( (order_ticket = OrderGetTicket(i) )>0 ){ //m_order.SelectByIndex(i); // selecionando a ordem para posterior alteracao se necessario... if( OrderGetString (ORDER_SYMBOL ) == symbol && OrderGetDouble (ORDER_PRICE_OPEN) == value && OrderGetInteger(ORDER_TYPE ) == ORDER_TYPE_SELL_LIMIT && orderStatePendente( (ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE) ) //order_state != ORDER_STATE_FILLED && // buscamos ordens pendentes //order_state != ORDER_STATE_REJECTED && //order_state != ORDER_STATE_CANCELED && //order_state != ORDER_STATE_EXPIRED ){ return true; } } // nao deveria chegar aqui se todas as ordens sao do comentario... //m_order.SelectByIndex(i); //Print( ":-( osc_minion_trade: " ,m_order.Comment() , // " Ticket:" ,m_order.Ticket() , // ":" ,m_order.Symbol() , // " Tipo:" ,m_order.TypeDescription() , // " State:" ,m_order.StateDescription(), // " PriceOpen:" ,m_order.PriceOpen()," value:",value, " igual?=",(m_order.PriceOpen()==value),OrderGetDouble (ORDER_PRICE_OPEN) == value, // " PriceCurrent:" ,m_order.PriceCurrent(), // " PriceStopLimit:",m_order.PriceStopLimit() ); } return false; } //+----------------------------------------------------------------------------------------------------------------------------------+ //| Verifica se tenho uma ordem limitada de venda no valor e volume especificados. Altera para o valor e volume especificados | //| caso encontre a ordem com outro valor/volume, mesmo comentario (comentario fazendo parte da ordem encontrada). | //+----------------------------------------------------------------------------------------------------------------------------------+ bool osc_minion_trade::tenhoOrdemLimitadaDeVenda(double value, string symbol, string comment, double volume, bool alterar, double tolerancia, string newComment=""){ ulong order_ticket = 0 ; double price_open; //--- passaando por todas as ordens pendentes for(int i=OrdersTotal()-1; i>=0; i--){ //m_order.SelectByIndex(i); if( (order_ticket = OrderGetTicket(i) )>0 ){ if( OrderGetString (ORDER_SYMBOL ) == symbol && StringFind(OrderGetString (ORDER_COMMENT ),comment) > -1 && OrderGetInteger(ORDER_TYPE ) == ORDER_TYPE_SELL_LIMIT && orderStatePendente( (ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE) ) //order_state == ORDER_STATE_PLACED ){ price_open = OrderGetDouble(ORDER_PRICE_OPEN); if( price_open >= value-tolerancia && price_open <= value+tolerancia && OrderGetDouble(ORDER_VOLUME_CURRENT) == volume ){ return true; // colcoado aqui em 04/02/2020 para que nao siga verificando todas as ordens pendentes. }else{ // se tiver mais de uma ordem, pode ser que altere todas nas chamadas subsequentes. // como estah sendo usado para uma ordem, vem funcionando. // corrija assim que possivel. if( alterar ){ Print(":-| ",__FUNCTION__ ,"(",value,",",symbol,",",comment,",",volume,",",alterar,",",tolerancia,") :-| Alt #",order_ticket, " OldP=",price_open, " NewP=",value," asyn"); //if( !cancelarOrdem(order_ticket) ) tenhoOrdem=true; alterarOrdem( (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE), value, volume, order_ticket, newComment); return true; // colcoado aqui em 04/02/2020 para que nao siga verificando todas as ordens pendentes. } } } } } return false; } //+--------------------------------------------------------------------------------------------+ //| Mantem uma sequencia de ordens limitadas de venda acima do valor informado. | //+--------------------------------------------------------------------------------------------+ void osc_minion_trade::preencherOrdensLimitadasDeVendaAcima(double valIni, int qtdOrdens, string symbol, string comment, double volume, double tickSize){ double valOrdem = valIni; //saveAsync(); setAsync(true); for( int i=0; i 0 ){ while(newValIni > valIni){ newValIni -= (tickSize*lag); newValIni = m_symb.NormalizePrice(newValIni); } }else{ // 1.2.2 Se nao encontrar, entao valIni eh o valor inicial valido. newValIni = valIni; } //double valOrdem = m_symb.NormalizePrice(newValIni+(tickSize*lag) ); double valOrdem = newValIni; //m_symb.RefreshRates(); //double ask = m_symb.Ask(); for( int i=0; i= valIni) enviarOrdemPendente(ORDER_TYPE_SELL_LIMIT, valOrdem, volume, comment); } // eliminando as ordens desalinhadas com o lag... for(int j=1; jqtdOrdens) cancelarOrdensComentadasDeVendaMaioresQue(symbol,comment,valOrdem); } //+--------------------------------------------------------------------------------------------+ //| Mantem uma sequencia de ordens limitadas de compra abaixo do valor informado. | //+--------------------------------------------------------------------------------------------+ void osc_minion_trade::preencherOrdensLimitadasDeCompraAbaixoComLag(double valIni, int qtdOrdens, string symbol, string comment, double volume, double tickSize, int lag){ // // Determinando o valor inicial // // 1.2 Busca menor ordem menor que a inicial. // 1.2.1 Se encontrar aumenta um lag por vez ateh encontrar o maior valor maior ou igual ao inicial. // Este serah o valor inicial. // // 1.2.2 Se nao encontrar, entao valIni eh o valor inicial valido. // ulong ticket; double newValIni = buscarMenorOrdemLimitadaDeCompraAbaixoDe(valIni, symbol, comment, volume, ticket); // 1.2.1 Se encontrar retorna um lag por vez ateh encontrar o menor valor maior que o inicial. // Este serah o valor inicial. if( newValIni > 0 ){ while(newValIni < valIni){ newValIni += (tickSize*lag); newValIni = m_symb.NormalizePrice(newValIni); } }else{ // 1.2.2 Se nao encontrar, entao valIni eh o valor inicial valido. newValIni = valIni; } //double valOrdem = m_symb.NormalizePrice( newValIni-(tickSize*lag) ); double valOrdem = newValIni ; //for( int i=0; i qtdOrdens ) cancelarOrdensComentadasDeCompraMenoresQue(symbol,comment,valOrdem); } //+--------------------------------------------------------------------------------------------+ //| Mantem uma sequencia de ordens limitadas de venda acima do valor informado. Versao 2 | //+--------------------------------------------------------------------------------------------+ void osc_minion_trade::preencherOrdensLimitadasDeVendaAcimaComLag2(double valIni, int qtdOrdens, string symbol, string comment, double volume, double tickSize, int lag){ // // Determinando o valor inicial // // 1.2 Busca menor ordem de venda. // 1.2.1 Se encontrar, entao este eh o valor inicial. // 1.2.2 Se nao encontrar, entao valIni eh o valor inicial valido. // // 1.2 Busca menor ordem de venda. ulong ticket; double newValIni = buscarMenorOrdemLimitadaDeVenda(symbol, comment, volume, ticket); // 1.2.1 Se encontrar, entao este eh o valor inicial. // 1.2.2 Se nao encontrar, entao valIni eh o valor inicial valido. //Print( __FUNCTION__, " :-| valIni:",valIni, " newValIni:",newValIni); if( newValIni == 0 || newValIni > valIni ){ newValIni = valIni; } double valOrdem = newValIni; //m_symb.RefreshRates(); //double ask = m_symb.Ask(); for( int i=0; i= valIni) enviarOrdemPendente(ORDER_TYPE_SELL_LIMIT, valOrdem, volume, comment); } // eliminando as ordens desalinhadas com o lag... for(int j=1; jqtdOrdens) cancelarOrdensComentadasDeVendaMaioresQue(symbol,comment,valOrdem); } //+--------------------------------------------------------------------------------------------+ //| Mantem uma sequencia de ordens limitadas de compra abaixo do valor informado. Versao 2. | //+--------------------------------------------------------------------------------------------+ void osc_minion_trade::preencherOrdensLimitadasDeCompraAbaixoComLag2(double valIni, int qtdOrdens, string symbol, string comment, double volume, double tickSize, int lag){ // // Determinando o valor inicial // // 1.2 Busca maior ordem de compra. // 1.2.1 Se encontrar, entao este eh o valor inicial. // 1.2.2 Se nao encontrar, entao valIni eh o valor inicial valido. // ulong ticket; double newValIni = buscarMaiorOrdemLimitadaDeCompra(symbol, comment, volume, ticket); // 1.2.1 Se encontrar, entao este eh o valor inicial. // 1.2.2 Se nao encontrar, entao valIni eh o valor inicial valido. //Print( __FUNCTION__, " :-| valIni:",valIni, " newValIni:",newValIni); if( newValIni == 0 || newValIni < valIni ){ newValIni = valIni; } double valOrdem = newValIni; for( int i=0; i qtdOrdens ) cancelarOrdensComentadasDeCompraMenoresQue(symbol,comment,valOrdem); } //+---------------------------------------------------------------------------+ //| Busca a menor ordem limitada de venda com valor MENOR que o especificado. | //+---------------------------------------------------------------------------+ double osc_minion_trade::buscarMenorOrdemLimitadaDeCompraAbaixoDe(double value, string symbol, string comment, double volume, ulong& ticket){ ulong order_ticket = 0 ; double price_open; double valMin = value; //--- passaando por todas as ordens pendentes for(int i=OrdersTotal()-1; i>=0; i--){ if( (order_ticket = OrderGetTicket(i) )>0 ){ if( OrderGetString (ORDER_SYMBOL ) == symbol && OrderGetDouble (ORDER_VOLUME_CURRENT) == volume && StringFind(OrderGetString (ORDER_COMMENT ),comment) > -1 && OrderGetInteger(ORDER_TYPE ) == ORDER_TYPE_BUY_LIMIT && OrderGetInteger(ORDER_STATE) == ORDER_STATE_PLACED ){ price_open = OrderGetDouble(ORDER_PRICE_OPEN); if( price_open < valMin ){ valMin = price_open; ticket = order_ticket; } } } } return valMin==value?0.0:valMin; } //+---------------------------------------------------------------------------+ //| Busca a maior ordem limitada de compra com valor MAIOR que o especificado.| //+---------------------------------------------------------------------------+ double osc_minion_trade::buscarMaiorOrdemLimitadaDeVendaAcimaDe(double value, string symbol, string comment, double volume, ulong& ticket){ ulong order_ticket = 0 ; double price_open ; double valMax = value; //--- passaando por todas as ordens pendentes for(int i=OrdersTotal()-1; i>=0; i--){ //m_order.SelectByIndex(i); if( (order_ticket = OrderGetTicket(i) )>0 ){ if( OrderGetString (ORDER_SYMBOL ) == symbol && OrderGetDouble (ORDER_VOLUME_CURRENT) == volume && StringFind(OrderGetString (ORDER_COMMENT ),comment) > -1 && OrderGetInteger(ORDER_TYPE ) == ORDER_TYPE_SELL_LIMIT && OrderGetInteger(ORDER_STATE ) == ORDER_STATE_PLACED ){ price_open = OrderGetDouble(ORDER_PRICE_OPEN); if( price_open > valMax ){ valMax = price_open; ticket = order_ticket; } } } } return valMax==value?0.0:valMax; } //+---------------------------------------------------------------------------------+ //| Busca a menor ordem limitada de venda para simbolo,volume e comentario informados //+---------------------------------------------------------------------------------+ double osc_minion_trade::buscarMenorOrdemLimitadaDeVenda(string symbol, string comment, double volume, ulong& ticket){ ulong order_ticket = 0; double price_open ; double valMin = DBL_MAX; //--- passaando por todas as ordens pendentes for(int i=OrdersTotal()-1; i>=0; i--){ //m_order.SelectByIndex(i); if( (order_ticket = OrderGetTicket(i) )>0 ){ if( OrderGetString (ORDER_SYMBOL ) == symbol && OrderGetDouble (ORDER_VOLUME_CURRENT) == volume && StringFind(OrderGetString (ORDER_COMMENT ),comment) > -1 && OrderGetInteger(ORDER_TYPE ) == ORDER_TYPE_SELL_LIMIT && OrderGetInteger(ORDER_STATE ) == ORDER_STATE_PLACED ){ price_open = OrderGetDouble(ORDER_PRICE_OPEN); if( price_open < valMin ){ valMin = price_open; ticket = order_ticket; } } } } return valMin==DBL_MAX?0.0:valMin; } //+------------------------------------------------------------------------------------+ //| Busca a maior ordem limitada de compra para o simbolo,volume e comentario informados //+------------------------------------------------------------------------------------+ double osc_minion_trade::buscarMaiorOrdemLimitadaDeCompra(string symbol, string comment, double volume, ulong& ticket){ ulong order_ticket = 0; double price_open ; double valMax = 0; //--- passando por todas as ordens pendentes for(int i=OrdersTotal()-1; i>=0; i--){ //m_order.SelectByIndex(i); if( (order_ticket = OrderGetTicket(i) )>0 ){ if( OrderGetString (ORDER_SYMBOL ) == symbol && OrderGetDouble (ORDER_VOLUME_CURRENT) == volume && StringFind(OrderGetString (ORDER_COMMENT ),comment) > -1 && OrderGetInteger(ORDER_TYPE ) == ORDER_TYPE_BUY_LIMIT && OrderGetInteger(ORDER_STATE ) == ORDER_STATE_PLACED ){ price_open = OrderGetDouble(ORDER_PRICE_OPEN); if( price_open > valMax ){ valMax = price_open; ticket = order_ticket; } } } } return valMax; } //+---------------------------------------------------------------------------+ //| Busca a MENOR ordem limitada de COMPRA com o comentario informado. | //| Se encontrar, retorna o valor da ordem e seta o ticket. | //| Se nao encontrar retorna zero. | //+---------------------------------------------------------------------------+ double osc_minion_trade::buscarMenorOrdemLimitadaDeCompraComComentarioNumerico( ulong& ticket){ ulong order_ticket = 0; double price_open = 0; double valMin = 0; string strComentarioNumerico; long comentarioNumerico; //--- passaando por todas as ordens pendentes for(int i=OrdersTotal()-1; i>=0; i--){ if( (order_ticket = OrderGetTicket(i) )>0 ){ if( OrderGetString (ORDER_SYMBOL ) == m_symb.Name() && OrderGetInteger(ORDER_TYPE ) == ORDER_TYPE_BUY_LIMIT && OrderGetInteger(ORDER_STATE) == ORDER_STATE_PLACED ){ strComentarioNumerico = OrderGetString(ORDER_COMMENT); comentarioNumerico = StringToInteger(strComentarioNumerico); // se o comentario da ordem eh um numero, entao a cancelamos... if( MathIsValidNumber(comentarioNumerico) && comentarioNumerico != 0 ){ price_open = OrderGetDouble(ORDER_PRICE_OPEN); if( price_open < valMin || valMin == 0){ valMin = price_open; ticket = order_ticket; } } } } } return valMin; } //+---------------------------------------------------------------------------+ //| Busca a MAIOR ordem limitada de VENDA com o comentario informado. | //| Se encontrar, retorna o valor da ordem e seta o ticket. | //| Se nao encontrar retorna zero. | //+---------------------------------------------------------------------------+ double osc_minion_trade::buscarMaiorOrdemLimitadaDeVendaComComentarioNumerico(ulong& ticket){ ticket = 0; ulong order_ticket = 0; double price_open = 0; double valMax = 0; string strComentarioNumerico; long comentarioNumerico; //--- passaando por todas as ordens pendentes for(int i=OrdersTotal()-1; i>=0; i--){ if( (order_ticket = OrderGetTicket(i) )>0 ){ if( OrderGetString (ORDER_SYMBOL ) == m_symb.Name() && OrderGetInteger(ORDER_TYPE ) == ORDER_TYPE_SELL_LIMIT && OrderGetInteger(ORDER_STATE) == ORDER_STATE_PLACED ){ strComentarioNumerico = OrderGetString(ORDER_COMMENT); comentarioNumerico = StringToInteger(strComentarioNumerico); // se o comentario da ordem eh um numero, entao a cancelamos... if( MathIsValidNumber(comentarioNumerico) && comentarioNumerico != 0 ){ price_open = OrderGetDouble(ORDER_PRICE_OPEN); if( price_open > valMax || valMax == 0){ valMax = price_open; ticket = order_ticket; } } } } } return valMax; } // Cancela a MAIOR ordem de VENDA com o comentario numerico. ulong osc_minion_trade::cancelarMaiorOrdemDeVendaComComentarioNumerico(){ ulong ticket; if( buscarMaiorOrdemLimitadaDeVendaComComentarioNumerico(ticket) > 0 ){ //Print(__FUNCTION__, " Cancelando ordem com coment numerico #",ticket, "..."); cancelarOrdem(ticket); } return ticket; } // Cancela a MENOR ordem de COMPRA com o comentario numerico. ulong osc_minion_trade::cancelarMenorOrdemDeCompraComComentarioNumerico(){ ulong ticket; if( buscarMenorOrdemLimitadaDeCompraComComentarioNumerico(ticket) > 0 ){ //Print(__FUNCTION__, " Cancelando ordem com coment numerico #",ticket, "..."); cancelarOrdem(ticket); } return ticket; } //+---------------------------------------------------------------------------+ //| Conta as ordens limitadas de venda do ticker e simbolos informados | //+---------------------------------------------------------------------------+ int osc_minion_trade::contarOrdensLimitadasDeVenda(string symbol, string comment){ int qtd = 0; //--- passaando por todas as ordens pendentes for(int i=OrdersTotal()-1; i>=0; i--){ if( (OrderGetTicket(i) )>0 ){ if( OrderGetString (ORDER_SYMBOL ) == symbol && StringFind(OrderGetString (ORDER_COMMENT ),comment) > -1 && OrderGetInteger(ORDER_TYPE ) == ORDER_TYPE_SELL_LIMIT && orderStatePendente((ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE)) //OrderGetInteger(ORDER_STATE ) == ORDER_STATE_PLACED ){ qtd++; } } } return qtd; } //+---------------------------------------------------------------------------+ //| Conta as ordens limitadas de compra do ticker e simbolos informados | //+---------------------------------------------------------------------------+ int osc_minion_trade::contarOrdensLimitadasDeCompra(string symbol, string comment){ int qtd = 0; //--- passaando por todas as ordens pendentes for(int i=OrdersTotal()-1; i>=0; i--){ if( (OrderGetTicket(i) )>0 ){ if( OrderGetString (ORDER_SYMBOL ) == symbol && StringFind(OrderGetString (ORDER_COMMENT ),comment) > -1 && OrderGetInteger(ORDER_TYPE ) == ORDER_TYPE_BUY_LIMIT && orderStatePendente((ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE)) //OrderGetInteger(ORDER_STATE ) == ORDER_STATE_PLACED ){ qtd++; } } } return qtd; } //+--------------------------------------------------------------------------------------------+ //| Verifica se tenho uma ordem limitada de venda MENOR que o valor e volume especificados. | //| Altera ordens com o valor maior e mesmo comentario. | //+--------------------------------------------------------------------------------------------+ double osc_minion_trade::tenhoOrdemLimitadaDeVendaMenorQue(double value, string symbol, string comment, double volume, ulong& ticket){ ulong order_ticket = 0 ; //bool tenhoOrdem = false; //ENUM_ORDER_STATE order_state; double price_open; //--- passaando por todas as ordens pendentes for(int i=OrdersTotal()-1; i>=0; i--){ //m_order.SelectByIndex(i); if( (order_ticket = OrderGetTicket(i) )>0 ){ //order_state = (ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE); if( OrderGetString (ORDER_SYMBOL ) == symbol && //OrderGetString (ORDER_COMMENT ) == comment && StringFind(OrderGetString (ORDER_COMMENT ),comment) > -1 && OrderGetInteger(ORDER_TYPE ) == ORDER_TYPE_SELL_LIMIT && orderStatePendente((ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE)) //order_state != ORDER_STATE_REJECTED && //order_state != ORDER_STATE_CANCELED && //order_state != ORDER_STATE_EXPIRED ){ price_open = OrderGetDouble(ORDER_PRICE_OPEN); if( price_open < value && OrderGetDouble(ORDER_VOLUME_CURRENT) == volume ){ //tenhoOrdem = true; //return true; // colcoado aqui em 04/02/2020 para que siga verificando todas as ordens pendentes. ticket = order_ticket; return price_open; // foi encontrada a ordem e nao precisou ser modificada }else{ //Print(":-| ",__FUNCTION__ ,"(",value,",",symbol,",",comment,",",volume,") :-| Alt #",order_ticket, // " OldP=",price_open, // " NewP=",value," asyn"); //if( !cancelarOrdem(order_ticket) ) tenhoOrdem=true; alterarOrdem( (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE), value, volume, order_ticket, ""); //tenhoOrdem=true; //return true; // colcoado aqui em 04/02/2020 para que siga verificando todas as ordens pendentes. ticket = order_ticket; return value; // foi encontrada ordem e modificada } } } } return 0; } //+----------------------------------------------------------------------------------------------------------------------------------+ //| Verifica se tenho uma ordem limitada de compra no valor e volume especificados. Altera para o valor e volume especificados | //| caso encontre a ordem com outro valor/volume, mesmo comentario (comentario fazendo parte da ordem encontrada). | //+----------------------------------------------------------------------------------------------------------------------------------+ bool osc_minion_trade::tenhoOrdemLimitadaDeCompra(double value, string symbol, string comment, double volume, bool cancelar, double tolerancia, string newComment=""){ ulong order_ticket = 0 ; //ENUM_ORDER_STATE order_state; double price_open; //--- passando por todas as ordens pendentes for(int i=OrdersTotal()-1; i>=0; i--){ if( (order_ticket = OrderGetTicket(i) )>0 ){ //order_state = (ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE); if( OrderGetString (ORDER_SYMBOL ) == symbol && StringFind(OrderGetString(ORDER_COMMENT),comment) > -1 && OrderGetInteger(ORDER_TYPE ) == ORDER_TYPE_BUY_LIMIT && orderStatePendente((ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE)) //order_state == ORDER_STATE_PLACED ){ price_open = OrderGetDouble (ORDER_PRICE_OPEN); if( price_open >= value-tolerancia && price_open <= value+tolerancia && OrderGetDouble(ORDER_VOLUME_CURRENT) == volume ){ return true; // colcoado aqui em 04/02/2020 para que nao siga verificando todas as ordens pendentes. }else{ if( cancelar ){ Print(":-| ",__FUNCTION__ ,"(",value,",",symbol,",",comment,",",volume,",",cancelar,",",tolerancia,") Alt #",order_ticket, " OldP=",price_open, " NewP=",value," asyn"); alterarOrdem( (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE), value, volume, order_ticket, newComment); return true; // colcoado aqui em 04/02/2020 para que nao siga verificando todas as ordens pendentes. } } } } } return false; } //+--------------------------------------------------------------------------------------------------------------------------------------------------------------+ //| Verifica se tenho uma ordem limitada de compra com valor MAIOR e volume igual aos especificados. Altera ordens com o valor menor e mesmo comentario e volume.| //+--------------------------------------------------------------------------------------------------------------------------------------------------------------+ double osc_minion_trade::tenhoOrdemLimitadaDeCompraMaiorQue(double value, string symbol, string comment, double volume, ulong& ticket){ ulong order_ticket = 0 ; //bool tenhoOrdem = false; //ENUM_ORDER_STATE order_state; double price_open; //--- passaANDO por todas as ordens pendentes for(int i=OrdersTotal()-1; i>=0; i--){ //m_order.SelectByIndex(i); if( (order_ticket = OrderGetTicket(i) )>0 ){ //order_state = (ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE); if( OrderGetString (ORDER_SYMBOL ) == symbol && //OrderGetString (ORDER_COMMENT) == comment && StringFind(OrderGetString(ORDER_COMMENT),comment) > -1 && OrderGetInteger(ORDER_TYPE ) == ORDER_TYPE_BUY_LIMIT && orderStatePendente((ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE)) //order_state != ORDER_STATE_REJECTED && //order_state != ORDER_STATE_CANCELED && //order_state != ORDER_STATE_EXPIRED ){ price_open = OrderGetDouble (ORDER_PRICE_OPEN); if( price_open > value && OrderGetDouble(ORDER_VOLUME_CURRENT) == volume ){ //tenhoOrdem = true; //return true; ticket = order_ticket; return price_open; // foi encontrada a ordem e nao precisou ser modificada }else{ Print(":-| ",__FUNCTION__ ,"(",value,",",symbol,",",comment,",",volume,",",ticket,") Alt #",order_ticket, " OldP=",price_open, " NewP=",value," asyn"); alterarOrdem( (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE), value, volume, order_ticket, ""); //tenhoOrdem = true; //return true; ticket = order_ticket; return value; // foi encontrada a ordem e precisou ser modificada } } } } return 0; } //+-----------------------------------------------------------------------------------------------------------------------+ //| Verifica se tenho uma ordem limitada com volume e comentario iguais aos informados e valor diferente do informado. | //| Se encontrar, altera o valor da ordem para o informardo em "valor". | //+-----------------------------------------------------------------------------------------------------------------------+ bool osc_minion_trade::alterarOrdemLimitadaComValorDiferenteDe(double value, string symbol, double volume, string comment, string newComment=""){ ulong order_ticket = 0 ; ENUM_ORDER_STATE order_state; double price_open; //--- passaando por todas as ordens pendentes for(int i=OrdersTotal()-1; i>=0; i--){ if( (order_ticket = OrderGetTicket(i) )>0 ){ order_state = (ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE); if( OrderGetString (ORDER_SYMBOL ) == symbol && StringFind(OrderGetString (ORDER_COMMENT ),comment) > -1 && //OrderGetInteger(ORDER_TYPE ) == ORDER_TYPE_SELL_LIMIT && order_state != ORDER_STATE_REJECTED && order_state != ORDER_STATE_CANCELED && order_state != ORDER_STATE_EXPIRED ){ price_open = OrderGetDouble(ORDER_PRICE_OPEN); if( price_open != value && OrderGetDouble(ORDER_VOLUME_CURRENT) == volume ){ Print(":-| ",__FUNCTION__ ,"(",value,",",symbol,",",volume,",",comment,",",newComment,") :-| Alt #",order_ticket, " OldP=",price_open, " NewP=",value," asyn"); alterarOrdem( (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE), value, volume, order_ticket, newComment); return true; } } } } return false; } //+---------------------------------------------------------------------+ //| Verifica se tenho uma ordem limitada com o comentario especificado | //+---------------------------------------------------------------------+ bool osc_minion_trade::tenhoOrdemPendenteComComentario( const string symbol, const string comment){ //ulong order_ticket; ENUM_ORDER_STATE order_state; //--- passando por todas as ordens pendentes for(int i=OrdersTotal()-1; i>=0; i--){ //if( (order_ticket = OrderGetTicket(i) )>0 ){ if( OrderGetTicket(i) >0 ){ //m_order.SelectByIndex(i); // selecionando a ordem para posterior alteracao se necessario... order_state = (ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE); if(//m_order.Symbol() == symbol && //m_order.Comment() == comment && OrderGetString (ORDER_SYMBOL ) == symbol && OrderGetString (ORDER_COMMENT) == comment && order_state != ORDER_STATE_REJECTED && order_state != ORDER_STATE_CANCELED && order_state != ORDER_STATE_EXPIRED ){ return true; } } } return false; } //+---------------------------------------------------------------------+ //| Conta e retorna o volume das ordens de venda pendentes. | //+---------------------------------------------------------------------+ double osc_minion_trade::getVolOrdensPendentesDeVenda(string symbol){ ulong order_ticket; double volOrdensPendentes = 0; ENUM_ORDER_STATE order_state; ENUM_ORDER_TYPE order_type; //--- passando por todas as ordens pendentes for(int i=OrdersTotal()-1; i>=0; i--){ if( (order_ticket = OrderGetTicket(i) )>0 ){ //m_order.SelectByIndex(i); // selecionando a ordem para posterior alteracao se necessario... order_state = (ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE); order_type = (ENUM_ORDER_TYPE )OrderGetInteger(ORDER_TYPE ); if( OrderGetString (ORDER_SYMBOL) == symbol && ( order_type == ORDER_TYPE_SELL_LIMIT || order_type == ORDER_TYPE_SELL_STOP || order_type == ORDER_TYPE_SELL_STOP_LIMIT )&& order_state != ORDER_STATE_REJECTED && order_state != ORDER_STATE_CANCELED && order_state != ORDER_STATE_EXPIRED ){ volOrdensPendentes += OrderGetDouble(ORDER_VOLUME_CURRENT); } } } return volOrdensPendentes; } //+---------------------------------------------------------------------+ //| Conta e retorna o volume das ordens de compra pendentes. | //+---------------------------------------------------------------------+ double osc_minion_trade::getVolOrdensPendentesDeCompra(string symbol){ ulong order_ticket; double volOrdensPendentes = 0; ENUM_ORDER_STATE order_state; ENUM_ORDER_TYPE order_type; //--- passando por todas as ordens pendentes for(int i=OrdersTotal()-1; i>=0; i--){ if( (order_ticket = OrderGetTicket(i) )>0 ){ //m_order.SelectByIndex(i); // selecionando a ordem para posterior alteracao se necessario... order_state = (ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE); order_type = (ENUM_ORDER_TYPE )OrderGetInteger(ORDER_TYPE ); if( OrderGetString (ORDER_SYMBOL) == symbol && ( order_type == ORDER_TYPE_BUY_LIMIT || order_type == ORDER_TYPE_BUY_STOP || order_type == ORDER_TYPE_BUY_STOP_LIMIT ) && order_state != ORDER_STATE_REJECTED && order_state != ORDER_STATE_CANCELED && order_state != ORDER_STATE_EXPIRED ){ volOrdensPendentes += OrderGetDouble(ORDER_VOLUME_CURRENT); } } } return volOrdensPendentes; } //+--------------------------------------------------------------------------------+ //| Se tiver ordem pendente sem stop no ativo que estamos operando, coloca o stop. | //+--------------------------------------------------------------------------------+ void osc_minion_trade::colocarStopEmTodasAsOrdens(double stp){ ulong order_ticket = 0 ; //--- passaANDO por todas as ordens pendentes for(int i=OrdersTotal()-1; i>=0; i--){ m_order.SelectByIndex(i); if( (order_ticket = OrderGetTicket(i) )>0 && m_order.Symbol() == _Symbol ){ //Print(":-| osc_minion_trade: 1Colocando stop na ordem ", order_ticket, "..."); colocarStopNaOrdem(order_ticket,stp); } } } //+------------------------------------------------------------------------------+ //| Coloca stop na ordem do ticket informado, se necessario. Sempre assincrono. | //+------------------------------------------------------------------------------+ bool osc_minion_trade::colocarStopNaOrdem(ulong ticket, double stp) { if( OrderSelect(ticket) && m_order.Select(ticket) ){ if( m_order.StopLoss() != 0 ) return true ;//{Print("ordem jah tem stop." ); return true ;} // ordem jah tem stop. //if( m_stp == 0 ) return false ;//{Print("nao tenho stop definido."); return false ;} // nao tenho stop definido. // tem acontecido tentativas de colocar stop em ordens com valor zero. Acho que sao ordens nao limitadas. Verifique. if( m_order.PriceOpen() == 0 ){ Print (__FUNCTION__," :-( Tentativa de colocar stop em ordem com PriceOpen zero. VERIFIQUE! Nao executarei!" ); return false; } double priceStop = m_symb.NormalizePrice(m_order.PriceOpen()-stp); //if( m_order.Type()==ORDER_TYPE_SELL_STOP || m_order.Type()==ORDER_TYPE_SELL_LIMIT ){ if( OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_SELL_STOP || OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_SELL_LIMIT ){ priceStop = m_symb.NormalizePrice(m_order.PriceOpen()+stp); } // Stop Loss //double priceStop = m_symbol.NormalizePrice(m_order.PriceOpen()-stp); //double priceStop = NormalizeDouble(m_order.PriceOpen()-stp, _Digits); //string strtipo; //m_order.FormatType( strtipo,OrderGetInteger(ORDER_TYPE) ); //Print("2Colocando stop na ordem ", ticket , // " param stp:" , stp , // " open:" , m_order.PriceOpen(), // " stop:" , priceStop , // " tipoordem:" , strtipo , // "..." ); bool sincro = m_async; m_async = true; bool retorno = OrderModify(ticket , m_order.PriceOpen() , priceStop , m_order.TakeProfit() , m_order.TypeTime() , m_order.TimeExpiration(), m_order.PriceStopLimit()); m_async = sincro; return retorno; } Print(__FUNCTION__,":-( ERRO colocarStopNaOrdem ticket=",ticket," ORDEM NAO ENCONTRADA!"); return false; return false; } //+-------------------------------------------------------------------------------------+ //| Cancela todas as ordens pendentes, do simbolo informado cujo comentario eh um numero. | //+-------------------------------------------------------------------------------------+ void osc_minion_trade::cancelarOrdensComComentarioNumerico(string symbol) { ulong order_ticket; int qtdOrdensPendentes = OrdersTotal(); //--- passar por todas as ordens pendentes for(int i=0; i 0 ){ if( OrderGetString(ORDER_SYMBOL ) == symbol && OrderGetString(ORDER_COMMENT) != NULL && OrderGetInteger(ORDER_STATE ) == ORDER_STATE_PLACED ){ string strComentarioNumerico = OrderGetString(ORDER_COMMENT); long comentarioNumerico = StringToInteger(strComentarioNumerico); // se o comentario da ordem eh um numero, entao a cancelamos... if( MathIsValidNumber(comentarioNumerico) && comentarioNumerico != 0 ){ //Print(":-| ",__FUNCTION__ ,"(",symbol,") :-| Canc #",order_ticket," coment=(", strComentarioNumerico, ") asyn"); cancelarOrdem(order_ticket); } } }else{ Print(":-( ", __FUNCTION__," :-( ERRO REMOCAO ORDEM ticket=",order_ticket,"IND=", i, " ORDEM NAO ENCONTRADA!"); } } } //+---------------------------------------------------------------------------------------------------------------+ //| Cancela todas as ordens pendentes, do simbolo informado cujo comentario eh um numero e seja do tipo informado.| //+---------------------------------------------------------------------------------------------------------------+ void osc_minion_trade::cancelarOrdensComComentarioNumerico(string symbol, ENUM_ORDER_TYPE tipo) { ulong order_ticket; int qtdOrdensPendentes = OrdersTotal(); //--- passar por todas as ordens pendentes for(int i=0; i 0 ){ if( OrderGetInteger(ORDER_TYPE ) == tipo && OrderGetString(ORDER_SYMBOL ) == symbol && OrderGetString(ORDER_COMMENT) != NULL && OrderGetInteger(ORDER_STATE ) == ORDER_STATE_PLACED ){ string strComentarioNumerico = OrderGetString(ORDER_COMMENT); long comentarioNumerico = StringToInteger(strComentarioNumerico); // se o comentario da ordem eh um numero, entao a cancelamos... if( MathIsValidNumber(comentarioNumerico) && comentarioNumerico != 0 ){ //Print(":-| ",__FUNCTION__ ,"(",symbol,",",EnumToString(tipo),") :-| Canc #",order_ticket," coment=(", strComentarioNumerico, ") asyn"); cancelarOrdem(order_ticket); } } }else{ Print(":-( ", __FUNCTION__," :-( ERRO REMOCAO ORDEM ticket=",order_ticket,"IND=", i, " ORDEM NAO ENCONTRADA!"); } } } //+------------------------------------------------------------------------------------------------+ //+------------------------------------------------------------------------------------------------+ //| Cancela todas as ordens pendentes, do tipo informado e com simbolo configurado nesta instancia.| //| e que tenham uma ou mais ordens no mesmo preco | //+------------------------------------------------------------------------------------------------+ void osc_minion_trade::cancelarOrdensDuplicadas(ENUM_ORDER_TYPE tipo) { ulong order_ticket; ulong ticket2; int qtdOrdensPendentes = OrdersTotal(); //--- passar por todas as ordens pendentes for(int i=0; i 0 ){ if( OrderGetInteger(ORDER_TYPE ) == tipo && OrderGetString(ORDER_SYMBOL ) == m_symb_str && orderStatePendente((ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE)) ){ ticket2 = tenhoOrdemPendente(OrderGetDouble(ORDER_PRICE_OPEN), tipo, order_ticket); if( ticket2 > order_ticket ){ Print(":-| ",__FUNCTION__ ,"(",EnumToString(tipo),") Canc #",ticket2, " asyn"); cancelarOrdem(ticket2); }else{ if(ticket2 > 0 ){ Print(":-| ",__FUNCTION__ ,"(",EnumToString(tipo),") Canc #",order_ticket, " asyn"); cancelarOrdem(order_ticket); } } } } } } //+------------------------------------------------------------------------------------------------+ //+------------------------------------------------------------------------------------------------+ //| Cancela todas as ordens pendentes, do tipo informado e com simbolo configurado nesta instancia.| //+------------------------------------------------------------------------------------------------+ void osc_minion_trade::cancelarOrdens(ENUM_ORDER_TYPE tipo) { ulong order_ticket; int qtdOrdensPendentes = OrdersTotal(); //--- passar por todas as ordens pendentes for(int i=0; i 0 ){ if( OrderGetInteger(ORDER_TYPE ) == tipo && OrderGetString(ORDER_SYMBOL ) == m_symb_str && orderStatePendente((ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE)) ){ Print(":-| ",__FUNCTION__ ,"(",EnumToString(tipo),") Canc #",order_ticket, " asyn"); cancelarOrdem(order_ticket); } }else{ Print(":-( ", __FUNCTION__," :-( ERRO REMOCAO ORDEM ticket=",order_ticket,"IND=", i, " ORDEM NAO ENCONTRADA!"); } } } //+------------------------------------------------------------------------------------------------+ //+----------------------------------------------------------------------------------------------------------------------+ //| Cancela todas as ordens de compra pendentes, menores que valor informado e com o simbolo configurado nesta instancia.| //+----------------------------------------------------------------------------------------------------------------------+ void osc_minion_trade::cancelarOrdensDeCompraMenoresQue(double valor){ ulong order_ticket; int qtdOrdensPendentes = OrdersTotal(); //--- passar por todas as ordens pendentes for(int i=0; i 0 ){ if( OrderGetDouble(ORDER_PRICE_OPEN) < valor && // valor OrderGetString(ORDER_SYMBOL ) == m_symb_str && orderStatePendente((ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE)) && OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT ){ Print(":-| ",__FUNCTION__ ,"(",valor,") Canc #",order_ticket, " asyn"); cancelarOrdem(order_ticket); } }else{ Print(":-( ", __FUNCTION__," :-( ERRO REMOCAO ORDEM ticket=",order_ticket,"IND=", i, " ORDEM NAO ENCONTRADA!"); } } } //+------------------------------------------------------------------------------------------------+ //+----------------------------------------------------------------------------------------------------------------------+ //| Cancela todas as ordens de venda pendentes, maiores que valor informado e com o simbolo configurado nesta instancia. | //+----------------------------------------------------------------------------------------------------------------------+ void osc_minion_trade::cancelarOrdensDeVendaMaioresQue(double valor){ ulong order_ticket; int qtdOrdensPendentes = OrdersTotal(); //--- passar por todas as ordens pendentes for(int i=0; i 0 ){ if( OrderGetDouble (ORDER_PRICE_OPEN) > valor && OrderGetString(ORDER_SYMBOL ) == m_symb_str && orderStatePendente((ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE)) && OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_LIMIT ){ Print(":-| ",__FUNCTION__ ,"(",valor,") Canc #",order_ticket, " asyn"); cancelarOrdem(order_ticket); } }else{ Print(":-( ", __FUNCTION__," :-( ERRO REMOCAO ORDEM ticket=",order_ticket,"IND=", i, " ORDEM NAO ENCONTRADA!"); } } } //+------------------------------------------------------------------------------------------------+ //+----------------------------------------------------------------------------------------------------+ //| Trata-se de uma forma de fechamento de posicao. Funciona no esquema de ordens pendentes | //| nas quais colocamos o ticket da ordem que estah sendo fechada no comentario da ordem de fechamento.| //| A estrategia eh trazer estas ordens que tem comentario numerico a seu valor presente. | //| Se todas as ordens forem executadas a posicao serah fechada, senao, esperamos que fiquem | //| poucas ordens pendentes. | //+----------------------------------------------------------------------------------------------------+ void osc_minion_trade::trazerOrdensComComentarioNumerico2valorPresente(string symbol, int qtdTicksDeslocamento=0) { if( !PositionSelect(symbol) ){ Print(__FUNCTION__,"(",symbol,",",qtdTicksDeslocamento, ") :-( Nao ha posicao aberta!"); } ulong order_ticket; ENUM_ORDER_STATE order_state; int qtdOrdensPendentes = OrdersTotal(); double valor_presente = 0; //ENUM_ORDER_TYPE order_type; double tick_size = SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE); // definindo o valor presente em funcao da posicao ser comprado ou vendido... if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY){ valor_presente = SymbolInfoDouble(symbol,SYMBOL_BID)+(tick_size*qtdTicksDeslocamento); }else{ valor_presente = SymbolInfoDouble(symbol,SYMBOL_ASK)-(tick_size*qtdTicksDeslocamento); } double precoAtual ; long comentarioNumerico ; string strComentarioNumerico; //--- passar por todas as ordens pendentes for(int i=0; i 0 ){ order_state = (ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE); if( OrderGetString(ORDER_SYMBOL) == symbol && OrderGetString(ORDER_COMMENT) != NULL && order_state == ORDER_STATE_PLACED ){ // 10/06/2020 evitando alterar ordens em estado de pendencia strComentarioNumerico = OrderGetString(ORDER_COMMENT); comentarioNumerico = StringToInteger(strComentarioNumerico); precoAtual = OrderGetDouble(ORDER_PRICE_OPEN); // se o comentario da ordem eh um numero, entao alteramos para o valor atual... if( MathIsValidNumber(comentarioNumerico) && comentarioNumerico != 0 ){ if( precoAtual != valor_presente ){ Print(":-| ",__FUNCTION__ ,"(",symbol,") :-| Alter #",order_ticket," coment=(", strComentarioNumerico, ") asyn"); alterarOrdem( (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE), valor_presente, OrderGetDouble(ORDER_VOLUME_CURRENT), order_ticket, "STOP_VP"); //if( !alterarOrdem( (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE), valor_presente, OrderGetDouble(ORDER_VOLUME_CURRENT), order_ticket, "STOP_VP") ){ // Print(":-( ", __FUNCTION__,"(",symbol,",",qtdTicksDeslocamento,",",deep,") ERRO ALTER ORDEM ticket=",order_ticket," IND=", i," PRECO_ATUAL=",precoAtual, " VAL_PRESENTE=", valor_presente); // if( deep==1 ){ // trazerOrdensComComentarioNumerico2valorPresente(symbol, qtdTicksDeslocamento, 2); // } // return; //} } } } }else{ Print(" :-( ",__FUNCTION__," ERRO ALTER ORDEM ticket=",order_ticket," IND=", i, " ORDEM NAO ENCONTRADA!"); // Diminuindo a quantidade de erros quando tenta trazer muitas ordens a valor presente, mas as mesmas jah foram executadas. // Visa evitar erros "Too many trade requests" que acontecem apos muitos erros de ordem nao encontrada. // testar online dia 08/06/2020 na conta demo. //if( deep==1 ){ // trazerOrdensComComentarioNumerico2valorPresente(symbol, qtdTicksDeslocamento, 2); //} return; } } } //+----------------------------------------------------------------------------------------------------+ //| Trata-se de uma forma de alteracao do preco de fechamento da posicao. Funciona no esquema de ordens| //| pendentes nas quais colocamos o ticket da ordem que estah sendo fechada no comentario da ordem de | //| fechamento. | //| Foi feita inicialmente para controlar risco, trazendo o valor de saida da posicao para proximo do | //| breakeven em funcao de criterios avaliados pela estrategia de controle de risco. | //+----------------------------------------------------------------------------------------------------+ bool osc_minion_trade::alterarValorDeOrdensNumericasPara(string symbol,double novoValor, double valorPosicao) { if(!PositionSelect(symbol)){ Print(__FUNCTION__,"(",symbol,",",novoValor,",",valorPosicao, ") :-( Nao ha posicao aberta!"); return false; } ENUM_POSITION_TYPE position_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); double tick_size = SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE); string strComentarioNumerico = ""; long comentarioNumerico = 0 ; double valorAnt = 0 ; novoValor = m_symb.NormalizePrice( novoValor ); ulong order_ticket; ENUM_ORDER_STATE order_state ; ENUM_ORDER_TYPE order_type ; //--- passar por todas as ordens pendentes int qtdOrdensPendentes = OrdersTotal(); for(int i=0; i 0 ){ order_state = (ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE); if( OrderGetString(ORDER_SYMBOL) == symbol && OrderGetString(ORDER_COMMENT) != NULL && order_state == ORDER_STATE_PLACED ){ // testando alteracao apenas de ordens aceitas //order_state != ORDER_STATE_FILLED && // ordens executadas nao podem ser alteradass strComentarioNumerico = OrderGetString(ORDER_COMMENT); comentarioNumerico = StringToInteger(strComentarioNumerico); // se o comentario da ordem eh um numero, entao alteramos para o valor atual... if( MathIsValidNumber(comentarioNumerico) && comentarioNumerico != 0 ){ valorAnt = m_symb.NormalizePrice( OrderGetDouble(ORDER_PRICE_OPEN) ); if( valorAnt != novoValor ){ order_type = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE); //if( position_type == POSITION_TYPE_BUY && novoValor < valorAnt && order_type==ORDER_TYPE_SELL_LIMIT ){ if( position_type == POSITION_TYPE_BUY && order_type==ORDER_TYPE_SELL_LIMIT ){ //Print(":-| ",__FUNCTION__ ,"(",symbol,",",novoValor,") Alter #",order_ticket," [coment=", strComentarioNumerico,",valorAnt=",valorAnt,"] asyn"); alterarOrdem( order_type, novoValor, OrderGetDouble(ORDER_VOLUME_CURRENT), order_ticket); }else{ //if( position_type == POSITION_TYPE_SELL && novoValor > valorAnt && order_type==ORDER_TYPE_BUY_LIMIT ){ if( position_type == POSITION_TYPE_SELL && order_type==ORDER_TYPE_BUY_LIMIT ){ //Print(":-| ",__FUNCTION__ ,"(",symbol,",",novoValor,") Alter #",order_ticket," [coment=", strComentarioNumerico,",valorAnt=",valorAnt,"] asyn"); alterarOrdem( order_type, novoValor, OrderGetDouble(ORDER_VOLUME_CURRENT), order_ticket); } } } } } } }//for return true; } //+-----------------------------------------------------------+ //| Cancela todas as ordens pendentes do ticker configurado. | //+-----------------------------------------------------------+ void osc_minion_trade::cancelarOrdens(string comentario) { ulong order_ticket; int totOrdens = OrdersTotal(); //--- passar por todas as ordens pendentes //for(int i=OrdersTotal()-1; i>=0; i--){ for(int i=0; i0 ){ //order_state = (ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE); if( OrderGetString(ORDER_SYMBOL) == m_symb.Name() && OrderGetInteger(ORDER_STATE) == ORDER_STATE_PLACED ) { //Print(":-| ", __FUNCTION__, "(", comentario, ") Canc #", order_ticket, " asyn"); cancelarOrdem(order_ticket); /* MqlTradeResult result = { 0 }; MqlTradeRequest request = { 0 }; request.order = order_ticket; request.action = TRADE_ACTION_REMOVE; //--- envio do pedido // 27/12/2019: cancelamento de ordens passa a ser assincrono. //if( m_async ){ //------------------------------------------------------------ // verificando se ordem de cancelamento jah foi enviada... //------------------------------------------------------------ if( !permiteCancelarOrdem(order_ticket) ) continue; //------------------------------------------------------------ Print(":-| ", __FUNCTION__, "(", comentario, ") :-| Canc #", order_ticket, " asyn"); if (!OrderSendAsync(request, result)) { addOrdem(request,result); Print(":-( ", __FUNCTION__, "(", comentario, ",", deep, ") :-( REMOCAO ERRO OrderSendAsync ", GetLastError(), ":", result.retcode, ":", result.comment, " order=", order_ticket); //if( result.retcode == TRADE_RETCODE_TOO_MANY_REQUESTS ){ // Print(__FUNCTION__,"(",comentario,":",deep,")"," :-( Aguardando ",M_TIME_SLEEP_MANY_REQUESTS,"ms..." ); // Sleep(M_TIME_SLEEP_MANY_REQUESTS); // consertar e tentar tirar este sleep daqui //} if (deep == 1) { Print(":-( ", __FUNCTION__, "(", comentario, ",", deep, ") :-( Aguardando ", M_TIME_SLEEP_MANY_REQUESTS, "ms e passando controle para execucao da segunda chamada..."); Sleep(M_TIME_SLEEP_MANY_REQUESTS); // consertar e tentar tirar este sleep daqui cancelarOrdens(comentario, 2); } return; } // ordem de cancelamento foi submetida, entao guardamos para posterior verificacao addOrdem(request,result); */ } } } } //+-----------------------------------------------------------+ //| Cancela todas as ordens pendentes do tipo informado | //+-----------------------------------------------------------+ void osc_minion_trade::cancelarOrdensDoTipo(ENUM_ORDER_TYPE tipo) { ulong order_ticket; int totOrdens = OrdersTotal(); //--- passar por todas as ordens pendentes //for(int i=OrdersTotal()-1; i>=0; i--){ for(int i=0; i 0 && OrderGetString (ORDER_SYMBOL ) == m_symb.Name() && OrderGetInteger(ORDER_TYPE) == tipo && OrderGetInteger(ORDER_STATE) == ORDER_STATE_PLACED ){ //Print(":-| ", __FUNCTION__, "(", tipo, ") Canc #", order_ticket, " asyn"); cancelarOrdem(order_ticket); } } } //+-------------------------------------------------------------+ //| Cancela todas as ordens pendentes do tipo e valor informados| //+-------------------------------------------------------------+ void osc_minion_trade::cancelarOrdensPorTipoEvalor(ENUM_ORDER_TYPE tipo, double valor){ ulong order_ticket; int totOrdens = OrdersTotal(); //--- passar por todas as ordens pendentes for(int i=0; i 0 && OrderGetString (ORDER_SYMBOL ) == m_symb.Name() && OrderGetInteger(ORDER_TYPE ) == tipo && OrderGetDouble (ORDER_PRICE_OPEN) == valor && OrderGetInteger(ORDER_STATE ) == ORDER_STATE_PLACED ){ //Print(":-| ", __FUNCTION__, "(", tipo, ") Canc #", order_ticket, " asyn"); cancelarOrdem(order_ticket); } } } //+--------------------------------------------------------------------------------------------------+ //| Cancela todas as ordens pendentes que nao tenham o texto(parametro) como parte do seu comentario.| //+--------------------------------------------------------------------------------------------------+ void osc_minion_trade::cancelarOrdensExcetoComTxt(string txtNaoCancelar, string comentario ) { ulong order_ticket; int totOrdens = OrdersTotal(); //--- passar por todas as ordens pendentes //for(int i=OrdersTotal()-1; i>=0; i--){ for(int i=0; i0 && OrderGetString(ORDER_COMMENT) != NULL && // NAO CANCELA ORDENS SEM COMENTARIO (colocadas manualmente) OrderGetString(ORDER_COMMENT) != "" && // NAO CANCELA ORDENS SEM COMENTARIO (colocadas manualmente) StringFind( OrderGetString(ORDER_COMMENT),txtNaoCancelar) < 0 ){ //Print(":-| ", __FUNCTION__, "(",txtNaoCancelar,",",comentario,") Canc #", order_ticket, " asyn"); cancelarOrdem(order_ticket); // MqlTradeResult result ={0}; // MqlTradeRequest request={0}; // // request.order = order_ticket; // request.action = TRADE_ACTION_REMOVE; // // //--- envio do pedido assincrono // // 27/12/2019: cancelamento de ordens passa a ser assincrono. // //Print(":-| ",__FUNCTION__ ,"(",txtNaoCancelar,",",comentario,") :-| Canc #", order_ticket, " asyn"); // if(!OrderSendAsync(request,result)){ // Print(__FUNCTION__,"(",txtNaoCancelar,",",comentario,",",deep,") :-( REMOCAO ERRO OrderSendAsync ",GetLastError(),":",result.retcode,":",result.comment, " order=",order_ticket); // se não for possível enviar o pedido, exibir um código de erro // //if( result.retcode == TRADE_RETCODE_TOO_MANY_REQUESTS ){ // // Print(__FUNCTION__,"(",txtNaoCancelar,",",comentario,",",deep,")"," :-( Aguardando ",M_TIME_SLEEP_MANY_REQUESTS,"ms..." ); // // Sleep(M_TIME_SLEEP_MANY_REQUESTS); // consertar e tentar tirar este sleep daqui // //} // // if( deep == 1 ){ // Print(__FUNCTION__,"(",txtNaoCancelar,",",comentario,",",deep,") :-| Aguardando ",M_TIME_SLEEP_MANY_REQUESTS,"ms e passando controle para execucao da segunda chamada..."); // Sleep(M_TIME_SLEEP_MANY_REQUESTS); // consertar e tentar tirar este sleep daqui // cancelarOrdensExcetoComTxt(txtNaoCancelar,comentario,2); // } // return; // } } } } //+---------------------------------------------------------------------+ //| Cancela todas as ordens pendentes que tenham o comentario informado.| //| A partir de 20/12/2019 passa a cancelar ordens que contenham a | //| a string informada como parte do seu comentario. | //| | //| A partir de 27/12/2019 cancelamento passa a ser assincrono. | //| | //| A partir de 30/01/2020 passa a cancelar ordens que sejam do simbolo | //| informado. | //| | //| A partir de 20/09/2020:passa a verificar se jah foi enviado pedido | //| - Passa a verificar se jah foi enviado pedido de cancelamento antes| //| de enviar novo pedido. | //| - Passa a nao mais executar duas vezes em caso de erro na primeira | //| execucao. Esperamos nao ser mais necessario devido a verificacao | //| de pedido acima. | //| - Passa a enviar pedidos de cancelamento somente para ordens em | //| estado ORDER_STATE_PLACED, visando menos rejeicoes por tentativa | //| de cancelar ordens em status que nao permitem cancelamento. | //+---------------------------------------------------------------------+ void osc_minion_trade::cancelarOrdensComentadas(string symbol, string comentario) { ulong order_ticket; int totOrdens = OrdersTotal(); //--- passar por todas as ordens pendentes //for(int i=OrdersTotal()-1; i>=0; i--){ for(int i=0; i 0 && OrderGetString(ORDER_SYMBOL ) == symbol && // ADICIONADO EM 30/01/2020 StringFind( OrderGetString(ORDER_COMMENT),comentario) > -1 && OrderGetInteger(ORDER_STATE) == ORDER_STATE_PLACED ){ // add em 20/09/2020 //Print(":-| ", __FUNCTION__, "(", comentario, ") Canc #", order_ticket, " asyn"); cancelarOrdem(order_ticket); // add em 21/09/2020 e comentado trecho abaixo /* MqlTradeResult result ={0}; MqlTradeRequest request={0}; request.order = order_ticket; request.action = TRADE_ACTION_REMOVE; //--- envio do pedido // 27/12/2019: cancelamento de ordens passa a ser assincrono. if(!OrderSendAsync(request,result)){ Print(__FUNCTION__,"(",symbol,",",comentario,",",deep,") :-( REMOCAO ERRO OrderSendAsync ",GetLastError(),":",result.retcode,":",result.comment, " order=", order_ticket); // se não for possível enviar o pedido, exibir um código de erro if( deep == 1 ){ Print(__FUNCTION__,"(",symbol,",",comentario,",",deep,") :-| Aguardando ",M_TIME_SLEEP_MANY_REQUESTS,"ms e passando controle para segunda chamada..."); Sleep(M_TIME_SLEEP_MANY_REQUESTS); // consertar e tentar tirar este sleep daqui cancelarOrdensComentadas(symbol,comentario,2); } return; } */ } } } //+-------------------------------------------------------------------------------+ //| Cancela todas as ordens pendentes de compra, do simbolo informado, | //| que tenham o comentario informado. | //| A partir de 21/01/2020 passa a cancelar ordens que contenham a | //| a string informada como parte do seu comentario. | //+-------------------------------------------------------------------------------+ bool osc_minion_trade::cancelarOrdensComentadasDeCompra(string symbol, string comentario) { ulong order_ticket; int totOrdens = OrdersTotal(); //--- passar por todas as ordens pendentes for(int i=0; i 0 && OrderGetString (ORDER_SYMBOL) == symbol && // ADICIONADO EM 21/01/2020 OrderGetInteger(ORDER_STATE) == ORDER_STATE_PLACED && StringFind( OrderGetString (ORDER_COMMENT),comentario) > -1 && ( OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT ) ){ //Print(":-| ", __FUNCTION__, "(",symbol,",",comentario,") Canc #", order_ticket, " asyn"); cancelarOrdem(order_ticket); // add em 21/09/2020 e comentado trecho abaixo } }//for return true; } //+------------------------------------------------------------------------------+ //| Cancela todas as ordens pendentes de venda, do simbolo informado, | //| que tenham o comentario informado. | //| A partir de 20/12/2019 passa a cancelar ordens que contenham a | //| a string informada como parte do seu comentario. | //+------------------------------------------------------------------------------+ bool osc_minion_trade::cancelarOrdensComentadasDeVenda(string symbol, string comentario) { ulong order_ticket; int totOrdens = OrdersTotal(); //--- passar por todas as ordens pendentes for(int i=0; i 0 && OrderGetString (ORDER_SYMBOL) == symbol && // ADICIONADO EM 21/01/2010 OrderGetInteger(ORDER_STATE) == ORDER_STATE_PLACED && StringFind( OrderGetString (ORDER_COMMENT),comentario) > -1 && ( OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_LIMIT ) ){ //Print(":-| ", __FUNCTION__, "(",symbol,",",comentario,") Canc #", order_ticket, " asyn"); cancelarOrdem(order_ticket); // add em 21/09/2020 e comentado trecho abaixo } } // for sobre total de ordens... return true; } //+-------------------------------------------------------------------------------+ //| Cancela ordens pendentes de venda, do simbolo, valor e comentario informados. | //+-------------------------------------------------------------------------------+ bool osc_minion_trade::cancelarOrdensComentadasDeVenda(string symbol, string comentario, double valor) { ulong order_ticket; int totOrdens = OrdersTotal(); //--- passar por todas as ordens pendentes //for(int i=OrdersTotal()-1; i>=0; i--){ for(int i=0; i 0 && OrderGetString(ORDER_SYMBOL) == symbol && // simbolo OrderGetInteger(ORDER_STATE) == ORDER_STATE_PLACED && OrderGetDouble(ORDER_PRICE_OPEN) == valor && // valor StringFind( OrderGetString (ORDER_COMMENT),comentario) > -1 && // comentario ( OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_LIMIT || // venda OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL || OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP || OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP_LIMIT ) ){ //Print(":-| ", __FUNCTION__, "(",symbol,",",comentario,",",valor,") Canc #", order_ticket, " asyn"); cancelarOrdem(order_ticket); // add em 21/09/2020 e comentado trecho abaixo /* MqlTradeResult result ={0}; MqlTradeRequest request={0}; request.order = order_ticket; request.action = TRADE_ACTION_REMOVE; //--- envio do pedido assincrono //Print(":-| ",__FUNCTION__ ,"(",symbol,",",comentario,") :-| Canc #", order_ticket, " asyn"); if(!OrderSendAsync(request,result)){ Print(__FUNCTION__,"(",symbol,",",comentario,",",valor,",",deep,") :-( REMOCAO ERRO OrderSendAsync ",GetLastError(), ":", result.retcode,":",result.comment, " order=", order_ticket); // se não for possível enviar o pedido, exibir um código de erro //if( result.retcode == TRADE_RETCODE_TOO_MANY_REQUESTS ){ // Print(__FUNCTION__,"(",symbol,",",comentario,",",valor,")"," :-( Aguardando ",M_TIME_SLEEP_MANY_REQUESTS,"ms..." ); // Sleep(M_TIME_SLEEP_MANY_REQUESTS); // consertar e tentar tirar este sleep daqui //} if( deep == 1 ){ Print(__FUNCTION__,"(",symbol,",",comentario,",",valor,",",deep,")"," :-( Aguardando ",M_TIME_SLEEP_MANY_REQUESTS,"ms e passando controle para segunda chamada..." ); Sleep(M_TIME_SLEEP_MANY_REQUESTS); // consertar e tentar tirar este sleep daqui cancelarOrdensComentadasDeVenda(symbol, comentario, valor, 2); } return false; // se retornou aqui, eh porque encontrou ordens a cancelar e chegou a ter algum problema, mesmo que // tenha conseguido cancelar as ordens. }else{ Print(":-| ",__FUNCTION__ ,"(",symbol,",",comentario,",",valor,",",deep,") :-| Canc #", order_ticket, " asyn"); } */ } }// for return true; } //+-------------------------------------------------------------------------------+ //| Cancela ordens pendentes de compra, do simbolo, valor e comentario informados. | //+-------------------------------------------------------------------------------+ bool osc_minion_trade::cancelarOrdensComentadasDeCompra(string symbol, string comentario, double valor) { ulong order_ticket; int totOrdens = OrdersTotal(); //--- passar por todas as ordens pendentes //for(int i=OrdersTotal()-1; i>=0; i--){ for(int i=0; i 0 && OrderGetString(ORDER_SYMBOL) == symbol && // simbolo OrderGetDouble(ORDER_PRICE_OPEN) == valor && // valor OrderGetInteger(ORDER_STATE) == ORDER_STATE_PLACED && StringFind( OrderGetString (ORDER_COMMENT),comentario) > -1 && // comentario ( OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT || // venda OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY || OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP || OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP_LIMIT ) ){ //Print(":-| ", __FUNCTION__, "(",symbol,",",comentario,",",valor,") Canc #", order_ticket, " asyn"); cancelarOrdem(order_ticket); // add em 21/09/2020 e comentado trecho abaixo /* MqlTradeResult result ={0}; MqlTradeRequest request={0}; request.order = order_ticket; request.action = TRADE_ACTION_REMOVE; //--- envio do pedido assincrono if(!OrderSendAsync(request,result)){ Print(__FUNCTION__,"(",symbol,",",comentario,",",valor,",",deep,") :-( REMOCAO ERRO OrderSendAsync ",GetLastError(), ":", result.retcode,":",result.comment, " order=", order_ticket); // se não for possível enviar o pedido, exibir um código de erro //if( result.retcode == TRADE_RETCODE_TOO_MANY_REQUESTS ){ // Print(__FUNCTION__,"(",symbol,",",comentario,",",valor,")"," :-( Aguardando ",M_TIME_SLEEP_MANY_REQUESTS,"ms..." ); // Sleep(M_TIME_SLEEP_MANY_REQUESTS); // consertar e tentar tirar este sleep daqui //} if( deep == 1 ){ Print(__FUNCTION__,"(",symbol,",",comentario,",",valor,",",deep,")"," :-( Aguardando ",M_TIME_SLEEP_MANY_REQUESTS,"ms e passando controle para segunda chamada..." ); Sleep(M_TIME_SLEEP_MANY_REQUESTS); // consertar e tentar tirar este sleep daqui cancelarOrdensComentadasDeCompra(symbol, comentario, valor, 2); } return false; // se retornou aqui, eh porque encontrou ordens a cancelar e chegou a ter algum problema, mesmo que // tenha conseguido cancelar as ordens. }else{ Print(":-| ",__FUNCTION__ ,"(",symbol,",",comentario,",",valor,",", deep, ") :-| Canc #", order_ticket, " asyn"); } */ } }// for return true; } //+-------------------------------------------------------------------------------+ //| Cancela ordens pendentes de compra, do simbolo, valor e comentario informados. | //+-------------------------------------------------------------------------------+ bool osc_minion_trade::cancelarOrdensComentadasDeCompraMenoresQue(string symbol,string comentario,double valor){ ulong order_ticket; int totOrdens = OrdersTotal(); //--- passar por todas as ordens pendentes for(int i=0; i 0 && OrderGetString(ORDER_SYMBOL) == symbol && // simbolo OrderGetDouble(ORDER_PRICE_OPEN) < valor && // valor OrderGetInteger(ORDER_STATE) == ORDER_STATE_PLACED && StringFind( OrderGetString (ORDER_COMMENT),comentario) > -1 && // comentario ( OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT || // venda OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY || OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP || OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP_LIMIT ) ){ //Print(":-| ", __FUNCTION__, "(",symbol,",",comentario,",",valor,",",deep,") Canc #", order_ticket, " asyn"); cancelarOrdem(order_ticket); // add em 21/09/2020 e comentado trecho abaixo } }// for return true; } //+-------------------------------------------------------------------------------+ //| Cancela ordens pendentes de venda, do simbolo, valor e comentario informados. | //+-------------------------------------------------------------------------------+ bool osc_minion_trade::cancelarOrdensComentadasDeVendaMaioresQue(string symbol, string comentario, double valor) { ulong order_ticket; int totOrdens = OrdersTotal(); //--- passar por todas as ordens pendentes for(int i=0; i 0 && OrderGetString(ORDER_SYMBOL) == symbol && // simbolo OrderGetDouble(ORDER_PRICE_OPEN) > valor && // valor OrderGetInteger(ORDER_STATE) == ORDER_STATE_PLACED && StringFind( OrderGetString (ORDER_COMMENT),comentario) > -1 && // comentario ( OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_LIMIT || // venda OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL || OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP || OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP_LIMIT ) ){ //Print(":-| ", __FUNCTION__, "(",symbol,",",comentario,",",valor,",",deep,") Canc #", order_ticket, " asyn"); cancelarOrdem(order_ticket); // add em 21/09/2020 e comentado trecho abaixo } }// for return true; } //+-----------------------------------------------------------+ //| Fecha as posicoes compradas | //| tem bug. Soh funciona em contas hedge | //+-----------------------------------------------------------+ void osc_minion_trade::fecharPosicaoComprada(string symbol, string comentario) { if( estouComprado(symbol) ){ fecharPosicao(comentario); } } //+-----------------------------------------------------------+ //| Fecha as posicoes vendidas | //| tem bug. Soh funciona em contas hedge | //+-----------------------------------------------------------+ void osc_minion_trade::fecharPosicaoVendida(string symbol, string comentario) { if( estouVendido(symbol) ){ fecharPosicao(comentario); } } //+-----------------------------------------------------------------+ //| Fecha todas as posicoes abertas pelo EA. Usa o magic para saber.| //+-----------------------------------------------------------------+ void osc_minion_trade::fecharPosicao(string comentario) { int total=PositionsTotal(); // qtd posicoes abertas for(int i=total-1; i>=0; i--) { //--- parâmetros da ordem ulong position_ticket=PositionGetTicket(i); // bilhete da posição string position_symbol=PositionGetString(POSITION_SYMBOL); // simbolo int digits=(int)SymbolInfoInteger(position_symbol,SYMBOL_DIGITS); // número de signos depois da coma ulong magic=PositionGetInteger(POSITION_MAGIC); // MagicNumber da posição double volume=PositionGetDouble(POSITION_VOLUME); // volume da posição ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); // tipo de posição //--- saída de informação sobre a posição PrintFormat(":-| osc_minion_trade: Fechando posicao #%I64u %s %s %.2f %s [%I64d] ...", position_ticket, position_symbol, EnumToString(type), volume, DoubleToString(PositionGetDouble(POSITION_PRICE_OPEN),digits), magic); //--- se o MagicNumber coincidir if(magic==m_mmagic){ //--- zerar os valores do pedido e os seus resultados ZeroMemory(m_treq); ZeroMemory(m_tres); //--- configuração dos parâmetros da ordem m_treq.action =TRADE_ACTION_DEAL; // tipo de operação de negociação //m_treq.type =ORDER_TYPE_CLOSE_BY; m_treq.position =position_ticket; // bilhete da posição m_treq.symbol =position_symbol; // símbolo m_treq.volume =volume; // volume da posição m_treq.deviation=m_desvio; // desvio permitido do preço m_treq.magic =m_mmagic; // MagicNumber da posição //--- envio do pedido if( m_async ){ if(!OrderSendAsync(m_treq,m_tres)){ PrintFormat(":-( osc_minion_trade: CLOSE ERRO OrderSend %d :" + comentario,GetLastError()); // se não for possível enviar o pedido, exibir um código de erro PrintFormat(":-( osc_minion_trade: CLOSE ERRO retcode=%u deal=%I64u order=%I64u :" + comentario, m_tres.retcode,m_tres.deal,m_tres.order); } }else{ if(!OrderSend(m_treq,m_tres)){ PrintFormat(":-( osc_minion_trade: CLOSE ERRO OrderSend %d :" + comentario,GetLastError()); // se não for possível enviar o pedido, exibir um código de erro PrintFormat(":-( Ctrade: CLOSE ERRO retcode=%u deal=%I64u order=%I64u :" + comentario, m_tres.retcode,m_tres.deal,m_tres.order); } } // aguardando a posicao ser fechada por eteh 10 segundos ... for(int a=0; a<100; a++){ if( PositionSelectByTicket(position_ticket) ){ Print( ":-| Fechando posicao ticket=",position_ticket, " volume=",volume, " ordem=",m_tres.order,"..." ); Sleep(1000); }else{ Print( ":-| Posicao fechada! ticket=",position_ticket, " volume=",volume, " ordem=",m_tres.order,"..." ); break; } } }//end if }// end for }// end fecharPosicao() //+-----------------------------------------------------------+ //| Fecha todas as posicoes da conta | //+-----------------------------------------------------------+ void osc_minion_trade::fecharQualquerPosicao(string comentario) { int total=PositionsTotal(); // qtd posicoes abertas for(int i=total-1; i>=0; i--) { //--- parâmetros da ordem ulong position_ticket=PositionGetTicket(i); // bilhete da posição string position_symbol=PositionGetString(POSITION_SYMBOL); // simbolo int digits=(int)SymbolInfoInteger(position_symbol,SYMBOL_DIGITS); // número de signos depois da coma ulong magic=PositionGetInteger(POSITION_MAGIC); // MagicNumber da posição double volume=PositionGetDouble(POSITION_VOLUME); // volume da posição ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); // tipo de posição //--- saída de informação sobre a posição PrintFormat(":-| Ctrade::fecharQualquerPosicao #%I64u %s %s %.2f %s [%I64d]", position_ticket, position_symbol, EnumToString(type), volume, DoubleToString(PositionGetDouble(POSITION_PRICE_OPEN),digits), magic); //--- se o MagicNumber coincidir //if(magic==m_mmagic){ //--- zerar os valores do pedido e os seus resultados ZeroMemory(m_treq); ZeroMemory(m_tres); //--- configuração dos parâmetros da ordem m_treq.action =TRADE_ACTION_DEAL; // tipo de operação de negociação //m_treq.type =ORDER_TYPE_CLOSE_BY; // MagicNumber da posição m_treq.position =position_ticket; // bilhete da posição m_treq.symbol =position_symbol; // símbolo m_treq.volume =volume; // volume da posição m_treq.deviation=m_desvio; // desvio permitido do preço m_treq.magic =m_mmagic; // MagicNumber da posição m_treq.type_filling = ORDER_FILLING_RETURN;// Order execution type //--- colocação do preço e tipo de ordem dependendo do tipo de ordem if(type==POSITION_TYPE_BUY){ //m_treq.price=SymbolInfoDouble(position_symbol,SYMBOL_BID); //m_treq.type =ORDER_TYPE_SELL; enviarOrdemPendente(ORDER_TYPE_SELL_LIMIT, SymbolInfoDouble(position_symbol,SYMBOL_BID), volume, comentario); return; }else{ //m_treq.price=SymbolInfoDouble(position_symbol,SYMBOL_ASK); //m_treq.type =ORDER_TYPE_BUY; enviarOrdemPendente(ORDER_TYPE_BUY_LIMIT , SymbolInfoDouble(position_symbol,SYMBOL_ASK), volume, comentario); return; } //--- envio do pedido //if( m_async ){ // if(!OrderSendAsync(m_treq,m_tres)){ // PrintFormat(":-( Ctrade: CLOSE ERRO OrderSend %d :" + comentario,GetLastError()); // se não for possível enviar o pedido, exibir um código de erro // PrintFormat(":-( Ctrade: CLOSE ERRO retcode=%u deal=%I64u order=%I64u :" + comentario, m_tres.retcode,m_tres.deal,m_tres.order); // return; // } //}else{ // if(!OrderSend(m_treq,m_tres)){ // PrintFormat(":-( Ctrade: CLOSE ERRO OrderSend %d :" + comentario,GetLastError()); // se não for possível enviar o pedido, exibir um código de erro // PrintFormat(":-( Ctrade: CLOSE ERRO retcode=%u deal=%I64u order=%I64u :" + comentario, m_tres.retcode,m_tres.deal,m_tres.order); // return; // } //} // aguardando a posicao ser fechada por eteh 10 segundos ... //for(int a=0; a<100; a++){ // if( PositionSelectByTicket(position_ticket) ){ // Print( ":-| Fechando posicao ticket=",position_ticket, " volume=",volume, " ordem=",m_tres.order,"..." ); // Sleep(1000); // }else{ // Print( ":-| Posicao fechada! ticket=",position_ticket, " volume=",volume, " ordem=",m_tres.order,"..." ); // break; // } //} //}//end if } // end for }// end fecharPosicao() //+-------------------------------------------------------------------+ //| Fecha posico em conta Neting, para o simbolo informado. Usa | //| ordem pendente para fechar a mesma. | //| Retorna: | //| - ticket da ordem usada para fechar a posicao. | //| - zero se a posicao nao for encontrada ou | //| - se houver erro ao enviar a ordem de fechamento da posicao.| //+-------------------------------------------------------------------+ ulong osc_minion_trade::fecharPosicaoCtaNetting(string symbol, string comentario="") { if (!PositionSelect(symbol)){ Print( __FUNCTION__, ":-| Erro obtendo posicao a fechar para ", symbol, " VERIFIQUE!", GetLastError() ); return -1; } //--- colocacao do preco e tipo de ordem dependendo do tipo de posicao que serah fechada if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY){ if( enviarOrdemPendente(ORDER_TYPE_SELL_LIMIT, SymbolInfoDouble(symbol,SYMBOL_BID), PositionGetDouble(POSITION_VOLUME), comentario) ){ return m_tres.order; } Print( __FUNCTION__, ":-( Erro fechando posicao!!", symbol, " VERIFIQUE!", GetLastError() ); return -1; }else{ if( enviarOrdemPendente(ORDER_TYPE_BUY_LIMIT , SymbolInfoDouble(symbol,SYMBOL_ASK), PositionGetDouble(POSITION_VOLUME), comentario) ){ return m_tres.order; } Print( __FUNCTION__, ":-( Erro fechando posicao!!", symbol, " VERIFIQUE!", GetLastError() ); return -1; } // aguardando a posicao ser fechada por eteh 10 segundos ... //for(int a=0; a<100; a++){ // if( PositionSelectByTicket(position_ticket) ){ // Print( ":-| Fechando posicao ticket=",position_ticket, " volume=",volume, " ordem=",m_tres.order,"..." ); // Sleep(1000); // }else{ // Print( ":-| Posicao fechada! ticket=",position_ticket, " volume=",volume, " ordem=",m_tres.order,"..." ); // break; // } //} } //+-----------------------------------------------------------+ //| Verifica se tem uma posicao e se eh de compra | //+-----------------------------------------------------------+ bool osc_minion_trade::estouComprado(string symbol) { // voltar aqui e melhorar a performance. Use positionselect diretamente sem perguntar por positiontotal. Ver uso em fecharPosicaoCtaNetting. if ( PositionsTotal() > 0 ){ m_position.Select(symbol); ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); // tipo de posicao if(type==POSITION_TYPE_BUY){ return true; } } return false; } //+-----------------------------------------------------------+ //| Verifica se tem uma posicao e se eh de venda | //+-----------------------------------------------------------+ bool osc_minion_trade::estouVendido(string symbol) { // voltar aqui e melhorar a performance. Use positionselect diretamente sem perguntar por positiontotal. Ver uso em fecharPosicaoCtaNetting. if ( PositionsTotal() > 0 ){ m_position.Select(symbol); ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); // tipo de posicao if(type==POSITION_TYPE_SELL){ return true; } } return false; } //+------------------------------------------------------------------+ //--------------------------------------------------------------- // Administracao de ordens e seus resultados de processamento //--------------------------------------------------------------- // adiciona requisicao e resultado de uma ordem void osc_minion_trade::addOrdem(MqlTradeRequest& req, MqlTradeResult& res, ulong ordem=0){ // montando o objeto que serah armazenado (requisicao e resposta) TradeOrder* ord = new TradeOrder; ord.req = req; ord.res = res; // se estiver na colecao, atualiza e termina if(ordem==0) ordem = req.order; // se a ordem nao foi informada, usa a da requisicao if(ordem==0) ordem = res.order; // se a ordem da requisicao estah zerada, usa a do resultado if( m_ordens.TrySetValue(ordem,ord) ) return; // nao estah na colecao, entao incluimos m_ordens.Add(ordem,ord); } // recupera ultima requisicao e resultado de uma ordem. Se nao encontrar, retorna nulo TradeOrder* osc_minion_trade::getOrdem(ulong ordem){ TradeOrder* ord; if( m_ordens.TryGetValue(ordem,ord) ) return ord; return NULL; } // valida se pode enviar pedido de alteracao de ordem bool osc_minion_trade::permiteAlterarOrdem(ulong ordem, double newPrice, double newVol, string newComment){ TradeOrder* to = getOrdem(ordem); if(to==NULL) return true; // parametros a alterar sao iguais aos ultimos do pedido. Nao permita alterar com mesmos parametros, ainda que a ultima alteracao tenha falhado. if( newPrice == to.req.price && newVol == to.req.volume && newComment == to.req.comment ){ Print(":-| ", __FUNCTION__,"(",ordem,",",newPrice,",",newVol,",",newComment,"): alteracao rejeitada antes do envio, pois ordem jah possui os parametros solicitados." ); return false; } return true; } // valida se pode enviar pedido de cancelamento de ordem bool osc_minion_trade::permiteCancelarOrdem(ulong ordem){ TradeOrder* to = getOrdem(ordem); if(to==NULL) return true; // Jah enviou um pedido de cancelamento. Nao permite enviar outro, ainda que o ultimo cancelamento tenha falhado. if( to.req.action == TRADE_ACTION_REMOVE ){ //Print(":-| ", __FUNCTION__, "(", ordem, ") Canc rejeitado antes do envio pois jah possui um pedido de cancelamento."); return false; } return true; } //--------------------------------------------------------------- //+----------------------------------------------------------------------------------------------------------------------+ //| verifica se ah ordem com comentario numerico no preco informado para o simbolo configurado na instancia deste objeto.| //+----------------------------------------------------------------------------------------------------------------------+ bool osc_minion_trade::tenhoOrdenComComentarioNumerico(double price, ENUM_ORDER_TYPE tipo){ ulong order_ticket; int qtdOrdensPendentes = OrdersTotal(); //--- passar por todas as ordens pendentes for(int i=0; i 0 ){ if( OrderGetInteger(ORDER_TYPE ) == tipo && OrderGetDouble (ORDER_PRICE_OPEN) == price && OrderGetString(ORDER_SYMBOL ) == m_symb_str && OrderGetString(ORDER_COMMENT ) != NULL && orderStatePendente( (ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE) ) //( OrderGetInteger(ORDER_STATE ) == ORDER_STATE_PLACED // || OrderGetInteger(ORDER_STATE ) == ORDER_STATE_STARTED // || OrderGetInteger(ORDER_STATE ) == ORDER_STATE_REQUEST_ADD // || OrderGetInteger(ORDER_STATE ) == ORDER_STATE_PARTIAL ) ){ string strComentarioNumerico = OrderGetString(ORDER_COMMENT); long comentarioNumerico = StringToInteger(strComentarioNumerico); // se o comentario da ordem eh um numero, entao encontramos... if( MathIsValidNumber(comentarioNumerico) && comentarioNumerico != 0 ){ return true; } } }else{ Print(":-( ", __FUNCTION__," :-( ERRO BUSCA_ORDEM_NUMERICA ticket=",order_ticket,"IND=", i, " ORDEM NAO ENCONTRADA!"); } } return false; } //+-------------------------------------------------------------------------------------------------------+ //| verifica se ah ordem pendente no preco informado para o simbolo configurado na instancia deste objeto.| //+-------------------------------------------------------------------------------------------------------+ bool osc_minion_trade::tenhoOrdemPendente(double price){ ulong order_ticket; int qtdOrdensPendentes = OrdersTotal(); //--- passar por todas as ordens pendentes for(int i=0; i 0 ){ if( OrderGetDouble (ORDER_PRICE_OPEN) == price && OrderGetString(ORDER_SYMBOL ) == m_symb_str && orderStatePendente( (ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE) ) ){ return true; } }else{ Print(":-( ", __FUNCTION__,"(",price,") ERRO BUSCA_ORDEM_PENDENTE ticket=",order_ticket,"IND=", i, " ORDEM NAO ENCONTRADA!"); } } return false; } //+-------------------------------------------------------------------------------------------------------+ //| verifica se ah ordem pendente no preco informado para o simbolo configurado na instancia deste objeto.| //+-------------------------------------------------------------------------------------------------------+ ulong osc_minion_trade::tenhoOrdemPendente(double price, ENUM_ORDER_TYPE tipo, ulong ticketOut){ ulong order_ticket; int qtdOrdensPendentes = OrdersTotal(); //--- passar por todas as ordens pendentes for(int i=0; i 0 ){ if( order_ticket != ticketOut && OrderGetDouble(ORDER_PRICE_OPEN) == price && OrderGetInteger(ORDER_TYPE ) == tipo && OrderGetString(ORDER_SYMBOL ) == m_symb_str && orderStatePendente( (ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE) ) ){ return order_ticket; } }else{ Print(":-( ", __FUNCTION__,"(",price,") ERRO BUSCA_ORDEM_PENDENTE ticket=",order_ticket,"IND=", i, " ORDEM NAO ENCONTRADA!"); } } return 0; }