Se você já tentou filtrar ordens abertas em um Expert Advisor e acabou preso num loop infinito ou recebeu resultados inesperados, sabe o quão frustrante pode ser. O ponto de atrito costuma estar na forma como o OrderSelect() é chamado: parâmetros errados, índices fora de alcance ou filtros que não consideram o tipo de operação. O objetivo aqui é mostrar, passo a passo, como usar a função de forma segura, qual é o seu retorno real e onde ela costuma “quebrar” em cenários de alta volatilidade.
Como o OrderSelect() funciona na prática
- Assinatura:
bool OrderSelect(int index, ENUM_SELECT select, ENUM_ORDER_TYPE type=ORDER_TYPE_ANY) - index: posição da ordem na lista interna do terminal (0‑n). Não confunda com ticket.
- select:
SELECT_BY_POSouSELECT_BY_TICKET. O primeiro percorre a lista; o segundo busca por número único. - type: filtro opcional (BUY, SELL, BUY_LIMIT, …). Se omitido, aceita qualquer tipo.
O retorno é true quando a ordem é carregada nos buffers internos; caso contrário, false e GetLastError() indica o motivo (ex.: ERR_INVALID_TICKET).
Passo a passo para evitar os erros mais comuns
- Verifique o total de ordens antes de iterar. Use
OrdersTotal()para limitar o laço. Exemplo:int total=OrdersTotal(); for(int i=0;i - Prefira SELECT_BY_TICKET quando o ticket já está em mãos. Isso elimina a dependência da ordem da lista, que pode mudar a cada tick.
if(OrderSelect(myTicket,SELECT_BY_TICKET)) // segura - Filtre por tipo logo na chamada. Evita checagens posteriores e reduz o risco de “acidentalmente” manipular ordens pendentes.
if(OrderSelect(i,SELECT_BY_POS,ORDER_TYPE_BUY)) // só compras - Trate o erro de índice fora de intervalo. Quando o número de ordens diminui entre duas chamadas, o
ipode ficar inválido. Sempre re‑obtenhaOrdersTotal()dentro do laço se houver cancelamento de ordens.
Exemplo completo – filtrando apenas posições abertas de compra
| Código | Descrição |
|---|---|
| Itera apenas sobre ordens BUY do símbolo corrente, ignorando erros silenciosamente. |
FAQ rápido
- OrderSelect falha ao abrir um novo ticket? Não. A função só lê; a criação de ordens usa
OrderSend(). - Posso usar OrderSelect dentro de OnTimer? Sim, mas lembre‑se de que o número de ordens pode mudar entre chamadas; recalcule
OrdersTotal()a cada timer. - Por que alguns tutoriais recomendam SELECT_BY_POS mesmo com ticket? Geralmente por simplicidade, mas em estratégias de alta frequência isso gera race conditions.
Em resumo, OrderSelect() é confiável desde que você controle o índice, escolha o modo de seleção adequado e trate os erros imediatamente. Quando usado corretamente, ele deixa de ser um “buraco negro” e vira a ferramenta de inspeção que todo EA precisa. Para aprofundar, veja a documentação oficial da MetaTrader – vale a pena conferir os detalhes de GetLastError() que salvam noites de debugging.
Primeiros passos após abrir o MetaEditor
1. Crie um novo script ou Expert Advisor (EA).
2. Inclua #include – a classe CTrade contém OrderSelect().
3. Instancie CTrade trade; logo abaixo das declarações globais.
Configuração inicial da função OrderSelect()
O protótipo da chamada é:
| Sintaxe | Descrição |
|---|---|
| bool OrderSelect(ulong ticket, ENUM_ORDER_SELECT select, ENUM_TIMEFRAMES timeframe=PERIOD_CURRENT) | Seleciona a ordem pelo ticket ou pela posição na lista. |
Parâmetros essenciais:
- ticket: identificador único da ordem. Use
PositionGetTicket(i)ouHistoryOrderGetTicket(i)para obtê‑lo. - select:
SELECT_BY_TICKETouSELECT_BY_POS. - timeframe: opcional – define o calendário de histórico (útil ao analisar trades fechados).
Checklist operacional – rotina recomendada
- ☑ Verificar
OrdersTotal()ouPositionsTotal()antes de iterar. - ☑ Usar
if(!OrderSelect(ticket, SELECT_BY_TICKET)) continue;para evitar falhas. - ☑ Capturar
OrderType(),OrderSymbol()eOrderProfit()imediatamente após a seleção. - ☑ Liberar recursos com
OrderCloseTime()ao analisar histórico.
Exemplo prático – filtrando ordens de compra abertas
O código abaixo percorre todas as posições abertas e soma o lucro das compras do par EURUSD:
double lucroEURUSD = 0; int total = PositionsTotal(); for(int i=0; iErros comuns e como evitá‑los
- Ticket inválido: ocorre quando a ordem já foi fechada. Sempre valide
OrderSelect()antes de ler atributos. - Uso de SELECT_BY_POS em histórico: posições mudam de ordem ao fechar. Prefira
SELECT_BY_TICKETpara consistência. - Timeframe inadequado: ao analisar trades antigos, defina
PERIOD_M1ou outro intervalo que contenha o histórico desejado.
FAQ rápido
- Posso usar OrderSelect() dentro de um OnTimer? Sim, desde que o timer não conflite com chamadas de negociação simultâneas. Use mutex lógico ou flags.
- Qual a diferença entre OrderSelect() e PositionSelect()?
OrderSelect()lida com a API de ordens (histórico e pendentes).PositionSelect()trabalha apenas com posições abertas, mais leve. - É possível selecionar todas as ordens de um símbolo de uma vez? Não diretamente. Crie um loop sobre
OrdersTotal()e filtre comOrderSymbol().
⚠️ Dica de performance: ao analisar milhares de registros históricos, limite o
timeframeao menor necessário e prefiraHistorySelect()antes de iterar comOrderSelect().
Para aprofundar a documentação oficial, acesse MetaTrader 5 Help – OrderSelect().
Quem realmente tira proveito do OrderSelect()?
Se você já atravessa o mercado como um operário que só quer abrir e fechar trades, este recurso não agrega nada.
Por outro lado, desenvolvedores de robôs que precisam varrer a lista de posições abertas ou históricas – estrategistas que constroem filtros avançados – encontram no OrderSelect() a única porta viável.
Perfil ideal
- Programador MQL5 com experiência mínima em
HistorySelect()ePositionsTotal(). - Estratégia que depende de inspeção sequencial de ordens (ex.: trailing stop customizado, gerenciamento de risco por ticket).
- Ambiente de teste onde a latência de chamada não afeta a lógica de decisão.
Quem deve evitar
Traders de varejo que utilizam Expert Advisors genéricos ou que confiam apenas em sinais pré‑configurados.
Scripts de curta duração que realizam apenas uma operação; o overhead de iterar toda a lista pode consumir ciclos preciosos.
Limitações práticas
O OrderSelect() só aceita índices de 0 a OrdersTotal()-1. Em contas com milhares de ordens, a iteração linear pode tardar alguns milissegundos – o suficiente para mudar o preço de entrada.
Não há suporte nativo a filtros por símbolo ou por tipo; cabe ao programador implementar loops de descarte, o que aumenta a complexidade e o risco de bugs.
Checklist rápido antes de apostar no recurso
| Item | Verificação |
|---|---|
| Precisa ler propriedades de cada ordem? | Sim/Não |
| Quantidade de ordens > 500? | Sim/Não |
| Latência crítica? | Sim/Não |
Disponibilidade de OrdersHistoryTotal()? | Sim/Não |
FAQ contextual
- Posso usar OrderSelect() para filtrar apenas ordens de compra? Sim, mas requer um
if (OrderType()==ORDER_TYPE_BUY)dentro do loop. - O que acontece se eu passar um índice fora do range? A função retorna
FALSEe o último erro fica emGetLastError(). - Existe forma de acelerar a varredura? Não nativamente; a única alternativa é manter um array de tickets atualizados manualmente.
Mini cenários reais
Um robô de scalping que fecha posições ao atingir 0,5% de lucro precisa checar o ticket de cada ordem aberta a cada tick. OrderSelect() permite identificar rapidamente a ordem alvo, mas em um spread de 2 000 ticks a latência pode gerar slippage.
Um gerenciador de portfólio de longo prazo, rodando a cada hora, consegue percorrer tranquilamente milhares de ordens, pois o timing não é crítico.
Observação prática
Combine OrderSelect() com HistorySelect() apenas se a lógica exigir histórico completo; caso contrário, limite‑se às posições atuais para economizar memória.
Próximos passos
Teste a função em um ambiente de demonstração com a mesma carga de ordens que seu EA verá ao vivo. Anote o tempo gasto (GetTickCount()) e decida se a latência está dentro do seu teto aceitável.

