Programar uma ordem de compra ou venda no MetaTrader parece simples na teoria, mas na prática o desenvolvedor esbarra em detalhes de sincronismo, validação de preço e tratamento de exceções que podem transformar um script em um ponto de falha silencioso. O objetivo aqui é mostrar, passo a passo, como usar OrderSend() de forma robusta, apontando armadilhas comuns e oferecendo um padrão de código que funciona em um ambiente de negociação real, onde latência e slippage são a regra, não a exceção.
Arquitetura mínima da chamada
- Defina o ticket, tipo (OP_BUY/OP_SELL) e volume antes de qualquer cálculo.
- Capture o preço de mercado imediatamente após
MarketInfo()ouSymbolInfoDouble()para evitar discrepâncias. - Monte o
MqlTradeRequestcom todos os campos obrigatórios –action, symbol, volume, type, price, sl, tp, deviation, magic, comment.
Fluxograma resumido
| Etapa | O que fazer |
|---|---|
| 1 | Verificar IsTradeAllowed() e horário de mercado. |
| 2 | Calcular preço de entrada e limites (SL/TP) com margem de segurança. |
| 3 | Preencher MqlTradeRequest e chamar OrderSend(). |
| 4 | Checar result.retcode – se != TRADE_RETCODE_DONE, registrar erro. |
| 5 | Persistir ticket em array ou arquivo para gerenciamento posterior. |
Estrutura do MqlTradeRequest
- action: sempre
TRADE_ACTION_DEALpara ordens à vista. - symbol: nome do ativo, ex.: “EURUSD”.
- volume: lote mínimo permitido, já validado contra
AccountFreeMargin(). - price: preço de mercado +
deviation(pips de tolerância). - sl / tp: calculados em pips, convertidos para preço usando
NormalizeDouble().
Exemplo prático – Compra
bool SendBuy(double lot){ MqlTradeRequest req; MqlTradeResult res; req.action = TRADE_ACTION_DEAL; req.symbol = _Symbol; req.volume = lot; req.type = ORDER_TYPE_BUY; req.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK); req.deviation= 10; req.sl = req.price - 30*_Point; req.tp = req.price + 60*_Point; req.magic = 123456; if(!OrderSend(req,res)){ Print("Erro OrderSend: ",GetLastError()); return false; } Print("Ordem enviada, ticket: ",res.order); return true; } Exemplo prático – Venda
bool SendSell(double lot){ MqlTradeRequest req; MqlTradeResult res; req.action = TRADE_ACTION_DEAL; req.symbol = _Symbol; req.volume = lot; req.type = ORDER_TYPE_SELL; req.price = SymbolInfoDouble(_Symbol, SYMBOL_BID); req.deviation= 10; req.sl = req.price + 30*_Point; req.tp = req.price - 60*_Point; req.magic = 123456; if(!OrderSend(req,res)){ Print("Erro OrderSend: ",GetLastError()); return false; } Print("Ordem enviada, ticket: ",res.order); return true; } Tratamento de erros crítico
Não confie apenas no retorno booleano. Sempre analise res.retcode – códigos como TRADE_RETCODE_REQUOTE ou TRADE_RETCODE_PRICE_CHANGED indicam que o preço evoluiu entre a captura e a submissão. Nestes casos, re‑executar a lógica com o novo preço costuma ser mais eficaz que abortar.
Otimização e limites reais
- Limite
deviationa 5‑10 pips; valores maiores mascaram problemas de latência. - Use
EventSetTimer()para evitar chamadas excessivas dentro de loops intensos. - Cacheie
SymbolInfoDouble()apenas quando o spread mudar significativamente.
Mesmo com tudo isso, OrderSend() pode falhar se a corretora impõe restrições de volume ou se o saldo cai abaixo da margem exigida. Nesses cenários, a única saída viável é abortar a estratégia ou reduzir o lote antes de tentar novamente. Para quem precisa de um ponto de partida pronto, confira a biblioteca de exemplos oficial – ela contém templates testados em contas demo.
Configuração inicial da função OrderSend()
Antes de chamar OrderSend() verifique três pré‑requisitos:
- Conta de negociação: habilite o modo trading no MetaTrader (Menu Tools → Options → Expert Advisors).
- Permissões de DLL: se usar bibliotecas externas, ative Allow DLL imports.
- Variáveis globais: defina
double Lots = 0.1;,int Slippage = 3;edouble StopLoss = 0;para evitar valores “na mão”.
Arquitetura da chamada – fluxo resumido
O processo pode ser visualizado como um mini‑pipeline de cinco etapas:
| Etapa | Objetivo | Resultado esperado |
|---|---|---|
| 1. Preparar MqlTradeRequest | Preencher campos obrigatórios | Estrutura pronta para envio |
| 2. Validar parâmetros | Checar lotes, preço, SL/TP | Abortar se fora de limites |
| 3. Executar OrderSend() | Chamar a API do servidor | Retorno de result.retcode |
| 4. Analisar result.retcode | Mapear códigos de erro | Log ou retry conforme caso |
| 5. Atualizar estado interno | Registrar ticket, preço médio | Estrutura de controle pronta |
Estrutura MqlTradeRequest – checklist operacional
Preencha os campos exatamente como indicado. Qualquer omissão gera ERR_TRADE_ERROR (10004).
⚠️ Dica: use
ZeroMemory(request);antes de atribuir valores. Garante que campos não usados fiquem nulos.
request.action = TRADE_ACTION_DEAL;request.symbol = _Symbol;request.volume = Lots;request.type = ORDER_TYPE_BUY // ou ORDER_TYPE_SELLrequest.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);request.deviation= Slippage;request.magic = 123456; // identificador EArequest.comment = "OrderSend() via EA";- Opcional:
request.stoplimit,request.sl,request.tp
Exemplo prático – compra (Buy)
O código abaixo demonstra a sequência mínima para abrir uma posição comprada.
void OpenBuy() { MqlTradeRequest request; MqlTradeResult result; ZeroMemory(request); request.action = TRADE_ACTION_DEAL; request.symbol = _Symbol; request.volume = Lots; request.type = ORDER_TYPE_BUY; request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK); request.deviation= Slippage; request.magic = 123456; request.comment = "Buy via OrderSend()"; if(!OrderSend(request,result)) { Print("Falha ao enviar ordem: ",GetLastError()); return; } Print("Ordem enviada. Ticket: ",result.order); } Exemplo prático – venda (Sell)
Idêntico ao Buy, altere apenas request.type e o preço de referência.
void OpenSell() { MqlTradeRequest request; MqlTradeResult result; ZeroMemory(request); request.action = TRADE_ACTION_DEAL; request.symbol = _Symbol; request.volume = Lots; request.type = ORDER_TYPE_SELL; request.price = SymbolInfoDouble(_Symbol, SYMBOL_BID); request.deviation= Slippage; request.magic = 123456; request.comment = "Sell via OrderSend()"; if(!OrderSend(request,result)) { Print("Erro ao vender: ",GetLastError()); return; } Print("Venda realizada. Ticket: ",result.order); } Tratamento de erros – mapa rápido
Use o campo result.retcode para decidir a ação corretiva.
- 10004 – ERR_TRADE_ERROR: parâmetros inválidos. Revise volume e price.
- 10007 – ERR_INVALID_PRICE: slippage insuficiente. Aumente
Slippageou ajuste preço. - 10009 – ERR_NOT_ENOUGH_MONEY: margem insuficiente. Reduza lotes ou libere margem.
- 10013 – ERR_TRADE_CONTEXT_BUSY: outra operação em andamento. Insira
Sleep(200);e re‑tente.
Otimização – rotina recomendada
Para evitar sobrecarga e melhorar a taxa de sucesso, siga o mini‑cronograma semanal:
| Dia | Atividade |
|---|---|
| Seg‑Qua | Back‑test com OrderSend() em dados históricos. Ajuste Slippage e LotSize. |
| Qui | Teste em conta demo. Verifique latência (< 50 ms) e comportamento de result.retcode. |
| Sex | Revisão de logs. Identifique padrões de falha e ajuste parâmetros. |
| Sáb‑Dom | Documentação interna: checklist preenchido, versão de código controlada. |
Com a checklist preenchida, a estrutura MqlTradeRequest sempre estará completa, os erros serão capturados rapidamente e a execução de OrderSend() ganhará consistência – ponto crucial para quem busca performance sustentável em EAs.
Quem realmente tira proveito do Como trabalhar com OrderSend()?
Se você já batalha com execuções tardias ou slippage inesperado no MetaTrader 5, este material pode virar seu ponto de apoio. Não é um manual para iniciantes que ainda confundem “buy” com “sell”; é um compêndio tático para programadores que já dominam MQL5 e buscam refinar a camada de envio de ordens.
Perfis compatíveis
- Desenvolvedores intermediários que já escrevem Expert Advisors e precisam consolidar a lógica de
MqlTradeRequestem um padrão reutilizável. - Traders algorítmicos que exigem controle fino sobre stop‑loss, take‑profit e gerenciamento de margem em tempo real.
- Consultores de corretoras que precisam auditar scripts de clientes e garantir conformidade com políticas de ordem.
Quem pode ficar a ver navios
- Quem ainda não entende a diferença entre “market order” e “pending order”.
- Quem procura um “plug‑and‑play” sem adaptar o código ao seu próprio gerenciamento de risco.
- Quem depende exclusivamente de indicadores “prontos” e não tem tempo para ajustar a rotina de erro.
Limitações práticas que o livro deixa claro
O texto não aborda latência de rede, nem otimizações de hardware; ele foca na lógica interna da API. Se a sua infraestrutura já está no limite de 50 ms, as dicas aqui não vão mudar isso. Além disso, o exemplo de ‘Sell’ usa apenas um nível de proteção contra erros – situações de “re‑quote” múltipla ainda exigem camada extra que o autor deixa como exercício.
FAQ contextual
| Pergunta | Resposta curta |
|---|---|
| Preciso de licença comercial do MetaTrader? | Não, a API é pública; porém, contas de demonstração podem não refletir restrições de corretoras reais. |
| O material cobre hedging? | Somente menciona a flag ALLOW_HEDGING sem aprofundar estratégias. |
| Posso usar em MQL4? | Não. A sintaxe MqlTradeRequest é exclusividade do MT5. |
Checklist final de compatibilidade
- ✅ Conhecimento sólido de MQL5.
- ✅ Necessidade de reduzir falhas de execução.
- ✅ Disposição para adaptar o fluxo ao seu gerenciamento de risco.
- ❌ Expectativa de solução automática para slippage.
- ❌ Busca por código pronto sem entender as nuances.
Parecer editorial equilibrado
Em termos de ROI de aprendizado, o guia entrega cerca de 3‑4 horas de insights práticos que poupam potencialmente dezenas de minutos por sessão de trading. Não é um “milagre de performance”, mas convém ao profissional que mede cada latência.
Mini cenários reais
Caso A: um EA de scalping que abre 15 ordens por minuto. A estrutura de tratamento de erros reduz o número de “retries” de 8 para 2, evitando perdas por “order reject”.
Caso B: um robô de swing trade que só executa duas ordens ao dia. O ganho de otimização é marginal, mas o código ajuda a documentar decisões de risco para compliance.
Próximos passos recomendados
Baixe o material, implemente o padrão em um ambiente de teste e compare a taxa de rejeição antes e depois. Se o número cair abaixo de 1 % de todas as ordens, o investimento de tempo foi justificado.
Pronto para experimentar? Acesse o guia completo


