Ao programar um Expert Advisor no MQL5, a primeira dor de cabeça costuma ser descobrir exatamente onde um símbolo está negociando e qual o valor numérico que o servidor devolve para cálculos de risco. SymbolInfoDouble() aparece como a solução “única” para esses casos, mas, na prática, sua sintaxe rígida e a variedade de propriedades que aceita podem gerar retornos inesperados, especialmente quando o trader mistura pares de moedas com CFDs de índices.
O que a função realmente faz
Ela consulta o terminal e devolve o valor de uma propriedade do símbolo indicado, sempre como double. Se a propriedade não existir ou o símbolo estiver offline, o retorno será 0.0 e o código de erro será definido por GetLastError().
Sintaxe e parâmetros
bool SymbolInfoDouble(const string symbol, ENUM_SYMBOL_INFO_DOUBLE prop_id, double &value);- symbol: nome do ativo (ex.: “EURUSD”).
- prop_id: constante da enumeração
ENUM_SYMBOL_INFO_DOUBLE(ex.:SYMBOL_BID,SYMBOL_TRADE_TICK_SIZE). - value: variável que receberá o resultado.
Tabela resumida das propriedades mais usadas
| Prop_ID | Descrição |
|---|---|
| SYMBOL_BID | Preço de compra atual. |
| SYMBOL_ASK | Preço de venda atual. |
| SYMBOL_TRADE_TICK_VALUE | Valor monetário de um tick. |
| SYMBOL_TRADE_CONTRACT_SIZE | Tamanho do contrato (lot size padrão). |
| SYMBOL_VOLUME_MIN | Volume mínimo permitido. |
Valor retornado e tratamento de erro
O retorno booleano indica sucesso (true) ou falha (false). Quando falha, GetLastError() pode devolver códigos como ERR_INVALID_PARAMETER (prop_id inexistente) ou ERR_SYMBOL_NOT_FOUND (símbolo desconhecido). Ignorar esses códigos gera cálculos de lotes com zero, o que costuma “estourar” a lógica de gerenciamento de risco.
Casos de uso práticos
- Calcular o valor do stop‑loss em pontos:
SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE, tickVal); stopLoss = points * tickVal; - Adaptar o tamanho do lote ao volume mínimo: usar
SYMBOL_VOLUME_MINpara garantir que a ordem não seja rejeitada. - Construir um filtro de liquidez: comparar
SYMBOL_VOLUME_REALcom um limiar antes de abrir posições.
Limitações e armadilhas
1. Cache interno – a função lê o último snapshot do terminal; se o preço mudar entre duas chamadas, o valor pode ficar desatualizado.
2. Propriedades exclusivas de CFDs – alguns IDs retornam 0 para Forex, mas valores válidos para índices, confundindo quem copia código sem validar o tipo de ativo.
3. Ambientes de teste – no Strategy Tester, algumas propriedades (ex.: SYMBOL_TRADE_TICK_VALUE) são fixas, o que pode mascarar bugs que só aparecem em tempo real.
Funções relacionadas que complementam
SymbolInfoInteger()– para valores inteiros comoSYMBOL_DIGITS.SymbolInfoString()– para descrições e nomes de exchange.CopyTicks()– quando precisar de precisão de tick ao invés de snapshots.
Em resumo, SymbolInfoDouble() é indispensável, mas só entrega valor quando o programador verifica o contexto (tipo de ativo, estado de conexão) e trata os erros imediatamente. O próximo passo é criar um wrapper que encapsule a chamada, valide GetLastError() e retorne um double? seguro para toda a base de código.
1. Primeiro passo: obter o identificador do símbolo
- Chame
Symbol()dentro do OnInit() para capturar o nome do ativo que o Expert Advisor (EA) vai analisar. - Armazene em uma
stringglobal, por exemplostring g_symbol; - Exemplo de código:
| Código |
|---|
void OnInit() { g_symbol=Symbol(); // “EURUSD” por padrão } |
2. Configuração da chamada SymbolInfoDouble()
- Assinatura:
double SymbolInfoDouble(string name, ENUM_SYMBOL_INFO_DOUBLE prop_id); - Parâmetros:
name– nome do ativo (ex.: “EURUSD”).prop_id– constante da enumeraçãoENUM_SYMBOL_INFO_DOUBLEque indica a propriedade desejada (ex.:SYMBOL_BID,SYMBOL_TRADE_TICK_VALUE).
- Valor retornado:
doublecontendo o valor solicitado ou0.0em caso de falha (verifiqueGetLastError()).
3. Checklist operacional – propriedades essenciais
| Propriedade | Constante | Uso típico |
|---|---|---|
| Preço de compra (Bid) | SYMBOL_BID | Calcular stop‑loss imediato |
| Preço de venda (Ask) | SYMBOL_ASK | Definir ponto de entrada |
| Valor do tick | SYMBOL_TRADE_TICK_VALUE | Dimensionar tamanho de lote |
| Size do lote mínimo | SYMBOL_VOLUME_MIN | Validar ordem antes de enviar |
| Spread em pontos | SYMBOL_SPREAD | Filtrar ativos com alta volatilidade |
4. Rotina recomendada – atualização a cada tick
void OnTick() { double bid=SymbolInfoDouble(g_symbol,SYMBOL_BID); double ask=SymbolInfoDouble(g_symbol,SYMBOL_ASK); double tickValue=SymbolInfoDouble(g_symbol,SYMBOL_TRADE_TICK_VALUE); // Exemplo de cálculo de risco: 0.01% do saldo por ponto double riskPerPoint=AccountInfoDouble(ACCOUNT_BALANCE)*0.0001/tickValue; // Decisão simples: compra se o spread < 2 pontos if(SymbolInfoDouble(g_symbol,SYMBOL_SPREAD) < 2.0) OrderSend(g_symbol,OP_BUY,0.1,bid,5,0,0,"AutoBuy",0,0,clrGreen); } 5. Fluxograma de decisão (texto)
- Início → OnTick
- Leitura de
SYMBOL_BIDeSYMBOL_SPREAD - Spread ≤ 2? Sim → Verificar margem → Enviar ordem
- Spread > 2? Não → Ignorar tick
- Fim
6. Erros comuns e como evitá‑los
- Valor zero sem diagnóstico – sempre checar
GetLastError()logo após a chamada. - Usar símbolo errado – prefira a variável
g_symbolao invés de strings literais espalhadas. - Ignorar lote mínimo – antes de
OrderSend, compare o volume desejado comSYMBOL_VOLUME_MIN.
7. Aceleração de resultados – integração com funções relacionadas
SymbolInfoInteger()– obtenha parâmetros inteiros comoSYMBOL_TRADE_MODEpara validar se o ativo aceita operações de compra/venda.SymbolInfoString()– recupere descrições ou nomes de corretoras quando for necessário log detalhado.CopyRates()– combine preços deBid/Askcom histórico para gerar sinais mais robustos.
⚠️ Dica prática: encapsule a chamada em uma função utilitária que retorne
NaNem caso de erro. Assim, seu código principal permanece limpo e fácil de debugar.
Implementando esses blocos, você transforma SymbolInfoDouble() de um simples getter em um motor de decisão que opera a cada tick, reduzindo latência e evitando falhas de validação.
Quem realmente tira proveito do SymbolInfoDouble()
Se você programa indicadores ou EAs no MQL5 e precisa de dados precisos de símbolos que não estão no gráfico ativo, essa função pode mudar seu jogo. Não é magia, é acesso direto ao repositório de propriedades do MetaTrader.
Perfil ideal
- Desenvolvedores de robôs que operam multi‑mercado (forex, CFDs, commodities).
- Analistas quantitativos que constroem back‑tests cruzados entre pares.
- Trader‑programadores que desejam comparar spreads, margem ou requisitos de alavancagem sem mudar de símbolo.
Quem deve evitar
- Iniciantes que ainda não dominam a lógica de tipos de retorno em MQL5.
- Usuários que só consultam o símbolo atual; a sobrecarga de chamada externa é desnecessária.
- Quem depende de valores em tempo real de alta frequência – a função lê o último tick armazenado, não garante low‑latency.
Limitações práticas
SymbolInfoDouble() devolve double ou EMPTY_VALUE caso a propriedade não exista ou esteja indisponível. Não há tratamento interno de exceções; cabe ao programador validar o retorno antes de usar o valor em cálculos críticos.
Algumas propriedades são “dinâmicas” (por exemplo, SYMBOL_BID) e podem mudar entre duas chamadas sequenciais, gerando inconsistência se usadas em loops sem sincronização.
FAQ contextual
| Pergunta | Resposta |
|---|---|
| Posso usar dentro de OnTick? | Sim, mas evite chamadas excessivas; prefira cachear resultados por símbolo. |
| O que acontece com símbolos desativados? | Retorna EMPTY_VALUE; trate com if(value==EMPTY_VALUE). |
| Funciona em back‑test? | Sim, porém o histórico pode não conter todas as propriedades (ex.: margem mínima). |
Checklist rápido antes de implementar
- Verificar suporte ao símbolo (Mode:
SYMBOL_TRADE_MODE). - Confirmar que a propriedade requerida está listada na documentação oficial.
- Implementar fallback para
EMPTY_VALUE. - Limitar chamadas a < 10 > por segundo para evitar sobrecarga.
Parecer editorial equilibrado
Na prática, SymbolInfoDouble() é um “must‑have” para quem desenvolve estratégias que cruzam dados de múltiplos ativos. Seu ponto fraco está na ausência de tratamento de erro interno e na latência mínima de acesso ao valor. Para quem busca otimização extrema, a função ainda pode ser um gargalo, mas para a maioria dos projetos de médio porte ela entrega exatamente o que promete: acesso simples e direto a propriedades numéricas de qualquer símbolo.
Mini cenários reais
1. Estratégia de carry trade que calcula a diferença de juros entre EURUSD e USDJPY. SymbolInfoDouble("EURUSD", SYMBOL_SWAP_LONG) + SymbolInfoDouble("USDJPY", SYMBOL_SWAP_LONG) gera o spread de swap.
2. Robô de arbitragem que verifica o spread instantâneo de duas corretoras usando SYMBOL_BID e SYMBOL_ASK de cada símbolo antes de abrir posições.
Próximos passos
Teste a função em modo demo, registre os valores retornados, e implemente a verificação de EMPTY_VALUE. Só depois de validar a consistência será seguro migrar para produção.

