No artigo anterior, introduzi como modelar o volume de negociação acumulado e analisei o fenômeno do impacto do preço. Neste artigo, vou continuar a analisar os dados de ordens de negociação.
Em geral, assume-se que o tempo de chegada das encomendas segue um processo de Poisson.Processo de PoissonAqui, vou fornecer provas empíricas.
Eu baixei os dados do aggTrades para 5 de agosto, que consiste em 1.931.193 negócios, o que é bastante significativo. Primeiro, vamos dar uma olhada na distribuição de ordens de compra. Podemos ver um pico local não suave em torno de 100ms e 500ms, o que provavelmente é causado por ordens de iceberg colocadas por bots de negociação em intervalos regulares. Isso também pode ser uma das razões para as condições incomuns do mercado naquele dia.
A função de massa de probabilidade (PMF) da distribuição de Poisson é dada pela seguinte fórmula:
Onde:
Em um processo de Poisson, os intervalos de tempo entre os eventos seguem uma distribuição exponencial.
O processo de Poisson subestima a frequência de longos intervalos de tempo e superestima a frequência de intervalos de tempo curtos. (A distribuição real de intervalos é mais próxima de uma distribuição de Pareto modificada)
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]:
trades = pd.read_csv('YGGUSDT-aggTrades-2023-08-05.csv')
trades['date'] = pd.to_datetime(trades['transact_time'], unit='ms')
trades.index = trades['date']
buy_trades = trades[trades['is_buyer_maker']==False].copy()
buy_trades = buy_trades.groupby('transact_time').agg({
'agg_trade_id': 'last',
'price': 'last',
'quantity': 'sum',
'first_trade_id': 'first',
'last_trade_id': 'last',
'is_buyer_maker': 'last',
'date': 'last',
'transact_time':'last'
})
buy_trades['interval']=buy_trades['transact_time'] - buy_trades['transact_time'].shift()
buy_trades.index = buy_trades['date']
Em [10]:
buy_trades['interval'][buy_trades['interval']<1000].plot.hist(bins=200,figsize=(10, 5));
Fora[10]:
Em [20]:
Intervals = np.array(range(0, 1000, 5))
mean_intervals = buy_trades['interval'].mean()
buy_rates = 1000/mean_intervals
probabilities = np.array([np.mean(buy_trades['interval'] > interval) for interval in Intervals])
probabilities_s = np.array([np.e**(-buy_rates*interval/1000) for interval in Intervals])
plt.figure(figsize=(10, 5))
plt.plot(Intervals, probabilities)
plt.plot(Intervals, probabilities_s)
plt.xlabel('Intervals')
plt.ylabel('Probability')
plt.grid(True)
Fora [1]:
Quando se compara a distribuição do número de ocorrências de ordem em 1 segundo com a distribuição de Poisson, a diferença também é significativa.
Em outras palavras, em um ambiente do mundo real, a frequência de ocorrências de ordens não é constante e precisa ser atualizada em tempo real. Também pode haver um efeito incentivador, onde mais ordens dentro de um período de tempo fixo estimulam mais ordens. Isso torna as estratégias incapazes de depender de um único parâmetro fixo.
Em [190]:
result_df = buy_trades.resample('1S').agg({
'price': 'count',
'quantity': 'sum'
}).rename(columns={'price': 'order_count', 'quantity': 'quantity_sum'})
Em [219]:
count_df = result_df['order_count'].value_counts().sort_index()[result_df['order_count'].value_counts()>20]
(count_df/count_df.sum()).plot(figsize=(10,5),grid=True,label='sample pmf');
from scipy.stats import poisson
prob_values = poisson.pmf(count_df.index, 1000/mean_intervals)
plt.plot(count_df.index, prob_values,label='poisson pmf');
plt.legend() ;
Fora[219]:
A partir da análise dos intervalos de ordens anteriores, pode-se concluir que os parâmetros fixos não são adequados para as condições reais do mercado, e os parâmetros-chave que descrevem o mercado na estratégia precisam ser atualizados em tempo real. A solução mais direta é usar uma média móvel de janela móvel. Os dois gráficos abaixo mostram a frequência de ordens de compra dentro de 1 segundo e a média do volume de negociação com um tamanho de janela de 1000. Pode-se observar que há um fenômeno de aglomeração na negociação, onde a frequência de ordens é significativamente maior do que o habitual por um período de tempo, e o volume também aumenta sincronicamente. Aqui, a média dos valores anteriores é usada para prever o valor absoluto mais recente, e o erro médio dos resíduos é usado para medir a qualidade da previsão.
A partir dos gráficos, também podemos entender por que a frequência de ordem se desvia tanto da distribuição de Poisson.
Descobriu-se que usar a média dos dois segundos anteriores para prever produz o menor erro residual, e é muito melhor do que simplesmente usar a média para resultados de previsão.
Em [221]:
result_df['order_count'].rolling(1000).mean().plot(figsize=(10,5),grid=True);
Fora[221]:
Em [193]:
result_df['quantity_sum'].rolling(1000).mean().plot(figsize=(10,5),grid=True);
Fora[193]:
Em [195]:
(result_df['order_count'] - result_df['mean_count'].mean()).abs().mean()
Fora[195]:
6.985628185332997
Em [205]:
result_df['mean_count'] = result_df['order_count'].rolling(2).mean()
(result_df['order_count'] - result_df['mean_count'].shift()).abs().mean()
Fora[205]:
3.091737586730269
Este artigo explica brevemente as razões para o desvio dos intervalos de tempo de ordem do processo de Poisson, principalmente devido à variação de parâmetros ao longo do tempo. Para prever com precisão o mercado, as estratégias precisam fazer previsões em tempo real dos parâmetros fundamentais do mercado. Os resíduos podem ser usados para medir a qualidade das previsões. O exemplo fornecido acima é uma demonstração simples, e há uma extensa pesquisa sobre análise de séries temporais específicas, agrupamento de volatilidade e outros tópicos relacionados, a demonstração acima pode ser melhorada.