![Funções para gerenciamento de dinheiro em um conselheiro especialista](https://c.mql5.com/i/articles/overlay.png)
Funções para gerenciamento de dinheiro em um conselheiro especialista
Introdução
A linguagem MQL5 fornece uma oportunidade para obter grandes quantidades de informação sobre as atuais condições dos terminais, do mql5-program, assim como do instrumento financeiro e da conta de negociação. De forma a organizar as funções do gerenciamento do capital, precisaremos estudar as propriedades das últimas duas seções listadas, assim como nos familiarizar com as seguintes funções:
- SymbolInfoInteger()
- SymbolInfoDouble()
- SymbolInfoString()
- AccountInfoInteger()
- AccountInfoDouble()
- AccountInfoString()
Obtendo informações sobre o balanço da sua conta
As primeiras duas características importantes de uma conta de negociação - balanço e igualdade. Para obter esses valores, utilize a função AccountInfoDouble():
double balance=AccountInfoDouble(ACCOUNT_BALANCE); double equity=AccountInfoDouble(ACCOUNT_EQUITY);
A próxima coisa que nos interessa é o tamanho dos fundos de depósito para posições abertas, e o lucro flutuante total ou prejuízo na conta, para todas as posições abertas.
double margin=AccountInfoDouble(ACCOUNT_MARGIN); double float_profit=AccountInfoDouble(ACCOUNT_PROFIT);
De forma a ser capaz de abrir novas posições e reforçar as existentes, precisamos de recursos livres, não participando no depósito.
double free_margin=AccountInfoDouble(ACCOUNT_FREEMARGIN);
Aqui deve ser observado, que os valores acima são expressos em termos monetários.
Valores monetários, devolvidos pela função AccountInfoDouble(), são expressos em moeda corrente de depósito. Para descobrir a moeda corrente de depósito, utilize a função AccountInfoString().
string account_currency=AccountInfoString(ACCOUNT_CURRENCY);
O nível dos fundos pessoais
A conta possui outra característica importante - o nível que o evento de interrupção ocorre (um fechamento obrigatório de uma posição devido a falta de fundos pessoais necessários para manter as posições aberas). Para obter esse valor, utilize novamente a função AccountInfoDouble():
double stopout_level=AccountInfoDouble(ACCOUNT_MARGIN_SO_SO);
A função apena retorna o valor em si, mas não explica o tipo de unidades no qual o valor é expresso. Há dois modos de especificação de nível para interrupção: em porcentagens e em moeda corrente. De forma a descobrir isso, utilize a função AccountInfoInteger():
//--- Get account currency string account_currency=AccountInfoString(ACCOUNT_CURRENCY); //--- Stop Out level double stopout_level=AccountInfoDouble(ACCOUNT_MARGIN_SO_SO); //--- Stop Out mode ENUM_ACCOUNT_STOPOUT_MODE so_mode=(ENUM_ACCOUNT_STOPOUT_MODE)AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE); if(so_mode==ACCOUNT_STOPOUT_MODE_PERCENT) PrintFormat("Stop Out level in percents %.2f%%",stopout_level); else PrintFormat("Stop Out level in currency %.2f %s",stopout_level,account_currency);
Informações adicionais sobre a conta
Frequentemente em cálculos é necessário saber o tamanho do fornecido na alavancagem da conta de negociação. Você pode obter essa informação utilizando a função AccountInfoInteger():
int leverage=(int)AccountInfoInteger(ACCOUNT_LEVERAGE);De forma a evitar executar acidentalmente o Expert Advisor não regulado em uma conta real, você precisa saber o tipo de conta.
ENUM_ACCOUNT_TRADE_MODE mode=(ENUM_ACCOUNT_TRADE_MODE)AccountInfoInteger(ACCOUNT_TRADE_MODE); switch(mode) { case ACCOUNT_TRADE_MODE_DEMO: Comment("Account demo"); break; case ACCOUNT_TRADE_MODE_CONTEST: Comment(com,"Account Contest"); break; case ACCOUNT_TRADE_MODE_REAL: Comment(com,"Account Real"); break; default: Comment(com,"Account unknown type"); }Negociar não é possível em todas as contas, por exemplo, em contas competitivas, operações de negociação somente podem ser feitas após o início da competição. Essa informação pode também ser obtida pela função AccountInfoInteger():
bool trade_allowed=(bool)AccountInfoInteger(ACCOUNT_TRADE_ALLOWED); if(trade_allowed) Print("Trade is allowed"); else Print(com,"Trade is not allowed");
Mesmo se a negociação nessa conta for permitida, não significa que o Expert Advisor possui o direito de negociar. Para verificar se o Expert Advisor pode negociar, escreva:
if(trade_allowed) { bool trade_expert=(bool)AccountInfoInteger(ACCOUNT_TRADE_EXPERT); if(trade_expert) Print("Experts are allowed to trade"); else Print("Experts are not allowed to trade");
Esses exemplos podem ser encontrados no conselheiro especialista anexado Account_Info.mq5. Eles podem ser utilizados nos programas MQL5 de qualquer complexidade.
Informação sobre o instrumento
Cada instrumento financeiro possui suas próprias descrições e é posicionado em um caminho, que esse instrumento caracteriza. Se abrirmos a janela de propriedades do EURUSD no terminal, veremos algo como isso:
Nesse caso, a descrição para EURUSD é - "EURUSD, Euro vs US Dollar". Para obter essa informação, utilizamos a função SymbolInfoString():
string symbol=SymbolInfoString(_Symbol,SYMBOL_DESCRIPTION); Print("Symbol: "+symbol); string symbol_path=SymbolInfoString(_Symbol,SYMBOL_PATH); Print("Path: "+symbol_path);
Para descobrir o tamanho de um contrato padrão, utilize a SymbolInfoDouble():
double lot_size=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_CONTRACT_SIZE); Print("Standard contract: "+DoubleToString(lot_size,2));
É uma característica dos instrumentos do FOREX de vender uma moeda corrente enquanto comprando outra. O contrato é indicado na moeda corrente, que é necessário para realizar a compra. Isso é uma moeda corrente base, e pode ser obtida utilizando a função SymbolInfoString():
string base_currency=SymbolInfoString(_Symbol,SYMBOL_CURRENCY_BASE); Print("Base currency: "+base_currency);
Mudanças no preço do instrumento levam a uma mudança no preço dos recursos comprados e, portanto, a uma variação do lucro para uma posição aberta (o lucro pode ser negativo se a posição está perdendo). Assim, a mudança de preço leva a mudanças na renda, expressa em uma moeda corrente particular. Essa moeda corrente é chamada de moeda de cotação. Para um par de moedas correntes EURUSD a moeda corrente base é normalmente o Euro, e a moeda de cotação é o dólar americano. Para obter a moeda de cotação você também pode utilizar a função SymbolInfoString():
string profit_currency=SymbolInfoString(_Symbol,SYMBOL_CURRENCY_PROFIT); Print("Currency quotes: "+profit_currency);
Para abrir uma posição no instrumento você precisa de fundos, e esses fundos são também expressos em uma moeda corrente particular. Essa moeda corrente é chamada de margem ou depósito da moeda corrente. Para os instrumentos FOREX as moedas correntes de margem e base são normalmente as mesmas. Para obter o valor da moeda corrente de depósito, utilize a função SymbolInfoString():
string margin_currency=SymbolInfoString(_Symbol,SYMBOL_CURRENCY_MARGIN); Print("Currency deposit: "+margin_currency);
Todas as funções descritas são fornecidas no código do conselheiro especialista Symbol_Info.mq5. A figura abaixo demonstra o resultado da informação no símbolo EURUSD, utilizando a função Comment().
Calculando o tamanho do depósito
A informação sobre instrumentos financeiros, mais necessitada por negociantes, é o tamanho dos fundos, exigida para abrir uma posição nela. Sem saber quanto dinheiro é necessário para comprar ou vender um número específico de lotes, nós não podemos implementar o sistema do Expert Advisor para gerenciamento do capital. Além disso, controlar o balanço da conta também se torna difícil.
Se você possui dificuldades em entender a discussão a seguir, recomendo que você leia o artigo ABC da negociação no Forex. As explicações descritas neles são também aplicáveis a esse artigo.
Nós precisamos calcular o tamanho da margem no depósito da moeda corrente, isto é, calcular novamente o depósito a partir da moeda corrente de financiamento para a moeda corrente de depósito, dividindo o valor obtido pela quantidade de alavancagem da conta fornecida. Para fazer isso nós reescrevemos a função GetMarginForOpening()://+------------------------------------------------------------------+ //| Return amount of equity needed to open position | //+------------------------------------------------------------------+ double GetMarginForOpening(double lot,string symbol,ENUM_POSITION_TYPE direction) { double answer=0; //--- ... //--- Return result - amount of equity in account currency, required to open position in specified volume return(answer); }
onde:
- Lote - o volume da posição aberta;
- Símbolo - o nome do instrumento financeiro;
- A alegada direção de posição.
- Moeda corrente de depósito;
- Moeda corrente de financiamento;
- Cotações da moeda corrente (pode ser necessário para os pares de moedas correntes cruzadas);
- Tamanho do contrato.
Escreva isso na linguagem MQL5:
//--- Get contract size double lot_size=SymbolInfoDouble(symbol,SYMBOL_TRADE_CONTRACT_SIZE); //--- Get account currency string account_currency=AccountInfoString(ACCOUNT_CURRENCY); //--- Margin currency string margin_currency=SymbolInfoString(_Symbol,SYMBOL_CURRENCY_MARGIN); //--- Profit currency string profit_currency=SymbolInfoString(_Symbol,SYMBOL_CURRENCY_PROFIT); //--- Calculation currency string calc_currency=""; //--- Reverse quote - true, Direct quote - false bool mode;
O modo variável afeta como nós calcularemos o tamanho do contrato na moeda corrente de depósito. Considere isso baseado em exemplos, em todas as classes adicionais vamos presumir que a moeda corrente é o dólar americano.
Os pares de moeda corrente são normalmente divididos em três categorias:
- Pares de moeda corrente diretos - a taxa de câmbio do dólar americano para uma moeda corrente em particular. Exemplos: USDCHF, USDCAD, USDJPY, USDSEK;
- Par de moeda corrente invertido - a taxa de câmbio de uma moeda corrente em particular para o dólar americano. Exemplos: EURUSD, GBPUSD, AUDUSD, NZDUSD;
- Pares de moeda corrente cruzados - um par atual, que não envolve o dólar americano. Exemplos: AUDCAD, EURJPY, EURCAD.
1. EURUSD - o par de moeda corrente inverso
Nós chamaremos os pares de moeda corrente, nos quais a moeda corrente de cotação é a moeda corrente da conta, pares de moeda corrente inversos. Em nossos exemplos, a moeda corrente da conta é representada pelo dólar americano, então a nossa classificação de pares de moeda corrente coincidirá com a classificação aceita geralmente. Mas se a sua conta de negociação utiliza uma moeda corrente diferente (que não o dólar americano), ela não coincidirá. Nesse caso, leve em consideração a moeda corrente da conta, de forma a entender quaisquer explicações a seguir.
O tamanho do contrato para EURUSD - 100 000 euros. Nós precisamos expressar 100 000 euros na moeda corrente do depósito - dólares americanos. Para fazer isso você precisa saber a taxa de câmbio, segundo a qual o euro pode ser contado em dólares. Nós introduzimos o conceito de moeda corrente de computação, isto é, a moeda corrente necessária para converter a moeda corrente de financiamento para a moeda corrente de depósito.
//--- Calculation currency string calc_currency="";
Felizmente, o par de moeda corrente EURUSD exibe a taxa de câmbio do euro contra o dólar, e portanto, nesse caso, o símbolo de EURUSD, para o qual você precisa calcular o tamanho do financiamento, é precisamente a taxa de câmbio:
//--- If profit currency and account currency are equal if(profit_currency==account_currency) { calc_currency=symbol; mode=true; }
Estabelecemos o valor do modo comoverdadeiro, o que significa que para converter Euros para dólares (moeda corrente financiada é convertível na moeda corrente de depósito), nós multiplicaremos a taxa de câmbio atual do EURUSD pelo tamanho do contrato. Se o modo = falso, então nós dividimos o tamanho do contrato pela taxa de câmbio da moeda corrente computacional. Para obter os preços atuais do instrumento, utilize a função SymbolInfoTick().
//--- We know calculation currency, let's get its last prices MqlTick tick; SymbolInfoTick(calc_currency,tick);
Essa função coloca o preço atual e tempo da última atualização de preços em uma variável do tipo MqlTick - essa estrutura foi especialmente projetada para esse propósito.
Portanto, é suficiente obter o preço mais atual nesse símbolo, multiplicá-lo pelo tamanho do contrato e então pelo número de lotes. Mas qual preço de cálculo devemos tomar, considerando que há um preço de compra e um preço de venda para esse instrumento? Então logicamente: se nós estamos comprando, o preço para cálculos é igual ao preço venda, e se nós estamos vendendo, precisaremos tomar o preço de compra.
//--- Now we have everything for calculation double calc_price; //--- Calculate for Buy if(direction==POSITION_TYPE_BUY) { //--- Reverse quote if(mode) { //--- Calculate using Buy price for reverse quote calc_price=tick.ask; answer=lot*lot_size*calc_price; } } //--- calculate for Sell if(direction==POSITION_TYPE_SELL) { //--- Reverse quote if(mode) { //--- Calculate using Sell price for reverse quote calc_price=tick.bid; answer=lot*lot_size*calc_price; } }
Assim, em nosso exemplo, para o símbolo EURUSD a moeda corrente de depósito é o Euro, o tamanho do contrato é 100 000, e o último preço de venda = 1.2500. Moeda corrente da conta - dólar americano, e a moeda corrente de cálculo é o mesmo par de moeda corrente EURUSD. Multiplique 100 000 por 1.2500 e obtenha 125 000 dólares americanos - isso é exatamente quanto um contrato padrão para comprar 1 lote de EURUSD custa, se o preço de venda =1.2500.
Podemos concluir que se a moeda corrente de cotação é igual a moeda corrente da conta, então, para obter o valor de um lote da moeda corrente da conta, simplesmente multiplicamos o tamanho do contrato pelo preço apropriado, compra ou venda, dependendo da direção desejada da posição.
margin=lots*lot_size*rate/leverage;
2. USDCHF - par de moeda corrente direto
A moeda corrente de financiamento e a moeda corrente da conta para a combinação USDCHF - o dólar americano. Os pares de moeda corrente, nos quais a moeda corrente de financiamento e a moeda corrente da conta são os mesmos, chamaremos pares de moeda corrente diretos. Tamanho do contrato - 100 000. Essa é a situação mais simples, simplesmente devolva o produto.
//--- if the base currency symbol and the deposit currency are the same if(margin_currency==account_currency) { calc_currency=symbol; //--- Just return the contract value, multiplied by the number of lots return(lot*lot_size); }
Se a moeda corrente de depósito coincide com a moeda corrente da conta, então o valor do depósito na moeda corrente da conta é igual ao produto do contrato padrão multiplicado pelo número de lotes (contratos) dividido pelo tamanho da alavancagem.
margin=lots*lot_size/leverage;
3. CADCHF - par de moeda corrente cruzado
O par de moeda corrente CADCHF é tomado para fins ilustrativos, e qualquer outro par, no qual a moeda corrente de depósito e a moeda corrente de cotação coincidem com a moeda corrente da conta, pode ser utilizado. Esses pares de moeda corrente são chamados cruzados, porque de forma a calcular a margem e o lucro deles, precisamos saber a taxa de câmbio de algum outro par de moeda corrente, que intercepta com aquele em uma das moedas correntes.
Normalmente, pares de moeda corrente cruzados são os pares que as cotações não usam o dólar americano. Mas chamaremos todos os pares, que não incluem a moeda corrente da conta em suas cotações, pares de moeda corrente. Assim, se a moeda corrente é em Euro, então o par GBPUSD será um par de moedas correntes cruzados, uma vez que a moeda corrente de depósito está em libras esterlinas, e as cotações das moedas correntes estão em dólares americanos. Nesse caso, para calcular a margem, precisaremos expressar a libra esterlina (GBP) em Euro (EUR).
Mas continuaremos a considerar um exemplo no qual o símbolo é o par de moeda corrente CADCHF. A moeda corrente está em dólares canadenses (CAD) e não coincide com o dólar americano (USD). A moeda corrente de cotação está em francos suíços e também não coincide com o dólar americano.
Apenas podemos dizer que o depósito para abrir uma posição em 1 lote é igual a 100,000 dólares canadenses. A nossa tarefa é recalcular o depósito na moeda corrente da conta, em dólares americanos. Para fazer isso precisamos encontrar o par de moedas correntes, a taxa de câmbio que contém o dólar americano e a moeda corrente de depósito - CAD. Há um total de duas opções em potencial:
- CADUSD
- USDCAD
Nós temos o valor de saída para o CADCHF:
margin_currency=CAD (Canadian dollar) profit_currency=CHF (Swiss frank)
Não sabemos antecipadamente qual dos pares de moedas correntes existem no terminal, e em termos de linguagem do MQL5, nenhuma opção é preferencial. Portanto, nós escrevemos a função GetSymbolByCurrencies(), que para o dado conjunto de moedas correntes irá nos fornecer o primeiro par de moedas correntes correspondente para os cálculos.
//+------------------------------------------------------------------+ //| Return symbol with specified margin currency and profit currency | //+------------------------------------------------------------------+ string GetSymbolByCurrencies(string margin_currency,string profit_currency) { //--- In loop process all symbols, that are shown in Market Watch window for(int s=0;s<SymbolsTotal(true);s++) { //--- Get symbol name by number in Market Watch window string symbolname=SymbolName(s,true); //--- Get margin currency string m_cur=SymbolInfoString(symbolname,SYMBOL_CURRENCY_MARGIN); //--- Get profit currency (profit on price change) string p_cur=SymbolInfoString(symbolname,SYMBOL_CURRENCY_PROFIT); //--- if If symbol matches both currencies, return symbol name if(m_cur==margin_currency && p_cur==profit_currency) return(symbolname); } return(NULL); }
Como pode ser visto no código, começamos a enumeração de todos os símbolos, disponíveis na janela de "visualização do mercado" (a função SymbolsTotal() com o parâmetro verdadeiro nos fornecerá essa quantidade). De forma a conseguir o nome de cada símbolo pelo número na lista do "visualizador do mercado", nós utilizamos a função SymbolName() com o parâmetro verdadeiro! Se configurarmos o parâmetro para "falso", então enumeraremos todos os símbolos apresentados no servidor de negociação, e isso é normalmente muito mais do que é selecionado no terminal.
Em seguida, nós utilizamos o nome do símbolo para obter o depósito da moeda corrente e as cotações, e para compará-las com as que foram passadas para a função GetSymbolByCurrencies(). Em caso de sucesso, retornamos o nome do símbolo, e o trabalho da função é completado com sucesso e antes do previsto. Se o ciclo é completado, e alcançamos a última linha da função, então nada se encaixou e o símbolo não foi encontrado - retorne NULL.
Agora podemos obter a moeda corrente de cálculo para o par de moedas correntes cruzados, utilizando a função GetSymbolByCurrencies(), faremos duas tentativas: na primeira tentativa procuraremos pelo símbolo, a moeda corrente de depósito da qual é margin_currency (moeda de depósito CADCHF - CAD), e a moeda corrente de cotação é a moeda corrente da conta (USD). Em outras palavras, nós estamos procurando por algo similar ao par de CADUSD.
//--- If calculation currency is still not determined //--- then we have cross currency if(calc_currency="") { calc_currency=GetSymbolByCurrencies(margin_currency,account_currency); mode=true; //--- If obtained value is equal to NULL, then this symbol is not found if(calc_currency==NULL) { //--- Lets try to do it reverse calc_currency=GetSymbolByCurrencies(account_currency,margin_currency); mode=false; } }
Se a tentativa falhar, tente encontrar outra opção: procure um símbolo, a moeda corrente de depósito da qual é account_currency (USD), e a moeda corrente de cotação é margin_currency (moeda corrente de depósito para CADCHF - CAD). Nós estamos procurando por algo similar a USDCAD.
Agora que encontramos o par de moedas correntes de cálculo, pode ser uma de duas opções - direta ou reversa. O modo variável presume o valor "verdadeiro" para o par de moedas correntes inverso. Se nós possuímos um par de moedas correntes direto, então o valor é igual a "falso". Para o valor "verdadeiro", nós multiplicamos ele pela taxa de cotação do par de moedas correntes, para o valor falso - nós dividimos ele pelo valor de depósito de um contrato padrão na moeda corrente da conta.
Aqui está o cálculo final do tamanho do depósito na moeda corrente da conta para a moeda corrente do cálculo encontrada. Se encaixa em ambas as opções - os pares de moedas correntes diretos e reversos.
//--- We know calculation currency, let's get its last prices MqlTick tick; SymbolInfoTick(calc_currency,tick); //--- Now we have everything for calculation double calc_price; //--- Calculate for Buy if(direction==POSITION_TYPE_BUY) { //--- Reverse quote if(mode) { //--- Calculate using Buy price for reverse quote calc_price=tick.ask; answer=lot*lot_size*calc_price; } //--- Direct quote else { //--- Calculate using Sell price for direct quote calc_price=tick.bid; answer=lot*lot_size/calc_price; } } //--- Calculate for Sell if(direction==POSITION_TYPE_SELL) { //--- Reverse quote if(mode) { //--- Calculate using Sell price for reverse quote calc_price=tick.bid; answer=lot*lot_size*calc_price; } //--- Direct quote else { //--- Calculate using Buy price for direct quote calc_price=tick.ask; answer=lot*lot_size/calc_price; } }
Retorne o resultado obtido:
//--- Return result - amount of equity in account currency, required to open position in specified volume return (Answer);
A função GetMarginForOpening() completa seu trabalho nesse momento. A última coisa que precisa ser feita é dividir o valor obtido pelo tamanho da alavancagem fornecida - e então nós obteremos o valor da margem para posições abertas com o volume especificado na direção presumida. Mantenha em mente que para os símbolos, representando o par de moedas correntes cruzado ou reverso, o valor da margem irá variar com cada variação.
Aqui está uma parte do código do conselheiro especialista SymbolInfo_Advanced.mq5. O código completo está anexado como arquivo.
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- String variable for comment string com="\r\n"; StringAdd(com,Symbol()); StringAdd(com,"\r\n"); //--- Size of standard contract double lot_size=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_CONTRACT_SIZE); //--- Margin currency string margin_currency=SymbolInfoString(_Symbol,SYMBOL_CURRENCY_MARGIN); StringAdd(com,StringFormat("Standard contract: %.2f %s",lot_size,margin_currency)); StringAdd(com,"\r\n"); //--- Leverage int leverage=(int)AccountInfoInteger(ACCOUNT_LEVERAGE); StringAdd(com,StringFormat("Leverage: 1/%d",leverage)); StringAdd(com,"\r\n"); //--- Calculate value of contract in account currency StringAdd(com,"Deposit for opening positions in 1 lot consists "); //--- Calculate margin using leverage double margin=GetMarginForOpening(1,Symbol(),POSITION_TYPE_BUY)/leverage; StringAdd(com,DoubleToString(margin,2)); StringAdd(com," "+AccountInfoString(ACCOUNT_CURRENCY)); Comment(com); }
E o resultado de seu trabalho no gráfico.
Conclusão
Fornecemos exemplos para demonstrar o quão fácil e simples é obter informação sobre as características mais importantes da conta de negociação e sobre as propriedades dos instrumentos financeiros.
Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/113
![Como escrever um indicador na base de um outro indicador](https://c.mql5.com/2/0/indicator_based_on_other_MQL5__1.png)
![Criar um quadro de informação utilizando classes de biblioteca padrão e o Google Chart API](https://c.mql5.com/2/0/info_panel_MQL5.png)
![20 sinais de negociação no MQL5](https://c.mql5.com/2/0/20_Trading_Signals_MQL5__1.png)
![Guia passo a passo para iniciantes para escrever um Expert Advisor no MQL5](https://c.mql5.com/2/0/create_EA_step_by_step_MQL5.png)
![MQL5 - Linguagem para estratégias de negociação inseridas no terminal do cliente MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- 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