Onde os preços se formam
Um preço na tela é o resultado de uma fila. Numa bolsa, compradores e vendedores colocam ordens limitadas: «comprar 300 a 99,50», «vender 200 a 100,00». As que não são executadas ficam no livro de ordens: as ofertas de compra (bids), a melhor no preço mais alto, e as de venda (asks), a melhor no preço mais baixo. Um negócio ocorre quando uma ordem que chega encontra uma em espera. Tudo o que os tópicos anteriores chamam de preço, spread, deslizamento e impacto vem dessa estrutura.
# A side of the book as a dict {price: total size}
bids = {99.5: 300, 99.4: 500, 99.0: 1200}
asks = {100.0: 200, 100.1: 400, 100.5: 800}
best_bid, best_ask = max(bids), min(asks)
print(best_bid, best_ask) # 99.5 100.0
print(round(best_ask - best_bid, 2), (best_bid + best_ask) / 2) # the spread 0.5 and the mid 99.75Spread, preço médio e profundidade
O melhor bid e o melhor ask são o topo do livro. Sua diferença é o spread, o preço de negociar na hora: um comprador que toma o ask e revende ao bid perde o spread. A meio caminho está o preço médio, a referência usual de um preço justo. A profundidade é o tamanho em espera em cada nível e além, e diz quanto pode ser negociado antes de o preço se mover. Um lado vazio significa que não há preço nesse lado, então spread e médio ficam indefinidos: None, não zero.
def best_bid_ask(bids, asks):
return (max(bids) if bids else None, min(asks) if asks else None)
def spread_and_mid(bids, asks):
bid, ask = best_bid_ask(bids, asks)
if bid is None or ask is None:
return None, None
return ask - bid, (bid + ask) / 2
print(spread_and_mid({99.5: 300, 99.4: 500}, {100.0: 200, 100.1: 400})) # (0.5, 99.75)
print(spread_and_mid({}, {100.0: 200})) # (None, None): one side is emptyAdicionar ordens sem mudar o passado
Uma nova ordem limitada se junta a um nível de preço existente, somando ao seu tamanho total, ou abre um nível novo. Escrever isso como uma função que devolve um dict novo em vez de alterar o antigo tem uma vantagem prática: guarda-se um instantâneo do livro antes da ordem, útil para testar e reproduzir. Copie com dict(side), altere a cópia, devolva-a. Uma função que altera em silêncio seu argumento é fonte clássica de bugs quando o mesmo livro é usado em dois lugares.
def add_limit_order(side, price, size):
new = dict(side) # a copy: the original book is not touched
new[price] = new.get(price, 0) + size
return new
bids = {99.5: 300, 99.4: 500}
after = add_limit_order(bids, 99.5, 100) # joins the existing level
after = add_limit_order(after, 99.3, 50) # opens a new level
print(after) # {99.5: 400, 99.4: 500, 99.3: 50}
print(bids) # {99.5: 300, 99.4: 500} unchangedCasar uma ordem a mercado
Uma compra a mercado leva os asks do preço mais baixo para cima: todo o primeiro nível, depois o segundo, até a ordem ser preenchida ou o livro esvaziar. Percorra os preços ordenados, leve min(left, size_at_price) em cada um, registre a execução e apague o nível (levado inteiro) ou reduza-o (levado em parte). A lista de execuções dá o preço médio visto no tópico de execuções, e o livro restante é o mercado após sua negociação: mais fino no topo, com um melhor ask pior.
def match_market_buy(asks, size):
remaining = dict(asks)
fills = []
left = size
for price in sorted(asks): # cheapest first
if left <= 0:
break
take = min(left, asks[price])
fills.append((price, take))
left -= take
if take == asks[price]:
del remaining[price] # the level is used up
else:
remaining[price] = asks[price] - take
return fills, remaining
asks = {100.0: 200, 100.1: 400, 100.5: 800}
fills, remaining = match_market_buy(asks, 500)
print(fills) # [(100.0, 200), (100.1, 300)]
print(remaining) # {100.1: 100, 100.5: 800}- Cada lado é um dict
{price: size}: o melhor bid émax(bids), o melhor askmin(asks); o spread éask - bid, o médio sua média, e ambos sãoNonese um lado estiver vazio. - Adicione uma ordem copiando o dict, somando no preço e devolvendo a cópia; o livro recebido fica inalterado.
- Uma compra a mercado percorre os asks ordenados, levando
min(left, size)por nível, apagando os esgotados e reduzindo os levados em parte; livros reais também têm uma fila em cada nível.
A seguir: o desequilíbrio do fluxo de ordens, ler a pressão no livro para antecipar o próximo movimento do preço.
Lab: o que é avaliado
- Achar o topo do livro com
best_bid_ask25 pts - Medir a diferença com
spread_and_mid25 pts - Colocar uma ordem no livro com
add_limit_order25 pts - Consumir as ofertas de venda com
match_market_buy25 pts