Guia prático do MQL5: obter propriedades de posição
Introdução
O artigo anterior, chamado "Livro de receitas MQL5: Utilização de diferentes modos de impressão" mostrou como podemos escrever um script rapidamente e imprimir as informações requeridas utilizando três modos diferentes. Agora vamos criar um script que obtém e exibe todas as propriedades de posição para o usuário.
Precisamos implementá-lo de forma que permita que o usuário selecione a opção adequada nos parâmetros externos do script, da seguinte forma: ou apenas obter as propriedades de posição de um símbolo (atual) ou ser executado para todas as posições abertas (se houver alguma), uma a uma, em todos os símbolos. Desta vez, visualizaremos as informações requeridas na própria caixa de diálogo, o que é muito conveniente e alguns de vocês podem achar este método mais útil.
Escrever um script
O começo do script é mais ou menos igual ao do artigo anterior (veja o código abaixo). Iniciamos com as propriedades do programa. Elas são seguidas pela linha com a diretiva #define e então atribuímos o nome do programa à variável SCRIPT_NAME utilizando a função MQLInfoString() e a constante MQL_PROGRAM_NAME que ela especifica. Mais informações sobre todos os valores possíveis da função MQLInfoString() podem ser encontradas na Referência MQL5.
Continuamos com a enumeração dos modos. Se você escrever um comentário para cada identificador, o texto desse comentário será exibido na lista suspensa nos parâmetros externos. Implementaremos duas opções:
- Símbolo atual - para exibir apenas as propriedades de posição para os símbolos atuais, e
- Todos os símbolos - para exibir propriedades de posição para todos os símbolos.
Haverá apenas um parâmetro externo (modo) a ser utilizado para selecionar o modo apropriado. O comentário que segue o parâmetro externo também será exibido na janela de parâmetros externos. Isso permitirá criarmos nomes de parâmetros mais significativos. Ao mesmo tempo, nomes de variáveis mais curtos seriam mais convenientes em termos de código.
#property copyright "Copyright 2012, http://tol64.blogspot.com" #property link "http://tol64.blogspot.com" #property description "email: hello.tol64@gmail.com" #property version "1.0" #property script_show_inputs //--- #define SCRIPT_NAME MQLInfoString(MQL_PROGRAM_NAME) // Script name //--- // ENUMERATION OF MODES enum ENUM_SYMBOLS_MODE { CURRENT_SYMBOL =0, // Current symbol ALL_SYMBOLS =1 // All symbols }; //--- // INPUT PARAMETERS input ENUM_SYMBOLS_MODE mode=CURRENT_SYMBOL; // Mode
O código continua com variáveis globais. Para que as variáveis globais possam ser acessadas de qualquer parte do script, elas devem ser colocadas fora das funções (geralmente logo no início do programa).
// GLOBAL VARIABLES long pos_magic=0; // Magic number string pos_symbol=""; // Symbol string pos_comment=""; // Comment double pos_swap=0.0; // Swap double pos_commission=0.0; // Commission double pos_price=0.0; // Current price of the position double pos_cprice=0.0; // Current price of the position double pos_profit=0.0; // Profit/Loss of the position double pos_volume=0.0; // Position volume double pos_sl=0.0; // Stop Loss of the position double pos_tp=0.0; // Take Profit of the position datetime pos_time=NULL; // Position opening time long pos_id=0; // Position identifier ENUM_POSITION_TYPE pos_type=NULL; // Position type //---
Na função principal do programa, chamaremos apenas uma função definida pelo usuário, PrintPositionProperties(), que realizará todas as operações requeridas:
//+------------------------------------------------------------------+ //| MAIN FUNCTION | //+------------------------------------------------------------------+ void OnStart() { PrintPositionProperties(); }
Vamos observar agora, passo a passo, a estrutura da função PrintPositionProperties() definida pelo usuário. Primeiramente, criaremos a base para o nosso trabalho futuro. Ela é muito simples e, quando implementada, tem o seguinte aspecto:
//+------------------------------------------------------------------+ //| OPENING A DIALOG BOX WITH SYMBOL DATA | //+------------------------------------------------------------------+ void PrintPositionProperties() { int err=0; // Variable for handling errors //--- // If you need to get position properties on the current symbol only if(mode==CURRENT_SYMBOL) { } //--- // If you need to get position properties on all symbols if(mode==ALL_SYMBOLS) { } }
Temos apenas dois ramos e uma variável local err que é responsável por gerenciar erros e é declarada no início da função. Agora precisamos escrever cenários de caso de uso para cada uma das opções. Vamos iniciar com a primeira, ou seja "Se você precisa obter apenas as propriedades de posição para o símbolo atual".
Isso é muito simples. Antes de mais nada, precisamos verificar se há uma posição no símbolo atual. Isso pode ser feito pela função PositionSelect() disponível em MQL5, a qual utiliza o nome do símbolo como parâmetro único. Para transferir o nome do símbolo atual, precisamos utilizar ou a função Symbol() ou a variável _Symbol predefinida que já contém o nome do símbolo atual. A função PositionSelect() retornará um resultado positivo, se houver uma posição naquele símbolo, ou um resultado negativo, se não houver uma posição ou se ocorreu um erro.
O código com comentários detalhados para a primeira opção é fornecido abaixo:
//--- // If a position exists, then... if(PositionSelect(_Symbol)) { // ...get its properties GetPositionProperties(); //--- // Open a dialog box to display all the data we obtained MessageBox("Symbol : "+pos_symbol+"\n"+ "Comment : "+pos_comment+"\n"+ "Magic Number : "+IntegerToString(pos_magic)+"\n"+ "Price Open : "+DoubleToString(pos_price,_Digits)+"\n"+ "Current Price : "+DoubleToString(pos_cprice,_Digits)+"\n"+ "Stop Loss : "+DoubleToString(pos_sl,_Digits)+"\n"+ "Take Profit : "+DoubleToString(pos_tp,_Digits)+"\n"+ "Type : "+PositionTypeToString(pos_type)+"\n"+ "Volume : "+DoubleToString(pos_volume,2)+"\n"+ "Commission : "+DoubleToString(pos_commission,2)+"\n"+ "Swap : "+DoubleToString(pos_swap,2)+"\n"+ "Profit : "+DoubleToString(pos_profit,2)+"\n"+ "Time : "+TimeToString(pos_time)+"\n"+ "Identifier : "+IntegerToString(pos_id)+"", //--- "Message Box",MB_ICONASTERISK); //--- return; } // If there is no position or an error has occurred, report it else { err=GetLastError(); // Get the code of the last registered error //--- if(err>0) // If there is an error { // Print the relevant message MessageBox("Error ("+IntegerToString(err)+") when selecting a position ("+_Symbol+") !\n\n"+ "It is possible that there is no position on this symbol. If this is not the case, please try again.", "Error", MB_ICONWARNING); //--- return; // Exit the function } } //---
No código acima, podemos observar mais duas funções definidas pelo usuário - GetPositionProperties() e PositionTypeToString(). Porque teremos que obter propriedades de posição em diversos pontos ao longo do programa, será bom criar uma função separada para reduzir a quantidade de códigos e facilitar a leitura. O código dessa função segue abaixo. Certifique-se de verificar a Referência MQL5 para obter informações adicionais sobre as funções e identificadores MQL5 utilizados em GetPositionProperties().
//+------------------------------------------------------------------+ //| GETTING SYMBOL PROPERTIES | //+------------------------------------------------------------------+ void GetPositionProperties() { pos_symbol =PositionGetString(POSITION_SYMBOL); pos_comment =PositionGetString(POSITION_COMMENT); pos_magic =PositionGetInteger(POSITION_MAGIC); pos_price =PositionGetDouble(POSITION_PRICE_OPEN); pos_cprice =PositionGetDouble(POSITION_PRICE_CURRENT); pos_sl =PositionGetDouble(POSITION_SL); pos_tp =PositionGetDouble(POSITION_TP); pos_type =(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); pos_volume =PositionGetDouble(POSITION_VOLUME); pos_commission =PositionGetDouble(POSITION_COMMISSION); pos_swap =PositionGetDouble(POSITION_SWAP); pos_profit =PositionGetDouble(POSITION_PROFIT); pos_time =(datetime)PositionGetInteger(POSITION_TIME); pos_id =PositionGetInteger(POSITION_IDENTIFIER); }
A função PositionTypeToString() definida pelo usuário converte o tipo de posição retornado como um inteiro para uma string para formato de leitura, conforme exibido no código abaixo:
//+------------------------------------------------------------------+ //| CONVERTING POSITION TYPE TO A STRING | //+------------------------------------------------------------------+ string PositionTypeToString(int position_type) { string str=""; //--- if(position_type==0) { str="buy"; } if(position_type==1) { str="sell"; } //--- return(str); }
Assim, o código da primeira posição através do qual podemos visualizar as propriedades de posição apenas para o símbolo atual está pronto. Se você seguiu todos os passos descritos no artigo, ele pode ser inclusive testado agora mesmo. Abra uma posição no MetaTrader 5 utilizando as ferramentas padrão. Para isso, aperte F9 e a janela de Ordem abrirá e nela você poderá encontrar todas as opções necessárias para configurar as propriedades da posição antes de abrí-la:
Figura 1. A janela de Ordem no terminal do cliente MetaTrader 5
Quando todas as propriedades forem configuradas, selecione Vender ou Comprar e execute o script com um clique duplo ou arrastando ele sobre o gráfico. Uma janela do script aparecerá. O valor requerido (Símbolo atual) do parâmetro Modo já foi configurado de forma automática. Um clique sobre o botão OK abrirá uma caixa de diálogo exibindo todas as propriedades de posição para o símbolo atual:
Figura 2. Caixa de diálogo com as propriedades de posição para o símbolo atual
Do contrário, se não houver posição no símbolo atual, aparecerá uma caixa de alerta:
Figura 3. Caixa de alerta
Tudo parece estar funcionando como planejado e implementado no código.
Agora vamos analisar o código de programa que será usado se você escolher visualizar todas as propriedades de posição aberta. O código com comentários detalhados é exibido abaixo:
//--- int digits=0; // Number of decimal places int mb_res=-1; // Variable with the option selected in the dialog box int pos_total=PositionsTotal(); // Number of open positions in the terminal //--- // View properties of all positions in a loop one by one for(int i=0; i<pos_total; i++) { ResetLastError(); // Reset the last error //--- pos_symbol=PositionGetSymbol(i); // Get the symbol name digits=(int)SymbolInfoInteger(pos_symbol,SYMBOL_DIGITS); // Get the number of digits in the price //--- // If a position on this symbol exists, then... if(PositionSelect(pos_symbol)) { // ...get its properties GetPositionProperties(); //--- // Open a dialog box to display all position properties obtained mb_res=MessageBox("Total Positions/Current: "+IntegerToString(pos_total)+"/"+IntegerToString(i+1)+"\n"+ "---------------------------------\n"+ "Symbol: " +pos_symbol+"\n"+ "Comment: " +pos_comment+"\n"+ "Magic Number: " +IntegerToString(pos_magic)+"\n"+ "Price Open: " +DoubleToString(pos_price,digits)+"\n"+ "Current Price: " +DoubleToString(pos_cprice,digits)+"\n"+ "Stop Loss: " +DoubleToString(pos_sl,digits)+"\n"+ "Take Profit: " +DoubleToString(pos_tp,digits)+"\n"+ "Type: " +PositionTypeToString(pos_type)+"\n"+ "Volume: " +DoubleToString(pos_volume,2)+"\n"+ "Commission: " +DoubleToString(pos_commission,2)+"\n"+ "Swap: " +DoubleToString(pos_swap,2)+"\n"+ "Profit: " +DoubleToString(pos_profit,2)+"\n"+ "Time: " +TimeToString(pos_time)+"\n"+ "Identifier: " +IntegerToString(pos_id)+"", //--- "Message Box",MB_CANCELTRYCONTINUE|MB_ICONASTERISK); //--- if(mb_res==IDCANCEL) // If you have clicked Cancel or Close { Print("The program ("+SCRIPT_NAME+") has been terminated by the user!"); return; } // Exit the function //--- // If you have clicked Retry if(mb_res==IDTRYAGAIN) { i--; } // Reset the counter to retry } else // If there is no position or an error has occurred, report it { err=GetLastError(); // Get the code of the last registered error //--- if(err>0) // If there is an error { // Print the relevant message MessageBox("Error ("+IntegerToString(err)+") when selecting a position ("+pos_symbol+") !\n\n"+ "It is possible that there is no position on this symbol. If this is not the case, please try again.", "Error", MB_ICONWARNING); } } } //---
Agora apenas precisamos testar essa opção. Vamos, por exemplo, abrir posições em dois símbolos (AUDUSD e EURUSD). Uma vez que executarmos o script, selecione o modo Todos os símbolos na lista suspensa nos parâmetros externos e clique em OK. Uma caixa de diálogo aparecerá, conforme exibido abaixo:
Figura 4. Caixa de diálogo com as propriedades de posição para a segunda opção
Conclusão
Como você pode ver na figura acima, há três botões na caixa de diálogo. Se você clicar em Tentar novamente, o contador cíclico será reiniciado e as propriedades de posição para o símbolo exibido atualmente na caixa de diálogo serão atualizadas. Se você clicar em Continuar, o programa passará ao próximo símbolo. O botão Cancelar serve para encerrar o programa.
Deve-se destacar também que a primeira linha acima da lista de propriedades de posição contém informações sobre o número total de posições abertas (Total de Posições) e número atual do contador de posições (Atual).
Isso é praticamente tudo. Sinta-se livre para fazer o download do arquivo do código-fonte anexo abaixo, o qual precisará ser compilado no MetaEditor.
Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/639
- 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