2772 lines
282 KiB
MQL5
2772 lines
282 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| 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 <Expert\ExpertTrade.mqh>
|
|
#include <Trade\SymbolInfo.mqh>
|
|
#include <Trade\Trade.mqh>
|
|
#include <Generic\HashMap.mqh>
|
|
#include <Object.mqh>
|
|
|
|
#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<ulong,TradeOrder*> 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); //<TODO> 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); //<TODO> 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); //<TODO> 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); //<TODO> 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{
|
|
//<TODO:> 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<qtdOrdens; i++ ){
|
|
if( !tenhoOrdemLimitadaDeVenda(valOrdem,symbol,comment ) ){
|
|
enviarOrdemPendente(ORDER_TYPE_SELL_LIMIT, valOrdem, volume, comment);
|
|
}
|
|
valOrdem = m_symb.NormalizePrice(valOrdem+tickSize);
|
|
}
|
|
//restoreAsync();
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------------------------+
|
|
//| Mantem uma sequencia de ordens limitadas de compra abaixo do valor informado. |
|
|
//+--------------------------------------------------------------------------------------------+
|
|
void osc_minion_trade::preencherOrdensLimitadasDeCompraAbaixo(double valIni, int qtdOrdens, string symbol, string comment, double volume, double tickSize){
|
|
|
|
double valOrdem = valIni;
|
|
//saveAsync(); setAsync(true);
|
|
|
|
for( int i=0; i<qtdOrdens; i++ ){
|
|
if( !tenhoOrdemLimitadaDeCompra(valOrdem,symbol,comment ) ){
|
|
enviarOrdemPendente(ORDER_TYPE_BUY_LIMIT, valOrdem, volume, comment);
|
|
}
|
|
valOrdem = m_symb.NormalizePrice(valOrdem-tickSize);
|
|
}
|
|
//restoreAsync();
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------------------------+
|
|
//| Mantem uma sequencia de ordens limitadas de venda acima do valor informado. |
|
|
//+--------------------------------------------------------------------------------------------+
|
|
void osc_minion_trade::preencherOrdensLimitadasDeVendaAcimaComLag(double valIni, int qtdOrdens, string symbol, string comment, double volume, double tickSize, int lag){
|
|
|
|
//
|
|
// Determinando o valor inicial
|
|
//
|
|
// 1.2 Busca maior ordem maior que a inicial.
|
|
// 1.2.1 Se encontrar retorna um lag por vez ateh encontrar o menor valor
|
|
// maior ou igual ao inicial. Este serah o valor inicial.
|
|
//
|
|
// 1.2.2 Se nao encontrar, entao valIni eh o valor inicial valido.
|
|
//
|
|
|
|
// 1.2 Busca maior ordem maior que a inicial.
|
|
ulong ticket;
|
|
double newValIni = buscarMaiorOrdemLimitadaDeVendaAcimaDe(valIni, symbol, comment, volume, ticket);
|
|
|
|
// 1.2.1 Se encontrar retorna um lag por vez ateh encontrar o menor valor maior ou igual ao 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;
|
|
|
|
//m_symb.RefreshRates();
|
|
//double ask = m_symb.Ask();
|
|
|
|
for( int i=0; i<qtdOrdens; i++ ){
|
|
|
|
// incluindo as ordens no lag...
|
|
if( !tenhoOrdemLimitadaDeVenda(valOrdem,symbol,comment ) ){
|
|
if(valOrdem >= valIni) enviarOrdemPendente(ORDER_TYPE_SELL_LIMIT, valOrdem, volume, comment);
|
|
}
|
|
|
|
// eliminando as ordens desalinhadas com o lag...
|
|
for(int j=1; j<lag;j++){
|
|
valOrdem = m_symb.NormalizePrice( valOrdem + tickSize );
|
|
if( tenhoOrdemLimitadaDeVenda(valOrdem,symbol,comment ) ){
|
|
//Print("Cancelando ordem de venda desalinhadas com o lag. Valor:",valOrdem);
|
|
cancelarOrdensComentadasDeVenda(symbol,comment,valOrdem);
|
|
}
|
|
}
|
|
valOrdem = m_symb.NormalizePrice( valOrdem + tickSize );
|
|
}
|
|
|
|
int qtd = contarOrdensLimitadasDeVenda(symbol,comment);
|
|
//Print("Cancelando ordens de venda maiores que:",valOrdem);
|
|
// Eliminando ordens acima da faixa ordens permitida...
|
|
if(qtd>qtdOrdens) 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; i++ ){
|
|
// valOrdem = m_symb.NormalizePrice( valOrdem -(tickSize*lag) );
|
|
// if( !tenhoOrdemLimitadaDeCompra(valOrdem,symbol,comment ) ){
|
|
// enviarOrdemPendente(ORDER_TYPE_BUY_LIMIT, valOrdem, volume, comment);
|
|
// }
|
|
// //valOrdem = m_symb.NormalizePrice( valOrdem -(tickSize*lag) );
|
|
//}
|
|
|
|
//m_symb.RefreshRates();
|
|
//double bid = m_symb.Bid();
|
|
for( int i=0; i<qtdOrdens; i++ ){
|
|
|
|
// incluindo as ordens no lag...
|
|
if( !tenhoOrdemLimitadaDeCompra(valOrdem,symbol,comment ) ){
|
|
if( valOrdem <= valIni ) enviarOrdemPendente(ORDER_TYPE_BUY_LIMIT, valOrdem, volume, comment);
|
|
}
|
|
|
|
// eliminando as ordens desalinhadas com o lag...
|
|
for(int j=1;j<lag;j++){
|
|
valOrdem = m_symb.NormalizePrice( valOrdem - tickSize );
|
|
if( tenhoOrdemLimitadaDeCompra(valOrdem,symbol,comment ) ){
|
|
//Print("Cancelando ordem de compra desalinhadas com o lag. Valor:",valOrdem);
|
|
cancelarOrdensComentadasDeCompra(symbol,comment,valOrdem);
|
|
}
|
|
}
|
|
valOrdem = m_symb.NormalizePrice( valOrdem - tickSize );
|
|
}
|
|
|
|
int qtd = contarOrdensLimitadasDeCompra(symbol,comment);
|
|
// Eliminando ordens abaixo da faixa ordens permitida...
|
|
if( qtd > 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<qtdOrdens; i++ ){
|
|
|
|
// incluindo as ordens no lag...
|
|
if( !tenhoOrdemLimitadaDeVenda(valOrdem,symbol,comment ) ){
|
|
if(valOrdem >= valIni) enviarOrdemPendente(ORDER_TYPE_SELL_LIMIT, valOrdem, volume, comment);
|
|
}
|
|
|
|
// eliminando as ordens desalinhadas com o lag...
|
|
for(int j=1; j<lag;j++){
|
|
valOrdem = m_symb.NormalizePrice( valOrdem + tickSize );
|
|
if( tenhoOrdemLimitadaDeVenda(valOrdem,symbol,comment ) ){
|
|
//Print("Cancelando ordem de venda desalinhadas com o lag. Valor:",valOrdem);
|
|
cancelarOrdensComentadasDeVenda(symbol,comment,valOrdem);
|
|
cancelarOrdensPorTipoEvalor(ORDER_TYPE_SELL_LIMIT,valOrdem);
|
|
}
|
|
}
|
|
valOrdem = m_symb.NormalizePrice( valOrdem + tickSize );
|
|
}
|
|
|
|
int qtd = contarOrdensLimitadasDeVenda(symbol,comment);
|
|
//Print("Cancelando ordens de venda maiores que:",valOrdem);
|
|
// Eliminando ordens acima da faixa ordens permitida...
|
|
if(qtd>qtdOrdens) 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; i++ ){
|
|
|
|
// incluindo as ordens no lag...
|
|
if( !tenhoOrdemLimitadaDeCompra(valOrdem,symbol,comment ) ){
|
|
if( valOrdem <= valIni ) enviarOrdemPendente(ORDER_TYPE_BUY_LIMIT, valOrdem, volume, comment);
|
|
}
|
|
|
|
// eliminando as ordens desalinhadas com o lag...
|
|
for(int j=1;j<lag;j++){
|
|
valOrdem = m_symb.NormalizePrice( valOrdem - tickSize );
|
|
if( tenhoOrdemLimitadaDeCompra(valOrdem,symbol,comment ) ){
|
|
//Print("Cancelando ordem de compra desalinhadas com o lag. Valor:",valOrdem);
|
|
//cancelarOrdensComentadasDeCompra(symbol,comment,valOrdem);
|
|
cancelarOrdensPorTipoEvalor(ORDER_TYPE_BUY_LIMIT,valOrdem);
|
|
}
|
|
}
|
|
valOrdem = m_symb.NormalizePrice( valOrdem - tickSize );
|
|
}
|
|
|
|
int qtd = contarOrdensLimitadasDeCompra(symbol,comment);
|
|
// Eliminando ordens abaixo da faixa ordens permitida...
|
|
if( qtd > 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<qtdOrdensPendentes; i++){
|
|
|
|
if( (order_ticket = OrderGetTicket(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<qtdOrdensPendentes; i++){
|
|
|
|
if( (order_ticket = OrderGetTicket(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<qtdOrdensPendentes; i++){
|
|
|
|
if( (order_ticket = OrderGetTicket(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<qtdOrdensPendentes; i++){
|
|
|
|
if( (order_ticket = OrderGetTicket(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<qtdOrdensPendentes; i++){
|
|
|
|
if( (order_ticket = OrderGetTicket(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<qtdOrdensPendentes; i++){
|
|
|
|
if( (order_ticket = OrderGetTicket(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<qtdOrdensPendentes; i++){
|
|
|
|
if( (order_ticket = OrderGetTicket(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<qtdOrdensPendentes; i++){
|
|
|
|
if( (order_ticket = OrderGetTicket(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; i<totOrdens; i++){ // assim processa primeiro as mais antigas
|
|
|
|
if( (order_ticket = OrderGetTicket(i) )>0 ){
|
|
|
|
//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); //<TODO> 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); //<TODO> 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<totOrdens; i++){ // assim processa primeiro as mais antigas
|
|
|
|
//order_state = (ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE);
|
|
|
|
if( (order_ticket = OrderGetTicket(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<totOrdens; i++){ // assim processa primeiro as mais antigas
|
|
|
|
if( (order_ticket = OrderGetTicket(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; i<totOrdens; i++){ // assim processa primeiro as mais antigas
|
|
|
|
if( (order_ticket = OrderGetTicket(i) )>0 &&
|
|
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); //<TODO> 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); //<TODO> 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<totOrdens; i++){ // assim processa primeiro as mais antigas
|
|
|
|
if( (order_ticket = OrderGetTicket(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); //<TODO> 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<totOrdens; i++){ // assim processa primeiro as mais antigas
|
|
|
|
if( (order_ticket = OrderGetTicket(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<totOrdens; i++){ // assim processa primeiro as mais antigas
|
|
|
|
if( (order_ticket = OrderGetTicket(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<totOrdens; i++){ // assim processa primeiro as mais antigas
|
|
|
|
if( ( order_ticket = OrderGetTicket(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); //<TODO> 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); //<TODO> 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<totOrdens; i++){ // assim processa primeiro as mais antigas
|
|
|
|
if( (order_ticket = OrderGetTicket(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); //<TODO> 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); //<TODO> 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<totOrdens; i++){ // assim processa primeiro as mais antigas
|
|
|
|
if( (order_ticket = OrderGetTicket(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<totOrdens; i++){ // assim processa primeiro as mais antigas
|
|
|
|
if( ( order_ticket = OrderGetTicket(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) {
|
|
|
|
//<TODO> 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) {
|
|
|
|
//<TODO> 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<qtdOrdensPendentes; i++){
|
|
|
|
if( (order_ticket = OrderGetTicket(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<qtdOrdensPendentes; i++){
|
|
|
|
if( (order_ticket = OrderGetTicket(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<qtdOrdensPendentes; i++){
|
|
|
|
if( (order_ticket = OrderGetTicket(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;
|
|
}
|