Reflexões sobre estratégias de negociação de alta frequência (3)

Autora:Ervas daninhas, Criado: 2023-08-07 18:17:28, Atualizado: 2023-09-18 19:50:53

img

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.

Tempo de encomenda

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:

img

Entre eles:

  • k é o número de eventos de nosso interesse.
  • λ é a frequência média de ocorrência de eventos em um período de tempo unitário (ou espaço unitário).
  • P ((k; λ) indica a probabilidade de ocorrência de k eventos por acaso, sob condições de uma média de ocorrência λ.

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:

img

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));

img

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)

img

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.

  • Incidência inconstante: O processo de Parsons assume que a incidência média de eventos em qualquer período de tempo é constante. Se esta hipótese não for verdadeira, a distribuição dos dados se desviará da distribuição de Parsons.
  • Interação de processos: Outra premissa básica do processo de Parsons é que os eventos são independentes uns dos outros. Se os eventos no mundo real se influenciarem, então sua distribuição pode se desviar da distribuição de Parsons.

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() ;

img

Atualização de parâmetros em tempo real

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);

img

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);

img

(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

Resumo

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.


Mais.