Dans l'article précédent, j'ai expliqué comment modéliser le volume cumulé des transactions et comment analyser simplement les chocs de prix. Cet article se concentrera sur les données des ordres de transactions.
En général, on suppose que l'heure d'arrivée de l'ordre est conforme au processus de partage.Le processus de BarthèsJe vais vous le prouver ci-dessous.
Le téléchargement de l'aggTrades du 5 août, avec un total de 1931.193 transactions, est très exagéré. Tout d'abord, en regardant la distribution des paiements, on peut voir un pic local peu lisse autour de 100 ms et 500 ms, qui devrait être causé par le calendrier robot mis en place par l'iceberg, ce qui pourrait être l'une des raisons de l'anomalie du jour.
La fonction de masse de probabilité (PMF) de la distribution de Parsons est donnée par la formule suivante:
Parmi eux:
Dans le processus de Parason, l'intervalle de temps entre les événements est soumis à une distribution indicielle. La fonction de densité de probabilité de la distribution indicielle (PDF) est donnée par la formule suivante:
En combinant les résultats et la distribution de Parsons, on constate une différence plus grande que ce qui est attendu, le processus de Parsons sous-estime la fréquence des temps d'intervalle longs et surestime la fréquence des temps d'intervalle bas.
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)
La distribution de la fréquence des commandes dans les 1s est comparée à la distribution de Parsons, où les différences sont également très évidentes. La distribution de Parsons sous-estime de manière significative la fréquence des événements à faible probabilité.
C'est-à-dire que, dans un environnement réel, la fréquence d'ordre n'est pas constante, nécessite des mises à jour en temps réel, et qu'il y a une incitation, c'est-à-dire que plus d'ordres dans un temps fixe stimulent plus d'ordres.
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() ;
L'analyse des intervalles d'ordres précédents permet de conclure que les paramètres fixes ne sont pas adaptés aux marchés réels et que les paramètres clés de la description du marché de la stratégie doivent être mis à jour en temps réel. La solution la plus facile à penser est la moyenne mobile des fenêtres coulissantes. Les deux graphiques suivants sont respectivement la moyenne de la fréquence des paiements en 1s et la moyenne de l'erreur absolue du résidu pour 1000 fenêtres de transactions.
On peut également comprendre sur le graphique pourquoi la fréquence des commandes s'écarte si fortement de la distribution de Parsons, alors que la moyenne de la quantité d'ordres par seconde est de seulement 8,5 fois, mais que la moyenne des commandes par seconde dans les cas extrêmes s'écarte beaucoup.
Il s'avère que l'erreur de décalage est la plus faible et bien meilleure que la simple moyenne des deux premières secondes.
result_df['order_count'][::10].rolling(1000).mean().plot(figsize=(10,5),grid=True);
result_df
Compte de commandes | quantité_somme | |
---|---|---|
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
Cet article présente brièvement les raisons pour lesquelles le processus de décalage des intervalles de temps des commandes se produit, principalement parce que les paramètres changent au fil du temps. Pour prédire le marché plus précisément, les stratégies nécessitent des prévisions en temps réel sur les paramètres de base du marché. On peut mesurer le bien et le mal des prévisions avec des résidus.