No artigo anterior, eu expliquei como modelar o volume acumulado de transações e fazer uma simples análise do fenômeno de choque de preço. Este artigo também vai continuar a análise em torno dos dados de pedidos de negociações.
Em geral, é assumido que o tempo de chegada da encomenda corresponde ao processo de Parasin.O processo de BartholinO que eu vou demonstrar abaixo.
O download do aggTrades de 5 de agosto, com um total de 1931.193 trades, é muito exagerado. Primeiro, olhe para a distribuição de pagamentos e veja que há um pico local irregular em torno de 100ms e 500ms, que deve ser causado pelo cronograma robótico encomendado pelo iceberg, que também pode ser uma das razões para a situação incomum do dia.
A função de massa de probabilidade (PMF) da distribuição de Parsons é dada pela seguinte fórmula:
Entre eles:
No processo de Parsons, o intervalo de tempo entre os eventos está sujeito a uma distribuição de índices. A função de densidade de probabilidade da distribuição de índices (PDF) é dada pela seguinte fórmula:
Ao combinar a descoberta de que os resultados e a distribuição de Parsons diferem muito do que se esperava, o processo de Parsons subestimou a frequência de tempos de intervalos longos e superestimou a frequência de tempos de intervalos baixos.
from datetime import date,datetime
import time
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
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']
buy_trades['interval'][buy_trades['interval']<1000].plot.hist(bins=200,figsize=(10, 5));
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)
A distribuição do número de vezes que a ordem ocorre em 1s é comparada com a distribuição de Parsons, que também é muito diferente. A distribuição de Parsons subestima significativamente a frequência de ocorrência de eventos de baixa probabilidade.
Isto é, no ambiente real, a freqüência com que as ordens ocorrem é inconstante, precisa ser atualizada em tempo real, e ocorre um efeito incentivador, ou seja, mais ordens em um tempo fixo incentivam mais ordens. Isso torna a estratégia impossível de fixar um único parâmetro.
result_df = buy_trades.resample('0.1S').agg({
'price': 'count',
'quantity': 'sum'
}).rename(columns={'price': 'order_count', 'quantity': 'quantity_sum'})
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() ;
A partir da análise anterior dos intervalos de encomendas, pode-se concluir que os parâmetros fixos não são adequados para o mercado real e que os parâmetros-chave da descrição do mercado da estratégia precisam ser atualizados em tempo real. O método mais fácil de pensar é a média móvel da janela deslizante. Os dois gráficos abaixo são os valores médios das janelas de 1000 de freqüência de pagamentos em 1s e volume de transações, respectivamente, e pode-se ver que há um fenômeno de aglomeração de transações, ou seja, há um período de tempo em que a frequência de encomendas é significativamente maior do que o normal e o volume também é sincronizado.
O gráfico também explica por que a freqüência de pedidos se desvia tanto da distribuição de Parsons, embora a média do número de pedidos por segundo seja de apenas 8,5 vezes, mas em casos extremos a média dos pedidos por segundo se desvia muito.
Aqui, foi encontrado que o erro de parâmetro é menor quando se prevê o valor médio dos dois primeiros segundos e muito melhor do que o resultado de uma simples previsão do valor médio.
result_df['order_count'][::10].rolling(1000).mean().plot(figsize=(10,5),grid=True);
result_df
ordem_conta | quantidade_som | |
---|---|---|
2023-08-05 03:30:06.100 | 1 | 76.0 |
2023-08-05 03:30:06.200 | 0 | 0.0 |
2023-08-05 03:30:06.300 | 0 | 0.0 |
2023-08-05 03:30:06.400 | 1 | 416.0 |
2023-08-05 03:30:06.500 | 0 | 0.0 |
… | … | … |
2023-08-05 23:59:59.500 | 3 | 9238.0 |
2023-08-05 23:59:59.600 | 0 | 0.0 |
2023-08-05 23:59:59.700 | 1 | 3981.0 |
2023-08-05 23:59:59.800 | 0 | 0.0 |
2023-08-05 23:59:59.900 | 2 | 534.0 |
result_df['quantity_sum'].rolling(1000).mean().plot(figsize=(10,5),grid=True);
(result_df['order_count'] - result_df['mean_count'].mean()).abs().mean()
6.985628185332997
result_df['mean_count'] = result_df['order_count'].ewm(alpha=0.11, adjust=False).mean()
(result_df['order_count'] - result_df['mean_count'].shift()).abs().mean()
0.6727616961866929
result_df['mean_quantity'] = result_df['quantity_sum'].ewm(alpha=0.1, adjust=False).mean()
(result_df['quantity_sum'] - result_df['mean_quantity'].shift()).abs().mean()
4180.171479076811
Este artigo apresenta brevemente as razões para o processo de desvio do intervalo de tempo das ordens, principalmente porque os parâmetros mudam ao longo do tempo. Para uma previsão mais precisa do mercado, a estratégia requer previsões em tempo real dos parâmetros básicos do mercado. O resíduo pode ser usado para medir o bom e o mau da previsão.