
MQL5 Trading Toolkit (Parte 3): Desenvolvimento de uma biblioteca EX5 para gerenciamento de ordens pendentes
Introdução
No primeiro e segundo artigos, exploramos o desenvolvimento e a programação de bibliotecas EX5 do zero, bem como a criação de documentação detalhada para auxiliar os usuários finais a integrá-las em seus projetos MQL5. Também vimos, de forma prática e passo a passo, como importar e implementar essas bibliotecas em diferentes aplicações MQL5.
Neste artigo, desenvolveremos uma biblioteca EX5 completa para gerenciamento de ordens pendentes (Pending Orders Management EX5 library) e criaremos um painel de interface gráfica do usuário (GUI) para demonstrar, na prática, como importar e integrar essa biblioteca. A biblioteca utilizará apenas funções padrão do MQL5 para abrir, modificar e excluir diversos tipos de ordens pendentes. Ela será um recurso valioso para iniciantes em programação MQL5 que desejam aprender a criar módulos simples e avançados para gerenciamento de ordens pendentes. Você também verá como classificar ordens pendentes em diferentes categorias.
As funções que criaremos a seguir serão exportadas e compiladas em uma biblioteca EX5, tornando-se um ativo importante que reduzirá significativamente o tempo de desenvolvimento de futuros projetos MQL5. Ao simplesmente importar a biblioteca EX5 de gerenciamento de ordens pendentes, será possível implementar essas funções, reduzindo tanto a base de código quanto o processo geral de desenvolvimento.
Criando o arquivo de código-fonte da biblioteca EX5 (.mq5)
Abra o MetaEditor IDE e execute o Assistente MQL usando o comando de menu "Criar". É necessário criar um arquivo de código-fonte de biblioteca. Vamos nomeá-lo PendingOrdersManager.mq5. Esse arquivo conterá as funções principais para gerenciamento de ordens pendentes. Salve-o na pasta Libraries\Toolkit, criada no primeiro artigo. Este é o mesmo diretório onde, anteriormente, salvamos a biblioteca EX5 de gerenciamento de posições (Positions Manager EX5 library).
Se precisar relembrar como criar uma biblioteca EX5, volte ao primeiro artigo. Lá, analisamos em detalhes o processo passo a passo de configuração da estrutura de pastas e criação de bibliotecas. Essa abordagem não apenas ajuda a otimizar o desenvolvimento, mas também facilita a manutenção e o reaproveitamento das suas bibliotecas em futuros projetos MQL5.
Diretivas de pré-processador, variáveis globais e importação da biblioteca EX5 para gerenciamento de posições
Vamos começar definindo todas as diretivas de pré-processador, variáveis globais, importação da biblioteca e estruturas de negociação em nosso recém-criado arquivo de código-fonte da biblioteca PendingOrdersManager.mq5. Isso garantirá que elas estejam acessíveis em toda a nossa biblioteca de gerenciamento de ordens pendentes e possam ser reutilizadas em diferentes funções sempre que necessário.
Iniciaremos definindo uma macro de pré-processador usando #define para criar uma constante que represente uma string vazia. Essa constante, chamada ALL_SYMBOLS, funcionará como um espaço reservado em funções de gerenciamento de ordens pendentes que exijam uma string de símbolo como parâmetro de entrada. Ao passar essa string vazia, as funções interpretarão como uma instrução para aplicar a ação especificada a todos os símbolos disponíveis, e não apenas a um único.
Essa técnica é simples, mas muito eficiente, especialmente ao lidar com múltiplos instrumentos, pois otimiza o processamento de ordens pendentes em diferentes símbolos. Para implementá-la, definiremos a constante ALL_SYMBOLS e a colocaremos logo abaixo das diretivas #property no seu código.
#define ALL_SYMBOLS "" //-- Used as a function parameter to select all symbols
Também será necessário criar duas constantes adicionais: uma para definir o número máximo de tentativas de reenvio de uma ordem ao servidor de negociação em caso de falha, e outra para definir o tempo de atraso entre cada tentativa. Isso ajuda a evitar a sobrecarga do servidor com solicitações consecutivas em alta velocidade. A primeira constante será MAX_ORDER_RETRIES com valor 600. A segunda será ORDER_RETRY_DELAY, com valor 500 (milissegundos).
Isso significa que, se não ocorrer um erro crítico, poderemos tentar abrir, modificar ou excluir uma ordem até 600 vezes. Após cada tentativa, a função fará uma pausa de meio segundo (500 milissegundos) antes de tentar novamente. Esse atraso garante que o servidor não seja sobrecarregado e que os recursos sejam utilizados de forma eficiente. Também permite que eventuais atrasos — como falta de atividade no mercado ou ausência de dados de ticks — sejam resolvidos antes que todas as tentativas sejam esgotadas, aumentando a probabilidade de execução bem-sucedida da ordem.
#define MAX_ORDER_RETRIES 600 //-- Sets the order sending retry limit #define ORDER_RETRY_DELAYS 500//-- Sets the duration to pause before re-sending a failed order request in milliseconds
Em seguida, adicionaremos as estruturas de dados MqlTradeRequest e MqlTradeResult. Essas estruturas são essenciais, pois serão responsáveis por todo o processo de comunicação com o servidor de negociação ao abrir, modificar e excluir diferentes ordens pendentes. A estrutura tradeRequest ficará encarregada de armazenar as informações sobre a ação de negociação que executaremos, incluindo parâmetros da ordem, como preço, stop loss e take profit. A estrutura tradeResult registrará e armazenará o resultado da operação, fornecendo um retorno do servidor sobre se o nosso pedido foi executado com sucesso ou se ocorreu algum erro.
//-- Trade operations request and result data structures global variables MqlTradeRequest tradeRequest; MqlTradeResult tradeResult;
Para monitorar e armazenar o status das diversas ordens pendentes, será necessário criar alguns tipos de variáveis que contenham essas informações. Essas variáveis de status de ordem serão declaradas como variáveis globais, garantindo que possam ser acessadas a partir de qualquer escopo dentro da nossa biblioteca, permitindo que qualquer função as consulte e atualize sempre que necessário. Elas serão inicializadas com valores padrão no momento da declaração e, posteriormente, receberão dados precisos em tempo real por meio da função GetPendingOrdersData(...), que será desenvolvida mais adiante neste artigo. Isso assegura que o status de todas as ordens pendentes permaneça consistente e atualizado durante toda a execução das funções que as utilizam.
//-- Pending orders status global variables //------------------------------------------------------------------------------------------------------------------- int accountBuyStopOrdersTotal = 0, accountSellStopOrdersTotal = 0, accountBuyLimitOrdersTotal = 0, accountSellLimitOrdersTotal = 0, symbolPendingOrdersTotal = 0, symbolBuyStopOrdersTotal = 0, symbolSellStopOrdersTotal = 0, symbolBuyLimitOrdersTotal = 0, symbolSellLimitOrdersTotal = 0, magicPendingOrdersTotal = 0, magicBuyStopOrdersTotal = 0, magicSellStopOrdersTotal = 0, magicBuyLimitOrdersTotal = 0, magicSellLimitOrdersTotal = 0; double accountPendingOrdersVolumeTotal = 0.0, accountBuyStopOrdersVolumeTotal = 0.0, accountSellStopOrdersVolumeTotal = 0.0, accountBuyLimitOrdersVolumeTotal = 0.0, accountSellLimitOrdersVolumeTotal = 0.0, symbolPendingOrdersVolumeTotal = 0.0, symbolBuyStopOrdersVolumeTotal = 0.0, symbolSellStopOrdersVolumeTotal = 0.0, symbolBuyLimitOrdersVolumeTotal = 0.0, symbolSellLimitOrdersVolumeTotal = 0.0, magicPendingOrdersVolumeTotal = 0.0, magicBuyStopOrdersVolumeTotal = 0.0, magicSellStopOrdersVolumeTotal = 0.0, magicBuyLimitOrdersVolumeTotal = 0.0, magicSellLimitOrdersVolumeTotal = 0.0;
Ao abrir, modificar ou excluir ordens, diferentes tipos de erros podem ocorrer. Para lidar de forma eficiente com esses erros e corrigi-los, precisaremos de uma função específica para esse propósito. Além disso, também é necessário contar com uma função capaz de verificar permissões de negociação essenciais, como confirmar se o nosso EA tem permissão para operar, se a negociação algorítmica está ativada no terminal e se o corretor autorizou a negociação algorítmica para a conta em uso.
Felizmente, já desenvolvemos funções com esse objetivo na biblioteca PositionsManager.ex5 apresentada em artigos anteriores. Em vez de recriar essas funções do zero, simplesmente importaremos essa biblioteca, tornando as funções de tratamento de erros e verificação de permissões facilmente acessíveis na nossa biblioteca de gerenciamento de ordens pendentes. Importaremos, portanto, as funções ErrorAdvisor(...) e TradingIsAllowed().
//+----------------------------------------------------------------------------+ //| PositionsManager.ex5 imports | //+----------------------------------------------------------------------------+ #import "Toolkit/PositionsManager.ex5" //-- Opening import directive //-- Function descriptions for the imported function prototypes //-- Error Handling and Permission Status Functions bool ErrorAdvisor(string callingFunc, string symbol, int tradeServerErrorCode); bool TradingIsAllowed(); #import //--- Closing import directive
Função PrintOrderDetails
A função PrintOrderDetails(...) registra no log do EA no MetaTrader 5 informações detalhadas sobre o pedido de negociação e a resposta recebida do servidor. Ela recebe dois parâmetros do tipo string: header, que contém uma mensagem personalizada, e symbol, que representa o símbolo ou instrumento de negociação sendo processado. A função exibe um relatório detalhado, incluindo dados essenciais da ordem, como símbolo, tipo de ordem, volume, preço, stop loss, take profit, comentário, número mágico e quaisquer desvios. Além disso, registra informações importantes sobre o resultado da operação, incluindo a resposta do servidor e eventuais erros de execução. O objetivo principal da função é auxiliar na depuração e no monitoramento das operações de negociação, fornecendo uma visão clara e formatada dos parâmetros e do status de cada ordem.
void PrintOrderDetails(string header, string symbol) { string orderDescription; int symbolDigits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS); //-- Print the order details orderDescription += "_______________________________________________________________________________________\r\n"; orderDescription += "--> " + tradeRequest.symbol + " " + EnumToString(tradeRequest.type) + " " + header + " <--\r\n"; orderDescription += "Volume: " + StringFormat("%d", tradeRequest.volume) + "\r\n"; orderDescription += "Price: " + DoubleToString(tradeRequest.price, symbolDigits) + "\r\n"; orderDescription += "Stop Loss: " + DoubleToString(tradeRequest.sl, symbolDigits) + "\r\n"; orderDescription += "Take Profit: " + DoubleToString(tradeRequest.tp, symbolDigits) + "\r\n"; orderDescription += "Comment: " + tradeRequest.comment + "\r\n"; orderDescription += "Magic Number: " + StringFormat("%d", tradeRequest.magic) + "\r\n"; orderDescription += "Order filling: " + EnumToString(tradeRequest.type_filling)+ "\r\n"; orderDescription += "Deviation points: " + StringFormat("%G", tradeRequest.deviation) + "\r\n"; orderDescription += "RETCODE: " + (string)(tradeResult.retcode) + "\r\n"; orderDescription += "Runtime Code: " + (string)(GetLastError()) + "\r\n"; orderDescription += "---"; Print(orderDescription); }
Função OpenBuyLimit
A função OpenBuyLimit(...) será responsável por posicionar ordens pendentes do tipo buy limit no terminal MetaTrader 5. Ela garante que todas as condições necessárias sejam atendidas antes de enviar o pedido de ordem, e o tratamento de erros integrado possibilita corrigir problemas potenciais. A função verifica se todos os parâmetros são válidos e estão em conformidade com as exigências do corretor. Além disso, implementa um ciclo de tentativas adicionais, aumentando a probabilidade de sucesso no posicionamento da ordem. Isso torna a função uma ferramenta confiável e eficiente para o gerenciamento de ordens pendentes. O tratamento de erros e os recursos de registro no log ajudam ainda mais na identificação e resolução de problemas que possam ocorrer durante o processo de envio da ordem. A função retorna o valor booleano true quando a ordem buy limit é aberta com sucesso, e false caso o pedido não seja bem-sucedido.
O que é uma ordem Buy Limit?
Uma ordem Buy Limit (ordem limitada de compra) é uma solicitação para comprar a um preço Ask igual ou inferior ao preço de entrada especificado. O preço de entrada de uma ordem limitada de compra é válido apenas quando o preço atual de mercado está acima do preço de entrada. Esse tipo de ordem é útil quando se espera que o preço de um símbolo caia até o nível desejado e, em seguida, suba, permitindo lucrar com o movimento de alta.
Começaremos definindo a função que receberá sete parâmetros, cada um desempenhando um papel específico no processo de posicionamento da ordem limitada de compra. A função será exportada, permitindo seu acesso externo a partir da biblioteca EX5. Os parâmetros:
- magicNumber (unsigned long) – identificador exclusivo da negociação, usado para diferenciar as ordens enviadas pelo nosso EA das demais.
- symbol (string) – instrumento ou símbolo de negociação (por exemplo, EURUSD) no qual a ordem será posicionada.
- entryPrice (double) – nível de disparo da ordem limitada de compra. É o preço-alvo no qual você deseja adquirir o ativo.
- lotSize (double) – volume ou tamanho da ordem a ser posicionada, indicando quantos lotes do ativo serão utilizados na operação.
- sl (int) – stop loss em pips. Determina a perda máxima que a operação poderá sofrer antes de ser encerrada automaticamente.
- tp (int) – take profit em pips. Nível de preço no qual o lucro será automaticamente registrado.
- orderComment (string) – comentário ou observação anexada à ordem para fins de identificação ou acompanhamento.
bool OpenBuyLimit(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment) export {
Após definir a função e seus parâmetros, o primeiro passo é verificar se a negociação algorítmica ou a negociação por EA está ativada no MetaTrader 5. Caso essa funcionalidade esteja desativada, a função será encerrada imediatamente, impedindo o posicionamento da ordem.
if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function }
Em seguida, criaremos as variáveis tpPrice e slPrice para armazenar os valores de take profit e stop loss, e então obteremos informações-chave sobre o símbolo de negociação, como o número de casas decimais (digits), o nível mínimo de stop e o spread. Esses dados nos ajudarão a garantir que o preço de entrada e os parâmetros da ordem estejam configurados corretamente para o símbolo escolhido.
double tpPrice = 0.0, slPrice = 0.0; //-- Get some information about the orders symbol int symbolDigits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS); int symbolStopLevel = (int)SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL); double symbolPoint = SymbolInfoDouble(symbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(symbol, SYMBOL_SPREAD); //-- Save the order type enumeration ENUM_ORDER_TYPE orderType = ORDER_TYPE_BUY_LIMIT;
Antes de enviar a ordem, será necessário verificar se o preço de entrada é válido, assegurando que ele não esteja excessivamente próximo do preço de mercado e que não fique abaixo do nível mínimo de stop permitido pelo corretor. Se o preço for inválido, registraremos o erro e encerraremos a função.
//-- check if the entry price is valid if( SymbolInfoDouble(symbol, SYMBOL_ASK) - (symbolStopLevel * symbolPoint) < entryPrice + (spread * symbolPoint) ) { Print( "\r\n", __FUNCTION__, ": Can't open a new ", EnumToString(orderType), ". (Reason --> INVALID ENTRY PRICE: ", DoubleToString(entryPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid entry price, log the error, exit the function and return false }
Também confirmaremos se os valores de stop loss (SL) e take profit (TP) atendem aos requisitos mínimos do corretor. Caso necessário, ajustaremos SL e TP para que estejam em conformidade com as regras antes de prosseguir.
//-- Check the validity of the sl and tp if(sl > 0 && sl < symbolStopLevel) { sl = symbolStopLevel; } if(tp > 0 && tp < symbolStopLevel) { tp = symbolStopLevel; } slPrice = (sl > 0) ? NormalizeDouble(entryPrice - sl * symbolPoint, symbolDigits) : 0; tpPrice = (tp > 0) ? NormalizeDouble(entryPrice + tp * symbolPoint, symbolDigits) : 0;
Depois de validar o preço e os demais parâmetros, prepararemos a estrutura tradeRequest com todos os detalhes, como tipo de ordem, símbolo, preço, volume, stop loss, take profit e comentário. Garantiremos ainda que o tamanho do lote esteja dentro dos limites permitidos pelo corretor e que todos os resultados ou erros anteriores sejam limpos.
//-- reset the the tradeRequest and tradeResult values by zeroing them ZeroMemory(tradeRequest); ZeroMemory(tradeResult); //-- initialize the parameters to open a buy limit order tradeRequest.type = orderType; tradeRequest.action = TRADE_ACTION_PENDING; tradeRequest.magic = magicNumber; tradeRequest.symbol = symbol; tradeRequest.price = NormalizeDouble(entryPrice, symbolDigits); tradeRequest.tp = tpPrice; tradeRequest.sl = slPrice; tradeRequest.comment = orderComment; tradeRequest.deviation = SymbolInfoInteger(symbol, SYMBOL_SPREAD) * 2; //-- Set and moderate the lot size or volume //-- Verify that volume is not less than allowed minimum lotSize = MathMax(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN)); //-- Verify that volume is not more than allowed maximum lotSize = MathMin(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX)); //-- Round down to nearest volume step lotSize = MathFloor(lotSize / SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP)) * SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP); tradeRequest.volume = lotSize; //--- Reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function ResetLastError();
Se o pedido de ordem for válido, tentaremos enviá-lo ao servidor de negociação do corretor. Caso a colocação da ordem falhe, repetiremos a tentativa de envio até 600 vezes, com um intervalo de meio segundo (500 milissegundos) entre cada tentativa, buscando várias oportunidades para garantir a execução bem-sucedida. Esse mecanismo de repetição aumenta significativamente as chances de abertura da ordem, especialmente em casos de problemas temporários de rede ou de instabilidade no servidor.
Se a ordem for posicionada com sucesso, registraremos seus dados e confirmaremos que o servidor de negociação a processou corretamente. Caso a ordem não seja executada mesmo após várias tentativas, utilizaremos a função ErrorAdvisor(..), importada da biblioteca PositionsManager.ex5 para diagnosticar o problema e retornaremos false, indicando que a ordem não foi posicionada.
for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try opening the order until it is successful { //--- send order to the trade server if(OrderSend(tradeRequest, tradeResult)) { //-- Print the order details PrintOrderDetails("Sent OK", symbol); //-- Confirm order execution if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009) { Print( __FUNCTION__, ": CONFIRMED: Successfully openend a ", symbol, " ", EnumToString(orderType), " #", tradeResult.order, ", Price: ", tradeResult.price ); PrintFormat("retcode=%u deal=%I64u order=%I64u", tradeResult.retcode, tradeResult.deal, tradeResult.order); Print("_______________________________________________________________________________________"); return(true); //-- exit the function //break; //--- success - order placed ok. exit the for loop } } else //-- Order request failed { //-- Print the order details PrintOrderDetails("Sending Failed", symbol); //-- order not sent or critical error found if(!ErrorAdvisor(__FUNCTION__, symbol, tradeResult.retcode) || IsStopped()) { Print( __FUNCTION__, ": ", symbol, " ERROR opening a ", EnumToString(orderType), " at: ", tradeRequest.price, ", Lot\\Vol: ", tradeRequest.volume ); Print("_______________________________________________________________________________________"); return(false); //-- exit the function //break; //-- exit the for loop Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server } } }
A seguir está o código completo da função com todos os segmentos na sequência correta. Certifique-se de que sua função OpenBuyLimit(...) contenha exatamente este código na íntegra.
bool OpenBuyLimit(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } double tpPrice = 0.0, slPrice = 0.0; //-- Get some information about the orders symbol int symbolDigits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS); int symbolStopLevel = (int)SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL); double symbolPoint = SymbolInfoDouble(symbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(symbol, SYMBOL_SPREAD); //-- Save the order type enumeration ENUM_ORDER_TYPE orderType = ORDER_TYPE_BUY_LIMIT; //-- check if the entry price is valid if( SymbolInfoDouble(symbol, SYMBOL_ASK) - (symbolStopLevel * symbolPoint) < entryPrice + (spread * symbolPoint) ) { Print( "\r\n", __FUNCTION__, ": Can't open a new ", EnumToString(orderType), ". (Reason --> INVALID ENTRY PRICE: ", DoubleToString(entryPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid entry price, log the error, exit the function and return false } //-- Check the validity of the sl and tp if(sl > 0 && sl < symbolStopLevel) { sl = symbolStopLevel; } if(tp > 0 && tp < symbolStopLevel) { tp = symbolStopLevel; } slPrice = (sl > 0) ? NormalizeDouble(entryPrice - sl * symbolPoint, symbolDigits) : 0; tpPrice = (tp > 0) ? NormalizeDouble(entryPrice + tp * symbolPoint, symbolDigits) : 0; //-- reset the the tradeRequest and tradeResult values by zeroing them ZeroMemory(tradeRequest); ZeroMemory(tradeResult); //-- initialize the parameters to open a buy limit order tradeRequest.type = orderType; tradeRequest.action = TRADE_ACTION_PENDING; tradeRequest.magic = magicNumber; tradeRequest.symbol = symbol; tradeRequest.price = NormalizeDouble(entryPrice, symbolDigits); tradeRequest.tp = tpPrice; tradeRequest.sl = slPrice; tradeRequest.comment = orderComment; tradeRequest.deviation = SymbolInfoInteger(symbol, SYMBOL_SPREAD) * 2; //-- Set and moderate the lot size or volume //-- Verify that volume is not less than allowed minimum lotSize = MathMax(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN)); //-- Verify that volume is not more than allowed maximum lotSize = MathMin(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX)); //-- Round down to nearest volume step lotSize = MathFloor(lotSize / SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP)) * SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP); tradeRequest.volume = lotSize; //--- Reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function ResetLastError(); for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try opening the order until it is successful { //--- send order to the trade server if(OrderSend(tradeRequest, tradeResult)) { //-- Print the order details PrintOrderDetails("Sent OK", symbol); //-- Confirm order execution if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009) { Print( __FUNCTION__, ": CONFIRMED: Successfully openend a ", symbol, " ", EnumToString(orderType), " #", tradeResult.order, ", Price: ", tradeResult.price ); PrintFormat("retcode=%u deal=%I64u order=%I64u", tradeResult.retcode, tradeResult.deal, tradeResult.order); Print("_______________________________________________________________________________________"); return(true); //-- exit the function //break; //--- success - order placed ok. exit the for loop } } else //-- Order request failed { //-- Print the order details PrintOrderDetails("Sending Failed", symbol); //-- order not sent or critical error found if(!ErrorAdvisor(__FUNCTION__, symbol, tradeResult.retcode) || IsStopped()) { Print( __FUNCTION__, ": ", symbol, " ERROR opening a ", EnumToString(orderType), " at: ", tradeRequest.price, ", Lot\\Vol: ", tradeRequest.volume ); Print("_______________________________________________________________________________________"); return(false); //-- exit the function //break; //-- exit the for loop Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server } } } return(false); }
Função OpenBuyStop
A função OpenBuyStop(...) é responsável por posicionar ordens pendentes do tipo Buy Stop. Ela é semelhante à função OpenBuyLimit(...). Retorna true quando a ordem buy stop é posicionada com sucesso e false caso o pedido de ordem não seja executado.
O que é uma ordem Buy Stop?
Uma ordem Buy Stop (ordem stop de compra) é um pedido para comprar a um preço Ask igual ou superior ao preço de entrada especificado. O preço de entrada de uma ordem stop de compra só é válido se o preço de mercado atual estiver abaixo desse nível. Esse tipo de ordem é útil quando se espera que o preço de um símbolo suba até o nível desejado e continue subindo, permitindo lucrar com a tendência de alta.
Abaixo está apresentada a função OpenBuyStop(...) com comentários explicativos que ajudarão você a entender rapidamente como cada parte do código funciona.
bool OpenBuyStop(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } double tpPrice = 0.0, slPrice = 0.0; //-- Get some information about the orders symbol int symbolDigits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS); int symbolStopLevel = (int)SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL); double symbolPoint = SymbolInfoDouble(symbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(symbol, SYMBOL_SPREAD); //-- Save the order type enumeration ENUM_ORDER_TYPE orderType = ORDER_TYPE_BUY_STOP; //-- check if the entry price is valid if( SymbolInfoDouble(symbol, SYMBOL_ASK) + (symbolStopLevel * symbolPoint) > entryPrice + (spread * symbolPoint) ) { Print( "\r\n", __FUNCTION__, ": Can't open a new ", EnumToString(orderType), ". (Reason --> INVALID ENTRY PRICE: ", DoubleToString(entryPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid entry price, log the error, exit the function and return false } //--- Validate Stop Loss (sl) and Take Profit (tp) if(sl > 0 && sl < symbolStopLevel) { sl = symbolStopLevel; } if(tp > 0 && tp < symbolStopLevel) { tp = symbolStopLevel; } slPrice = (sl > 0) ? NormalizeDouble(entryPrice - sl * symbolPoint, symbolDigits) : 0; tpPrice = (tp > 0) ? NormalizeDouble(entryPrice + tp * symbolPoint, symbolDigits) : 0; //-- reset the the tradeRequest and tradeResult values by zeroing them ZeroMemory(tradeRequest); ZeroMemory(tradeResult); //-- initialize the parameters to open a buy stop order tradeRequest.type = orderType; tradeRequest.action = TRADE_ACTION_PENDING; tradeRequest.magic = magicNumber; tradeRequest.symbol = symbol; tradeRequest.price = NormalizeDouble(entryPrice, symbolDigits); tradeRequest.tp = tpPrice; tradeRequest.sl = slPrice; tradeRequest.comment = orderComment; tradeRequest.deviation = SymbolInfoInteger(symbol, SYMBOL_SPREAD) * 2; //-- Set and moderate the lot size or volume //-- Verify that volume is not less than allowed minimum lotSize = MathMax(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN)); //-- Verify that volume is not more than allowed maximum lotSize = MathMin(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX)); //-- Round down to nearest volume step lotSize = MathFloor(lotSize / SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP)) * SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP); tradeRequest.volume = lotSize; //--- Reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function ResetLastError(); for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try opening the order until it is successful { //--- send order to the trade server if(OrderSend(tradeRequest, tradeResult)) { //-- Print the order details PrintOrderDetails("Sent OK", symbol); //-- Confirm order execution if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009) { Print( __FUNCTION__, ": CONFIRMED: Successfully openend a ", symbol, " ", EnumToString(orderType), " #", tradeResult.order, ", Price: ", tradeResult.price ); PrintFormat("retcode=%u deal=%I64u order=%I64u", tradeResult.retcode, tradeResult.deal, tradeResult.order); Print("_______________________________________________________________________________________"); return(true); //-- exit the function //break; //--- success - order placed ok. exit the for loop } } else //-- Order request failed { //-- Print the order details PrintOrderDetails("Sending Failed", symbol); //-- order not sent or critical error found if(!ErrorAdvisor(__FUNCTION__, symbol, tradeResult.retcode) || IsStopped()) { Print( __FUNCTION__, ": ", symbol, " ERROR opening a ", EnumToString(orderType), " at: ", tradeRequest.price, ", Lot\\Vol: ", tradeRequest.volume ); Print("_______________________________________________________________________________________"); return(false); //-- exit the function //break; //-- exit the for loop Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server } } } return(false); }
Função OpenSellLimit
A função OpenSellLimit(...) é responsável por posicionar ordens pendentes do tipo Sell Limit. Retorna true quando a ordem sell limit é posicionada com sucesso e false caso o pedido de ordem não seja executado.
O que é uma ordem Sell Limit?
Uma ordem Sell Limit (ordem limitada de venda) é um pedido para vender a um preço Bid igual ou superior ao preço de entrada especificado. O preço de entrada de uma ordem desse tipo só é válido se o preço de mercado atual estiver abaixo do nível definido. Esse tipo de ordem é útil quando se espera que o preço de um símbolo suba até determinado nível e, em seguida, mude de direção, permitindo lucrar com uma esperada reversão de baixa.
Abaixo está apresentada a função OpenSellLimit(...) com comentários explicativos que ajudarão você a entender rapidamente como cada parte do código funciona.
bool OpenSellLimit(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } double tpPrice = 0.0, slPrice = 0.0; //-- Get some information about the orders symbol int symbolDigits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS); int symbolStopLevel = (int)SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL); double symbolPoint = SymbolInfoDouble(symbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(symbol, SYMBOL_SPREAD); //-- Save the order type enumeration ENUM_ORDER_TYPE orderType = ORDER_TYPE_SELL_LIMIT; //-- check if the entry price is valid if( SymbolInfoDouble(symbol, SYMBOL_BID) + (symbolStopLevel * symbolPoint) > entryPrice - (spread * symbolPoint) ) { Print( "\r\n", __FUNCTION__, ": Can't open a new ", EnumToString(orderType), ". (Reason --> INVALID ENTRY PRICE: ", DoubleToString(entryPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid entry price, log the error, exit the function and return false } //-- Check the validity of the sl and tp if(sl > 0 && sl < symbolStopLevel) { sl = symbolStopLevel; } if(tp > 0 && tp < symbolStopLevel) { tp = symbolStopLevel; } slPrice = (sl > 0) ? NormalizeDouble(entryPrice + sl * symbolPoint, symbolDigits) : 0; tpPrice = (tp > 0) ? NormalizeDouble(entryPrice - tp * symbolPoint, symbolDigits) : 0; //-- reset the the tradeRequest and tradeResult values by zeroing them ZeroMemory(tradeRequest); ZeroMemory(tradeResult); //-- initialize the parameters to open a sell limit order tradeRequest.type = orderType; tradeRequest.action = TRADE_ACTION_PENDING; tradeRequest.magic = magicNumber; tradeRequest.symbol = symbol; tradeRequest.price = NormalizeDouble(entryPrice, symbolDigits); tradeRequest.tp = tpPrice; tradeRequest.sl = slPrice; tradeRequest.comment = orderComment; tradeRequest.deviation = SymbolInfoInteger(symbol, SYMBOL_SPREAD) * 2; //-- Set and moderate the lot size or volume //-- Verify that volume is not less than allowed minimum lotSize = MathMax(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN)); //-- Verify that volume is not more than allowed maximum lotSize = MathMin(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX)); //-- Round down to nearest volume step lotSize = MathFloor(lotSize / SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP)) * SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP); tradeRequest.volume = lotSize; //--- Reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function ResetLastError(); for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try opening the order until it is successful { //--- send order to the trade server if(OrderSend(tradeRequest, tradeResult)) { //-- Print the order details PrintOrderDetails("Sent OK", symbol); //-- Confirm order execution if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009) { Print( __FUNCTION__, ": CONFIRMED: Successfully openend a ", symbol, " ", EnumToString(orderType), " #", tradeResult.order, ", Price: ", tradeResult.price ); PrintFormat("retcode=%u deal=%I64u order=%I64u", tradeResult.retcode, tradeResult.deal, tradeResult.order); Print("_______________________________________________________________________________________"); return(true); //-- exit the function //break; //--- success - order placed ok. exit the for loop } } else //-- Order request failed { //-- Print the order details PrintOrderDetails("Sending Failed", symbol); //-- order not sent or critical error found if(!ErrorAdvisor(__FUNCTION__, symbol, tradeResult.retcode) || IsStopped()) { Print( __FUNCTION__, ": ", symbol, " ERROR opening a ", EnumToString(orderType), " at: ", tradeRequest.price, ", Lot\\Vol: ", tradeRequest.volume ); Print("_______________________________________________________________________________________"); return(false); //-- exit the function //break; //-- exit the for loop Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server } } } return(false); }
Função OpenSellStop
A função OpenSellStop(...) é responsável por posicionar ordens pendentes do tipo Sell Stop. Ela retorna true quando a ordem sell stop é posicionada com sucesso, indicando que o pedido foi processado sem problemas. Em caso de falha na tentativa, retorna false.
O que é uma ordem Sell Stop?
Uma ordem Sell Stop (ordem stop de venda) é um pedido para vender a um preço Bid igual ou inferior ao preço de entrada especificado. O preço de entrada de uma ordem stop de venda só é válido se o preço de mercado atual estiver acima desse nível. Esse tipo de ordem é útil quando se espera que o preço de um símbolo caia até o nível definido de entrada e continue a cair, permitindo lucrar com uma tendência de baixa esperada.
A seguir está apresentada a função OpenSellStop(...) com comentários explicativos que ajudarão você a compreender rapidamente como cada parte do código funciona.
bool OpenSellStop(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } double slPrice = 0.0, tpPrice = 0.0; //-- Get some information about the orders symbol int symbolDigits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS); int symbolStopLevel = (int)SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL); double symbolPoint = SymbolInfoDouble(symbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(symbol, SYMBOL_SPREAD); //-- Save the order type enumeration ENUM_ORDER_TYPE orderType = ORDER_TYPE_SELL_STOP; //-- check if the entry price is valid if( SymbolInfoDouble(symbol, SYMBOL_BID) - (symbolStopLevel * symbolPoint) < entryPrice - (spread * symbolPoint) ) { Print( "\r\n", __FUNCTION__, ": Can't open a new ", EnumToString(orderType), ". (Reason --> INVALID ENTRY PRICE: ", DoubleToString(entryPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid entry price, log the error, exit the function and return false } //-- Check the validity of the sl and tp if(sl > 0 && sl < symbolStopLevel) { sl = symbolStopLevel; } if(tp > 0 && tp < symbolStopLevel) { tp = symbolStopLevel; } slPrice = (sl > 0) ? NormalizeDouble(entryPrice + sl * symbolPoint, symbolDigits) : 0; tpPrice = (tp > 0) ? NormalizeDouble(entryPrice - tp * symbolPoint, symbolDigits) : 0; //-- reset the the tradeRequest and tradeResult values by zeroing them ZeroMemory(tradeRequest); ZeroMemory(tradeResult); //-- initialize the parameters to open a sell stop order tradeRequest.type = orderType; tradeRequest.action = TRADE_ACTION_PENDING; tradeRequest.magic = magicNumber; tradeRequest.symbol = symbol; tradeRequest.price = NormalizeDouble(entryPrice, symbolDigits); tradeRequest.tp = tpPrice; tradeRequest.sl = slPrice; tradeRequest.comment = orderComment; tradeRequest.deviation = SymbolInfoInteger(symbol, SYMBOL_SPREAD) * 2; //-- Set and moderate the lot size or volume //-- Verify that volume is not less than allowed minimum lotSize = MathMax(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN)); //-- Verify that volume is not more than allowed maximum lotSize = MathMin(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX)); //-- Round down to nearest volume step lotSize = MathFloor(lotSize / SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP)) * SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP); tradeRequest.volume = lotSize; //--- Reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function ResetLastError(); for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try opening the order until it is successful { //--- send order to the trade server if(OrderSend(tradeRequest, tradeResult)) { //-- Print the order details PrintOrderDetails("Sent OK", symbol); //-- Confirm order execution if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009) { Print( __FUNCTION__, ": CONFIRMED: Successfully openend a ", symbol, " ", EnumToString(orderType), " #", tradeResult.order, ", Price: ", tradeResult.price ); PrintFormat("retcode=%u deal=%I64u order=%I64u", tradeResult.retcode, tradeResult.deal, tradeResult.order); Print("_______________________________________________________________________________________"); return(true); //-- exit the function //break; //--- success - order placed ok. exit the for loop } } else //-- Order request failed { //-- Print the order details PrintOrderDetails("Sending Failed", symbol); //-- order not sent or critical error found if(!ErrorAdvisor(__FUNCTION__, symbol, tradeResult.retcode) || IsStopped()) { Print( __FUNCTION__, ": ", symbol, " ERROR opening a ", EnumToString(orderType), " at: ", tradeRequest.price, ", Lot\\Vol: ", tradeRequest.volume ); Print("_______________________________________________________________________________________"); return(false); //-- exit the function //break; //-- exit the for loop Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server } } } return(false); }
Função ModifyPendingOrderByTicket
A função ModifyPendingOrderByTicket(...) é destinada a modificar o stop loss (SL), o take profit (TP) ou o preço de entrada de uma ordem pendente ativa. Ela verifica se as alterações estão de acordo com as regras do corretor, registra o andamento da execução e quaisquer erros que possam ocorrer, além de utilizar um mecanismo de tentativas adicionais para repetir a modificação em caso de falha ou condições desfavoráveis de execução da ordem.
A função recebe quatro parâmetros:
- orderTicket (ulong) – identificador exclusivo da ordem. Utilizado para referenciar a ordem específica que se deseja modificar.
- newEntryPrice (double) – novo preço de entrada para a ordem pendente. Se for 0, mantém o preço atual.
- newSl (int) – novo valor de stop loss (SL) em pontos. Se for 0, o SL será removido ou permanecerá inalterado.
- newTp (int) – novo valor de take profit (TP) em pontos. Se for 0, o TP será removido ou permanecerá inalterado.
Essa é uma função booleana. Ela retorna true quando a ordem é modificada com sucesso e false em caso de falha devido a parâmetros inválidos, seleção incorreta da ordem ou problemas com o servidor. Começaremos implementando a definição da função.
bool ModifyPendingOrderByTicket(ulong orderTicket, double newEntryPrice, int newSl, int newTp) export {
Antes de alterar a ordem, é necessário confirmar se o ambiente de negociação permite operações algorítmicas. Para isso, utilizaremos a função TradingIsAllowed().
if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function }
Para garantir que estamos modificando a ordem correta, devemos selecioná-la usando a função padrão do MQL5 OrderSelect(), passando o parâmetro orderTicket. Se o ticket da ordem for inválido ou não puder ser selecionado com sucesso, registraremos o erro e encerraremos a função retornando false. Caso a seleção do ticket seja bem-sucedida, imprimiremos uma breve mensagem no log e daremos início ao processamento da ordem.
//--- Confirm and select the order using the provided orderTicket ResetLastError(); //--- Reset error cache incase of ticket selection errors if(OrderSelect(orderTicket)) { //---Order selected Print("\r\n_______________________________________________________________________________________"); Print(__FUNCTION__, ": Order with ticket:", orderTicket, " selected and ready to set SLTP."); } else { Print("\r\n_______________________________________________________________________________________"); Print(__FUNCTION__, ": Selecting order with ticket:", orderTicket, " failed. ERROR: ", GetLastError()); return(false); //-- Exit the function }
Após selecionar a ordem, criaremos algumas variáveis do tipo double para armazenar o preço de take profit e o preço de stop loss, inicializando-as com valores padrão iguais a 0.0. Em seguida, obteremos detalhes completos da ordem (como símbolo, volume, SL/TP atuais, entre outros), que serão necessários para as verificações e modificações.
double newTpPrice = 0.0, newSlPrice = 0.0; //--- Order ticket selected, save the order properties string orderSymbol = OrderGetString(ORDER_SYMBOL); double currentEntryPrice = OrderGetDouble(ORDER_PRICE_OPEN); double volume = OrderGetDouble(ORDER_VOLUME_INITIAL); double currentOrderSlPrice = OrderGetDouble(ORDER_SL); double currentOrderTpPrice = OrderGetDouble(ORDER_TP); ENUM_ORDER_TYPE orderType = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE); double orderPriceCurrent = OrderGetDouble(ORDER_PRICE_CURRENT); //-- Get some information about the orders symbol int symbolDigits = (int)SymbolInfoInteger(orderSymbol, SYMBOL_DIGITS); //-- Number of symbol decimal places int symbolStopLevel = (int)SymbolInfoInteger(orderSymbol, SYMBOL_TRADE_STOPS_LEVEL); double symbolPoint = SymbolInfoDouble(orderSymbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(orderSymbol, SYMBOL_SPREAD);
O próximo passo é verificar se o novo preço de entrada está adequado ao tipo de ordem (por exemplo, buy limit, buy stop, sell stop ou sell limit). Isso nos permitirá identificar e rejeitar rapidamente preços inválidos.
if(newEntryPrice > 0.0) { if(orderType == ORDER_TYPE_BUY_STOP || orderType == ORDER_TYPE_SELL_LIMIT) { if( SymbolInfoDouble(orderSymbol, SYMBOL_ASK) + (symbolStopLevel * symbolPoint) > newEntryPrice - (spread * symbolPoint) ) { Print( "\r\n", __FUNCTION__, ": Can't MODIFY ", EnumToString(orderType), ". (Reason --> INVALID NEW ENTRY PRICE: ", DoubleToString(newEntryPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid new entry price, log the error, exit the function and return false } } if(orderType == ORDER_TYPE_BUY_LIMIT || orderType == ORDER_TYPE_SELL_STOP) { if( SymbolInfoDouble(orderSymbol, SYMBOL_BID) - (symbolStopLevel * symbolPoint) < newEntryPrice + (spread * symbolPoint) ) { Print( "\r\n", __FUNCTION__, ": Can't MODIFY ", EnumToString(orderType), ". (Reason --> INVALID NEW ENTRY PRICE: ", DoubleToString(newEntryPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid new entry price, log the error, exit the function and return false } } } else { newEntryPrice = currentEntryPrice; //-- Do not modify the entry price }
Também será necessário calcular o stop loss e o take profit com base nos parâmetros de entrada e verificar esses valores em relação ao nível mínimo de ordens stop permitido pelo corretor.
if(orderType == ORDER_TYPE_BUY_STOP || orderType == ORDER_TYPE_BUY_LIMIT) { if(newSl == 0) { newSlPrice = 0.0; //-- Remove the sl } else { newSlPrice = newEntryPrice - (newSl * symbolPoint); } if(newTp == 0) { newTpPrice = 0.0; //-- Remove the tp } else { newTpPrice = newEntryPrice + (newTp * symbolPoint); } //-- Check the validity of the newSlPrice if(newSlPrice > 0 && newEntryPrice - newSlPrice < symbolStopLevel * symbolPoint) { Print( "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType), ". (Reason --> INVALID NEW SL PRICE: ", DoubleToString(newSlPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid sl price, log the error, exit the function and return false } //-- Check the validity of the newTpPrice if(newTpPrice > 0 && newTpPrice - newEntryPrice < symbolStopLevel * symbolPoint) { Print( "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType), ". (Reason --> INVALID NEW TP PRICE: ", DoubleToString(newTpPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid tp price, log the error, exit the function and return false } } if(orderType == ORDER_TYPE_SELL_STOP || orderType == ORDER_TYPE_SELL_LIMIT) { if(newSl == 0) { newSlPrice = 0.0; //-- Remove the sl } else { newSlPrice = newEntryPrice + (newSl * symbolPoint); } if(newTp == 0) { newTpPrice = 0.0; //-- Remove the tp } else { newTpPrice = newEntryPrice - (newTp * symbolPoint); } //-- Check the validity of the newSlPrice if(newSlPrice > 0 && newSlPrice - newEntryPrice < symbolStopLevel * symbolPoint) { Print( "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType), ". (Reason --> INVALID NEW SL PRICE: ", DoubleToString(newSlPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid sl price, log the error, exit the function and return false } //-- Check the validity of the newTpPrice if(newTpPrice > 0 && newEntryPrice - newTpPrice < symbolStopLevel * symbolPoint) { Print( "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType), ". (Reason --> INVALID NEW TP PRICE: ", DoubleToString(newTpPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid tp price, log the error, exit the function and return false } }
Como todos os valores já foram validados, passaremos à preparação do pedido de negociação para modificar a ordem pendente, definindo os parâmetros adequados. Primeiro, faremos a limpeza da estrutura de dados tradeRequest e, em seguida, inicializaremos essa estrutura com os dados verificados e válidos da ordem.
ZeroMemory(tradeRequest); ZeroMemory(tradeResult); //-- initialize the parameters to set the sltp tradeRequest.action = TRADE_ACTION_MODIFY; //-- Trade operation type for modifying the pending order tradeRequest.order = orderTicket; tradeRequest.symbol = orderSymbol; tradeRequest.price = newEntryPrice; tradeRequest.sl = newSlPrice; tradeRequest.tp = newTpPrice; tradeRequest.deviation = SymbolInfoInteger(orderSymbol, SYMBOL_SPREAD) * 2;
Depois, implementaremos um mecanismo de tentativas adicionais para reenviar o pedido de modificação várias vezes caso a primeira tentativa não seja bem-sucedida, aumentando assim a probabilidade de alterar a ordem com sucesso. Em caso de erro crítico ou quando todas as tentativas forem esgotadas, a função retornará false e será encerrada. Se a modificação da ordem for concluída com êxito, a função retornará true e sairá. Para evitar sobrecarregar o servidor de negociação com uma série rápida de solicitações consecutivas, também será inserido um atraso entre as iterações usando a função Sleep(...).
ResetLastError(); //--- reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try modifying the price open, sl, and tp until the request is successful { //--- send order to the trade server if(OrderSend(tradeRequest, tradeResult)) { //-- Confirm order execution if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009) { PrintFormat("Successfully modified Pending Order: #%I64d %s %s", orderTicket, orderSymbol, EnumToString(orderType)); PrintFormat("retcode=%u runtime_code=%u", tradeResult.retcode, GetLastError()); Print("_______________________________________________________________________________________\r\n\r\n"); return(true); //-- exit function //break; //--- success - order placed ok. exit for loop } } else //-- Order request failed { //-- order not sent or critical error found if(!ErrorAdvisor(__FUNCTION__, orderSymbol, tradeResult.retcode) || IsStopped()) { PrintFormat("ERROR modifying Pending Order: #%I64d %s %s", orderTicket, orderSymbol, EnumToString(orderType)); Print("_______________________________________________________________________________________\r\n\r\n"); return(false); //-- exit function //break; //-- exit for loop Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server } } }
A seguir está o código completo da função, incluindo algumas partes anteriormente ausentes, com todos os segmentos na sequência correta.
bool ModifyPendingOrderByTicket(ulong orderTicket, double newEntryPrice, int newSl, int newTp) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } //--- Confirm and select the order using the provided orderTicket ResetLastError(); //--- Reset error cache incase of ticket selection errors if(OrderSelect(orderTicket)) { //---Order selected Print("\r\n_______________________________________________________________________________________"); Print(__FUNCTION__, ": Order with ticket:", orderTicket, " selected and ready to set SLTP."); } else { Print("\r\n_______________________________________________________________________________________"); Print(__FUNCTION__, ": Selecting order with ticket:", orderTicket, " failed. ERROR: ", GetLastError()); return(false); //-- Exit the function } //-- create variables to store the calculated tp and sl prices to send to the trade server double newTpPrice = 0.0, newSlPrice = 0.0; //--- Order ticket selected, save the order properties string orderSymbol = OrderGetString(ORDER_SYMBOL); double currentEntryPrice = OrderGetDouble(ORDER_PRICE_OPEN); double volume = OrderGetDouble(ORDER_VOLUME_INITIAL); double currentOrderSlPrice = OrderGetDouble(ORDER_SL); double currentOrderTpPrice = OrderGetDouble(ORDER_TP); ENUM_ORDER_TYPE orderType = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE); double orderPriceCurrent = OrderGetDouble(ORDER_PRICE_CURRENT); //-- Get some information about the orders symbol int symbolDigits = (int)SymbolInfoInteger(orderSymbol, SYMBOL_DIGITS); //-- Number of symbol decimal places int symbolStopLevel = (int)SymbolInfoInteger(orderSymbol, SYMBOL_TRADE_STOPS_LEVEL); double symbolPoint = SymbolInfoDouble(orderSymbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(orderSymbol, SYMBOL_SPREAD); //-- Check the validity of the newEntryPrice if(newEntryPrice > 0.0) { if(orderType == ORDER_TYPE_BUY_STOP || orderType == ORDER_TYPE_SELL_LIMIT) { if( SymbolInfoDouble(orderSymbol, SYMBOL_ASK) + (symbolStopLevel * symbolPoint) > newEntryPrice - (spread * symbolPoint) ) { Print( "\r\n", __FUNCTION__, ": Can't MODIFY ", EnumToString(orderType), ". (Reason --> INVALID NEW ENTRY PRICE: ", DoubleToString(newEntryPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid new entry price, log the error, exit the function and return false } } if(orderType == ORDER_TYPE_BUY_LIMIT || orderType == ORDER_TYPE_SELL_STOP) { if( SymbolInfoDouble(orderSymbol, SYMBOL_BID) - (symbolStopLevel * symbolPoint) < newEntryPrice + (spread * symbolPoint) ) { Print( "\r\n", __FUNCTION__, ": Can't MODIFY ", EnumToString(orderType), ". (Reason --> INVALID NEW ENTRY PRICE: ", DoubleToString(newEntryPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid new entry price, log the error, exit the function and return false } } } else { newEntryPrice = currentEntryPrice; //-- Do not modify the entry price } //-- Calculate and store the non-validated sl and tp prices if(orderType == ORDER_TYPE_BUY_STOP || orderType == ORDER_TYPE_BUY_LIMIT) { if(newSl == 0) { newSlPrice = 0.0; //-- Remove the sl } else { newSlPrice = newEntryPrice - (newSl * symbolPoint); } if(newTp == 0) { newTpPrice = 0.0; //-- Remove the tp } else { newTpPrice = newEntryPrice + (newTp * symbolPoint); } //-- Check the validity of the newSlPrice if(newSlPrice > 0 && newEntryPrice - newSlPrice < symbolStopLevel * symbolPoint) { Print( "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType), ". (Reason --> INVALID NEW SL PRICE: ", DoubleToString(newSlPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid sl price, log the error, exit the function and return false } //-- Check the validity of the newTpPrice if(newTpPrice > 0 && newTpPrice - newEntryPrice < symbolStopLevel * symbolPoint) { Print( "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType), ". (Reason --> INVALID NEW TP PRICE: ", DoubleToString(newTpPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid tp price, log the error, exit the function and return false } } if(orderType == ORDER_TYPE_SELL_STOP || orderType == ORDER_TYPE_SELL_LIMIT) { if(newSl == 0) { newSlPrice = 0.0; //-- Remove the sl } else { newSlPrice = newEntryPrice + (newSl * symbolPoint); } if(newTp == 0) { newTpPrice = 0.0; //-- Remove the tp } else { newTpPrice = newEntryPrice - (newTp * symbolPoint); } //-- Check the validity of the newSlPrice if(newSlPrice > 0 && newSlPrice - newEntryPrice < symbolStopLevel * symbolPoint) { Print( "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType), ". (Reason --> INVALID NEW SL PRICE: ", DoubleToString(newSlPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid sl price, log the error, exit the function and return false } //-- Check the validity of the newTpPrice if(newTpPrice > 0 && newEntryPrice - newTpPrice < symbolStopLevel * symbolPoint) { Print( "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType), ". (Reason --> INVALID NEW TP PRICE: ", DoubleToString(newTpPrice, symbolDigits), ")\r\n" ); return(false); //-- Invalid tp price, log the error, exit the function and return false } } //-- Print order properties before modification string orderProperties = "--> " + orderSymbol + " " + EnumToString(orderType) + " SLTP Modification Details" + " <--\r\n"; orderProperties += "------------------------------------------------------------\r\n"; orderProperties += "Ticket: " + (string)orderTicket + "\r\n"; orderProperties += "Volume: " + DoubleToString(volume, symbolDigits) + "\r\n"; orderProperties += "Price Open: " + DoubleToString(currentEntryPrice, symbolDigits) + " -> New Proposed Price Open: " + DoubleToString(newEntryPrice, symbolDigits) + "\r\n"; orderProperties += "Current SL: " + DoubleToString(currentOrderSlPrice, symbolDigits) + " -> New Proposed SL: " + DoubleToString(newSlPrice, symbolDigits) + "\r\n"; orderProperties += "Current TP: " + DoubleToString(currentOrderTpPrice, symbolDigits) + " -> New Proposed TP: " + DoubleToString(newTpPrice, symbolDigits) + "\r\n"; orderProperties += "Comment: " + OrderGetString(ORDER_COMMENT) + "\r\n"; orderProperties += "Magic Number: " + (string)OrderGetInteger(ORDER_MAGIC) + "\r\n"; orderProperties += "---"; //-- Print verified order properties before modification orderProperties += "--> Validated and Confirmed NewEntry, SL, and TP Prices: <--\r\n"; orderProperties += "Order Price Current: " + DoubleToString(orderPriceCurrent, symbolDigits) + "\r\n"; orderProperties += "Current Entry Price: " + DoubleToString(currentEntryPrice, symbolDigits) + ", New Entry Price: " + DoubleToString(newEntryPrice, symbolDigits) + "\r\n"; orderProperties += "Current SL: " + DoubleToString(currentOrderSlPrice, symbolDigits) + " -> New SL: " + DoubleToString(newSlPrice, symbolDigits) + "\r\n"; orderProperties += "Current TP: " + DoubleToString(currentOrderTpPrice, symbolDigits) + " -> New TP: " + DoubleToString(newTpPrice, symbolDigits) + "\r\n"; Print(orderProperties); //-- reset the the tradeRequest and tradeResult values by zeroing them ZeroMemory(tradeRequest); ZeroMemory(tradeResult); //-- initialize the parameters to set the sltp tradeRequest.action = TRADE_ACTION_MODIFY; //-- Trade operation type for modifying the pending order tradeRequest.order = orderTicket; tradeRequest.symbol = orderSymbol; tradeRequest.price = newEntryPrice; tradeRequest.sl = newSlPrice; tradeRequest.tp = newTpPrice; tradeRequest.deviation = SymbolInfoInteger(orderSymbol, SYMBOL_SPREAD) * 2; ResetLastError(); //--- reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try modifying the price open, sl, and tp until the request is successful { //--- send order to the trade server if(OrderSend(tradeRequest, tradeResult)) { //-- Confirm order execution if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009) { PrintFormat("Successfully modified Pending Order: #%I64d %s %s", orderTicket, orderSymbol, EnumToString(orderType)); PrintFormat("retcode=%u runtime_code=%u", tradeResult.retcode, GetLastError()); Print("_______________________________________________________________________________________\r\n\r\n"); return(true); //-- exit function //break; //--- success - order placed ok. exit for loop } } else //-- Order request failed { //-- order not sent or critical error found if(!ErrorAdvisor(__FUNCTION__, orderSymbol, tradeResult.retcode) || IsStopped()) { PrintFormat("ERROR modifying Pending Order: #%I64d %s %s", orderTicket, orderSymbol, EnumToString(orderType)); Print("_______________________________________________________________________________________\r\n\r\n"); return(false); //-- exit function //break; //-- exit for loop Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server } } } return(false); }
Função DeletePendingOrderByTicket
A função DeletePendingOrderByTicket(...) é responsável por excluir uma ordem pendente a partir de seu número único de ticket. Primeiro, ela verifica se a negociação algorítmica está habilitada, seleciona a ordem e, em seguida, tenta removê-la do servidor de negociação. Durante todo o processo, a função registra informações relevantes sobre a ordem em diferentes etapas e utiliza um mecanismo de tentativas adicionais para aumentar ao máximo as chances de exclusão bem-sucedida, repetindo o procedimento quantas vezes for necessário.
A função recebe um parâmetro do tipo ulong – orderTicket, que representa o ticket único da ordem a ser excluída. Ela retorna um valor booleano, em que true indica que a ordem pendente foi removida com sucesso e false indica que a exclusão falhou ou ocorreu um erro crítico.
A seguir está o código completo da função com comentários detalhados para facilitar o entendimento.
bool DeletePendingOrderByTicket(ulong orderTicket) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } //--- Confirm and select the order using the provided orderTicket ResetLastError(); //--- Reset error cache incase of ticket selection errors if(OrderSelect(orderTicket)) { //---Order selected Print("..........................................................................................."); Print(__FUNCTION__, ": Order with ticket:", orderTicket, " selected and ready to be deleted."); } else { Print("..........................................................................................."); Print(__FUNCTION__, ": Selecting order with ticket:", orderTicket, " failed. ERROR: ", GetLastError()); return(false); //-- Exit the function } //--- Order ticket selected, save the order properties string orderSymbol = OrderGetString(ORDER_SYMBOL); double orderVolume = OrderGetDouble(ORDER_VOLUME_CURRENT); int symbolDigits = (int)SymbolInfoInteger(orderSymbol, SYMBOL_DIGITS); ENUM_ORDER_TYPE orderType = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE); //-- Print order properties before deleting it string orderProperties; orderProperties += "-- " + orderSymbol + " " + EnumToString(orderType) + " Details" + " -------------------------------------------------------------\r\n"; orderProperties += "Ticket: " + (string)orderTicket + "\r\n"; orderProperties += "Volume: " + DoubleToString(orderVolume) + "\r\n"; orderProperties += "Price Open: " + DoubleToString(OrderGetDouble(ORDER_PRICE_OPEN), symbolDigits) + "\r\n"; orderProperties += "SL: " + DoubleToString(OrderGetDouble(ORDER_SL), symbolDigits) + "\r\n"; orderProperties += "TP: " + DoubleToString(OrderGetDouble(ORDER_TP), symbolDigits) + "\r\n"; orderProperties += "Comment: " + OrderGetString(ORDER_COMMENT) + "\r\n"; orderProperties += "Magic Number: " + (string)OrderGetInteger(ORDER_MAGIC) + "\r\n"; orderProperties += "_______________________________________________________________________________________"; Print(orderProperties); //-- reset the the tradeRequest and tradeResult values by zeroing them ZeroMemory(tradeRequest); ZeroMemory(tradeResult); //-- initialize the trade reqiest parameters to delete the order tradeRequest.action = TRADE_ACTION_REMOVE; //-- Trade operation type for deleting an order tradeRequest.order = orderTicket; ResetLastError(); //--- reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try deleting the order until the request is successful { //--- send order to the trade server if(OrderSend(tradeRequest, tradeResult)) { //-- Confirm order execution if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009) { Print(__FUNCTION__, "_________________________________________________________________________"); PrintFormat("Successfully deleted order #%I64d %s %s", orderTicket, orderSymbol, EnumToString(orderType)); PrintFormat("retcode=%u runtime_code=%u", tradeResult.retcode, GetLastError()); Print("_______________________________________________________________________________________"); return(true); //-- exit function //break; //--- success - order placed ok. exit for loop } } else //-- order deleting request failed { //-- order not sent or critical error found if(!ErrorAdvisor(__FUNCTION__, orderSymbol, tradeResult.retcode) || IsStopped()) { Print(__FUNCTION__, "_________________________________________________________________________"); PrintFormat("ERROR deleting order #%I64d %s %s", orderTicket, orderSymbol, EnumToString(orderType)); Print("_______________________________________________________________________________________"); return(false); //-- exit function //break; //-- exit for loop Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server } } } return(false); }
Função DeleteAllPendingOrders
A função DeleteAllPendingOrders(...) é projetada para remover todas as ordens pendentes de um determinado símbolo e número mágico. Primeiramente, ela verifica se a negociação algorítmica está habilitada. Em seguida, percorre todas as ordens abertas, verifica se elas correspondem ao símbolo e ao número mágico especificados e tenta removê-las uma a uma. Nos casos em que algumas ordens não possam ser excluídas imediatamente, a função utiliza um mecanismo de callback e tentativas adicionais para continuar tentando até que todas as ordens necessárias sejam removidas. Durante todo o processo, ela registra os erros e verifica a ocorrência de problemas críticos para evitar possíveis loops infinitos.
A função recebe dois parâmetros opcionais:
- symbol (string) – parâmetro do tipo string que representa o símbolo de negociação. Por padrão, é definido como ALL_SYMBOLS, ou seja, será direcionado para ordens de todos os símbolos, caso nenhum símbolo específico seja informado.
- magicNumber (ulong) – número inteiro sem sinal do tipo long, que representa o número mágico exclusivo das ordens. Por padrão, é igual a 0, o que significa que a função atuará sobre todas as ordens, independentemente do número mágico, caso nenhum valor específico seja fornecido.
A função retorna um valor booleano (bool), onde true indica que todas as ordens pendentes alvo foram removidas com sucesso, e false indica falha na exclusão de algumas ou todas as ordens, ou a ocorrência de um erro crítico.
A seguir está o código completo da função com comentários para facilitar a compreensão:
bool DeleteAllPendingOrders(string symbol = ALL_SYMBOLS, ulong magicNumber = 0) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } bool returnThis = false; //-- Scan for symbol and magic number for the specified orders and close them int totalOpenOrders = OrdersTotal(); for(int x = 0; x < totalOpenOrders; x++) { //--- Get order properties ulong orderTicket = OrderGetTicket(x); //-- Get ticket to select the order string selectedSymbol = OrderGetString(ORDER_SYMBOL); ulong orderMagicNo = OrderGetInteger(ORDER_MAGIC); //-- Filter orders by symbol and magic number if( (symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (magicNumber != 0 && orderMagicNo != magicNumber) ) { continue; } //-- Delete the order DeletePendingOrderByTicket(orderTicket); } //-- Confirm that we have closed all the orders being targeted int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop while(SymbolOrdersTotal(symbol, magicNumber) > 0) { breakerBreaker++; DeleteAllPendingOrders(symbol, magicNumber); //-- We still have some open orders, do a function callback Sleep(ORDER_RETRY_DELAYS); //-- Micro sleep to pace the execution and give some time to the trade server //-- Check for critical errors so that we exit the loop if we run into trouble if(!ErrorAdvisor(__FUNCTION__, symbol, GetLastError()) || IsStopped() || breakerBreaker > MAX_ORDER_RETRIES) { break; } } //-- Final confirmations that all targeted orders have been closed if(SymbolOrdersTotal(symbol, magicNumber) == 0) { returnThis = true; //-- Save this status for the function return value } return(returnThis); }
Para agilizar a remoção de todas as ordens pendentes, sobrecarregaremos a função DeleteAllPendingOrders(...) com uma segunda versão que não recebe argumentos. Quando chamada, essa versão removerá todas as ordens pendentes da conta. A seguir está apresentada a função sobrecarregada DeleteAllPendingOrders():
bool DeleteAllPendingOrders() export { return(DeleteAllPendingOrders(ALL_SYMBOLS, 0)); }
Função DeleteAllBuyStops
A função DeleteAllBuyStops(...) é responsável por excluir todas as ordens pendentes do tipo stop de compra para um determinado símbolo e número mágico. Assim como nas demais funções de exclusão, ela começa verificando se a negociação algorítmica está habilitada. Em seguida, percorre todas as ordens abertas, identificando aquelas que possuem o símbolo, o número mágico e o tipo de ordem (buy stop) correspondentes, e tenta excluí-las. Se alguma ordem não for removida na primeira varredura, a função utiliza um mecanismo de callback e tentativas adicionais para continuar tentando a exclusão. Ela garante que não haja loops infinitos, implementando medidas de segurança e verificações de erros. Durante todo o processo, a função registra as informações necessárias e gerencia erros críticos.
A função recebe dois parâmetros opcionais:
- symbol (string) – string que representa o símbolo de negociação. O valor padrão ALL_SYMBOLS significa que a função buscará ordens buy stop em todos os símbolos, caso nenhum símbolo específico seja informado.
- magicNumber (ulong) – número inteiro sem sinal do tipo long, que representa o número mágico exclusivo das ordens. Por padrão, é igual a 0, o que significa que a função atuará sobre todas as ordens buy stop, independentemente do número mágico, caso nenhum valor específico seja fornecido.
A função retorna um valor booleano (bool), onde true indica que todas as ordens buy stop alvo foram removidas com sucesso, e false indica que a função não conseguiu excluir algumas ou todas as ordens ou encontrou um problema crítico.
A seguir está o código completo da função com comentários úteis para facilitar a compreensão:
bool DeleteAllBuyStops(string symbol = ALL_SYMBOLS, ulong magicNumber = 0) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } bool returnThis = false; //-- Scan for symbol and magic number specific buy stop orders and close them int totalOpenOrders = OrdersTotal(); for(int x = 0; x < totalOpenOrders; x++) { //--- Get order properties ulong orderTicket = OrderGetTicket(x); //-- Get ticket to select the order string selectedSymbol = OrderGetString(ORDER_SYMBOL); ulong orderMagicNo = OrderGetInteger(ORDER_MAGIC); ulong orderType = OrderGetInteger(ORDER_TYPE); //-- Filter order by symbol, type and magic number if( (symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (orderType != ORDER_TYPE_BUY_STOP) || (magicNumber != 0 && orderMagicNo != magicNumber) ) { continue; } //-- Close the order DeletePendingOrderByTicket(orderTicket); } //-- Confirm that we have closed all the buy stop orders being targeted int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop while(SymbolBuyStopOrdersTotal(symbol, magicNumber) > 0) { breakerBreaker++; DeleteAllBuyStops(symbol, magicNumber); //-- We still have some open buy stop orders, do a function callback Sleep(ORDER_RETRY_DELAYS); //-- Micro sleep to pace the execution and give some time to the trade server //-- Check for critical errors so that we exit the loop if we run into trouble if(!ErrorAdvisor(__FUNCTION__, symbol, GetLastError()) || IsStopped() || breakerBreaker > MAX_ORDER_RETRIES) { break; } } if(SymbolBuyStopOrdersTotal(symbol, magicNumber) == 0) { returnThis = true; } return(returnThis); }
Função DeleteAllBuyLimits
A função DeleteAllBuyLimits(...) tem como objetivo remover todas as ordens pendentes do tipo buy limit para um determinado símbolo e número mágico. Ela retorna um valor booleano (bool), em que true significa que todas as ordens buy limit alvo foram excluídas com sucesso, e false indica que a função não conseguiu excluir algumas ou todas as ordens ou encontrou um problema crítico.
bool DeleteAllBuyLimits(string symbol = ALL_SYMBOLS, ulong magicNumber = 0) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } bool returnThis = false; //-- Scan for symbol and magic number specific buy limit orders and close them int totalOpenOrders = OrdersTotal(); for(int x = 0; x < totalOpenOrders; x++) { //--- Get order properties ulong orderTicket = OrderGetTicket(x); //-- Get ticket to select the order string selectedSymbol = OrderGetString(ORDER_SYMBOL); ulong orderMagicNo = OrderGetInteger(ORDER_MAGIC); ulong orderType = OrderGetInteger(ORDER_TYPE); //-- Filter order by symbol, type and magic number if( (symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (orderType != ORDER_TYPE_BUY_LIMIT) || (magicNumber != 0 && orderMagicNo != magicNumber) ) { continue; } //-- Close the order DeletePendingOrderByTicket(orderTicket); } //-- Confirm that we have closed all the buy limit orders being targeted int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop while(SymbolBuyLimitOrdersTotal(symbol, magicNumber) > 0) { breakerBreaker++; DeleteAllBuyLimits(symbol, magicNumber); //-- We still have some open buy limit orders, do a function callback Sleep(ORDER_RETRY_DELAYS); //-- Micro sleep to pace the execution and give some time to the trade server //-- Check for critical errors so that we exit the loop if we run into trouble if(!ErrorAdvisor(__FUNCTION__, symbol, GetLastError()) || IsStopped() || breakerBreaker > MAX_ORDER_RETRIES) { break; } } if(SymbolBuyLimitOrdersTotal(symbol, magicNumber) == 0) { returnThis = true; } return(returnThis); }
Função DeleteAllSellStops
A função DeleteAllSellStops(...) é responsável por remover todas as ordens pendentes do tipo sell stop para um determinado símbolo e número mágico. Ela retorna um valor booleano (bool), onde true indica que todas as ordens sell stop alvo foram excluídas com sucesso, e false indica que a função não conseguiu excluir algumas ou todas as ordens ou encontrou um problema crítico.
bool DeleteAllSellStops(string symbol = ALL_SYMBOLS, ulong magicNumber = 0) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } bool returnThis = false; //-- Scan for symbol and magic number specific sell stop orders and close them int totalOpenOrders = OrdersTotal(); for(int x = 0; x < totalOpenOrders; x++) { //--- Get order properties ulong orderTicket = OrderGetTicket(x); //-- Get ticket to select the order string selectedSymbol = OrderGetString(ORDER_SYMBOL); ulong orderMagicNo = OrderGetInteger(ORDER_MAGIC); ulong orderType = OrderGetInteger(ORDER_TYPE); //-- Filter order by symbol, type and magic number if( (symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (orderType != ORDER_TYPE_SELL_STOP) || (magicNumber != 0 && orderMagicNo != magicNumber) ) { continue; } //-- Close the order DeletePendingOrderByTicket(orderTicket); } //-- Confirm that we have closed all the sell stop orders being targeted int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop while(SymbolSellStopOrdersTotal(symbol, magicNumber) > 0) { breakerBreaker++; DeleteAllSellStops(symbol, magicNumber); //-- We still have some open sell stop orders, do a function callback Sleep(ORDER_RETRY_DELAYS); //-- Micro sleep to pace the execution and give some time to the trade server //-- Check for critical errors so that we exit the loop if we run into trouble if(!ErrorAdvisor(__FUNCTION__, symbol, GetLastError()) || IsStopped() || breakerBreaker > MAX_ORDER_RETRIES) { break; } } if(SymbolSellStopOrdersTotal(symbol, magicNumber) == 0) { returnThis = true; } return(returnThis); }
Função DeleteAllSellLimits
A função DeleteAllSellLimits(...) lida com a exclusão de todas as ordens pendentes do tipo sell limit para um símbolo e número mágico específicos. Ela retorna um valor booleano (bool) igual a true quando todas as ordens sell limit são removidas com sucesso, e false quando a função não conseguiu excluir algumas ou todas as ordens ou encontrou um problema crítico.
bool DeleteAllSellLimits(string symbol = ALL_SYMBOLS, ulong magicNumber = 0) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } bool returnThis = false; //-- Scan for symbol and magic number specific sell limit orders and close them int totalOpenOrders = OrdersTotal(); for(int x = 0; x < totalOpenOrders; x++) { //--- Get order properties ulong orderTicket = OrderGetTicket(x); //-- Get ticket to select the order string selectedSymbol = OrderGetString(ORDER_SYMBOL); ulong orderMagicNo = OrderGetInteger(ORDER_MAGIC); ulong orderType = OrderGetInteger(ORDER_TYPE); //-- Filter order by symbol, type and magic number if( (symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (orderType != ORDER_TYPE_SELL_LIMIT) || (magicNumber != 0 && orderMagicNo != magicNumber) ) { continue; } //-- Close the order DeletePendingOrderByTicket(orderTicket); } //-- Confirm that we have closed all the sell limit orders being targeted int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop while(SymbolSellLimitOrdersTotal(symbol, magicNumber) > 0) { breakerBreaker++; DeleteAllSellLimits(symbol, magicNumber); //-- We still have some open sell limit orders, do a function callback Sleep(ORDER_RETRY_DELAYS); //-- Micro sleep to pace the execution and give some time to the trade server //-- Check for critical errors so that we exit the loop if we run into trouble if(!ErrorAdvisor(__FUNCTION__, symbol, GetLastError()) || IsStopped() || breakerBreaker > MAX_ORDER_RETRIES) { break; } } if(SymbolSellLimitOrdersTotal(symbol, magicNumber) == 0) { returnThis = true; } return(returnThis); }
Função DeleteAllMagicOrders
A função DeleteAllMagicOrders(...) é responsável por remover todas as ordens pendentes associadas a um determinado número mágico. Ela retorna um valor booleano (bool), onde true significa que todas as ordens com o número mágico especificado foram excluídas com sucesso, e false indica que a função não conseguiu excluir algumas ou todas as ordens ou encontrou um problema crítico.
bool DeleteAllMagicOrders(ulong magicNumber) export { //-- first check if the EA is allowed to trade if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function } bool returnThis = false; //-- Variables to store the selected orders data ulong orderTicket, orderMagicNo; string orderSymbol; //-- Scan for magic number specific orders and delete them int totalOpenOrders = OrdersTotal(); for(int x = 0; x < totalOpenOrders; x++) { //--- Get order properties orderTicket = OrderGetTicket(x); //-- Get ticket to select the order orderMagicNo = OrderGetInteger(ORDER_MAGIC); orderSymbol = OrderGetString(ORDER_SYMBOL); //-- Filter orders by magic number if(magicNumber == orderMagicNo) { //-- Delete the order DeletePendingOrderByTicket(orderTicket); } } //-- Confirm that we have deleted all the orders being targeted int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop while(MagicOrdersTotal(magicNumber) > 0) { breakerBreaker++; DeleteAllMagicOrders(magicNumber); //-- We still have some open orders, do a function callback Sleep(ORDER_RETRY_DELAYS); //-- Micro sleep to pace the execution and give some time to the trade server //-- Check for critical errors so that we exit the loop if we run into trouble if(!ErrorAdvisor(__FUNCTION__, orderSymbol, GetLastError()) || IsStopped() || breakerBreaker > MAX_ORDER_RETRIES) { break; } } if(MagicOrdersTotal(magicNumber) == 0) { returnThis = true; } return(returnThis); }
Função GetPendingOrdersData
Para que qualquer sistema de negociação algorítmica autônomo ou EA seja confiável e, no fim das contas, gere lucros consistentes, ele precisa conhecer o estado de todas as posições e ordens na conta. Na segunda parte desta série, desenvolvemos uma função de monitoramento de posições que coleta dados sobre todas as posições abertas. Como o foco desta parte é voltado para ordens pendentes, criaremos uma função para varrer e armazenar os dados de todas as ordens pendentes, disponibilizando essas informações em toda a biblioteca para serem utilizadas por outras funções. Isso será alcançado utilizando as variáveis globais definidas no início deste artigo.
Como essas variáveis globais não podem ser exportadas nem acessadas fora do arquivo de código-fonte da biblioteca ou do arquivo binário .EX5, nós as passaremos para diferentes funções exportáveis de status de ordens pendentes, permitindo que fiquem disponíveis na biblioteca .EX5 final. Começaremos criando a função GetPendingOrdersData(...) para a extração dos dados de todas as ordens pendentes.
A função GetPendingOrdersData(...) obtém e armazena os estados das ordens pendentes abertas, incluindo a conta, os símbolos de negociação e número mágico do EA. Ela inicia limpando as diversas variáveis globais que armazenam os valores e volumes totais para os diferentes tipos de ordens pendentes, como buy stop, buy limit, sell stop e sell limit. Em seguida, a função verifica se existem ordens pendentes abertas e itera sobre elas para coletar os dados relevantes. Depois, classifica as ordens com base no símbolo e no número mágico, acumulando os valores e volumes totais para as ordens pendentes correspondentes. Esse método abrangente garante que a função colete dados em tempo real sobre o estado das ordens pendentes, que poderão ser utilizados por outras funções do EA.
A função receberá dois parâmetros:
- symbol (string): string que representa o símbolo de negociação para o qual serão obtidos os dados das ordens pendentes. O valor padrão é ALL_SYMBOLS, o que significa que serão coletados dados de todos os símbolos.
- magicNumber (ulong) – número inteiro sem sinal do tipo long que representa o número mágico exclusivo das ordens pendentes do EA. Por padrão, esse parâmetro é definido como 0, permitindo que a função colete dados de todas as ordens pendentes, independentemente do número mágico, caso nenhum valor específico seja informado.
A função não retornará nenhum valor (void), pois seu objetivo principal é preencher e atualizar as variáveis globais de status com os dados das ordens pendentes. Essas variáveis, por sua vez, serão acessadas por outras partes da biblioteca para auxiliar nas estratégias de tomada de decisão e execução de negociações.
A seguir está o código completo da função com comentários detalhados para melhor compreensão:
void GetPendingOrdersData(string symbol, ulong magicNumber) { //-- Reset the account open pending orders status accountBuyStopOrdersTotal = 0; accountBuyLimitOrdersTotal = 0; accountSellStopOrdersTotal = 0; accountSellLimitOrdersTotal = 0; accountPendingOrdersVolumeTotal = 0.0; accountBuyStopOrdersVolumeTotal = 0.0; accountBuyLimitOrdersVolumeTotal = 0.0; accountSellStopOrdersVolumeTotal = 0.0; accountSellLimitOrdersVolumeTotal = 0.0; //-- Reset the EA's magic open pending orders status magicPendingOrdersTotal = 0; magicBuyStopOrdersTotal = 0; magicBuyLimitOrdersTotal = 0; magicSellStopOrdersTotal = 0; magicSellLimitOrdersTotal = 0; magicPendingOrdersVolumeTotal = 0.0; magicBuyStopOrdersVolumeTotal = 0.0; magicBuyLimitOrdersVolumeTotal = 0.0; magicSellStopOrdersVolumeTotal = 0.0; magicSellLimitOrdersVolumeTotal = 0.0; //-- Reset the symbol open pending orders status symbolPendingOrdersTotal = 0; symbolBuyStopOrdersTotal = 0; symbolBuyLimitOrdersTotal = 0; symbolSellStopOrdersTotal = 0; symbolSellLimitOrdersTotal = 0; symbolPendingOrdersVolumeTotal = 0.0; symbolBuyStopOrdersVolumeTotal = 0.0; symbolBuyLimitOrdersVolumeTotal = 0.0; symbolSellStopOrdersVolumeTotal = 0.0; symbolSellLimitOrdersVolumeTotal = 0.0; //-- Update and save the open pending orders status with realtime data int totalOpenPendingOrders = OrdersTotal(); if(totalOpenPendingOrders > 0) { //-- Scan for symbol and magic number specific pending orders and save their status for(int x = 0; x < totalOpenPendingOrders; x++) { //--- Get the pending orders properties ulong orderTicket = OrderGetTicket(x); //-- Get ticket to select the pending order string selectedSymbol = OrderGetString(ORDER_SYMBOL); ulong orderMagicNo = OrderGetInteger(ORDER_MAGIC); //-- Filter pending orders by magic number if(magicNumber != 0 && orderMagicNo != magicNumber) { continue; } //-- Save the account pending orders status first accountPendingOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP) { //-- Account properties ++accountBuyStopOrdersTotal; accountBuyStopOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT) { //-- Account properties ++accountBuyLimitOrdersTotal; accountBuyLimitOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP) { //-- Account properties ++accountSellStopOrdersTotal; accountSellStopOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_LIMIT) { //-- Account properties ++accountSellLimitOrdersTotal; accountSellLimitOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } //-- Filter pending orders openend by EA and save their status if( OrderGetInteger(ORDER_REASON) == ORDER_REASON_EXPERT && orderMagicNo == magicNumber ) { ++magicPendingOrdersTotal; magicPendingOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP) { //-- Magic properties ++magicBuyStopOrdersTotal; magicBuyStopOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT) { //-- Magic properties ++magicBuyLimitOrdersTotal; magicBuyLimitOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP) { //-- Magic properties ++magicSellStopOrdersTotal; magicSellStopOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_LIMIT) { //-- Magic properties ++magicSellLimitOrdersTotal; magicSellLimitOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } } //-- Filter positions by symbol if(symbol == ALL_SYMBOLS || selectedSymbol == symbol) { ++symbolPendingOrdersTotal; symbolPendingOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP) { ++symbolBuyStopOrdersTotal; symbolBuyStopOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT) { ++symbolBuyLimitOrdersTotal; symbolBuyLimitOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP) { ++symbolSellStopOrdersTotal; symbolSellStopOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_LIMIT) { ++symbolSellLimitOrdersTotal; symbolSellLimitOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT); } } } } }
Função BuyStopOrdersTotal
Retorna um valor inteiro que representa o número total de ordens stop de compra abertas na conta.
int BuyStopOrdersTotal() export { GetPendingOrdersData(ALL_SYMBOLS, 0); return(accountBuyStopOrdersTotal); }
Função BuyLimitOrdersTotal
Retorna um valor inteiro que representa o número total de ordens stop de compra abertas na conta.
int BuyLimitOrdersTotal() export { GetPendingOrdersData(ALL_SYMBOLS, 0); return(accountBuyLimitOrdersTotal); }
Função SellStopOrdersTotal
Retorna um valor inteiro que representa o número total de ordens stop de venda abertas na conta.
int SellStopOrdersTotal() export { GetPendingOrdersData(ALL_SYMBOLS, 0); return(accountSellStopOrdersTotal); }
Função SellLimitOrdersTotal
Retorna um valor inteiro que representa o número total de ordens limitadas de venda abertas na conta.
int SellLimitOrdersTotal() export { GetPendingOrdersData(ALL_SYMBOLS, 0); return(accountSellLimitOrdersTotal); }
Função OrdersTotalVolume
Retorna um valor do tipo double que representa o volume/lote/quantidade total de todas as ordens abertas na conta.
double OrdersTotalVolume() export { GetPendingOrdersData(ALL_SYMBOLS, 0); return(accountPendingOrdersVolumeTotal); }
Função BuyStopOrdersTotalVolume
Retorna um valor do tipo double que representa o volume/lote/quantidade total de todas as ordens stop de compra abertas na conta.
double BuyStopOrdersTotalVolume() export { GetPendingOrdersData(ALL_SYMBOLS, 0); return(accountBuyStopOrdersVolumeTotal); }
Função BuyLimitOrdersTotalVolume
Retorna um valor do tipo double que representa o volume/lote/quantidade total de todas as ordens limitadas de compra abertas na conta.
double BuyLimitOrdersTotalVolume() export { GetPendingOrdersData(ALL_SYMBOLS, 0); return(accountBuyLimitOrdersVolumeTotal); }
Função SellStopOrdersTotalVolume
Retorna um valor do tipo double que representa o volume/lote/quantidade total de todas as ordens stop de venda abertas na conta.
double SellStopOrdersTotalVolume() export { GetPendingOrdersData(ALL_SYMBOLS, 0); return(accountSellStopOrdersVolumeTotal); }
Função SellLimitOrdersTotalVolume
Retorna um valor do tipo double que representa o volume/lote/quantidade total de todas as ordens limitadas de venda abertas na conta.
double SellLimitOrdersTotalVolume() export { GetPendingOrdersData(ALL_SYMBOLS, 0); return(accountSellLimitOrdersVolumeTotal); }
Função MagicOrdersTotal
Retorna um valor inteiro que representa o número total de todas as ordens pendentes abertas para o número mágico especificado na conta.
int MagicOrdersTotal(ulong magicNumber) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); return(magicPendingOrdersTotal); }
Função MagicBuyStopOrdersTotal
Retorna um valor inteiro que representa o número total de todas as ordens stop de compra abertas para o número mágico especificado na conta.
int MagicBuyStopOrdersTotal(ulong magicNumber) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); return(magicBuyStopOrdersTotal); }
Função MagicBuyLimitOrdersTotal
Retorna um valor inteiro que representa o número total de todas as ordens limitadas de compra abertas para o número mágico especificado na conta.
int MagicBuyLimitOrdersTotal(ulong magicNumber) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); return(magicBuyLimitOrdersTotal); }
Função MagicSellStopOrdersTotal
Retorna um valor inteiro que representa o número total de todas as ordens stop de venda abertas para o número mágico especificado na conta.
int MagicSellStopOrdersTotal(ulong magicNumber) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); return(magicSellStopOrdersTotal); }
Função MagicSellLimitOrdersTotal
Retorna um valor inteiro que representa o número total de todas as ordens limitadas de venda abertas para o número mágico especificado na conta.
int MagicSellLimitOrdersTotal(ulong magicNumber) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); return(magicSellLimitOrdersTotal); }
Função MagicOrdersTotalVolume
Retorna um valor do tipo double que representa o volume/lote/quantidade total de todas as ordens pendentes abertas para o número mágico especificado na conta.
double MagicOrdersTotalVolume(ulong magicNumber) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); return(magicPendingOrdersVolumeTotal); }
Função MagicBuyStopOrdersTotalVolume
Retorna um valor do tipo double que representa o volume/lote/quantidade total de todas as ordens stop de compra abertas para o número mágico especificado na conta.
double MagicBuyStopOrdersTotalVolume(ulong magicNumber) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); return(magicBuyStopOrdersVolumeTotal); }
Função MagicBuyLimitOrdersTotalVolume
Retorna um valor do tipo double que representa o volume/lote/quantidade total de todas as ordens limitadas de compra abertas para o número mágico especificado na conta.
double MagicBuyLimitOrdersTotalVolume(ulong magicNumber) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); return(magicBuyLimitOrdersVolumeTotal); }
Função MagicSellStopOrdersTotalVolume
Retorna um valor do tipo double que representa o volume/lote/quantidade total de todas as ordens stop de venda abertas para o número mágico especificado na conta.
double MagicSellStopOrdersTotalVolume(ulong magicNumber) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); return(magicSellStopOrdersVolumeTotal); }
Função MagicSellLimitOrdersTotalVolume
Retorna um valor do tipo double que representa o volume/lote/quantidade total de todas as ordens limitadas de venda abertas para o número mágico especificado na conta.
double MagicSellLimitOrdersTotalVolume(ulong magicNumber) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); return(magicSellLimitOrdersVolumeTotal); }
Função SymbolOrdersTotal
Retorna um valor inteiro que representa o número total de todas as ordens pendentes abertas para o símbolo e número mágico especificados na conta.
int SymbolOrdersTotal(string symbol, ulong magicNumber) export { GetPendingOrdersData(symbol, magicNumber); return(symbolPendingOrdersTotal); }
Função SymbolBuyStopOrdersTotal
Retorna um valor inteiro que representa o número total de todas as ordens stop de compra abertas para o símbolo e número mágico especificados na conta.
int SymbolBuyStopOrdersTotal(string symbol, ulong magicNumber) export { GetPendingOrdersData(symbol, magicNumber); return(symbolBuyStopOrdersTotal); }
Função SymbolBuyLimitOrdersTotal
Retorna um valor inteiro que representa o número total de todas as ordens limitadas de compra abertas para o símbolo e número mágico especificados na conta.
int SymbolBuyLimitOrdersTotal(string symbol, ulong magicNumber) export { GetPendingOrdersData(symbol, magicNumber); return(symbolBuyLimitOrdersTotal); }
Função SymbolSellStopOrdersTotal
Retorna um valor inteiro que representa o número total de todas as ordens stop de venda abertas para o símbolo e número mágico especificados na conta.
int SymbolSellStopOrdersTotal(string symbol, ulong magicNumber) export { GetPendingOrdersData(symbol, magicNumber); return(symbolSellStopOrdersTotal); }
Função SymbolSellLimitOrdersTotal
Retorna um valor inteiro que representa o número total de todas as ordens limitadas de venda abertas para o símbolo e número mágico especificados na conta.
int SymbolSellLimitOrdersTotal(string symbol, ulong magicNumber) export { GetPendingOrdersData(symbol, magicNumber); return(symbolSellLimitOrdersTotal); }
Função SymbolOrdersTotalVolume
Retorna um valor do tipo double que representa o volume/lote/quantidade total de todas as ordens pendentes abertas para o símbolo e número mágico especificados na conta.
double SymbolOrdersTotalVolume(string symbol, ulong magicNumber) export { GetPendingOrdersData(symbol, magicNumber); return(symbolPendingOrdersVolumeTotal); }
Função SymbolBuyStopOrdersTotalVolume
Retorna um valor do tipo double que representa o volume/lote/quantidade total de todas as ordens stop de compra abertas para o símbolo e número mágico especificados na conta.
double SymbolBuyStopOrdersTotalVolume(string symbol, ulong magicNumber) export { GetPendingOrdersData(symbol, magicNumber); return(symbolBuyStopOrdersVolumeTotal); }
Função SymbolBuyLimitOrdersTotalVolume
Retorna um valor do tipo double que representa o volume/lote/quantidade total de todas as ordens limitadas de compra abertas para o símbolo e número mágico especificados na conta.
double SymbolBuyLimitOrdersTotalVolume(string symbol, ulong magicNumber) export { GetPendingOrdersData(symbol, magicNumber); return(symbolBuyLimitOrdersVolumeTotal); }
Função SymbolSellStopOrdersTotalVolume
Retorna um valor do tipo double que representa o volume/lote/quantidade total de todas as ordens stop de venda abertas para o símbolo e número mágico especificados na conta.
double SymbolSellStopOrdersTotalVolume(string symbol, ulong magicNumber) export { GetPendingOrdersData(symbol, magicNumber); return(symbolSellStopOrdersVolumeTotal); }
Função SymbolSellLimitOrdersTotalVolume
Retorna um valor do tipo double que representa o volume/lote/quantidade total de todas as ordens limitadas de venda abertas para o símbolo e número mágico especificados na conta.
double SymbolSellLimitOrdersTotalVolume(string symbol, ulong magicNumber) export { GetPendingOrdersData(symbol, magicNumber); return(symbolSellLimitOrdersVolumeTotal); }
Função AccountOrdersStatus
Retorna uma string previamente formatada contendo o status das ordens da conta, que pode ser exibida no log ou apresentada nos comentários do gráfico. A função recebe um parâmetro booleano formatForComment. Quando formatForComment é igual a true, a função formata os dados para exibição na janela do gráfico; quando é igual a false, formata os dados para a aba de log do EA.
string AccountOrdersStatus(bool formatForComment) export { GetPendingOrdersData(ALL_SYMBOLS, 0); //-- Update the orders status variables before we display their data string spacer = ""; if(formatForComment) //-- Add some formating space for the chart comment string { spacer = " "; } string accountOrdersStatus = "\r\n" + spacer + "|---------------------------------------------------------------------------\r\n"; accountOrdersStatus += spacer + "| " + (string)AccountInfoInteger(ACCOUNT_LOGIN) + " - ACCOUNT ORDERS STATUS \r\n"; accountOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n"; accountOrdersStatus += spacer + "| Total Open: " + (string)OrdersTotal() + "\r\n"; accountOrdersStatus += spacer + "| Total Volume: " + (string)accountPendingOrdersVolumeTotal + "\r\n"; accountOrdersStatus += spacer + "|------------------------------------------------------------------\r\n"; accountOrdersStatus += spacer + "| BUY STOP ORDERS: \r\n"; accountOrdersStatus += spacer + "| Total Open: " + (string)accountBuyStopOrdersTotal + "\r\n"; accountOrdersStatus += spacer + "| Total Volume: " + (string)accountBuyStopOrdersVolumeTotal + "\r\n"; accountOrdersStatus += spacer + "|------------------------------------------------------------------\r\n"; accountOrdersStatus += spacer + "| BUY LIMIT ORDERS: \r\n"; accountOrdersStatus += spacer + "| Total Open: " + (string)accountBuyLimitOrdersTotal + "\r\n"; accountOrdersStatus += spacer + "| Total Volume: " + (string)accountBuyLimitOrdersVolumeTotal + "\r\n"; accountOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n"; accountOrdersStatus += spacer + "| SELL STOP ORDERS: \r\n"; accountOrdersStatus += spacer + "| Total Open: " + (string)accountSellStopOrdersTotal + "\r\n"; accountOrdersStatus += spacer + "| Total Volume: " + (string)accountSellStopOrdersVolumeTotal + "\r\n"; accountOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n"; accountOrdersStatus += spacer + "| SELL LIMIT ORDERS: \r\n"; accountOrdersStatus += spacer + "| Total Open: " + (string)accountSellLimitOrdersTotal + "\r\n"; accountOrdersStatus += spacer + "| Total Volume: " + (string)accountSellLimitOrdersVolumeTotal + "\r\n"; accountOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n"; accountOrdersStatus += spacer + "\r\n"; return(accountOrdersStatus); }
Função MagicOrdersStatus
Retorna uma string previamente formatada que indica o status das ordens pelo número mágico, podendo ser exibida no log ou nos comentários do gráfico. A função recebe dois parâmetros: um valor long sem sinal chamado magicNumber, que especifica o número mágico alvo, e um valor booleano chamado formatForComment, que define o tipo de formatação. Se formatForComment for igual a true, a função formatará os dados para exibição na janela do gráfico; se for false, formatará os dados para a aba de log do EA.
string MagicOrdersStatus(ulong magicNumber, bool formatForComment) export { GetPendingOrdersData(ALL_SYMBOLS, magicNumber); //-- Update the order status variables before we display their data string spacer = ""; if(formatForComment) //-- Add some formating space for the chart comment string { spacer = " "; } string magicOrdersStatus = "\r\n" + spacer + "|---------------------------------------------------------------------------\r\n"; magicOrdersStatus += spacer + "| " + (string)magicNumber + " - MAGIC ORDERS STATUS \r\n"; magicOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n"; magicOrdersStatus += spacer + "| Total Open: " + (string)magicPendingOrdersTotal + "\r\n"; magicOrdersStatus += spacer + "| Total Volume: " + (string)magicPendingOrdersVolumeTotal + "\r\n"; magicOrdersStatus += spacer + "|------------------------------------------------------------------\r\n"; magicOrdersStatus += spacer + "| BUY STOP ORDERS: \r\n"; magicOrdersStatus += spacer + "| Total Open: " + (string)magicBuyStopOrdersTotal + "\r\n"; magicOrdersStatus += spacer + "| Total Volume: " + (string)magicBuyStopOrdersVolumeTotal + "\r\n"; magicOrdersStatus += spacer + "|------------------------------------------------------------------\r\n"; magicOrdersStatus += spacer + "| BUY LIMIT ORDERS: \r\n"; magicOrdersStatus += spacer + "| Total Open: " + (string)magicBuyLimitOrdersTotal + "\r\n"; magicOrdersStatus += spacer + "| Total Volume: " + (string)magicBuyLimitOrdersVolumeTotal + "\r\n"; magicOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n"; magicOrdersStatus += spacer + "| SELL STOP ORDERS: \r\n"; magicOrdersStatus += spacer + "| Total Open: " + (string)magicSellStopOrdersTotal + "\r\n"; magicOrdersStatus += spacer + "| Total Volume: " + (string)magicSellStopOrdersVolumeTotal + "\r\n"; magicOrdersStatus += spacer + "|------------------------------------------------------------------\r\n"; magicOrdersStatus += spacer + "| SELL LIMIT ORDERS: \r\n"; magicOrdersStatus += spacer + "| Total Open: " + (string)magicSellLimitOrdersTotal + "\r\n"; magicOrdersStatus += spacer + "| Total Volume: " + (string)magicSellLimitOrdersVolumeTotal + "\r\n"; magicOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n"; magicOrdersStatus += spacer + "\r\n"; return(magicOrdersStatus); }
Função SymbolOrdersStatus
Retorna uma string previamente formatada que indica o status das ordens por símbolo, podendo ser exibida no log ou nos comentários do gráfico. A função recebe três parâmetros: uma string symbol, um valor long sem sinal chamado magicNumber, que especifica o número mágico alvo (valor zero desativa a filtragem por número mágico), e um valor booleano chamado formatForComment, que define o tipo de formatação. Se formatForComment for igual a true, a função formatará os dados para exibição na janela do gráfico; se for false, formatará os dados para a aba de log do EA.
string SymbolOrdersStatus(string symbol, ulong magicNumber, bool formatForComment) export { GetPendingOrdersData(symbol, magicNumber); //-- Update the order status variables before we display their data string spacer = ""; if(formatForComment) //-- Add some formating space for the chart comment string { spacer = " "; } string symbolOrdersStatus = "\r\n" + spacer + "|---------------------------------------------------------------------------\r\n"; symbolOrdersStatus += spacer + "| " + symbol + " - SYMBOL ORDERS STATUS \r\n"; symbolOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n"; symbolOrdersStatus += spacer + "| Total Open: " + (string)symbolPendingOrdersTotal + "\r\n"; symbolOrdersStatus += spacer + "| Total Volume: " + (string)symbolPendingOrdersVolumeTotal + "\r\n"; symbolOrdersStatus += spacer + "|------------------------------------------------------------------\r\n"; symbolOrdersStatus += spacer + "| BUY STOP ORDERS: \r\n"; symbolOrdersStatus += spacer + "| Total Open: " + (string)symbolBuyStopOrdersTotal + "\r\n"; symbolOrdersStatus += spacer + "| Total Volume: " + (string)symbolBuyStopOrdersVolumeTotal + "\r\n"; symbolOrdersStatus += spacer + "|------------------------------------------------------------------\r\n"; symbolOrdersStatus += spacer + "| BUY LIMIT ORDERS: \r\n"; symbolOrdersStatus += spacer + "| Total Open: " + (string)symbolBuyLimitOrdersTotal + "\r\n"; symbolOrdersStatus += spacer + "| Total Volume: " + (string)symbolBuyLimitOrdersVolumeTotal + "\r\n"; symbolOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n"; symbolOrdersStatus += spacer + "| SELL STOP ORDERS: \r\n"; symbolOrdersStatus += spacer + "| Total Open: " + (string)symbolSellStopOrdersTotal + "\r\n"; symbolOrdersStatus += spacer + "| Total Volume: " + (string)symbolSellStopOrdersVolumeTotal + "\r\n"; symbolOrdersStatus += spacer + "|------------------------------------------------------------------\r\n"; symbolOrdersStatus += spacer + "| SELL LIMIT ORDERS: \r\n"; symbolOrdersStatus += spacer + "| Total Open: " + (string)symbolSellLimitOrdersTotal + "\r\n"; symbolOrdersStatus += spacer + "| Total Volume: " + (string)symbolSellLimitOrdersVolumeTotal + "\r\n"; symbolOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n"; symbolOrdersStatus += spacer + "\r\n"; return(symbolOrdersStatus); }
As funções criadas compõem nossa biblioteca EX5 para gerenciamento de ordens pendentes. No final do artigo, está anexado o arquivo com o código-fonte PendingOrdersManager.mq5, bem como o arquivo binário compilado PendingOrdersManager.ex5, que você poderá facilmente importar e utilizar em seus projetos MQL5.
Como importar e implementar a biblioteca EX5 de gerenciamento de ordens pendentes
Desenvolvemos uma biblioteca EX5 robusta para gerenciamento de ordens pendentes, contendo as funções essenciais para manipular essas ordens, obter seu status e exibir informações relevantes. Agora é o momento de documentar e demonstrar como importar e utilizar corretamente essa biblioteca em qualquer projeto MQL5.
Para simplificar o processo de implementação, começaremos descrevendo todas as funções e módulos da biblioteca de gerenciamento de ordens pendentes, além de apresentar exemplos práticos de código na seção de documentação a seguir. Isso fornecerá uma visão clara dos componentes incluídos no arquivo binário PendingOrdersManager.ex5.
Documentação da biblioteca EX5 de gerenciamento de ordens pendentes
Passo 1: Copie os arquivos executáveis da biblioteca (PositionsManager.ex5 e PendingOrdersManager.ex5)Coloque os arquivos PositionsManager.ex5 e PendingOrdersManager.ex5 na pasta MQL5/Libraries/Toolkit ou na mesma pasta do arquivo de código-fonte que importa a biblioteca. Certifique-se de que esses arquivos estejam carregados e copiados para o local indicado, caso ainda não estejam. Para sua conveniência, cópias de ambos os arquivos estão anexadas ao final do artigo.
Passo 2: Importe as definições dos protótipos de funções
Na seção de cabeçalho do código-fonte, adicione as diretivas import para a biblioteca de gerenciamento de ordens pendentes e as definições dos protótipos de suas funções. Utilize o seguinte trecho de código para importar de forma eficiente todas as funções ou módulos da biblioteca PendingOrdersManager.ex5. Também foi criado um modelo vazio de EA (PendingOrdersManager_Imports_Template.mq5) que já inclui esse trecho de código. Você pode comentar ou remover quaisquer definições de funções que não sejam necessárias para o seu projeto. Esse arquivo PendingOrdersManager_Imports_Template.mq5 também está anexado ao final deste artigo.
//+------------------------------------------------------------------------------------------+ //-- Copy and paste the import derictives below to use the Pending Orders Manager EX5 Library //--- //+-------------------------------------------------------------------------------------+ //| PendingOrdersManager.ex5 imports template | //+-------------------------------------------------------------------------------------+ #import "Toolkit/PendingOrdersManager.ex5" //-- Opening import directive //-- Function descriptions for the imported function prototypes //-- Pending Orders Execution and Modification Functions bool OpenBuyLimit(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment); bool OpenBuyStop(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment); bool OpenSellLimit(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment); bool OpenSellStop(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment); bool ModifyPendingOrderByTicket(ulong orderTicket, double newEntryPrice, int newSl, int newTp); bool DeletePendingOrderByTicket(ulong orderTicket); bool DeleteAllPendingOrders(string symbol, ulong magicNumber); bool DeleteAllPendingOrders(); bool DeleteAllBuyStops(string symbol, ulong magicNumber); bool DeleteAllBuyLimits(string symbol, ulong magicNumber); bool DeleteAllSellStops(string symbol, ulong magicNumber); bool DeleteAllSellLimits(string symbol, ulong magicNumber); bool DeleteAllMagicOrders(ulong magicNumber); //-- Pending Orders Status Monitoring Functions int BuyStopOrdersTotal(); int BuyLimitOrdersTotal(); int SellStopOrdersTotal(); int SellLimitOrdersTotal(); double OrdersTotalVolume(); double BuyStopOrdersTotalVolume(); double BuyLimitOrdersTotalVolume(); double SellStopOrdersTotalVolume(); double SellLimitOrdersTotalVolume(); //-- Pending Orders Filtered By Magic Number Status Monitoring Functions int MagicOrdersTotal(ulong magicNumber); int MagicBuyStopOrdersTotal(ulong magicNumber); int MagicBuyLimitOrdersTotal(ulong magicNumber); int MagicSellStopOrdersTotal(ulong magicNumber); int MagicSellLimitOrdersTotal(ulong magicNumber); double MagicOrdersTotalVolume(ulong magicNumber); double MagicBuyStopOrdersTotalVolume(ulong magicNumber); double MagicBuyLimitOrdersTotalVolume(ulong magicNumber); double MagicSellStopOrdersTotalVolume(ulong magicNumber); double MagicSellLimitOrdersTotalVolume(ulong magicNumber); //-- Pending Orders Filtered By Symbol and/or Magic Number Status Monitoring Functions int SymbolOrdersTotal(string symbol, ulong magicNumber); int SymbolBuyStopOrdersTotal(string symbol, ulong magicNumber); int SymbolBuyLimitOrdersTotal(string symbol, ulong magicNumber); int SymbolSellStopOrdersTotal(string symbol, ulong magicNumber); int SymbolSellLimitOrdersTotal(string symbol, ulong magicNumber); double SymbolOrdersTotalVolume(string symbol, ulong magicNumber); double SymbolBuyStopOrdersTotalVolume(string symbol, ulong magicNumber); double SymbolBuyLimitOrdersTotalVolume(string symbol, ulong magicNumber); double SymbolSellStopOrdersTotalVolume(string symbol, ulong magicNumber); double SymbolSellLimitOrdersTotalVolume(string symbol, ulong magicNumber); //-- Log and Data Display Functions string AccountOrdersStatus(bool formatForComment); string MagicOrdersStatus(ulong magicNumber, bool formatForComment); string SymbolOrdersStatus(string symbol, ulong magicNumber, bool formatForComment); #import //--- Closing import directive //+-------------------------------------------------------------------------------------+
Agora que os protótipos das funções da biblioteca .EX5 foram importados para o seu projeto MQL5 ou código-fonte, utilize a tabela abaixo, que apresenta a documentação detalhada e exemplos práticos de como implementar e utilizar essas funções no seu código.
Descrição do protótipo da função | Descrição | Exemplo de uso |
---|---|---|
bool OpenBuyLimit( ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment ); | Abre uma nova ordem limitada de compra com os parâmetros especificados. | double symbolPoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD); //--- ulong magicNo = 123; string symbol = _Symbol; double entryPrice = SymbolInfoDouble( _Symbol, SYMBOL_ASK) - ((spread * 20) * symbolPoint ); double lotSize = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN); int sl = spread * 50; //-- pips int tp = spread * 100; //-- pips string orderComment = "Pending Orders Manager Buy Limit Order"; OpenBuyLimit( magicNumber, symbol, entryPrice, lotSize, sl, tp, orderComment ); |
bool OpenBuyStop( ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment ); | Abre uma nova ordem stop de compra com os parâmetros especificados. | double symbolPoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD); //--- ulong magicNo = 123; string symbol = _Symbol; double entryPrice = SymbolInfoDouble( _Symbol, SYMBOL_ASK) + ((spread * 20) * symbolPoint ); double lotSize = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN); int sl = spread * 50; //-- pips int tp = spread * 100; //-- pips string orderComment = "Pending Orders Manager Buy Stop Order"; OpenBuyStop( magicNumber, symbol, entryPrice, lotSize, sl, tp, orderComment ); |
bool OpenSellLimit( ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment ); | Abre uma nova ordem limitada de venda com os parâmetros especificados. | double symbolPoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD); //--- ulong magicNo = 123; string symbol = _Symbol; double entryPrice = SymbolInfoDouble( _Symbol, SYMBOL_ASK) + ((spread * 20) * symbolPoint ); double lotSize = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN); int sl = spread * 50; //-- pips int tp = spread * 100; //-- pips string orderComment = "Pending Orders Manager Sell Limit Order"; OpenSellLimit( magicNumber, symbol, entryPrice, lotSize, sl, tp, orderComment ); |
bool OpenSellStop( ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment ); | Abre uma nova ordem stop de venda com os parâmetros especificados. | double symbolPoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD); //--- ulong magicNo = 123; string symbol = _Symbol; double entryPrice = SymbolInfoDouble( _Symbol, SYMBOL_ASK) - ((spread * 20) * symbolPoint ); double lotSize = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN); int sl = spread * 50; //-- pips int tp = spread * 100; //-- pips string orderComment = "Pending Orders Manager Sell Stop Order"; OpenSellStop( magicNumber, symbol, entryPrice, lotSize, sl, tp, orderComment ); |
bool ModifyPendingOrderByTicket( ulong orderTicket, double newEntryPrice, int newSl, int newTp ); | Modifica uma ordem pendente usando os parâmetros especificados. | double symbolPoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT); int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD); int totalOpenOders = OrdersTotal(); for(int x = 0; x < totalOpenOders; x++) { ulong orderTicket = OrderGetTicket(x); if(orderTicket > 0) { //-- Modify a buy stop order if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP) { double newEntryPrice = OrderGetDouble( ORDER_PRICE_OPEN) + ((spread * 40) * symbolPoint ); int newSl = 0; //-- Do not modify the stop loss level int newTp = 0; //-- Don not modify the take profit level ModifyPendingOrderByTicket( orderTicket, newEntryPrice, newSl, newTp ); break; } } } |
bool DeletePendingOrderByTicket( ulong orderTicket ); | Exclui uma ordem pendente pelo número do ticket. | for(int x = 0; x < totalOpenOders; x++) { ulong orderTicket = OrderGetTicket(x); if(orderTicket > 0) { DeletePendingOrderByTicket(orderTicket); break; } } |
bool DeleteAllPendingOrders( string symbol = ALL_SYMBOLS, ulong magicNumber = 0 ); | Exclui todas as ordens pendentes pelo nome do símbolo e número mágico. | //Deletes all orders in the account DeleteAllPendingOrders("", 0); //Deletes all orders belonging to the symbol DeleteAllPendingOrders(_Symbol, 0); //Deletes all orders that have a magic number 101 DeleteAllPendingOrders("", 101); //Deletes all EURUSD orders that have a magic number 101 DeleteAllPendingOrders("EURUSD", 101); |
bool DeleteAllPendingOrders() | Exclui todas as ordens pendentes abertas na conta. | //Deletes all orders in the account
DeleteAllPendingOrders(); |
bool DeleteAllBuyStops( string symbol = ALL_SYMBOLS, ulong magicNumber = 0 ); | Exclui todas as ordens stop de compra pelo nome do símbolo e número mágico. | //Deletes all buy stops in the account DeleteAllBuyStops("", 0); //Deletes all buy stops belonging to the symbol DeleteAllBuyStops(_Symbol, 0); //Deletes all buy stops that have a magic number 101 DeleteAllBuyStops("", 101); //Deletes all EURUSD buy stops that have a magic number 101 DeleteAllBuyStops("EURUSD", 101); |
bool DeleteAllBuyLimits( string symbol = ALL_SYMBOLS, ulong magicNumber = 0 ); | Exclui todas as ordens limitadas de compra pelo nome do símbolo e número mágico. | //Deletes all buy limits in the account DeleteAllBuyLimits("", 0); //Deletes all buy limits belonging to the symbol DeleteAllBuyLimits(_Symbol, 0); //Deletes all buy limits that have a magic number 101 DeleteAllBuyLimits("", 101); //Deletes all GBPUSD buy limits that have a magic number 101 DeleteAllBuyLimits("GBPUSD", 101); |
bool DeleteAllSellStops( string symbol = ALL_SYMBOLS, ulong magicNumber = 0 ); | Exclui todas as ordens stop de venda pelo nome do símbolo e número mágico. | //Deletes all sell stops in the account DeleteAllSellStops("", 0); //Deletes all sell stops belonging to the symbol DeleteAllSellStops(_Symbol, 0); //Deletes all sell stops that have a magic number 101 DeleteAllSellStops("", 101); //Deletes all JPYUSD sell stops that have a magic number 101 DeleteAllSellStops("JPYUSD", 101); |
bool DeleteAllSellLimits( string symbol = ALL_SYMBOLS, ulong magicNumber = 0 ); | Exclui todas as ordens limitadas de venda pelo nome do símbolo e número mágico. | //Deletes all sell limits in the account DeleteAllSellLimits("", 0); //Deletes all sell limits belonging to the symbol DeleteAllSellLimits(_Symbol, 0); //Deletes all sell limits that have a magic number 101 DeleteAllSellLimits("", 101); //Deletes all AUDJPY sell limits that have a magic number 101 DeleteAllSellLimits("AUDJPY", 101); |
bool DeleteAllMagicOrders( ulong magicNumber ); | Exclui todas as ordens pendentes pelo número mágico. | //-- Deletes all orders open in the account DeleteAllMagicOrders("", 0); //-- Deletes all orders that have a magic number 101 DeleteAllMagicOrders(101); |
int BuyStopOrdersTotal(); | Retorna a quantidade total de ordens stop de compra abertas. | //Get the total number of open buy stops in the account
BuyStopOrdersTotal(); |
int BuyLimitOrdersTotal(); | Retorna a quantidade total de ordens limitadas de compra abertas. | //Get the total number of open buy limits in the account
BuyLimitOrdersTotal(); |
int SellStopOrdersTotal(); | Retorna a quantidade total de ordens stop de venda abertas. | //Get the total number of open sell stops in the account SellStopOrdersTotal(); |
int SellLimitOrdersTotal(); | Retorna a quantidade total de ordens limitadas de venda abertas. | //Get the total number of open sell limits in the account
SellLimitOrdersTotal(); |
double OrdersTotalVolume(); | Retorna o volume total de todas as ordens abertas. | //Get the total volume/lot of open orders in the account
OrdersTotalVolume(); |
double BuyStopOrdersTotalVolume(); | Retorna o volume total de todas as ordens stop de compra. | //Get the total volume/lot of open buy stops in the account
BuyStopOrdersTotalVolume(); |
double BuyLimitOrdersTotalVolume(); | Retorna o volume total de todas as ordens limitadas de compra. | //Get the total volume/lot of open buy limits in the account
BuyLimitOrdersTotalVolume(); |
double SellStopOrdersTotalVolume(); | Retorna o volume total de todas as ordens stop de venda. | //Get the total volume/lot of open sell stops in the account
SellStopOrdersTotalVolume(); |
double SellLimitOrdersTotalVolume(); | Retorna o volume total de todas as ordens limitadas de venda. | //Get the total volume/lot of open sell limits in the account
SellLimitOrdersTotalVolume(); |
int MagicOrdersTotal( ulong magicNumber ); | Retorna a quantidade de ordens abertas para o número mágico especificado. | //Get the total open pending orders for magic number 101 MagicOrdersTotal(101); |
int MagicBuyStopOrdersTotal( ulong magicNumber ); | Retorna a quantidade de ordens stop de compra abertas para o número mágico especificado. | //Get the total open buy stop orders for magic number 101 MagicBuyStopOrdersTotal(101); |
int MagicBuyLimitOrdersTotal( ulong magicNumber ); | Retorna a quantidade de ordens limitadas de compra abertas para o número mágico especificado. | //Get the total open buy limit orders for magic number 101 MagicBuyLimitOrdersTotal(101); |
int MagicSellStopOrdersTotal( ulong magicNumber ); | Retorna a quantidade de ordens stop de venda abertas para o número mágico especificado. | //Get the total open sell stop orders for magic number 101 MagicSellStopOrdersTotal(101); |
int MagicSellLimitOrdersTotal( ulong magicNumber ); | Retorna a quantidade de ordens limitadas de venda abertas para o número mágico especificado. | //Get the total open sell limit orders for magic number 101 MagicSellLimitOrdersTotal(101); |
double MagicOrdersTotalVolume( ulong magicNumber ); | Retorna o volume total de todas as ordens abertas para o número mágico especificado. | //Get the total volume/lot of all open orders for magic 101 MagicOrdersTotalVolume(101); |
double MagicBuyStopOrdersTotalVolume( ulong magicNumber ); | Retorna o volume total de todas as ordens stop de compra abertas para o número mágico especificado. | //Get the total volume/lot of all buy stop orders for magic 101 MagicBuyStopOrdersTotalVolume(101); |
double MagicBuyLimitOrdersTotalVolume( ulong magicNumber ); | Retorna o volume total de todas as ordens limitadas de compra abertas para o número mágico especificado. | //Get the total volume/lot of all buy limit orders for magic 101 MagicBuyLimitOrdersTotalVolume(101); |
double MagicSellStopOrdersTotalVolume( ulong magicNumber ); | Retorna o volume total de todas as ordens stop de venda abertas para o número mágico especificado. | //Get the total volume/lot of all sell stop orders for magic 101 MagicSellStopOrdersTotalVolume(101); |
double MagicSellLimitOrdersTotalVolume( ulong magicNumber ); | Retorna o volume total de todas as ordens limitadas de venda abertas para o número mágico especificado. | //Get the total volume/lot of all sell limit orders for magic 101 MagicSellLimitOrdersTotalVolume(101); |
int SymbolOrdersTotal( string symbol, ulong magicNumber ); | Retorna a quantidade de ordens abertas para o símbolo e número mágico especificados. | //Get the total open orders for the symbol SymbolOrdersTotal(_Symbol, 0); //Get the total open orders for the symbol and magic 101 SymbolOrdersTotal(_Symbol, 101); |
int SymbolBuyStopOrdersTotal( string symbol, ulong magicNumber ); | Retorna a quantidade de ordens stop de compra abertas para o símbolo e número mágico especificados. | //Get the total buy stop orders for the symbol SymbolBuyStopOrdersTotal(_Symbol, 0); //Get the total buy stop orders for the symbol and magic number 101 SymbolBuyStopOrdersTotal(_Symbol, 101); |
int SymbolBuyLimitOrdersTotal( string symbol, ulong magicNumber ); | Retorna a quantidade de ordens limitadas de compra abertas para o símbolo e número mágico especificados. | //Get the total buy limit orders for the symbol SymbolBuyLimitOrdersTotal(_Symbol, 0); //Get the total buy limit orders for the symbol and magic number 101 SymbolBuyLimitOrdersTotal(_Symbol, 101); |
int SymbolSellStopOrdersTotal( string symbol, ulong magicNumber ); | Retorna a quantidade de ordens stop de venda abertas para o símbolo e número mágico especificados. | //Get the total sell stop orders for the symbol SymbolSellStopOrdersTotal(_Symbol, 0); //Get the total sell stop orders for the symbol and magic 101 SymbolSellStopOrdersTotal(_Symbol, 101); |
int SymbolSellLimitOrdersTotal( string symbol, ulong magicNumber ); | Retorna a quantidade de ordens limitadas de venda abertas para o símbolo e número mágico especificados. | //Get the total sell limit orders for the symbol SymbolSellLimitOrdersTotal(_Symbol, 0); //Get the total sell limit orders for the symbol and magic 101 SymbolSellLimitOrdersTotal(_Symbol, 101); |
double SymbolOrdersTotalVolume( string symbol, ulong magicNumber ); | Retorna o volume total de todas as ordens abertas para o símbolo e número mágico especificados. | //Get the total orders volume/lot for the symbol SymbolOrdersTotalVolume(_Symbol, 0); //Get the total orders volume/lot for the symbol and magic 101 SymbolOrdersTotalVolume(_Symbol, 101); |
double SymbolBuyStopOrdersTotalVolume( string symbol, ulong magicNumber ); | Retorna o volume total de todas as ordens stop de compra abertas para o símbolo e número mágico especificados. | //Get the total buy stops volume/lot for the symbol SymbolBuyStopOrdersTotalVolume(_Symbol, 0); //Get the total buy stops volume/lot for the symbol and magic 101 SymbolBuyStopOrdersTotalVolume(_Symbol, 101); |
double SymbolBuyLimitOrdersTotalVolume( string symbol, ulong magicNumber ); | Retorna o volume total de todas as ordens limitadas de compra abertas para o símbolo e número mágico especificados. | //Get the total buy limits volume/lot for the symbol SymbolBuyLimitOrdersTotalVolume(_Symbol, 0); //Get the total buy limits volume/lot for symbol and magic 101 SymbolBuyLimitOrdersTotalVolume(_Symbol, 101); |
double SymbolSellStopOrdersTotalVolume( string symbol, ulong magicNumber ); | Retorna o volume total de todas as ordens stop de venda abertas para o símbolo e número mágico especificados. | //Get the total sell stops volume/lot for symbol SymbolSellStopOrdersTotalVolume(_Symbol, 0); //Get the total sell stops volume/lot for symbol and magic 101 SymbolSellStopOrdersTotalVolume(_Symbol, 101); |
double SymbolSellLimitOrdersTotalVolume( string symbol, ulong magicNumber ); | Retorna o volume total de todas as ordens limitadas de venda abertas para o símbolo e número mágico especificados. | //Get the total sell limits volume/lot for symbol SymbolSellLimitOrdersTotalVolume(_Symbol, 0); //Get the total sell limits volume/lot for symbol and magic 101 SymbolSellLimitOrdersTotalVolume(_Symbol, 101); |
string AccountOrdersStatus( bool formatForComment ); | Exibe na tela o status em formato de string de todas as ordens abertas no gráfico do símbolo ou na aba “Experts” do MetaTrader 5. | //Print the status of all open orders //formatted for the chart comments Comment(AccountOrdersStatus(true)); //Print the status of all open orders //formatted for the Experts tab Print(AccountOrdersStatus(false)); //Activate an alert with the status of all //open orders formatted for printing Print(AccountOrdersStatus(false)); |
string MagicOrdersStatus( ulong magicNumber, bool formatForComment ); | Exibe na tela o status em formato de string de todas as ordens abertas que correspondam ao número mágico especificado, no gráfico do símbolo ou na aba “Experts” do MetaTrader 5. | //Print the status of all open orders matching //magic number 101 formatted for the chart comments Comment(MagicOrdersStatus(101, true)); //Print the status of all open orders matching //magic number 101 formatted for the Experts tab Print(MagicOrdersStatus(101, false)); //Activate an alert with the status of all open orders //matching magic number 101 formatted for printing Print(MagicOrdersStatus(101, false)); |
string SymbolOrdersStatus( string symbol, ulong magicNumber, bool formatForComment ); | Exibe na tela o status em formato de string de todas as ordens abertas que correspondam ao símbolo e número mágico especificados, no gráfico do símbolo ou na aba “Experts” do MetaTrader 5. | //Print the status of all open orders matching //the symbol and magic number 101 formatted for the chart comments Comment(SymbolOrdersStatus(_Symbol, 101, true)); //Print the status of all open orders matching //the symbol and magic number 101 formatted for the Experts tab Print(SymbolOrdersStatus(_Symbol, 101, false)); //Activate an alert with the status of all open orders //matching the symbol and magic number 101 formatted for printing Print(SymbolOrdersStatus(_Symbol, 101, false)); |
Após importar a biblioteca, você agora pode facilmente abrir, modificar, excluir ou obter dados sobre o status de ordens pendentes por meio de simples chamadas de função. Para demonstrar isso, na próxima seção criaremos um painel de negociação prático com interface gráfica do usuário (GUI) para gerenciamento de ordens pendentes.
Desenvolvimento do painel de ordens pendentes (GUI) com base na biblioteca EX5
Nesta seção, desenvolveremos uma interface gráfica do usuário (GUI) para o painel de ordens pendentes do EA, utilizando a biblioteca EX5 de gerenciamento de ordens pendentes. O painel permitirá abrir, excluir e monitorar todas as ordens associadas ao número mágico especificado e vinculado ao painel. Este exemplo demonstra de forma prática como importar e implementar a biblioteca EX5 que acabamos de criar em uma aplicação real em MQL5.
O painel de ordens pendentes utilizará a biblioteca padrão do MQL5 para painéis e caixas de diálogo, o que nos permitirá manter uma base de código mínima e eficiente. A interface final do painel é apresentada abaixo.
Para criar a interface gráfica, geraremos um EA com o assistente MQL no MetaEditor e o nomearemos PendingOrdersPanel.mq5. Como o EA fará uso da biblioteca PendingOrdersManager.ex5, o primeiro passo será importar e incluir as definições dos protótipos das funções da biblioteca, conforme descrito anteriormente. Insira o código de importação da biblioteca logo abaixo das diretivas #property. Considerando que a biblioteca contém diversas funções, importaremos apenas os protótipos necessários, listados no código a seguir.
#import "Toolkit/PendingOrdersManager.ex5" //-- Opening import directive //-- Function descriptions for the imported function prototypes //-- Pending Orders Execution and Modification Functions bool OpenBuyLimit(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment); bool OpenBuyStop(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment); bool OpenSellLimit(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment); bool OpenSellStop(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment); //-- int MagicOrdersTotal(ulong magicNumber); int MagicBuyStopOrdersTotal(ulong magicNumber); int MagicBuyLimitOrdersTotal(ulong magicNumber); int MagicSellStopOrdersTotal(ulong magicNumber); int MagicSellLimitOrdersTotal(ulong magicNumber); //-- bool DeleteAllBuyStops(string symbol, ulong magicNumber); bool DeleteAllBuyLimits(string symbol, ulong magicNumber); bool DeleteAllSellStops(string symbol, ulong magicNumber); bool DeleteAllSellLimits(string symbol, ulong magicNumber); bool DeleteAllMagicOrders(ulong magicNumber); #import //--- Closing import directive
Criaremos variáveis globais que serão usadas para armazenar as propriedades das ordens.
//-- Global variables //----------------------- ulong magicNo = 10101010; double symbolPoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT); long symbolDigits = SymbolInfoInteger(_Symbol, SYMBOL_DIGITS); int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD); double volumeLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); int sl = (int)spread * 50; int tp = (int)spread * 100;
Em seguida, será necessário definir algumas constantes para armazenar todas as propriedades dos objetos gráficos. Isso facilitará a atualização ou modificação desses valores em um único local, caso seja necessário realizar alterações no layout dos painéis de ordens.
//-- Define some values for the main panel #define MAIN_PANEL_NAME string("Orders Panel - Trading: " + _Symbol + " - Magic No: " + IntegerToString(magicNo)) #define MAIN_PANEL_SUBWINDOW 0 #define MAIN_PANEL_X1 350 #define MAIN_PANEL_Y1 10 #define MAIN_PANEL_WIDTH int(800 + MAIN_PANEL_X1) #define MAIN_PANEL_X2 MAIN_PANEL_WIDTH //-- Define the GUI objects general properties #define GUI_OBJECTS_MARGIN 5 #define GUI_OBJECTS_HEIGHT 40//40 #define GUI_OBJECTS_WIDTH int((MAIN_PANEL_WIDTH) / 7) #define GUI_OBJECTS_FONT_SIZE 9//10 #define GUI_OBJECTS_HEADER_FONT_SIZE GUI_OBJECTS_FONT_SIZE //----- #define MAIN_PANEL_HEIGHT int(((GUI_OBJECTS_HEIGHT + (GUI_OBJECTS_MARGIN * 2)) * 10) + MAIN_PANEL_Y1) #define MAIN_PANEL_Y2 MAIN_PANEL_HEIGHT //-- Define the GUI objects colors #define GUI_OBJECTS_HEADING_COLOR clrNavy #define GUI_OBJECTS_BUY_BTN_COLOR clrWhite #define GUI_OBJECTS_BUY_BTN_BG_COLOR clrBlue #define GUI_OBJECTS_BUY_EDIT_COLOR clrBlue #define GUI_OBJECTS_BUY_EDIT_BG_COLOR clrAliceBlue #define GUI_OBJECTS_SELL_BTN_COLOR clrWhite #define GUI_OBJECTS_SELL_BTN_BG_COLOR clrCrimson #define GUI_OBJECTS_SELL_EDIT_COLOR clrMaroon #define GUI_OBJECTS_SELL_EDIT_BG_COLOR clrMistyRose /*------------------------------------------------------ * Define GUI components for the heading labels **** *-----------------------------------------------------*/ //-- Define values for the lotVolHeaderLabel #define VOLUME_LOT_LABEL_NAME "Volume Lot Header Label" #define VOLUME_LOT_LABEL_SUBWINDOW 0 #define VOLUME_LOT_LABEL_X1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_WIDTH) #define VOLUME_LOT_LABEL_Y1 int(GUI_OBJECTS_MARGIN * 2) #define VOLUME_LOT_LABEL_TEXT "VOLUME/LOT" //-- Define values for the openPriceHeaderLabel #define OPEN_PRICE_LABEL_NAME "Open Price Header Label" #define OPEN_PRICE_LABEL_SUBWINDOW 0 #define OPEN_PRICE_LABEL_X1 (int(GUI_OBJECTS_WIDTH) * 2) #define OPEN_PRICE_LABEL_Y1 int(GUI_OBJECTS_MARGIN * 2) #define OPEN_PRICE_LABEL_TEXT "OPENING PRICE" //-- Define values for the slHeaderLabel #define SL_LABEL_NAME "Sl Header Label" #define SL_LABEL_SUBWINDOW 0 #define SL_LABEL_X1 (int(GUI_OBJECTS_WIDTH) * 3) #define SL_LABEL_Y1 int(GUI_OBJECTS_MARGIN * 2) #define SL_LABEL_TEXT "SL (Pips)" //-- Define values for the tpHeaderLabel #define TP_LABEL_NAME "Tp Header Label" #define TP_LABEL_SUBWINDOW 0 #define TP_LABEL_X1 (int(GUI_OBJECTS_WIDTH) * 3.75) #define TP_LABEL_Y1 int(GUI_OBJECTS_MARGIN * 2) #define TP_LABEL_TEXT "TP (Pips)" /*------------------------------------------------------ * Define Buy Stop Order GUI components **** *-----------------------------------------------------*/ //-- Define values for the buyStopBtn #define BUY_STOP_BTN_NAME "Buy Stop Button" #define BUY_STOP_BTN_SUBWINDOW 0 #define BUY_STOP_BTN_X1 GUI_OBJECTS_MARGIN #define BUY_STOP_BTN_Y1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) #define BUY_STOP_BTN_TEXT "BUY STOP" //-- Define values for the buyStopVolumeLotEdit #define BUY_STOP_VOLUME_LOT_EDIT_NAME "Buy Stop Volume Lot Edit" #define BUY_STOP_VOLUME_LOT_EDIT_SUBWINDOW 0 #define BUY_STOP_VOLUME_LOT_EDIT_X1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_WIDTH) #define BUY_STOP_VOLUME_LOT_EDIT_Y1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) //-- Define values for the buyStopOpenPriceEdit #define BUY_STOP_OPEN_PRICE_EDIT_NAME "Buy Stop Open Price Edit" #define BUY_STOP_OPEN_PRICE_EDIT_SUBWINDOW 0 #define BUY_STOP_OPEN_PRICE_EDIT_X1 int((GUI_OBJECTS_WIDTH) * 2) #define BUY_STOP_OPEN_PRICE_EDIT_Y1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) //-- Define values for the buyStopSlEdit #define BUY_STOP_SL_EDIT_NAME "Buy Stop SL Edit" #define BUY_STOP_SL_EDIT_SUBWINDOW 0 #define BUY_STOP_SL_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3) #define BUY_STOP_SL_EDIT_Y1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) //-- Define values for the buyStopTpEdit #define BUY_STOP_TP_EDIT_NAME "Buy Stop TP Edit" #define BUY_STOP_TP_EDIT_SUBWINDOW 0 #define BUY_STOP_TP_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3.7) #define BUY_STOP_TP_EDIT_Y1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) /*------------------------------------------------------ * Define Sell Stop Order GUI components **** *-----------------------------------------------------*/ //-- Define values for the sellStopBtn #define SELL_STOP_BTN_NAME "Sell Stop Button" #define SELL_STOP_BTN_SUBWINDOW 0 #define SELL_STOP_BTN_X1 GUI_OBJECTS_MARGIN #define SELL_STOP_BTN_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 2) #define SELL_STOP_BTN_TEXT "SELL STOP" //-- Define values for the sellStopVolumeLotEdit #define SELL_STOP_VOLUME_LOT_EDIT_NAME "Sell Stop Volume Lot Edit" #define SELL_STOP_VOLUME_LOT_EDIT_SUBWINDOW 0 #define SELL_STOP_VOLUME_LOT_EDIT_X1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_WIDTH) #define SELL_STOP_VOLUME_LOT_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 2) //-- Define values for the sellStopOpenPriceEdit #define SELL_STOP_OPEN_PRICE_EDIT_NAME "Sell Stop Open Price Edit" #define SELL_STOP_OPEN_PRICE_EDIT_SUBWINDOW 0 #define SELL_STOP_OPEN_PRICE_EDIT_X1 int((GUI_OBJECTS_WIDTH) * 2) #define SELL_STOP_OPEN_PRICE_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 2) //-- Define values for the sellStopSlEdit #define SELL_STOP_SL_EDIT_NAME "Sell Stop SL Edit" #define SELL_STOP_SL_EDIT_SUBWINDOW 0 #define SELL_STOP_SL_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3) #define SELL_STOP_SL_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 2) //-- Define values for the sellStopTpEdit #define SELL_STOP_TP_EDIT_NAME "Sell Stop TP Edit" #define SELL_STOP_TP_EDIT_SUBWINDOW 0 #define SELL_STOP_TP_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3.7) #define SELL_STOP_TP_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 2) /*------------------------------------------------------ * Define Buy Limit Order GUI components **** *-----------------------------------------------------*/ //-- Define values for the buyLimitBtn #define BUY_LIMIT_BTN_NAME "Buy Limit Button" #define BUY_LIMIT_BTN_SUBWINDOW 0 #define BUY_LIMIT_BTN_X1 GUI_OBJECTS_MARGIN #define BUY_LIMIT_BTN_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 3) #define BUY_LIMIT_BTN_TEXT "BUY LIMIT" //-- Define values for the buyLimitVolumeLotEdit #define BUY_LIMIT_VOLUME_LOT_EDIT_NAME "Buy Limit Volume Lot Edit" #define BUY_LIMIT_VOLUME_LOT_EDIT_SUBWINDOW 0 #define BUY_LIMIT_VOLUME_LOT_EDIT_X1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_WIDTH) #define BUY_LIMIT_VOLUME_LOT_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 3) //-- Define values for the buySLimitOpenPriceEdit #define BUY_LIMIT_OPEN_PRICE_EDIT_NAME "Buy Limit Open Price Edit" #define BUY_LIMIT_OPEN_PRICE_EDIT_SUBWINDOW 0 #define BUY_LIMIT_OPEN_PRICE_EDIT_X1 int((GUI_OBJECTS_WIDTH) * 2) #define BUY_LIMIT_OPEN_PRICE_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 3) //-- Define values for the buyLimitSlEdit #define BUY_LIMIT_SL_EDIT_NAME "Buy Limit SL Edit" #define BUY_LIMIT_SL_EDIT_SUBWINDOW 0 #define BUY_LIMIT_SL_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3) #define BUY_LIMIT_SL_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 3) //-- Define values for the buyLimitTpEdit #define BUY_LIMIT_TP_EDIT_NAME "Buy Limit TP Edit" #define BUY_LIMIT_TP_EDIT_SUBWINDOW 0 #define BUY_LIMIT_TP_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3.7) #define BUY_LIMIT_TP_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 3) /*------------------------------------------------------ * Define Sell Limit Order GUI components **** *-----------------------------------------------------*/ //-- Define values for the sellLimitBtn #define SELL_LIMIT_BTN_NAME "Sell Limit Button" #define SELL_LIMIT_BTN_SUBWINDOW 0 #define SELL_LIMIT_BTN_X1 GUI_OBJECTS_MARGIN #define SELL_LIMIT_BTN_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 4) #define SELL_LIMIT_BTN_TEXT "SELL LIMIT" //-- Define values for the sellLimitVolumeLotEdit #define SELL_LIMIT_VOLUME_LOT_EDIT_NAME "Sell Limit Volume Lot Edit" #define SELL_LIMIT_VOLUME_LOT_EDIT_SUBWINDOW 0 #define SELL_LIMIT_VOLUME_LOT_EDIT_X1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_WIDTH) #define SELL_LIMIT_VOLUME_LOT_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 4) //-- Define values for the sellLimitOpenPriceEdit #define SELL_LIMIT_OPEN_PRICE_EDIT_NAME "Sell Limit Open Price Edit" #define SELL_LIMIT_OPEN_PRICE_EDIT_SUBWINDOW 0 #define SELL_LIMIT_OPEN_PRICE_EDIT_X1 int((GUI_OBJECTS_WIDTH) * 2) #define SELL_LIMIT_OPEN_PRICE_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 4) //-- Define values for the sellLimitSlEdit #define SELL_LIMIT_SL_EDIT_NAME "Sell Limit SL Edit" #define SELL_LIMIT_SL_EDIT_SUBWINDOW 0 #define SELL_LIMIT_SL_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3) #define SELL_LIMIT_SL_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 4) //-- Define values for the sellLimitTpEdit #define SELL_LIMIT_TP_EDIT_NAME "Sell Limit TP Edit" #define SELL_LIMIT_TP_EDIT_SUBWINDOW 0 #define SELL_LIMIT_TP_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3.7) #define SELL_LIMIT_TP_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 4) /*------------------------------------------------------ * Define Order Status GUI components **** *-----------------------------------------------------*/ //-- Define values for the orders status #define STATUS_HEADER_FONT_SIZE int(GUI_OBJECTS_FONT_SIZE)// / 1.1) #define STATUS_EDIT_FONT_SIZE int(GUI_OBJECTS_FONT_SIZE)// / 1.1) #define STATUS_EDIT_WIDTH int((MAIN_PANEL_WIDTH / 1.485) - (GUI_OBJECTS_MARGIN * 2)) #define STATUS_EDIT_COLOR clrBlack #define STATUS_EDIT_BG_COLOR clrLemonChiffon #define STATUS_EDIT_BORDER_COLOR clrMidnightBlue #define DELETE_ORDERS_BTN_COLOR clrLightYellow #define DELETE_BUY_ORDERS_BTN_BG_COLOR clrRoyalBlue #define DELETE_SELL_ORDERS_BTN_BG_COLOR clrCrimson #define DELETE_ALL_ORDERS_BTN_BG_COLOR clrMediumVioletRed #define DELETE_ORDERS_BTN_BORDER_COLOR clrBlack #define DELETE_ORDERS_BTN_WIDTH int((STATUS_EDIT_WIDTH / 1.93) - (GUI_OBJECTS_MARGIN * 3)) #define DELETE_ORDERS_BTN_FONT_SIZE int((GUI_OBJECTS_FONT_SIZE))// / 1.05) //-- Define values for the magicOrderStatusLabel #define MAGIC_ORDER_STATUS_LABEL_NAME "Magic Order Status Label" #define MAGIC_ORDER_STATUS_LABEL_SUBWINDOW 0 #define MAGIC_ORDER_STATUS_LABEL_X1 int(GUI_OBJECTS_MARGIN * 3) #define MAGIC_ORDER_STATUS_LABEL_Y1 int((GUI_OBJECTS_HEIGHT * 6) + (GUI_OBJECTS_MARGIN * 2)) #define MAGIC_ORDER_STATUS_LABEL_TEXT string("MAGIC No: " + IntegerToString(magicNo) + " - TOTAL OPEN ORDERS: ") //-- Define values for the magicOrdersStatusEdit #define MAGIC_ORDER_STATUS_EDIT_NAME "Magic Order Status Edit" #define MAGIC_ORDER_STATUS_EDIT_SUBWINDOW 0 #define MAGIC_ORDER_STATUS_EDIT_X1 int(GUI_OBJECTS_MARGIN * 2) #define MAGIC_ORDER_STATUS_EDIT_Y1 int((MAGIC_ORDER_STATUS_LABEL_Y1) + (GUI_OBJECTS_HEIGHT / 1.7)) //-- Define values for the deleteAllMagicBuyStopsBtn #define DELETE_ALL_MAGIC_BUY_STOPS_BTN_NAME "Delete All Magic Buy Stops Btn" #define DELETE_ALL_MAGIC_BUY_STOPS_BTN_SUBWINDOW 0 #define DELETE_ALL_MAGIC_BUY_STOPS_BTN_X1 int(GUI_OBJECTS_MARGIN * 2) #define DELETE_ALL_MAGIC_BUY_STOPS_BTN_Y1 int((MAGIC_ORDER_STATUS_EDIT_Y1) + (GUI_OBJECTS_HEIGHT + GUI_OBJECTS_MARGIN)) #define DELETE_ALL_MAGIC_BUY_STOPS_BTN_TEXT "DELETE ALL MAGIC BUY STOPS" //-- Define values for the deleteAllMagicSellStopsBtn #define DELETE_ALL_MAGIC_SELL_STOPS_BTN_NAME "Delete All Magic Sell Stops Btn" #define DELETE_ALL_MAGIC_SELL_STOPS_BTN_SUBWINDOW 0 #define DELETE_ALL_MAGIC_SELL_STOPS_BTN_X1 int((GUI_OBJECTS_MARGIN * 3) + DELETE_ORDERS_BTN_WIDTH) #define DELETE_ALL_MAGIC_SELL_STOPS_BTN_Y1 int((MAGIC_ORDER_STATUS_EDIT_Y1) + (GUI_OBJECTS_HEIGHT + GUI_OBJECTS_MARGIN)) #define DELETE_ALL_MAGIC_SELL_STOPS_BTN_TEXT "DELETE ALL MAGIC SELL STOPS" //-- Define values for the deleteAllMagicBuyLimitsBtn #define DELETE_ALL_MAGIC_BUY_LIMITS_BTN_NAME "Delete All Magic Buy Limits Btn" #define DELETE_ALL_MAGIC_BUY_LIMITS_BTN_SUBWINDOW 0 #define DELETE_ALL_MAGIC_BUY_LIMITS_BTN_X1 int(GUI_OBJECTS_MARGIN * 2) #define DELETE_ALL_MAGIC_BUY_LIMITS_BTN_Y1 int((DELETE_ALL_MAGIC_BUY_STOPS_BTN_Y1) + (GUI_OBJECTS_HEIGHT + GUI_OBJECTS_MARGIN)) #define DELETE_ALL_MAGIC_BUY_LIMITS_BTN_TEXT "DELETE ALL MAGIC BUY LIMITS" //-- Define values for the deleteAllMagicSellLimitsBtn #define DELETE_ALL_MAGIC_SELL_LIMITS_BTN_NAME "Delete All Magic Sell Limits Btn" #define DELETE_ALL_MAGIC_SELL_LIMITS_BTN_SUBWINDOW 0 #define DELETE_ALL_MAGIC_SELL_LIMITS_BTN_X1 int((GUI_OBJECTS_MARGIN * 3) + DELETE_ORDERS_BTN_WIDTH) #define DELETE_ALL_MAGIC_SELL_LIMITS_BTN_Y1 DELETE_ALL_MAGIC_BUY_LIMITS_BTN_Y1//int((MAGIC_ORDER_STATUS_EDIT_Y1) + (GUI_OBJECTS_HEIGHT + GUI_OBJECTS_MARGIN)) #define DELETE_ALL_MAGIC_SELL_LIMITS_BTN_TEXT "DELETE ALL MAGIC SELL LIMITS" //-- Define values for the deleteAllMagicOrdersBtn #define DELETE_ALL_MAGIC_ORDERS_BTN_NAME "Delete All Magic Orders Btn" #define DELETE_ALL_MAGIC_ORDERS_BTN_SUBWINDOW 0 #define DELETE_ALL_MAGIC_ORDERS_BTN_X1 int(GUI_OBJECTS_MARGIN * 2) #define DELETE_ALL_MAGIC_ORDERS_BTN_Y1 int((DELETE_ALL_MAGIC_BUY_LIMITS_BTN_Y1) + (GUI_OBJECTS_HEIGHT + GUI_OBJECTS_MARGIN)) #define DELETE_ALL_MAGIC_ORDERS_BTN_TEXT "DELETE ALL MAGIC PENDING ORDERS"
Adicionaremos ao nosso código as classes padrão do MQL5 para painéis e diálogos.
//-- Include the MQL5 standard library for panels and dialogs #include <Controls\Dialog.mqh> #include <Controls\Button.mqh> #include <Controls\Label.mqh> #include <Controls\Edit.mqh>
Agora que as classes de painéis e caixas de diálogo estão incluídas e disponíveis no nosso arquivo, podemos prosseguir para a criação de seus objetos, expandindo a funcionalidade dentro do nosso código.
//-- Create objects for the included standard classes CAppDialog mainPanelWindow; //-- Create the header label components CLabel lotVolHeaderLabel; CLabel openPriceHeaderLabel; CLabel slHeaderLabel; CLabel tpHeaderLabel; //-- Create the buy stop GUI components //--BuyStopBtn CButton buyStopBtn; //--BuyStopEdits CEdit buyStopVolumeLotEdit; CEdit buyStopOpenPriceEdit; CEdit buyStopSlEdit; CEdit buyStopTpEdit; //-- Create the sell stop GUI components //--SellStopBtn CButton sellStopBtn; //--sellStopEdits CEdit sellStopVolumeLotEdit; CEdit sellStopOpenPriceEdit; CEdit sellStopSlEdit; CEdit sellStopTpEdit; //-- Create the buy limit GUI components //--BuyLimitBtn CButton buyLimitBtn; //--BuyLimitEdits CEdit buyLimitVolumeLotEdit; CEdit buyLimitOpenPriceEdit; CEdit buyLimitSlEdit; CEdit buyLimitTpEdit; //-- Create the sell limit GUI components //--sellLimitBtn CButton sellLimitBtn; //--sellLimitEdits CEdit sellLimitVolumeLotEdit; CEdit sellLimitOpenPriceEdit; CEdit sellLimitSlEdit; CEdit sellLimitTpEdit; //-- Create the order status GUI components //--magic order status CLabel magicOrderStatusLabel; CEdit magicOrdersStatusEdit; //--Magic orders delete buttons CButton deleteAllMagicBuyStopsBtn; CButton deleteAllMagicSellStopsBtn; CButton deleteAllMagicBuyLimitsBtn; CButton deleteAllMagicSellLimitsBtn; CButton deleteAllMagicOrdersBtn;
Criaremos variáveis responsáveis por armazenar os preços de entrada e uma string para manter o status de todas as ordens abertas pelo nosso EA.
//-- Default starting entry prices for different pending orders double buyStopEntryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK) + ((spread * 20) * symbolPoint); double buyLimitEntryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK) - ((spread * 20) * symbolPoint); double sellStopEntryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK) - ((spread * 20) * symbolPoint); double sellLimitEntryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK) + ((spread * 20) * symbolPoint); //-- String values for the orders status string magicOrderStatus;
O próximo passo será criar a função responsável por gerar e carregar a interface gráfica durante a inicialização do EA. Chamaremos essa função de CreateGui().
void CreateGui() { //-- Create the orders panel mainPanelWindow.Create( 0, MAIN_PANEL_NAME, MAIN_PANEL_SUBWINDOW, MAIN_PANEL_X1, MAIN_PANEL_Y1, MAIN_PANEL_X2, MAIN_PANEL_Y2 ); /*------------------------------------------------------ * Header Labels GUI components creation **** *-----------------------------------------------------*/ //--Create the lot volume header label lotVolHeaderLabel.Create( 0, VOLUME_LOT_LABEL_NAME, VOLUME_LOT_LABEL_SUBWINDOW, VOLUME_LOT_LABEL_X1, VOLUME_LOT_LABEL_Y1, GUI_OBJECTS_WIDTH, GUI_OBJECTS_HEIGHT ); lotVolHeaderLabel.Text(VOLUME_LOT_LABEL_TEXT); lotVolHeaderLabel.Color(GUI_OBJECTS_HEADING_COLOR); lotVolHeaderLabel.FontSize(GUI_OBJECTS_HEADER_FONT_SIZE); mainPanelWindow.Add(lotVolHeaderLabel); //--Create the open price header label openPriceHeaderLabel.Create( 0, OPEN_PRICE_LABEL_NAME, OPEN_PRICE_LABEL_SUBWINDOW, OPEN_PRICE_LABEL_X1, OPEN_PRICE_LABEL_Y1, GUI_OBJECTS_WIDTH, GUI_OBJECTS_HEIGHT ); openPriceHeaderLabel.Text(OPEN_PRICE_LABEL_TEXT); openPriceHeaderLabel.Color(GUI_OBJECTS_HEADING_COLOR); openPriceHeaderLabel.FontSize(GUI_OBJECTS_HEADER_FONT_SIZE); mainPanelWindow.Add(openPriceHeaderLabel); //--Create the sl header label slHeaderLabel.Create( 0, SL_LABEL_NAME, SL_LABEL_SUBWINDOW, SL_LABEL_X1, SL_LABEL_Y1, int(GUI_OBJECTS_WIDTH / 1.4), GUI_OBJECTS_HEIGHT ); slHeaderLabel.Text(SL_LABEL_TEXT); slHeaderLabel.Color(GUI_OBJECTS_HEADING_COLOR); slHeaderLabel.FontSize(GUI_OBJECTS_HEADER_FONT_SIZE); mainPanelWindow.Add(slHeaderLabel); //--Create the tp header label tpHeaderLabel.Create( 0, TP_LABEL_NAME, TP_LABEL_SUBWINDOW, TP_LABEL_X1, TP_LABEL_Y1, int(GUI_OBJECTS_WIDTH / 1.4), GUI_OBJECTS_HEIGHT ); tpHeaderLabel.Text(TP_LABEL_TEXT); tpHeaderLabel.Color(GUI_OBJECTS_HEADING_COLOR); tpHeaderLabel.FontSize(GUI_OBJECTS_HEADER_FONT_SIZE); mainPanelWindow.Add(tpHeaderLabel); /*------------------------------------------------------ * Buy Stop Order GUI components creation **** *-----------------------------------------------------*/ //--Create the open buy stop button buyStopBtn.Create( 0, BUY_STOP_BTN_NAME, BUY_STOP_BTN_SUBWINDOW, BUY_STOP_BTN_X1, BUY_STOP_BTN_Y1, 0, 0 ); buyStopBtn.Text(BUY_STOP_BTN_TEXT); buyStopBtn.Width(GUI_OBJECTS_WIDTH); buyStopBtn.Height(GUI_OBJECTS_HEIGHT); buyStopBtn.Color(GUI_OBJECTS_BUY_BTN_COLOR); buyStopBtn.ColorBackground(GUI_OBJECTS_BUY_BTN_BG_COLOR); buyStopBtn.FontSize(GUI_OBJECTS_FONT_SIZE); mainPanelWindow.Add(buyStopBtn); //--Create the buy stop volume lot edit to get the buy stop volume/lot user input buyStopVolumeLotEdit.Create( 0, BUY_STOP_VOLUME_LOT_EDIT_NAME, BUY_STOP_VOLUME_LOT_EDIT_SUBWINDOW, BUY_STOP_VOLUME_LOT_EDIT_X1, BUY_STOP_VOLUME_LOT_EDIT_Y1, 0, 0 ); buyStopVolumeLotEdit.Text(DoubleToString(volumeLot)); buyStopVolumeLotEdit.Width(GUI_OBJECTS_WIDTH); buyStopVolumeLotEdit.Height(GUI_OBJECTS_HEIGHT); buyStopVolumeLotEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR); buyStopVolumeLotEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR); buyStopVolumeLotEdit.FontSize(GUI_OBJECTS_FONT_SIZE); buyStopVolumeLotEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR); mainPanelWindow.Add(buyStopVolumeLotEdit); //--Create the buy stop price edit to get the buy stop opening price user input buyStopOpenPriceEdit.Create( 0, BUY_STOP_OPEN_PRICE_EDIT_NAME, BUY_STOP_OPEN_PRICE_EDIT_SUBWINDOW, BUY_STOP_OPEN_PRICE_EDIT_X1, BUY_STOP_OPEN_PRICE_EDIT_Y1, 0, 0 ); buyStopOpenPriceEdit.Text(DoubleToString(buyStopEntryPrice, int(symbolDigits))); buyStopOpenPriceEdit.Width(GUI_OBJECTS_WIDTH); buyStopOpenPriceEdit.Height(GUI_OBJECTS_HEIGHT); buyStopOpenPriceEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR); buyStopOpenPriceEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR); buyStopOpenPriceEdit.FontSize(GUI_OBJECTS_FONT_SIZE); buyStopOpenPriceEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR); mainPanelWindow.Add(buyStopOpenPriceEdit); //--Create the buy stop sl edit to get the buy stop sl user input buyStopSlEdit.Create( 0, BUY_STOP_SL_EDIT_NAME, BUY_STOP_SL_EDIT_SUBWINDOW, BUY_STOP_SL_EDIT_X1, BUY_STOP_SL_EDIT_Y1, 0, 0 ); buyStopSlEdit.Text(IntegerToString(sl)); buyStopSlEdit.Width(int(GUI_OBJECTS_WIDTH / 1.4)); buyStopSlEdit.Height(GUI_OBJECTS_HEIGHT); buyStopSlEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR); buyStopSlEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR); buyStopSlEdit.FontSize(GUI_OBJECTS_FONT_SIZE); buyStopSlEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR); mainPanelWindow.Add(buyStopSlEdit); //--Create the buy stop tp edit to get the buy stop tp user input buyStopTpEdit.Create( 0, BUY_STOP_TP_EDIT_NAME, BUY_STOP_TP_EDIT_SUBWINDOW, BUY_STOP_TP_EDIT_X1, BUY_STOP_TP_EDIT_Y1, 0, 0 ); buyStopTpEdit.Text(IntegerToString(tp)); buyStopTpEdit.Width(GUI_OBJECTS_WIDTH); buyStopTpEdit.Height(GUI_OBJECTS_HEIGHT); buyStopTpEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR); buyStopTpEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR); buyStopTpEdit.FontSize(GUI_OBJECTS_FONT_SIZE); buyStopTpEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR); mainPanelWindow.Add(buyStopTpEdit); /*------------------------------------------------------ * Sell Stop Order GUI components creation **** *-----------------------------------------------------*/ //--Create the open sell stop button sellStopBtn.Create( 0, SELL_STOP_BTN_NAME, SELL_STOP_BTN_SUBWINDOW, SELL_STOP_BTN_X1, SELL_STOP_BTN_Y1, 0, 0 ); sellStopBtn.Text(SELL_STOP_BTN_TEXT); sellStopBtn.Width(GUI_OBJECTS_WIDTH); sellStopBtn.Height(GUI_OBJECTS_HEIGHT); sellStopBtn.Color(GUI_OBJECTS_SELL_BTN_COLOR); sellStopBtn.ColorBackground(GUI_OBJECTS_SELL_BTN_BG_COLOR); sellStopBtn.FontSize(GUI_OBJECTS_FONT_SIZE); mainPanelWindow.Add(sellStopBtn); //--Create the sell stop volume lot edit to get the sell stop volume/lot user input sellStopVolumeLotEdit.Create( 0, SELL_STOP_VOLUME_LOT_EDIT_NAME, SELL_STOP_VOLUME_LOT_EDIT_SUBWINDOW, SELL_STOP_VOLUME_LOT_EDIT_X1, SELL_STOP_VOLUME_LOT_EDIT_Y1, 0, 0 ); sellStopVolumeLotEdit.Text(DoubleToString(volumeLot)); sellStopVolumeLotEdit.Width(GUI_OBJECTS_WIDTH); sellStopVolumeLotEdit.Height(GUI_OBJECTS_HEIGHT); sellStopVolumeLotEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR); sellStopVolumeLotEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR); sellStopVolumeLotEdit.FontSize(GUI_OBJECTS_FONT_SIZE); sellStopVolumeLotEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR); mainPanelWindow.Add(sellStopVolumeLotEdit); //--Create the sell stop price edit to get the sell stop opening price user input sellStopOpenPriceEdit.Create( 0, SELL_STOP_OPEN_PRICE_EDIT_NAME, SELL_STOP_OPEN_PRICE_EDIT_SUBWINDOW, SELL_STOP_OPEN_PRICE_EDIT_X1, SELL_STOP_OPEN_PRICE_EDIT_Y1, 0, 0 ); sellStopOpenPriceEdit.Text(DoubleToString(sellStopEntryPrice, int(symbolDigits))); sellStopOpenPriceEdit.Width(GUI_OBJECTS_WIDTH); sellStopOpenPriceEdit.Height(GUI_OBJECTS_HEIGHT); sellStopOpenPriceEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR); sellStopOpenPriceEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR); sellStopOpenPriceEdit.FontSize(GUI_OBJECTS_FONT_SIZE); sellStopOpenPriceEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR); mainPanelWindow.Add(sellStopOpenPriceEdit); //--Create the sell stop sl edit to get the sell stop sl user input sellStopSlEdit.Create( 0, SELL_STOP_SL_EDIT_NAME, SELL_STOP_SL_EDIT_SUBWINDOW, SELL_STOP_SL_EDIT_X1, SELL_STOP_SL_EDIT_Y1, 0, 0 ); sellStopSlEdit.Text(IntegerToString(sl)); sellStopSlEdit.Width(int(GUI_OBJECTS_WIDTH / 1.4)); sellStopSlEdit.Height(GUI_OBJECTS_HEIGHT); sellStopSlEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR); sellStopSlEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR); sellStopSlEdit.FontSize(GUI_OBJECTS_FONT_SIZE); sellStopSlEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR); mainPanelWindow.Add(sellStopSlEdit); //--Create the sell stop tp edit to get the sell stop tp user input sellStopTpEdit.Create( 0, SELL_STOP_TP_EDIT_NAME, SELL_STOP_TP_EDIT_SUBWINDOW, SELL_STOP_TP_EDIT_X1, SELL_STOP_TP_EDIT_Y1, 0, 0 ); sellStopTpEdit.Text(IntegerToString(tp)); sellStopTpEdit.Width(GUI_OBJECTS_WIDTH); sellStopTpEdit.Height(GUI_OBJECTS_HEIGHT); sellStopTpEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR); sellStopTpEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR); sellStopTpEdit.FontSize(GUI_OBJECTS_FONT_SIZE); sellStopTpEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR); mainPanelWindow.Add(sellStopTpEdit); /*------------------------------------------------------ * Buy Limit Order GUI components creation **** *-----------------------------------------------------*/ //--Create the open buy limit button buyLimitBtn.Create( 0, BUY_LIMIT_BTN_NAME, BUY_LIMIT_BTN_SUBWINDOW, BUY_LIMIT_BTN_X1, BUY_LIMIT_BTN_Y1, 0, 0 ); buyLimitBtn.Text(BUY_LIMIT_BTN_TEXT); buyLimitBtn.Width(GUI_OBJECTS_WIDTH); buyLimitBtn.Height(GUI_OBJECTS_HEIGHT); buyLimitBtn.Color(GUI_OBJECTS_BUY_BTN_COLOR); buyLimitBtn.ColorBackground(GUI_OBJECTS_BUY_BTN_BG_COLOR); buyLimitBtn.FontSize(GUI_OBJECTS_FONT_SIZE); mainPanelWindow.Add(buyLimitBtn); //--Create the buy limit volume lot edit to get the buy limit volume/lot user input buyLimitVolumeLotEdit.Create( 0, BUY_LIMIT_VOLUME_LOT_EDIT_NAME, BUY_LIMIT_VOLUME_LOT_EDIT_SUBWINDOW, BUY_LIMIT_VOLUME_LOT_EDIT_X1, BUY_LIMIT_VOLUME_LOT_EDIT_Y1, 0, 0 ); buyLimitVolumeLotEdit.Text(DoubleToString(volumeLot)); buyLimitVolumeLotEdit.Width(GUI_OBJECTS_WIDTH); buyLimitVolumeLotEdit.Height(GUI_OBJECTS_HEIGHT); buyLimitVolumeLotEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR); buyLimitVolumeLotEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR); buyLimitVolumeLotEdit.FontSize(GUI_OBJECTS_FONT_SIZE); buyLimitVolumeLotEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR); mainPanelWindow.Add(buyLimitVolumeLotEdit); //--Create the buy limit price edit to get the buy limit opening price user input buyLimitOpenPriceEdit.Create( 0, BUY_LIMIT_OPEN_PRICE_EDIT_NAME, BUY_LIMIT_OPEN_PRICE_EDIT_SUBWINDOW, BUY_LIMIT_OPEN_PRICE_EDIT_X1, BUY_LIMIT_OPEN_PRICE_EDIT_Y1, 0, 0 ); buyLimitOpenPriceEdit.Text(DoubleToString(buyLimitEntryPrice, int(symbolDigits))); buyLimitOpenPriceEdit.Width(GUI_OBJECTS_WIDTH); buyLimitOpenPriceEdit.Height(GUI_OBJECTS_HEIGHT); buyLimitOpenPriceEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR); buyLimitOpenPriceEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR); buyLimitOpenPriceEdit.FontSize(GUI_OBJECTS_FONT_SIZE); buyLimitOpenPriceEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR); mainPanelWindow.Add(buyLimitOpenPriceEdit); //--Create the buy limit sl edit to get the buy limit sl user input buyLimitSlEdit.Create( 0, BUY_LIMIT_SL_EDIT_NAME, BUY_LIMIT_SL_EDIT_SUBWINDOW, BUY_LIMIT_SL_EDIT_X1, BUY_LIMIT_SL_EDIT_Y1, 0, 0 ); buyLimitSlEdit.Text(IntegerToString(sl)); buyLimitSlEdit.Width(int(GUI_OBJECTS_WIDTH / 1.4)); buyLimitSlEdit.Height(GUI_OBJECTS_HEIGHT); buyLimitSlEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR); buyLimitSlEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR); buyLimitSlEdit.FontSize(GUI_OBJECTS_FONT_SIZE); buyLimitSlEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR); mainPanelWindow.Add(buyLimitSlEdit); //--Create the buy limit tp edit to get the buy limit tp user input buyLimitTpEdit.Create( 0, BUY_LIMIT_TP_EDIT_NAME, BUY_LIMIT_TP_EDIT_SUBWINDOW, BUY_LIMIT_TP_EDIT_X1, BUY_LIMIT_TP_EDIT_Y1, 0, 0 ); buyLimitTpEdit.Text(IntegerToString(tp)); buyLimitTpEdit.Width(GUI_OBJECTS_WIDTH); buyLimitTpEdit.Height(GUI_OBJECTS_HEIGHT); buyLimitTpEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR); buyLimitTpEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR); buyLimitTpEdit.FontSize(GUI_OBJECTS_FONT_SIZE); buyLimitTpEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR); mainPanelWindow.Add(buyLimitTpEdit); /*------------------------------------------------------ * Sell Limit Order GUI components creation **** *-----------------------------------------------------*/ //--Create the open sell limit button sellLimitBtn.Create( 0, SELL_LIMIT_BTN_NAME, SELL_LIMIT_BTN_SUBWINDOW, SELL_LIMIT_BTN_X1, SELL_LIMIT_BTN_Y1, 0, 0 ); sellLimitBtn.Text(SELL_LIMIT_BTN_TEXT); sellLimitBtn.Width(GUI_OBJECTS_WIDTH); sellLimitBtn.Height(GUI_OBJECTS_HEIGHT); sellLimitBtn.Color(GUI_OBJECTS_SELL_BTN_COLOR); sellLimitBtn.ColorBackground(GUI_OBJECTS_SELL_BTN_BG_COLOR); sellLimitBtn.FontSize(GUI_OBJECTS_FONT_SIZE); mainPanelWindow.Add(sellLimitBtn); //--Create the sell limit volume lot edit to get the sell limit volume/lot user input sellLimitVolumeLotEdit.Create( 0, SELL_LIMIT_VOLUME_LOT_EDIT_NAME, SELL_LIMIT_VOLUME_LOT_EDIT_SUBWINDOW, SELL_LIMIT_VOLUME_LOT_EDIT_X1, SELL_LIMIT_VOLUME_LOT_EDIT_Y1, 0, 0 ); sellLimitVolumeLotEdit.Text(DoubleToString(volumeLot)); sellLimitVolumeLotEdit.Width(GUI_OBJECTS_WIDTH); sellLimitVolumeLotEdit.Height(GUI_OBJECTS_HEIGHT); sellLimitVolumeLotEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR); sellLimitVolumeLotEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR); sellLimitVolumeLotEdit.FontSize(GUI_OBJECTS_FONT_SIZE); sellLimitVolumeLotEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR); mainPanelWindow.Add(sellLimitVolumeLotEdit); //--Create the sell limit price edit to get the sell limit opening price user input sellLimitOpenPriceEdit.Create( 0, SELL_LIMIT_OPEN_PRICE_EDIT_NAME, SELL_LIMIT_OPEN_PRICE_EDIT_SUBWINDOW, SELL_LIMIT_OPEN_PRICE_EDIT_X1, SELL_LIMIT_OPEN_PRICE_EDIT_Y1, 0, 0 ); sellLimitOpenPriceEdit.Text(DoubleToString(sellLimitEntryPrice, int(symbolDigits))); sellLimitOpenPriceEdit.Width(GUI_OBJECTS_WIDTH); sellLimitOpenPriceEdit.Height(GUI_OBJECTS_HEIGHT); sellLimitOpenPriceEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR); sellLimitOpenPriceEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR); sellLimitOpenPriceEdit.FontSize(GUI_OBJECTS_FONT_SIZE); sellLimitOpenPriceEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR); mainPanelWindow.Add(sellLimitOpenPriceEdit); //--Create the sell limit sl edit to get the sell limit sl user input sellLimitSlEdit.Create( 0, SELL_LIMIT_SL_EDIT_NAME, SELL_LIMIT_SL_EDIT_SUBWINDOW, SELL_LIMIT_SL_EDIT_X1, SELL_LIMIT_SL_EDIT_Y1, 0, 0 ); sellLimitSlEdit.Text(IntegerToString(sl)); sellLimitSlEdit.Width(int(GUI_OBJECTS_WIDTH / 1.4)); sellLimitSlEdit.Height(GUI_OBJECTS_HEIGHT); sellLimitSlEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR); sellLimitSlEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR); sellLimitSlEdit.FontSize(GUI_OBJECTS_FONT_SIZE); sellLimitSlEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR); mainPanelWindow.Add(sellLimitSlEdit); //--Create the sell limit tp edit to get the sell limit tp user input sellLimitTpEdit.Create( 0, SELL_LIMIT_TP_EDIT_NAME, SELL_LIMIT_TP_EDIT_SUBWINDOW, SELL_LIMIT_TP_EDIT_X1, SELL_LIMIT_TP_EDIT_Y1, 0, 0 ); sellLimitTpEdit.Text(IntegerToString(tp)); sellLimitTpEdit.Width(GUI_OBJECTS_WIDTH); sellLimitTpEdit.Height(GUI_OBJECTS_HEIGHT); sellLimitTpEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR); sellLimitTpEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR); sellLimitTpEdit.FontSize(GUI_OBJECTS_FONT_SIZE); sellLimitTpEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR); mainPanelWindow.Add(sellLimitTpEdit); /*------------------------------------------------------------- * Status Labels and readonly edits GUI components creation **** *------------------------------------------------------------*/ //--Create the order magic status label magicOrderStatusLabel.Create( 0, MAGIC_ORDER_STATUS_LABEL_NAME, MAGIC_ORDER_STATUS_LABEL_SUBWINDOW, MAGIC_ORDER_STATUS_LABEL_X1, MAGIC_ORDER_STATUS_LABEL_Y1, GUI_OBJECTS_WIDTH, GUI_OBJECTS_HEIGHT ); magicOrderStatusLabel.Text(MAGIC_ORDER_STATUS_LABEL_TEXT + " - (Total Open Orders: " + (string(MagicOrdersTotal(magicNo))) + ")"); magicOrderStatusLabel.Color(STATUS_EDIT_COLOR); magicOrderStatusLabel.FontSize(STATUS_HEADER_FONT_SIZE); mainPanelWindow.Add(magicOrderStatusLabel); //--Create the magic order status edit to display the magic orders status magicOrdersStatusEdit.Create( 0, MAGIC_ORDER_STATUS_EDIT_NAME, MAGIC_ORDER_STATUS_EDIT_SUBWINDOW, MAGIC_ORDER_STATUS_EDIT_X1, MAGIC_ORDER_STATUS_EDIT_Y1, 0, 0 ); magicOrdersStatusEdit.ReadOnly(true); magicOrdersStatusEdit.Text(magicOrderStatus); magicOrdersStatusEdit.Width(STATUS_EDIT_WIDTH); magicOrdersStatusEdit.Height(GUI_OBJECTS_HEIGHT); magicOrdersStatusEdit.Color(STATUS_EDIT_COLOR); magicOrdersStatusEdit.ColorBackground(STATUS_EDIT_BG_COLOR); magicOrdersStatusEdit.FontSize(STATUS_EDIT_FONT_SIZE); magicOrdersStatusEdit.ColorBorder(STATUS_EDIT_BORDER_COLOR); mainPanelWindow.Add(magicOrdersStatusEdit); //--Create the delete all magic buy stops button deleteAllMagicBuyStopsBtn.Create( 0, DELETE_ALL_MAGIC_BUY_STOPS_BTN_NAME, DELETE_ALL_MAGIC_BUY_STOPS_BTN_SUBWINDOW, DELETE_ALL_MAGIC_BUY_STOPS_BTN_X1, DELETE_ALL_MAGIC_BUY_STOPS_BTN_Y1, 0, 0 ); deleteAllMagicBuyStopsBtn.Text(DELETE_ALL_MAGIC_BUY_STOPS_BTN_TEXT); deleteAllMagicBuyStopsBtn.Width(DELETE_ORDERS_BTN_WIDTH); deleteAllMagicBuyStopsBtn.Height(GUI_OBJECTS_HEIGHT); deleteAllMagicBuyStopsBtn.Color(DELETE_ORDERS_BTN_COLOR); deleteAllMagicBuyStopsBtn.ColorBackground(DELETE_BUY_ORDERS_BTN_BG_COLOR); deleteAllMagicBuyStopsBtn.ColorBorder(DELETE_ORDERS_BTN_BORDER_COLOR); deleteAllMagicBuyStopsBtn.FontSize(DELETE_ORDERS_BTN_FONT_SIZE); mainPanelWindow.Add(deleteAllMagicBuyStopsBtn); //--Create the delete all magic sell stops button deleteAllMagicSellStopsBtn.Create( 0, DELETE_ALL_MAGIC_SELL_STOPS_BTN_NAME, DELETE_ALL_MAGIC_SELL_STOPS_BTN_SUBWINDOW, DELETE_ALL_MAGIC_SELL_STOPS_BTN_X1, DELETE_ALL_MAGIC_SELL_STOPS_BTN_Y1, 0, 0 ); deleteAllMagicSellStopsBtn.Text(DELETE_ALL_MAGIC_SELL_STOPS_BTN_TEXT); deleteAllMagicSellStopsBtn.Width(DELETE_ORDERS_BTN_WIDTH); deleteAllMagicSellStopsBtn.Height(GUI_OBJECTS_HEIGHT); deleteAllMagicSellStopsBtn.Color(DELETE_ORDERS_BTN_COLOR); deleteAllMagicSellStopsBtn.ColorBackground(DELETE_SELL_ORDERS_BTN_BG_COLOR); deleteAllMagicSellStopsBtn.ColorBorder(DELETE_ORDERS_BTN_BORDER_COLOR); deleteAllMagicSellStopsBtn.FontSize(DELETE_ORDERS_BTN_FONT_SIZE); mainPanelWindow.Add(deleteAllMagicSellStopsBtn); //--Create the delete all magic buy limits button deleteAllMagicBuyLimitsBtn.Create( 0, DELETE_ALL_MAGIC_BUY_LIMITS_BTN_NAME, DELETE_ALL_MAGIC_BUY_LIMITS_BTN_SUBWINDOW, DELETE_ALL_MAGIC_BUY_LIMITS_BTN_X1, DELETE_ALL_MAGIC_BUY_LIMITS_BTN_Y1, 0, 0 ); deleteAllMagicBuyLimitsBtn.Text(DELETE_ALL_MAGIC_BUY_LIMITS_BTN_TEXT); deleteAllMagicBuyLimitsBtn.Width(DELETE_ORDERS_BTN_WIDTH); deleteAllMagicBuyLimitsBtn.Height(GUI_OBJECTS_HEIGHT); deleteAllMagicBuyLimitsBtn.Color(DELETE_ORDERS_BTN_COLOR); deleteAllMagicBuyLimitsBtn.ColorBackground(DELETE_BUY_ORDERS_BTN_BG_COLOR); deleteAllMagicBuyLimitsBtn.ColorBorder(DELETE_ORDERS_BTN_BORDER_COLOR); deleteAllMagicBuyLimitsBtn.FontSize(DELETE_ORDERS_BTN_FONT_SIZE); mainPanelWindow.Add(deleteAllMagicBuyLimitsBtn); //--Create the delete all magic sell limits button deleteAllMagicSellLimitsBtn.Create( 0, DELETE_ALL_MAGIC_SELL_LIMITS_BTN_NAME, DELETE_ALL_MAGIC_SELL_LIMITS_BTN_SUBWINDOW, DELETE_ALL_MAGIC_SELL_LIMITS_BTN_X1, DELETE_ALL_MAGIC_SELL_LIMITS_BTN_Y1, 0, 0 ); deleteAllMagicSellLimitsBtn.Text(DELETE_ALL_MAGIC_SELL_LIMITS_BTN_TEXT); deleteAllMagicSellLimitsBtn.Width(DELETE_ORDERS_BTN_WIDTH); deleteAllMagicSellLimitsBtn.Height(GUI_OBJECTS_HEIGHT); deleteAllMagicSellLimitsBtn.Color(DELETE_ORDERS_BTN_COLOR); deleteAllMagicSellLimitsBtn.ColorBackground(DELETE_SELL_ORDERS_BTN_BG_COLOR); deleteAllMagicSellLimitsBtn.ColorBorder(DELETE_ORDERS_BTN_BORDER_COLOR); deleteAllMagicSellLimitsBtn.FontSize(DELETE_ORDERS_BTN_FONT_SIZE); mainPanelWindow.Add(deleteAllMagicSellLimitsBtn); //--Create the delete all magic orders button deleteAllMagicOrdersBtn.Create( 0, DELETE_ALL_MAGIC_ORDERS_BTN_NAME, DELETE_ALL_MAGIC_ORDERS_BTN_SUBWINDOW, DELETE_ALL_MAGIC_ORDERS_BTN_X1, DELETE_ALL_MAGIC_ORDERS_BTN_Y1, 0, 0 ); deleteAllMagicOrdersBtn.Text(DELETE_ALL_MAGIC_ORDERS_BTN_TEXT); deleteAllMagicOrdersBtn.Width(STATUS_EDIT_WIDTH); deleteAllMagicOrdersBtn.Height(GUI_OBJECTS_HEIGHT); deleteAllMagicOrdersBtn.Color(DELETE_ORDERS_BTN_COLOR); deleteAllMagicOrdersBtn.ColorBackground(DELETE_ALL_ORDERS_BTN_BG_COLOR); deleteAllMagicOrdersBtn.ColorBorder(DELETE_ORDERS_BTN_BORDER_COLOR); deleteAllMagicOrdersBtn.FontSize(DELETE_ORDERS_BTN_FONT_SIZE); mainPanelWindow.Add(deleteAllMagicOrdersBtn); //--Call the Run() method to load the main panel window mainPanelWindow.Run(); }
Agora precisamos detectar qualquer clique de botão ou ativação por meio da implementação da função OnChartEvent(...). Essa função atuará como o manipulador de eventos para todas as interações do usuário, tornando-se o principal componente responsável pela responsividade do nosso painel. Nesta parte, chamaremos as funções de protótipo importadas da biblioteca PendingOrdersManager.ex5, o que nos permitirá gerenciar ordens pendentes de acordo com os dados fornecidos pelo usuário. Por exemplo, se o usuário clicar em um botão para abrir uma nova ordem pendente, a função correspondente da biblioteca será acionada para executar a operação.
Para aprimorar ainda mais a experiência do usuário com o painel de ordens pendentes, também integraremos feedback sonoro. O resultado de cada ação — como a colocação bem-sucedida de uma ordem ou a ocorrência de um erro — será acompanhado por um som específico. Isso proporciona retorno em tempo real e adiciona um nível extra de interatividade, tornando o painel mais intuitivo e agradável de usar. A combinação de sinais visuais e sonoros permitirá que os usuários acompanhem facilmente o status de suas ações e reajam de forma adequada.
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { //--Detect any clicks or events performed to the orders panel window and make it moveable mainPanelWindow.ChartEvent(id, lparam, dparam, sparam); //--Detect any click events on the chart if(id == CHARTEVENT_OBJECT_CLICK) { //--Detect when the buyStopBtn is clicked and open a new buy stop order if(sparam == buyStopBtn.Name()) { Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam); Print("Opening a new Buy Stop Order with the details below: "); Print("Volume: ", buyStopVolumeLotEdit.Text()); Print("Open Price: ", buyStopOpenPriceEdit.Text()); Print("Sl (Pips): ", buyStopSlEdit.Text()); Print("Tp (Pips): ", buyStopTpEdit.Text()); if( OpenBuyStop( magicNo, _Symbol, StringToDouble(buyStopOpenPriceEdit.Text()), StringToDouble(buyStopVolumeLotEdit.Text()), (uint)StringToInteger(buyStopSlEdit.Text()), (uint)StringToInteger(buyStopTpEdit.Text()), "EX5 PendingOrdersManager Panel" ) ) { PlaySound("ok.wav");//-- Order placed ok } else { PlaySound("alert2.wav");//-- Order failed } } //--Detect when the sellStopBtn is clicked and open a new sell stop order if(sparam == sellStopBtn.Name()) { Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam); Print("Opening a new Sell Stop Order with the details below: "); Print("Volume: ", sellStopVolumeLotEdit.Text()); Print("Open Price: ", sellStopOpenPriceEdit.Text()); Print("Sl (Pips): ", sellStopSlEdit.Text()); Print("Tp (Pips): ", sellStopTpEdit.Text()); if( OpenSellStop( magicNo, _Symbol, StringToDouble(sellStopOpenPriceEdit.Text()), StringToDouble(sellStopVolumeLotEdit.Text()), (uint)StringToInteger(sellStopSlEdit.Text()), (uint)StringToInteger(sellStopTpEdit.Text()), "EX5 PendingOrdersManager Panel" ) ) { PlaySound("ok.wav");//-- Order placed ok } else { PlaySound("alert2.wav");//-- Order failed } } //--Detect when the buyLimitBtn is clicked and open a new buy limit order if(sparam == buyLimitBtn.Name()) { Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam); Print("Opening a new Buy Limit Order with the details below: "); Print("Volume: ", buyLimitVolumeLotEdit.Text()); Print("Open Price: ", buyLimitOpenPriceEdit.Text()); Print("Sl (Pips): ", buyLimitSlEdit.Text()); Print("Tp (Pips): ", buyLimitTpEdit.Text()); if( OpenBuyLimit( magicNo, _Symbol, StringToDouble(buyLimitOpenPriceEdit.Text()), StringToDouble(buyLimitVolumeLotEdit.Text()), (uint)StringToInteger(buyLimitSlEdit.Text()), (uint)StringToInteger(buyLimitTpEdit.Text()), "EX5 PendingOrdersManager Panel" ) ) { PlaySound("ok.wav");//-- Order placed ok } else { PlaySound("alert2.wav");//-- Order failed } } //--Detect when the sellLimitBtn is clicked and open a new sell limit order if(sparam == sellLimitBtn.Name()) { Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam); Print("Opening a new Sell Limit Order with the details below: "); Print("Volume: ", sellLimitVolumeLotEdit.Text()); Print("Open Price: ", sellLimitOpenPriceEdit.Text()); Print("Sl (Pips): ", sellLimitSlEdit.Text()); Print("Tp (Pips): ", sellLimitTpEdit.Text()); if( OpenSellLimit( magicNo, _Symbol, StringToDouble(sellLimitOpenPriceEdit.Text()), StringToDouble(sellLimitVolumeLotEdit.Text()), (uint)StringToInteger(sellLimitSlEdit.Text()), (uint)StringToInteger(sellLimitTpEdit.Text()), "EX5 PendingOrdersManager Panel" ) ) { PlaySound("ok.wav");//-- Order placed ok } else { PlaySound("alert2.wav");//-- Order failed } } //--Detect when the deleteAllMagicBuyStopsBtn is clicked and delete all the specified orders if(sparam == deleteAllMagicBuyStopsBtn.Name() && MagicBuyStopOrdersTotal(magicNo) > 0) { Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam); Print("Deleting all the buy stop orders with magic number: ", magicNo); if(DeleteAllBuyStops("", magicNo)) { PlaySound("ok.wav");//-- Orders deleted ok } else { PlaySound("alert2.wav");//-- Order deleting failed } } //--Detect when the deleteAllMagicSellStopsBtn is clicked and delete all the specified orders if(sparam == deleteAllMagicSellStopsBtn.Name() && MagicSellStopOrdersTotal(magicNo) > 0) { Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam); Print("Deleting all the sell stop orders with magic number: ", magicNo); if(DeleteAllSellStops("", magicNo)) { PlaySound("ok.wav");//-- Orders deleted ok } else { PlaySound("alert2.wav");//-- Order deleting failed } } //--Detect when the deleteAllMagicBuyLimitsBtn is clicked and delete all the specified orders if(sparam == deleteAllMagicBuyLimitsBtn.Name() && MagicBuyLimitOrdersTotal(magicNo) > 0) { Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam); Print("Deleting all the buy limit orders with magic number: ", magicNo); if(DeleteAllBuyLimits("", magicNo)) { PlaySound("ok.wav");//-- Orders deleted ok } else { PlaySound("alert2.wav");//-- Order deleting failed } } //--Detect when the deleteAllMagicSellLimitsBtn is clicked and delete all the specified orders if(sparam == deleteAllMagicSellLimitsBtn.Name() && MagicSellLimitOrdersTotal(magicNo) > 0) { Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam); Print("Deleting all the sell limit orders with magic number: ", magicNo); if(DeleteAllSellLimits("", magicNo)) { PlaySound("ok.wav");//-- Orders deleted ok } else { PlaySound("alert2.wav");//-- Order deleting failed } } //--Detect when the deleteAllMagicOrdersBtn is clicked and delete all the specified orders if(sparam == deleteAllMagicOrdersBtn.Name() && MagicOrdersTotal(magicNo) > 0) { Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam); Print("Deleting all the open peding orders with magic number: ", magicNo); if(DeleteAllMagicOrders(magicNo)) { PlaySound("ok.wav");//-- Orders deleted ok } else { PlaySound("alert2.wav");//-- Order deleting failed } } } }
Logo após ser carregado, o EA preencherá automaticamente os campos volume/lote, preços de entrada, stop loss (SL) e take profit (TP) com valores predefinidos com base no spread atual. Esses valores oferecem ao usuário um ponto de partida para posicionar ordens, otimizando o processo de negociação e reduzindo ao mínimo a necessidade de inserção manual de dados. Além disso, os botões de exclusão de ordens, posicionados abaixo dos status das ordens por número mágico, permanecerão inicialmente desativados caso não sejam detectadas ordens pendentes ou ativas que correspondam ao número mágico do EA. Assim que o sistema detectar ordens correspondentes, os botões serão ativados e terão sua cor alterada, sinalizando que estão prontos para serem usados para executar as exclusões.
Quando o EA detecta a existência de ordens abertas correspondentes ao número mágico especificado, os botões de exclusão de ordens são ativados, mudando de cor para indicar que estão disponíveis e podem ser utilizados.
Para implementar essa funcionalidade, será necessário adicionar o seguinte código à função OnTick(). Isso nos permitirá utilizar as funções importadas da biblioteca EX5 para monitorar e atualizar constantemente a interface gráfica do usuário em tempo real, garantindo sua sincronização com o status das ordens a cada novo tick recebido.
void OnTick() { //--- magicOrderStatus = " Buy Stops: " + (string(MagicBuyStopOrdersTotal(magicNo))) + ", Sell Stops: " + (string(MagicSellStopOrdersTotal(magicNo))) + ", Buy Limits: " + (string(MagicBuyLimitOrdersTotal(magicNo))) + ", Sell Limits: " + (string(MagicSellLimitOrdersTotal(magicNo))) + " "; magicOrderStatusLabel.Text(MAGIC_ORDER_STATUS_LABEL_TEXT + (string(MagicOrdersTotal(magicNo)))); magicOrdersStatusEdit.Text(magicOrderStatus); //-- Disable and change the background color of the deleteAllMagicBuyStopsBtn depending on the open orders status if(MagicBuyStopOrdersTotal(magicNo) == 0) { deleteAllMagicBuyStopsBtn.Disable(); deleteAllMagicBuyStopsBtn.ColorBackground(clrLightSlateGray); } else { deleteAllMagicBuyStopsBtn.Enable(); deleteAllMagicBuyStopsBtn.ColorBackground(DELETE_BUY_ORDERS_BTN_BG_COLOR); } //-- Disable and change the background color of the deleteAllMagicSellStopsBtn depending on the open orders status if(MagicSellStopOrdersTotal(magicNo) == 0) { deleteAllMagicSellStopsBtn.Disable(); deleteAllMagicSellStopsBtn.ColorBackground(clrLightSlateGray); } else { deleteAllMagicSellStopsBtn.Enable(); deleteAllMagicSellStopsBtn.ColorBackground(DELETE_SELL_ORDERS_BTN_BG_COLOR); } //-- Disable and change the background color of the deleteAllMagicBuyLimitsBtn depending on the open orders status if(MagicBuyLimitOrdersTotal(magicNo) == 0) { deleteAllMagicBuyLimitsBtn.Disable(); deleteAllMagicBuyLimitsBtn.ColorBackground(clrLightSlateGray); } else { deleteAllMagicBuyLimitsBtn.Enable(); deleteAllMagicBuyLimitsBtn.ColorBackground(DELETE_BUY_ORDERS_BTN_BG_COLOR); } //-- Disable and change the background color of the deleteAllMagicSellLimitsBtn depending on the open orders status if(MagicSellLimitOrdersTotal(magicNo) == 0) { deleteAllMagicSellLimitsBtn.Disable(); deleteAllMagicSellLimitsBtn.ColorBackground(clrLightSlateGray); } else { deleteAllMagicSellLimitsBtn.Enable(); deleteAllMagicSellLimitsBtn.ColorBackground(DELETE_SELL_ORDERS_BTN_BG_COLOR); } //-- Disable and change the background color of the deleteAllMagicOrdersBtn depending on the open orders status if(MagicOrdersTotal(magicNo) == 0) { deleteAllMagicOrdersBtn.Disable(); deleteAllMagicOrdersBtn.ColorBackground(clrLightSlateGray); } else { deleteAllMagicOrdersBtn.Enable(); deleteAllMagicOrdersBtn.ColorBackground(DELETE_ALL_ORDERS_BTN_BG_COLOR); } }
Por fim, precisamos garantir que todos os recursos sejam devidamente liberados e limpos após o encerramento do EA. Para isso, adicionaremos o código apropriado na função OnDeinit(...).
void OnDeinit(const int reason) { //--- //-- Delete and garbage collect the graphical user interface and other graphical objects mainPanelWindow.Destroy(); //-- Clear any chart comments Comment(""); }
O arquivo PendingOrdersPanel.mq5 está anexado ao final do artigo.
Conclusão
Criamos uma biblioteca EX5 versátil para gerenciamento de ordens pendentes, capaz de abrir, modificar, excluir e classificar diferentes tipos dessas ordens. Essa biblioteca é um recurso valioso para qualquer desenvolvedor MQL5 que necessite de uma ferramenta flexível e fácil de usar para controlar ordens pendentes, permitindo obter rapidamente informações sobre o status delas ou executar ações por meio de simples chamadas de função.
A biblioteca é rica em funcionalidades e acompanha documentação clara e exemplos práticos. No próximo artigo, aplicaremos um método semelhante para criar a biblioteca EX5 de gerenciamento de histórico (History Management EX5 library), que irá simplificar consideravelmente o processamento do histórico de negociações e ordens no MQL5.
Obrigado pela atenção! Desejo a você muito sucesso no trading e na programação em MQL5!
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/15888
Aviso: Todos os direitos sobre esses materiais pertencem à MetaQuotes Ltd. É proibida a reimpressão total ou parcial.
This article was written by a user of the site and reflects their personal views. MetaQuotes Ltd is not responsible for the accuracy of the information presented, nor for any consequences resulting from the use of the solutions, strategies or recommendations described.





- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso