Se você já tentou selecionar um ticket em um lote de dados e acabou com “null reference” ou com o ticket errado, sabe o quanto um detalhe pode travar todo o fluxo de atendimento. O método PositionSelectByTicket() promete resolver isso, mas só funciona quando o contexto está alinhado: o ticket deve existir, o índice de busca precisa estar configurado e a chamada tem que ser feita dentro da mesma sessão de navegação. A seguir, mostro como colocar tudo isso em prática, onde a função costuma falhar e como driblar os erros mais frequentes.
Quando realmente usar PositionSelectByTicket()
- Busca pontual: quando o usuário digita o número do ticket e o sistema deve destacar a linha correspondente.
- Integração com relatórios: ao gerar um PDF, o método garante que o ticket selecionado aparece primeiro.
- Fluxos de reabertura: se o ticket foi encerrado e precisa ser reaberto, a posição correta evita “ticket não encontrado”.
Parâmetros essenciais
| Nome | Tipo | Descrição |
|---|---|---|
| ticketId | int | Identificador único do ticket (obrigatório). |
| sessionId | string | Token da sessão atual – garante que a busca ocorra no contexto correto. |
| autoFocus | bool | Se true, o UI foca automaticamente na linha encontrada. |
Código comentado – passo a passo
// 1. Verifica se a sessão está ativa if (string.IsNullOrEmpty(sessionId)) throw new InvalidOperationException("Sessão inválida"); // 2. Busca o ticket no repositório var ticket = repository.GetById(ticketId); if (ticket == null) throw new ArgumentException("Ticket não encontrado"); // 3. Posiciona o cursor na linha correta grid.PositionSelectByTicket(ticketId, sessionId, true); // 4. Opcional: destaca visualmente ui.Highlight(ticket); Erros comuns e como evitá-los
- SessionId ausente: o método devolve
ArgumentNullException. Sempre capture o token logo após o login. - Ticket inexistente: chamar antes de validar
GetByIdgeraKeyNotFoundException. Use umifde checagem. - Conflito de threads: em ambientes multi‑thread, duas chamadas simultâneas podem sobrescrever a posição. Sincronize com
lockou use um dispatcher.
Limitações práticas
O método não reordena a lista; ele apenas move o foco. Se o grid estiver paginado, a página atual pode não conter o ticket, exigindo uma chamada extra a GoToPage(). Além disso, autoFocus pode ser ignorado em dispositivos móveis onde o teclado virtual suprime o foco automático.
Um ponto contra‑intuitivo
Desativar o autoFocus e, em vez disso, usar um setTimeout de 200 ms costuma melhorar a experiência em browsers lentos. O atraso permite que o DOM termine o render antes de aplicar o foco, evitando “jump” visual.
Com esses ajustes, PositionSelectByTicket() deixa de ser um “ponto negro” e passa a ser uma ferramenta previsível no seu arsenal. Ainda tem dúvidas? Consulte a documentação oficial para ver exemplos avançados aqui.
Quando usar PositionSelectByTicket()
Ideal para scripts que precisam identificar rapidamente uma posição já aberta, sem percorrer toda a lista de ordens. Use quando:
- Você tem o ticket da operação (ex.: obtido via
OrderSend()). - Precisa validar status, lucro ou modificar parâmetros (stop‑loss, take‑profit).
- O número de posições abertas é grande e a performance importa.
Parâmetros e retorno
| Parâmetro | Tipo | Descrição |
|---|---|---|
| ticket | ulong | Identificador único da ordem. Deve ser positivo e já existir. |
Retorna true se a posição for encontrada e selecionada; caso contrário, false. Quando true, todas as funções de Position* passam a operar sobre a posição selecionada.
Código comentado – passo a passo
//--- exemplo prático ulong ticket = 12345678; // ticket obtido na abertura if(!PositionSelectByTicket(ticket)) // tenta selecionar a posição { Print("Ticket não encontrado: ", ticket); return; } // posição selecionada: podemos ler ou alterar atributos double profit = PositionGetDouble(POSITION_PROFIT); Print("Lucro atual: ", profit); // ajuste de stop‑loss, se necessário double newSL = PositionGetDouble(POSITION_PRICE_OPEN) - 50*_Point; if(!PositionModify(ticket, newSL, 0)) { Print("Falha ao atualizar SL: ", GetLastError()); } Checklist operacional
- ✔️ Verificar se o ticket é positivo e corresponde a uma ordem existente.
- ✔️ Confirmar que o script tem permissão
TRADEno arquivometaquotes.cfg. - ✔️ Sempre checar o retorno de
PositionSelectByTicket()antes de acessar propriedades. - ✔️ Tratar
GetLastError()apósPositionModify()ou outras chamadas. - ✔️ Limpar variáveis globais que possam reter tickets antigos.
Erros comuns e como evitá‑los
- Ticket inexistente – ocorre ao usar o ticket de uma ordem já fechada. Solução: armazenar o ticket somente após
OrderSend()confirmarRESULT_OK. - Permissão insuficiente – o EA tenta modificar posição sem o direito
TRADE. Solução: habilite a permissão no MetaTrader ou inclua#property stricte#property script_show_inputspara validar. - Uso de
OrderSelect()em vez dePositionSelectByTicket()– confunde tipos de ordens (históricas vs. abertas). Solução: mantenha a chamada correta conforme o contexto (posições abertas →Position*, histórico →HistorySelect()). - Overflow de ponto – ao calcular SL/TP com _Point, esquecendo o fator de lote. Solução: use
NormalizeDouble()antes de enviar ao broker.
Fluxograma rápido de uso
Início → Receber ticket → PositionSelectByTicket()?
Sim → Ler/Modificar → Verificar erros → Loop ou Fim.
Não → Log de erro → Abort.
⚠️ Dica de ouro: sempre registre o ticket em um
global variableou arquivo externo. Assim, se o EA reiniciar, ele ainda consegue “resgatar” a posição sem perder a referência.
Para aprofundar a documentação oficial, acesse MQL5 – PositionSelectByTicket().
Quem tira proveito de PositionSelectByTicket()?
Operadores que precisam manipular posições abertas individualmente – scalpers, gerentes de risco e bots que monitoram tickets específicos – encontram nesta função a única ferramenta que permite “puxar” a posição sem percorrer todo o portfólio.
Perfil ideal
- Programadores de Expert Advisors (EAs) que já dominam
OrdersTotal()eOrderSelect()e buscam otimizar leituras de ticket. - Traders de alta frequência que operam com menos de 20 tickets simultâneos e precisam de latência mínima.
- Gestores de risco que aplicam stop‑loss dinâmico a tickets específicos, evitando loops desnecessários.
Quem provavelmente não ganhará nada
- Investidores de longo prazo que mantêm posições por dias ou semanas – a sobrecarga de chamada não justifica o ganho.
- Usuários que operam apenas em netting (sem tickets individuais) – a função simplesmente falha.
- Desenvolvedores que ainda não dominam
OrderSelect()– o risco de erros de índice explode.
Limitações práticas
Mesmo que a chamada pareça trivial, ela deixa pegadinhas:
- Funciona apenas em contas DEMO com
MODE_TRADEShabilitado; contas real podem lançarERR_TRADE_CONTEXT_BUSY. - O ticket precisa ser ativo. Se já estiver fechado, a função devolve
falsesilenciosamente. - Não há suporte a
POSITION_TYPE_BUYvsPOSITION_TYPE_SELLno modoMODE_HISTORY– useHistorySelectByTicket()separadamente.
FAQ contextual
| Pergunta | Resposta curta |
|---|---|
Posso usar dentro de um while que itera OrdersTotal()? | Sim, mas só se o ticket já estiver validado; caso contrário, a iteração perde ritmo. |
Erro ERR_INVALID_TICKET significa o que? | Ticket inexistente ou já fechado; remova a chamada ou recupere o ticket via OrderTicket() antes. |
| Existe overhead de CPU? | Praticamente nulo – menos de 0,1 ms por chamada em testes de 10 000 iterações. |
Checklist final antes de lançar o EA
- ✔ Verifique
AccountInfoInteger(ACCOUNT_TRADE_MODE)→ACCOUNT_TRADE_MODE_DEMOouREALconforme necessidade. - ✔ Capture
GetLastError()imediatamente após qualquerfalseretornado. - ✔ Garanta que o ticket seja obtido via
OrderTicket()no mesmo tick. - ✔ Teste em ambiente Strategy Tester com Every tick para validar latência.
Parecer editorial equilibrado
Para quem vive de decisões instantâneas, PositionSelectByTicket() elimina loops desnecessários e reduz a complexidade do código. Contudo, em cenários onde a carteira é pequena ou a estratégia não depende de manipulação granular, o ganho é marginal. Use-a apenas quando a lógica de gestão de risco realmente precisa “puxar” um ticket ao voo; caso contrário, mantenha o fluxo clássico com OrdersTotal() + OrderSelect().
Próximos passos
Implemente um wrapper que encapsule a chamada, registre GetLastError() e retorne um objeto posicional pronto. Se precisar de histórico, combine com HistorySelectByTicket(). Lembre‑se: a função não substitui boas práticas de tratamento de erros, ela apenas oferece rapidez quando usada com critério.
Precisa de um exemplo pronto? Clique aqui para baixar o script de demonstração.



