Überlegungen zur Hochfrequenz-Handelsstrategie (3)

Schriftsteller:Das Gras, Erstellt: 2023-08-07 18:17:28, Aktualisiert: 2023-09-18 19:50:53

img

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.

Zeitintervalle für Bestellungen

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:

img

Sie sind:

  • k ist die Anzahl der Ereignisse, an denen wir interessiert sind.
  • λ ist die durchschnittliche Häufigkeit der Ereignisse in der Zeit (oder im Raum).
  • P ((k; λ) gibt die Wahrscheinlichkeit an, dass k Ereignisse zufällig unter gegebenen durchschnittlichen Vorkommenszahlen λ eintreten.

Die Zeitintervalle zwischen den Ereignissen unterliegen einer Indexverteilung. Die Wahrscheinlichkeitsdichte der Indexverteilung (PDF) wird durch folgende Formel angegeben:

img

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

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

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.

  • Unkonstante Ereignisfrequenz: Der Parsons-Prozess geht davon aus, dass die durchschnittliche Ereignisfrequenz in irgendeinem bestimmten Zeitraum eine Konstante ist. Wenn diese Annahme nicht zutrifft, ist die Verteilung der Daten mit der Parsons-Verteilung abweichend.
  • Interaktion der Prozesse: Eine andere grundlegende Annahme des Parsons-Prozesses ist, dass die Ereignisse unabhängig voneinander sind. Wenn Ereignisse in der realen Welt sich gegenseitig beeinflussen, kann ihre Verteilung von der Parsons-Verteilung abweichen.

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

img

Echtzeit-Aktualisierung der Parameter

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

img

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

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

Zusammenfassung

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.


Mehr