Na prática, quem tenta usar MqlTradeRequest costuma tropeçar na ordem dos campos e na validação de preço. O erro mais comum não é o código em si, mas a falta de um “pipeline” claro: montar a estrutura, preencher os campos obrigatórios, enviar e tratar o retorno. Quando tudo isso falha, o trader perde tempo – e dinheiro – tentando descobrir se o problema está na lógica ou na API.
Estrutura completa do MqlTradeRequest
- action – tipo de operação (TRADE_ACTION_DEAL, TRADE_ACTION_PENDING etc.).
- symbol – par de moedas ou ativo.
- volume – lote a ser negociado.
- price – preço de execução; obrigatório para ordens pendentes.
- stoplimit – preço stop‑limit, só usado em STOP‑LIMIT.
- sl e tp – níveis de stop‑loss e take‑profit.
- deviation – margem de slippage aceitável.
- type – ordem de compra (ORDER_TYPE_BUY) ou venda (ORDER_TYPE_SELL).
- type_filling – método de preenchimento (ORDER_FILLING_FOK, ORDER_FILLING_IOC, ORDER_FILLING_RETURN).
- type_time – validade (ORDER_TIME_GTC, ORDER_TIME_DAY, etc.).
Campos obrigatórios e armadilhas
Mesmo que a documentação liste “obrigatórios”, a realidade é mais rigorosa: symbol, volume e type nunca podem ficar vazios. Se action for TRADE_ACTION_DEAL, price pode ser zero, mas deviation deve ser >0 para evitar “ERR_INVALID_PRICE”.
Um ponto contra‑intuitivo: definir sl ou tp fora do intervalo de preço permitido gera ERR_INVALID_SL_TP mesmo que a ordem seja aceita. A API checa esses limites antes de enviar a requisição ao servidor.
Exemplo prático – Compra (Buy)
MqlTradeRequest request; ZeroMemory(request); request.action = TRADE_ACTION_DEAL; request.symbol = "EURUSD"; request.volume = 0.1; request.type = ORDER_TYPE_BUY; request.price = 0; // preço de mercado request.deviation= 10; // 10 pontos de slippage request.type_filling = ORDER_FILLING_FOK; request.type_time = ORDER_TIME_GTC; request.sl = 1.0800; request.tp = 1.1000;
Observe o price = 0: indica mercado. Trocar por um valor fixo sem mudar type_filling pode gerar ERR_INVALID_PRICE.
Exemplo prático – Venda (Sell)
MqlTradeRequest request; ZeroMemory(request); request.action = TRADE_ACTION_DEAL; request.symbol = "GBPUSD"; request.volume = 0.2; request.type = ORDER_TYPE_SELL; request.price = 0; request.deviation= 5; request.type_filling = ORDER_FILLING_IOC; request.type_time = ORDER_TIME_GTC; request.sl = 1.3000; request.tp = 1.2700;
A diferença crucial está em type_filling = IOC. Se o preço mudar mais que 5 pontos antes da execução, a ordem será rejeitada silenciosamente.
Erros frequentes e como mitigá‑los
- ERR_INVALID_PRICE – preço fora do spread ou zero quando a ordem exige preço fixo.
- ERR_INVALID_VOLUME – lote menor que o mínimo permitido pelo corretor.
- ERR_TRADE_CONTEXT_BUSY – duas requisições simultâneas; resolva com
Sleep(1000)ou fila de pedidos. - ERR_TRADE_REJECTED – stop‑loss/take‑profit fora do intervalo permitido.
Uma estratégia simples: encapsular a chamada em uma função que retorne o código de erro, logue GetLastError() e, se for ERR_TRADE_CONTEXT_BUSY, tente novamente após 200 ms.
Quando o MqlTradeRequest pode falhar
Mesmo com tudo correto, a ordem pode ser rejeitada se o mercado estiver “frozen” (horário de manutenção) ou se o saldo for insuficiente. Nesses casos, a API devolve ERR_NOT_ENOUGH_MONEY, mas o trader muitas vezes interpreta como “erro de código”. A solução é checar AccountInfoDouble(ACCOUNT_BALANCE) antes de montar a requisição.
Para quem já está no ambiente MetaTrader, experimentar os exemplos acima em um Strategy Tester ajuda a visualizar a latência e a necessidade de ajustes finos no deviation. Se quiser aprofundar, confira o guia avançado de trade requests que traz casos de uso em alta frequência.
Estrutura completa do MqlTradeRequest
O objeto MqlTradeRequest reúne todos os parâmetros que o servidor de negociação aceita. Cada campo tem tipo definido e, fora o symbol e action, a maioria é opcional, porém recomenda‑se preenchê‑los para evitar rejeições.
| Campo | Tipo | Obrigatório? | Descrição |
|---|---|---|---|
| action | ENUM_TRADE_REQUEST_ACTIONS | Sim | Tipo de operação: TRADE_ACTION_DEAL (compra/venda), TRADE_ACTION_PENDING (ordem pendente) etc. |
| symbol | string | Sim | Par de moedas ou ativo a ser negociado. |
| volume | double | Sim | Quantidade de lotes. Deve respeitar MarketInfo(symbol, MODE_MINLOT) e MODE_MAXLOT. |
| price | double | Não | Preço de execução. Necessário para ordens pendentes ou para TRADE_ACTION_DEAL quando type_filling for ORDER_FILLING_FOK. |
| sl | double | Não | Stop‑Loss. 0 desabilita. |
| tp | double | Não | Take‑Profit. 0 desabilita. |
| deviation | int | Não | Desvio máximo aceitável em pontos. |
| type | ENUM_ORDER_TYPE | Não | Tipo de ordem (OP_BUY, OP_SELL, OP_BUYLIMIT …). |
| type_filling | ENUM_ORDER_FILLING | Não | Política de preenchimento (ORDER_FILLING_RETURN, ORDER_FILLING_FOK, ORDER_FILLING_IOC). |
| expiration | datetime | Não | Validade da ordem pendente. |
| comment | string | Não | Texto livre que aparecerá no histórico. |
| magic | ulong | Não | Identificador exclusivo do EA. |
Primeiros passos após a compra do EA
- Instale o arquivo .ex5 na pasta
MQL5/Experts. - Abra o MetaEditor, inclua
#includee declareCTrade trade;. - Crie uma função
SendRequest()que preencha umMqlTradeRequeste chameOrderSend(request, result).
Checklist operacional para envio de ordem
- Verificar spread:
MarketInfo(sym, MODE_SPREAD)≤maxSpreaddefinido. - Confirmar margem:
AccountFreeMargin()≥volume * marginRequired. - Calcular SL/TP em pontos ou percentuais antes de atribuir.
- Definir
deviationde acordo com a volatilidade atual. - Resetar
requestcomZeroMemory(request)a cada operação.
Exemplo prático – Compra (Buy)
void Buy(double lot, double price=0) { MqlTradeRequest request; MqlTradeResult result; ZeroMemory(request); request.action = TRADE_ACTION_DEAL; request.symbol = _Symbol; request.volume = lot; request.type = ORDER_TYPE_BUY; request.price = (price>0)?price:SymbolInfoDouble(_Symbol,SYMBOL_ASK); request.deviation= 10; request.magic = 123456; request.comment = "Buy via MqlTradeRequest"; if(!OrderSend(request,result)) Print("Erro: ",GetLastError()); else Print("Ordem enviada: ",result.order); } Exemplo prático – Venda (Sell)
void Sell(double lot, double price=0) { MqlTradeRequest request; MqlTradeResult result; ZeroMemory(request); request.action = TRADE_ACTION_DEAL; request.symbol = _Symbol; request.volume = lot; request.type = ORDER_TYPE_SELL; request.price = (price>0)?price:SymbolInfoDouble(_Symbol,SYMBOL_BID); request.deviation= 10; request.magic = 123456; request.comment = "Sell via MqlTradeRequest"; if(!OrderSend(request,result)) Print("Erro: ",GetLastError()); else Print("Ordem enviada: ",result.order); } Erros frequentes e como evitá‑los
- 1314 – Invalid price: ocorre quando
priceestá fora do intervaloAsk ± deviation. UseNormalizeDouble(price,_Digits)e ajustedeviation. - 1300 – Invalid volume: lote não respeita
MODE_MINLOTouMODE_VOLUME_STEP. ConsulteSymbolInfoDouble(sym,SYMBOL_VOLUME_MIN)antes. - 1346 – Trade context busy: chamada concorrente ao servidor. Insira
while(!IsTradeAllowed()) Sleep(100);antes de enviar. - 1308 – Invalid stops: SL/TP demasiado próximos ao preço atual. Calcule
stopLevel = SymbolInfoInteger(sym,SYMBOL_TRADE_STOPS_LEVEL)e adicione margem.
Rotina semanal de otimização
Dedique 30 min ao final de cada sessão de trading:
| Dia | Atividade |
|---|---|
| Segunda | Revisar logs de OrderSend, filtrar erros > 3 ocorrências. |
| Quarta | Ajustar deviation com base no ATR de 14 períodos. |
| Sexta | Testar nova configuração de type_filling em conta demo. |
Micro insight: manter o
magicconstante facilita a filtragem de ordens no histórico e reduz risco de conflitos entre múltiplos EAs.
Perfil ideal e limitações do MqlTradeRequest
Se você precisa automatizar ordens direto do código MQL5, o Como trabalhar com MqlTradeRequest pode ser a ferramenta que vai salvar seu tempo. Mas não é um curinga universal; ele serve a um nicho bem definido.
Quem realmente tira proveito?
- Desenvolvedores de Expert Advisors (EAs) que exigem controle fino sobre parâmetros como
price,deviationetype. Eles costumam precisar enviar pedidos de compra e venda em milissegundos. - Operadores de corretoras internas que utilizam scripts para validar fluxos de trading antes de abrir contas de clientes.
- Analistas de risco que testam cenários de rejeição de ordem (erro 4107, 4108) em ambientes de simulação.
Quem deve evitar?
- Iniciantes que mal sabem diferenciar
ORDER_TYPE_BUYdeORDER_TYPE_SELL. O risco de enviar pedidos incompletos é alto. - Quem usa apenas indicadores simples e nunca entrou em contato com
TradeCheckResult. O overhead de aprendizado pode superar o ganho. - Corretoras que operam exclusivamente via API REST; o módulo MQL5 não se comunica nativamente com esses serviços.
Limitações práticas
O MqlTradeRequest não aceita price fora do intervalo de MarketInfo(Symbol(), MODE_BID/ASK). Qualquer tentativa fora desse “band” gera erro 4105, que interrompe o loop do EA se não for capturado. Além disso, o número máximo de pedidos pendentes simultâneos é 10 por símbolo – um limite imposto pelo servidor.
FAQ contextual
- Posso usar o mesmo request para BUY e SELL? Não. Cada operação exige
typedistinto e, preferencialmente, um novo objetoMqlTradeRequestpara evitar sobrescrita de campos. - O que fazer quando
retcode= 4108? Verifique a margem livre; o trade falha por falta de capital. Ajustevolumeou libere margem antes de tentar novamente. - O módulo aceita stops dinâmicos? Sim, mas só se o servidor suportar
ORDER_TYPE_STOPouORDER_TYPE_TAKE_PROFIT. Caso contrário, o retorno será 4106.
Checklist final antes de colocar em produção
| Item | Condição |
|---|---|
| Campos obrigatórios preenchidos | Sim (symbol, volume, type, price) |
| Verificação de margem | Realizada via AccountFreeMarginCheck |
| Gerenciamento de erros | Tratamento de retcode em switch‑case |
| Limites de pedidos pendentes | ≤10 por símbolo |
| Teste em conta demo | Executado por, no mínimo, 5.000 ticks |
Parecer editorial equilibrado
Em termos de praticidade, o material entrega tudo que um trader avançado espera: estrutura completa, exemplos claros de compra e venda, além de um capítulo dedicado aos erros mais frequentes. Porém, ele não resolve a curva de aprendizado de quem ainda não domina os conceitos de margem e tipos de ordem.
Se o seu objetivo é montar EAs sofisticados que precisem de respostas instantâneas do mercado, o investimento vale a pena. Para quem apenas quer “clicar e lucrar”, o custo de treinamento pode ser desproporcional.
Próximos passos: teste o código em ambiente de demo; ajuste o parâmetro deviation conforme o spread da sua corretora; implemente um log de retcode para auditoria. Só depois de validar tudo, migre para conta real.
