Sequência em que as ordens são processadas - página 2

 
Rodrigo Malacarne:

Olá Trader_Patinhas,

Sua questão é absolutamente interessante !!!!

Essa é uma daquelas questões que fazem toda a diferença em sistemas de negociação de curtíssimo prazo ...

Na minha humilde opinião, isso vai depender de inúmeros fatores... uns deles sob o seu controle, outros não... Como já disseram no fórum em inglês, questões relacionadas a ping, queda de conexão, etc, podem sim afetar a execução dessa sua lógica.

Entretanto, isolando todos os problemas e supondo que você E TAMBÉM a corretora possuem conexões e dados absolutamente estáveis, eu ACREDITO (atenção... ACREDITO !!!) que um cancelamento assíncrono enviado antes de uma ordem assíncrona não causaria um "zé-com-zé"... que é o termo de mercado que utilizamos quando um comitente compra e vende pra ele mesmo.

Na minha opinião, temos duas latências aqui: uma para que a corretora CANCELE sua ordem pendente na bolsa, e outra para que a corretora EXECUTE sua ordem. Sua lógica operacional assíncrona em princípio deverá funcionar CASO o tempo necessário para a corretora cancelar sua ordem junto à bolsa seja menor ou igual ao tempo necessário para que a corretora execute sua ordem.

Nesse caso, temos aqui uma segunda latência, que é aquela entre a corretora e a própria bolsa, já que estamos falando de ordens limitadas (que, portanto, vão pro book de ofertas do ativo).

De qualquer maneira, eu faria primeiro um teste numa conta demonstração em um ativo com book "ralo", pra ver o comportamento dessa lógica dentro do SERVIDOR MT5 instalado na corretora...

Se na conta demo a lógica conseguir ser executada corretamente, é sinal de que o servidor MT5 instalado na corretora processa sequencialmente o cancelamento e depois o envio da ordem.

A partir daí, na conta real, mesmo que a sequência seja a mesma (cancelamento anterior ao envio de nova ordem), não há como saber se a latência entre corretora e bolsa permite executar esse tipo de operação ...

Só mesmo "arriscando", sendo que você corre o risco de tomar multa, receber uma ligação da mesa da corretora com alguém eventualmente soltando os cachorros pra cima de você...

Por fim, me lembro uma vez de ter conversado com um dos responsáveis pelo MT5 na XP (atenção... XP!!!! não estou falando das outras corretoras do mercado brasileiro) e ele me disse que a corretora tem um filtro interno para evitar ordens do tipo zé-com-zé...

Portanto, pelo menos na XP (grupo XP, desconfio eu) você não teria problemas de zé-com-zé...

MAS... caso queira fazer o teste, experimente por sua conta e risco!

Como disse acima, essa é uma daquelas questões interessantíssimas que aparecem de vez em quando por aqui no fórum em português!

Parabéns pela pergunta!

Espero ter ajudado!

Abraços,
Malacarne

@Rodrigo Malacarne

Eu que te agradeço pela resposta, que me parece fazer total sentido. E também pela dica de que a XP tem filtro pra evitar o "zé-com-zé".

Na conta demo a estratégia aparentemente funciona bem. Na conta real eu tive 2 transações "zé-com-zé" dentre mais de 200 transações que o robô executou em 2 dias de operação (uma em cada dia).

A corretora foi a Modal. Tenho conta na XP também, mas como opero com frequência alta, opto pela Modal devido ao menor custo da corretagem.

Eventuais transações "zé-com-zé" não causariam nenhum problema na minha estratégia, se não fossem proibidas pela B3.

Se fosse possível prevê-las olhando o book, eu poderia não só evitar o "zé-com-zé" como ainda poderia economizar as corretagens e emolumentos remanejando os volumes negociados internamente, sem ter que pagar corretagem e emolumentos para vender os ativos para mim mesmo.

O problema é que o book do MT5 só mostra os volumes consolidados por nível de preço, não dá pra ver em que lugar da fila a minha ordem está e, mesmo que desse pra ver, as ordens que estivessem na frente da minha ordem poderiam ser executadas ou canceladas milésimos de segundos após eu ter olhado.

Posso tentar fazer um experimento na XP ... mas a R$ 12 de corretagem por ordem (os ativos negociados nessa estratégia são ações e opções), ou seja, R$ 24 ida-e-volta pra cada trade, e com minha estratégia fazendo mais de 100 trades por dia, essa brincadeira iria custar caro ... a margem de lucro por operação é muito pequena, eu teria que negociar volumes muito grandes para diluir o custo da corretagem e nesses níveis de volume provavelmente vai faltar liquidez suficiente para a estratégia dar lucro ... a corretagem de R$ 0,99 da Modal torna a estratégia bem mais viável ... por outro lado já constatei da pior maneira que a Modal não tem filtro para evitar "zé-com-zé" ... vou pensar mais a respeito do problema e ver se encontro uma solução. 

 
Rodrigo Malacarne:

Acho que você entendeu errado ...

Com OrderSend isso é perfetiamente possível !!!

Apenas com OrderSendAsync isso não é garantido...

Abraços,
Malacarne

@Rodrigo Malacarne

É que eu tinha perguntado lá no fórum inglês

What if I use OrderSend() instead of OrderSendAsync() ?

e o @Alain Verleyen , que me parece ser um dos principais conhecedores do assunto por lá, respondeu

Nothing is guarantee whatever you will use. If you want to be sure a pending is deleted before requesting a market order, you need to check it by code.

Seria ótimo se vc entrasse no tópico e discutisse com ele se o OrderSend() síncrono garantiria o cancelamento da primeira ordem antes da execução da segunda ou não (os "zé-com-zé" que observei ocorreram com o OrderSendAsync() ).

O link do tópico é https://www.mql5.com/en/forum/261538

Eu torço para que você esteja certo, pois para mim seria muito menos ruim apenas trocar o OrderSendAsync() por OrderSend(), tendo que aguardar apenas o ticket de reconhecimento do comando emitido pelo servidor, do que ter que aguardar a chegada do evento TradeTransaction notificando que a ordem foi cancelada, para só então poder executar o segundo OrderSend(). Se eu tiver que fazer isso, meu "HFT de pobre" vai se tornar um "HFT de mendigo"! 

OrderSendAsync() - is it guaranteed that the commands are processed in the same order they are sent?
OrderSendAsync() - is it guaranteed that the commands are processed in the same order they are sent?
  • 2018.06.28
  • www.mql5.com
Dear friends, Suppose I have a pending sell limit order for a certain instrument in a stock exchange market...
 

@Rodrigo Malacarne e colegas,

No fórum russo também me responderam que a ordem não será garantida. Veja uma das respostas (traduzida pelo tradutor automático, pois não sei falar russo - acredito que "autorização" seja a ordem limitada pendente a ser cancelada e "entrar no mercado" seja a segunda ordem, enviada a mercado):

Essa é uma boa pergunta.

Não há garantias.
Pelo menos porque o primeiro OrderSendAsync pode se perder no caminho para o servidor, e o segundo virá mais cedo.

Se você precisar excluir a autorização e, em seguida, entrar no mercado, use OrderSend ou OrderSendAsync com a análise de resultado em OnTradeTransaction .

Pensando aqui com meus botões ...

1) De fato, redes TCP/IP (internet em geral) usam roteamento dinâmico e por isso NÃO garantem que os pacotes de dados cheguem no destino na mesma ordem em que foram enviados na origem. Isso é fato.

2) Com base no item (1) podemos afirmar que, com OrderSendAsync(), os comandos poderão chegar fora de ordem nos servidor MT5 e a execução da ordem a mercado poderá ocorrer antes do cancelamento da ordem anterior, podendo gerar o "zé-com-zé", como eu mesmo tive a infeliz oportunidade de verificar na prática.

3) Entretanto, se for usada a versão síncrona, OrderSend(), os comandos certamente chegarão no servidor MT5 na ordem correta, pois o OrderSend() aguarda a confirmação de que o servidor MT5 recebeu o comando (não necessariamente já o processou, mas já o recebeu, e isso é o que importa para garantir que o segundo comando será recebido após o primeiro).

4) Com base no item (3), podemos afirmar que, com OrderSend(), os comandos chegarão sempre nas ordem correta no servidor MT5.

5) Entretanto, mesmo que os comandos cheguem na ordem certa no servidor MT5, ainda existem pelo menos duas brechas adicionais que poderiam permitir a execução dos comandos fora de ordem (e o eventual "zé-com-zé", no meu caso) mesmo com OrderSend():

5.1) se o servidor MT5 não enviar à B3 os comandos na mesma ordem em que os recebeu;

5.2) se os comandos forem enviados na ordem correta do servidor MT5 para a B3, mas chegarem na B3 na ordem errada.

obs: uma terceira possibilidade seria a B3 processar os comandos em ordem diferente da ordem em que foram recebidos, mas isto eu acredito que não aconteça, pelo menos não para comandos que venham de uma mesma corretora.

6) Não sei se a brecha (5.1) existe, mas acredito que a brecha (5.2) dependerá do tipo de conexão entre o servidor MT5 da corretora e a B3. Se for uma conexão de internet normal (TCP/IP), a ordem de execução dos comandos não será garantida. Somente um link direto, com rota única, entre a corretora e a B3 poderia garantir que os comandos cheguem na B3 na ordem correta.

Com base no raciocínio acima, as perguntas-chave seriam: 

1) O servidor MT5 processa os comandos OrderSend() sempre na mesma ordem em que os recebe?

2) Como são os links entre o servidor MT5 das corretoras brasileiras e a B3? Há alguma corretora que tenha link direto com a B3, garantindo que os comandos são recebidos pela B3 na mesma ordem em que são enviados pelo servidor MT5?

Alguém sabe?

Abraços

 
Já pensou em usa duas contas diferentes, diferentes comitentes, um só pendura e a outra só agride, assim, caso ocorra o "zé-com-zé" não teria problema com a B3.
 
Rafael Gazzinelli:
Já pensou em usa duas contas diferentes, diferentes comitentes, um só pendura e a outra só agride, assim, caso ocorra o "zé-com-zé" não teria problema com a B3.

Sim, já pensei em abrir outra conta no CPF da minha esposa (com a anuência dela, evidentemente). Nesse caso eu teria que colocar um robô em cada conta na mesma máquina, ou em duas máquinas na mesma rede local, se comunicando um com o outro via pipe (senão o delay de comunicação entre os robôs iria anular a vantagem de usar OrderSendAsync e seria mais simples eu aguardar a confirmação de cancelamento da bolsa e usar um robô só).

Acho complexa demais essa solução. E ainda corre o risco de ser mal-interpretada pelas autoridades (duas pessoas comprando e vendendo uma pra outra com ordens partindo de ambos os lados do mesmo endereço ip). A Policia Federal vive monitorando padrões atípicos de movimentação em bolsa à procura de artimanhas dos políticos (veja o caso do Eduardo Cunha, que fazia aquela estrutura de 4 pontas com opções da Petrobrás) e de repente podem achar que eu (pobre coitado!) também estou fazendo alguma treta pra algum esquema de lavagem de dinheiro com essas operações malucas dos meus robôs, rsrs.

Por enquanto tenho testado uma versão alternativa da minha estratégia que pendura ordem de um lado de cada vez, agredindo somente o lado oposto à ordem que estiver pendurada. É menos eficiente que a ideia original de pendurar ordens simultaneamente dos dois lados, pois perde metade das oportunidades de arbitragem que aparecem, mas funciona sem complicações adicionais.

 
Trader_Patinhas:

Obrigado, @Márcio Andrade . Vou traduzir pro inglês e pro russo e postar nos respectivos fóruns (no caso do russo vou ter que usar o google tradutor, espero que fique inteligível pra eles).

@Rodrigo Malacarne , acredito que dá pra conciliar as duas coisas: podemos postar sempre aqui primeiramente, para fomentar nosso fórum local, e repetir a questão nos fóruns estrangeiros caso ela demore a ser respondida aqui.

Obrigado! Abraços!

Em tempo: nos testes que eu fiz, tenho observado que as ordens têm sido sempre processadas na mesma ordem em que são enviadas pelo comando OrderSend(). Mas eu queria ter uma segurança maior sobre isso, pois seria muito ruim ter meu CPF bloqueado na B3 por "tentativa de manipular o mercado operando nas duas pontas". Sem falar que vender para si mesmo significa pagar corretagem e emolumentos à toa, o que pode sair caro pra quem opera com frequência alta e margem de lucro apertada. Eu poderia verificar o book antes de enviar a ordem a mercado pra ver se a ordem que vai ser consumida na outra ponta é minha, é praticamente impossível garantir que não vou pegar minha própria ordem, pois as ordens que estão na frente da minha podem ser consumidas ou canceladas 1 milésimo de segundo após eu ter verificado. Pra ter segurança total eu teria que cancelar a ordem oposta e aguardar a confirmação do cancelamento, para só então enviar a ordem a mercado, aguardar a confirmação da execução da ordem a mercado e então colocar de volta a ordem limitada que estava lá ... a menos que nossos amigos russos garantam que a ordem de processamento é sempre preservada ... nesse caso eu poderia mandar três OrderSendAsync de uma vez só sem medo de ser feliz (cancelamento da outra ponta, ordem a mercado e recolocação da ordem na outra ponta) ... como estou conseguindo 8 ms ida-e-volta de latência entre meu servidor Amazon e a B3, já dá pra implementar um "HFT de pobre" usando OrderSendAsync !

Não é ilegal colocar diversas ordens pendentes (ordens limite). O nome disse é grid. Não é possível comprar de si mesmo. Se a ordem limite estiver com o valor errado (uma compra acima do ask ou uma venda limite abaixo do bid), a ordem se transforma em ordem a mercado e é executada quase que imediatamente como agressor. Neste caso, e eu não estou certo disso para a BMF, o valor pago é o menor valor que satisfaça a solicitação. Logo, uma ordem limite de compra acima do ask será executada a mercado pelo valor de ask e será vendido pelo primeiro da fila. Por isso, não dá para garantir que você ira agredir a si mesmo e manipular o valor de last.

Para manipular o valor de last você teria que colocar um grande volume de ordens agredindo sua posição limite e com CPF ou CNPJ distintos e robôs sincronizados. Mas não tem como escolher quem é agredido. Logo, haverá uma grande perda de slippagem.

 
Arthur Albano:

Não é ilegal colocar diversas ordens pendentes (ordens limite). O nome disse é grid. Não é possível comprar de si mesmo. Se a ordem limite estiver com o valor errado (uma compra acima do ask ou uma venda limite abaixo do bid), a ordem se transforma em ordem a mercado e é executada quase que imediatamente como agressor. Neste caso, e eu não estou certo disso para a BMF, o valor pago é o menor valor que satisfaça a solicitação. Logo, uma ordem limite de compra acima do ask será executada a mercado pelo valor de ask e será vendido pelo primeiro da fila. Por isso, não dá para garantir que você ira agredir a si mesmo e manipular o valor de last.

Para manipular o valor de last você teria que colocar um grande volume de ordens agredindo sua posição limite e com CPF ou CNPJ distintos e robôs sincronizados. Mas não tem como escolher quem é agredido. Logo, haverá uma grande perda de slippagem.

Oi Arthur.

Minha intenção nunca foi manipular o valor do last, eu apenas não quero ser confundido com quem faz isso, visto que o comportamento do meu robô me fez levar duas advertências da B3 sem eu realmente ter tido essa intenção.  

Esse caso aí é um robô de arbitragem que eu estava construindo, que deixava ordens pendentes de venda e de compra em um conjunto de ativos. Quando a oportunidade de arbitragem aparecia, ele precisava enviar imediatamente ordens a mercado para completar os demais ativos da "cesta de arbitragem" e o que ocorria é que, como havia ordens pendentes minhas no sentido oposto, ocasionalmente a liquidez à frente da minha ordem pendente era consumida e eu acaba negociando comigo mesmo, sem querer.

Para evitar isso eu precisaria primeiro cancelar as minhas ordens pendentes antes de enviar a ordem a mercado no sentido oposto. A questão que coloquei é se, ao enviar o cancelamento da ordem pendente seguido da ordem a mercado usando o modo assíncrono (OrderSendAsync), eu teria a garantia de que o cancelamento da ordem limite seria efetuado antes da ordem a mercado, ou se eu teria que usar o modo síncrono para garantir isso.

Para mim seria importante usar o modo assíncrono porque as oportunidades de arbitragem geralmente se dissipam em questão de dezenas de milissegundos. As de maior volume já são exploradas pelos robôs institucionais, que são invencíveis em velocidade por operarem dentro da infraestrutura da B3, mas ainda existem algumas oportunidades de pequeno volume dando sopa aqui e ali de vez em quando, além de inúmeras oportunidades de "arbitragem estatística" (estilo "lato sensu" de arbitragem onde o lucro não é garantido, mas tem probabilidade muito alta).  

 

Parabéns pela rica discussão.

@Trader_Patinhas, caso tenha tido experiência com o DMA4 da Modal, pode compartilhar se há ganho  de tempo no processamento da ordem entre OrderSend() e OrderSendAsync()?

Nesta data, o tempo de processamento de ordem que tenho obtido na Modal DMA4 é em média de 50 a 100 ms (tempo obtido no diário do MT5 para processamento da ordem).

Isso quando seleciono "servidor 05" da Modal. Nele o ping é em torno de 2,3 ms.

No "servidor 01", apesar do ping em torno de 1ms (menos da metade do "servidor 05"), o tempo de processamento da ordem é em média 900 a 1100 ms.

Como se percebe, no "servidor 01"  o tempo de processamento da ordem costuma ser de 10 até 20 vezes mais lento que no "servidor 05". Informações do pegão de 01/02/2019.

Gostaria de entender se com OrderSendAsync() esse tempo de processamento da Ordem diminuiria.
 

@Trader Patinhas, você pode simplesmente criar um filtro para limitar as ordens pelo tempo.Por exemplo, se a ordem não for executada em 20 ou 30 segundos ela é cancelada e restringir o envio de ordens de tipos diferentes a um intervalo.
Por exemplo, pelo menos 1 minuto entre cada ordem de tipo diferente. if(previous_type != current_type and previous_time+60 <= current_time) OrderSend();
Obviamente você pode reduzir o o tempo entre envio de ordens e expiração. Em todo caso é recomendável confirmar o cancelamento.

 
Você precisa considerar que um boa oportunidade não vai aparecer simultaneamente na compra e na venda e por isso agurdar a confirmação de cancelamento não deve ser um problema. E uma vez que a oportunidade passou e ordem não foi executada deve ser cancelada imediatamente e não apenas quando enviar uma ordem oposta, caso contrário corre o risco de executar operações indesejadas se ficar ordem passiva no book.
Razão: