In dem vorherigen Artikel habe ich erklärt, wie man die kumulative Transaktionsmenge modelliert und eine einfache Analyse von Preis-Shock-Phänomenen durchführt. In diesem Artikel werde ich weiter analysieren, was sich um die Transaktionsorderdaten dreht.
In der Regel wird davon ausgegangen, dass die Ankunft der Bestellung im Einklang mit dem Parasol-Prozess steht.Der ParthenonprozessIch werde es Ihnen nachfolgend beweisen.
Der AggTrades-Download vom 5. August, mit insgesamt 193193 Trades, ist sehr übertrieben. Zunächst einmal, wenn man sich die Verteilung der Zahlungen ansieht, kann man sehen, dass es einen schlechten lokalen Spitzenwert zwischen 100 ms und 500 ms gibt, der vermutlich durch die von einem Eisberg beauftragten Roboter-Zeitpläne verursacht wurde.
Die Wahrscheinlichkeitsmassenfunktion (PMF) der Parsons-Verteilung wird durch folgende Formel angegeben:
Sie sind:
Die Zeitintervalle zwischen den Ereignissen unterliegen einer Indexverteilung. Die Wahrscheinlichkeitsdichte der Indexverteilung (PDF) wird durch folgende Formel angegeben:
Durch die Kombination wurde festgestellt, dass die Ergebnisse und die erwarteten Unterschiede in der Pareto-Verteilung größer waren, und der Pareto-Prozess unterschätzte die Häufigkeit der langen Intervallzeiten und überschätzte die Häufigkeit der niedrigen Intervallzeiten.
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)
Die Anzahl der Aufträge innerhalb von 1 s wird mit der Parsons-Verteilung verglichen. Die Unterschiede sind ebenfalls sehr deutlich. Die Parsons-Verteilung unterschätzt die Häufigkeit von geringen Wahrscheinlichkeitsereignissen erheblich.
Das heißt, in einer realen Umgebung ist die Häufigkeit der Aufträge nicht konstant, sie müssen in Echtzeit aktualisiert werden, und es gibt eine Anreizwirkung, dass mehr Aufträge in einer festen Zeit mehr Aufträge anregen. Dies macht es für die Strategie unmöglich, einen einzigen Parameter festzulegen.
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() ;
Die vorhergehende Analyse der Auftragsintervalle führt zu dem Schluss, dass feststehende Parameter nicht für den realen Markt geeignet sind und dass die wichtigsten Parameter der Strategie für die Marktbeschreibung in Echtzeit aktualisiert werden müssen. Die am einfachsten denkbare Lösung ist der gleitende Durchschnitt des Gleitfensters. Die folgenden beiden Diagramme sind die Durchschnittswerte der Zahlungsfrequenz innerhalb von 1s und des Handelsvolumens in 1000 Fenstern.
Aus dem Diagramm ist auch zu verstehen, warum die Bestellfrequenz so stark von der Parsons-Verteilung abweicht, obwohl die durchschnittliche Anzahl der Bestellungen nur 8,5 Mal pro Sekunde beträgt, aber die durchschnittliche Anzahl der Bestellungen pro Sekunde in extremen Fällen weit abweicht.
Hier wurde festgestellt, dass die Prognose mit dem Mittelwert der ersten zwei Sekunden den geringsten Parameterfehler hat und viel besser ist als die einfache Prognose mit dem Mittelwert.
result_df['order_count'][::10].rolling(1000).mean().plot(figsize=(10,5),grid=True);
result_df
Anzahl der Bestellungen | Menge_summe | |
---|---|---|
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
Dieser Artikel beschreibt kurz die Gründe für den Abweichungsprozess zwischen den Auftragszeiten, hauptsächlich weil sich die Parameter mit der Zeit verändern. Um den Markt genauer prognostizieren zu können, müssen Strategien in Echtzeit auf die grundlegenden Parameter des Marktes hingewiesen werden.