O artigo anterior demonstrou a necessidade de ajustar dinamicamente os parâmetros e como avaliar a qualidade das estimativas, estudando os intervalos de chegada de pedidos.
Binance fornece downloads de dados históricos para best_bid_price (o preço de compra mais alto), best_bid_quantity (a quantidade no melhor preço de compra), best_ask_price (o preço de venda mais baixo), best_ask_quantity (a quantidade no melhor preço de compra) e transaction_time. Estes dados não incluem os níveis do segundo ou mais profundo livro de pedidos. A análise neste artigo é baseada no mercado YGG em 7 de agosto, que experimentou volatilidade significativa com mais de 9 milhões de pontos de dados.
Primeiro, vamos dar uma olhada nas condições do mercado naquele dia. Houve grandes flutuações e o volume da carteira de pedidos mudou significativamente junto com a volatilidade do mercado. O spread, em particular, indicou a extensão das flutuações do mercado, que é a diferença entre os melhores preços de compra e venda. Nas estatísticas do mercado YGG naquele dia, o spread foi maior que um tick por 20% do tempo. Nesta era de vários bots de negociação competindo na carteira de pedidos, tais situações estão se tornando cada vez mais raras.
Em [1]:
from datetime import date,datetime
import time
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
Em [2]:
books = pd.read_csv('YGGUSDT-bookTicker-2023-08-07.csv')
Em [3]:
tick_size = 0.0001
Em [4]:
books['date'] = pd.to_datetime(books['transaction_time'], unit='ms')
books.index = books['date']
Em [5]:
books['spread'] = round(books['best_ask_price'] - books['best_bid_price'],4)
Em [6]:
books['best_bid_price'][::10].plot(figsize=(10,5),grid=True);
Fora[6]:
Em [7]:
books['best_bid_qty'][::10].rolling(10000).mean().plot(figsize=(10,5),grid=True);
books['best_ask_qty'][::10].rolling(10000).mean().plot(figsize=(10,5),grid=True);
Fora[7]:
Em [8]:
(books['spread'][::10]/tick_size).rolling(10000).mean().plot(figsize=(10,5),grid=True);
Fora[8]:
Em [9]:
books['spread'].value_counts()[books['spread'].value_counts()>500]/books['spread'].value_counts().sum()
Fora[9]:
As cotações desequilibradas são observadas a partir da diferença significativa nos volumes do livro de ordens entre as ordens de compra e venda na maior parte do tempo. Esta diferença tem um forte efeito preditivo sobre as tendências de curto prazo do mercado, semelhante à razão mencionada anteriormente de que uma diminuição no volume de ordens de compra geralmente leva a um declínio. Se um lado do livro de ordens for significativamente menor do que o outro, assumindo que as ordens de compra e venda ativas sejam semelhantes em volume, há uma maior probabilidade de o lado menor ser consumido, impulsionando assim as mudanças de preço.
Onde Q_b representa o montante das ordens de compra pendentes (best_bid_qty) e Q_a representa o montante das ordens de venda pendentes (best_ask_qty).
Defina o preço médio:
O gráfico abaixo mostra a relação entre a taxa de mudança do preço médio no próximo intervalo de 1 e o desequilíbrio I. Como esperado, quanto mais provável é que o preço aumente à medida que I aumenta e quanto mais perto ele se aproxima de 1, mais a mudança de preço acelera. Na negociação de alta frequência, a introdução do preço intermediário é para prever melhor as mudanças de preço futuras, ou seja, e a diferença de preço futura é menor, quanto melhor o preço intermediário é definido. Obviamente, o desequilíbrio de ordens pendentes fornece informações adicionais para a previsão da estratégia, tendo isso em mente, definindo o preço médio ponderado:
Em [10]:
books['I'] = books['best_bid_qty'] / (books['best_bid_qty'] + books['best_ask_qty'])
Em [11]:
books['mid_price'] = (books['best_ask_price'] + books['best_bid_price'])/2
Em [12]:
bins = np.linspace(0, 1, 51)
books['I_bins'] = pd.cut(books['I'], bins, labels=bins[1:])
books['price_change'] = (books['mid_price'].pct_change()/tick_size).shift(-1)
avg_change = books.groupby('I_bins')['price_change'].mean()
plt.figure(figsize=(8,5))
plt.plot(avg_change)
plt.xlabel('I Value Range')
plt.ylabel('Average Mid Price Change Rate');
plt.grid(True)
Fora[12]:
Em [13]:
books['weighted_mid_price'] = books['mid_price'] + books['spread']*books['I']/2
bins = np.linspace(-1, 1, 51)
books['I_bins'] = pd.cut(books['I'], bins, labels=bins[1:])
books['weighted_price_change'] = (books['weighted_mid_price'].pct_change()/tick_size).shift(-1)
avg_change = books.groupby('I_bins')['weighted_price_change'].mean()
plt.figure(figsize=(8,5))
plt.plot(avg_change)
plt.xlabel('I Value Range')
plt.ylabel('Weighted Average Mid Price Change Rate');
plt.grid(True)
Fora[13]:
A partir do gráfico, pode-se observar que o preço médio ponderado mostra variações menores em comparação com diferentes valores de I, indicando que é um melhor ajuste. No entanto, ainda há alguns desvios, particularmente em torno de 0,2 e 0,8. Isso sugere que eu ainda forneço informações adicionais. A suposição de uma relação completamente linear entre o termo de correção de preço e I, como implícito pelo preço médio ponderado, não está alinhada com a realidade. Pode-se ver no gráfico que a velocidade de desvio aumenta quando me aproximo de 0 e 1, indicando uma relação não linear.
Para fornecer uma representação mais intuitiva, aqui está uma redefinição de I:
Definição revista de I:
Neste momento:
Ao observar, pode-se notar que o preço médio ponderado é uma correção para o preço médio médio, onde o termo de correção é multiplicado pelo spread. O termo de correção é uma função de I, e o preço médio ponderado assume uma relação simples de I/2. Neste caso, a vantagem da distribuição I ajustada (-1, 1) torna-se aparente, pois I é simétrica em torno da origem, tornando conveniente encontrar uma relação adequada para a função. Examinando o gráfico, parece que esta função deve satisfazer potências de I, pois se alinha com o rápido crescimento em ambos os lados ímpares e simetria da origem. Além disso, pode-se observar que os valores próximos à origem são próximos da linear. Além disso, quando I é 0, o resultado da função é 0, e quando I é 1, o resultado é 0.5.
Aqui N é um número par positivo, após testes reais, é melhor quando N é 8.
Neste ponto, a previsão de mudanças de preço médio não está mais significativamente relacionada com I. Embora este resultado seja ligeiramente melhor do que o preço médio ponderado simples, ele ainda não é aplicável em cenários reais de negociação.Micro-PreçoO método de Markov é introduzido usando uma abordagem de cadeia de Markov, e o código relacionado é fornecido.
Em [14]:
books['I'] = (books['best_bid_qty'] - books['best_ask_qty']) / (books['best_bid_qty'] + books['best_ask_qty'])
Em [15]:
books['weighted_mid_price'] = books['mid_price'] + books['spread']*books['I']/2
bins = np.linspace(-1, 1, 51)
books['I_bins'] = pd.cut(books['I'], bins, labels=bins[1:])
books['weighted_price_change'] = (books['weighted_mid_price'].pct_change()/tick_size).shift(-1)
avg_change = books.groupby('I_bins')['weighted_price_change'].mean()
plt.figure(figsize=(8,5))
plt.plot(avg_change)
plt.xlabel('I Value Range')
plt.ylabel('Weighted Average Mid Price Change Rate');
plt.grid(True)
Fora [1]:
Em [16]:
books['adjust_mid_price'] = books['mid_price'] + books['spread']*books['I']*(books['I']**8+1)/4
bins = np.linspace(-1, 1, 51)
books['I_bins'] = pd.cut(books['I'], bins, labels=bins[1:])
books['adjust_mid_price'] = (books['adjust_mid_price'].pct_change()/tick_size).shift(-1)
avg_change = books.groupby('I_bins')['adjust_mid_price'].mean()
plt.figure(figsize=(8,5))
plt.plot(avg_change)
plt.xlabel('I Value Range')
plt.ylabel('Weighted Average Mid Price Change Rate');
plt.grid(True)
Fora [1]:
O preço médio é crucial para estratégias de alta frequência, pois serve como uma previsão de preços futuros de curto prazo. Portanto, é importante que o preço médio seja o mais preciso possível. As abordagens de preço médio discutidas anteriormente são baseadas em dados do livro de ordens, pois apenas o nível superior do livro de ordens é utilizado na análise. Na negociação ao vivo, as estratégias devem visar utilizar todos os dados disponíveis, incluindo dados comerciais, para validar as previsões de preço médio contra os preços reais da transação.