Размышления о стратегии высокочастотного трейдинга (3)

Автор:Трава, Создано: 2023-08-07 18:17:28, Обновлено: 2023-09-18 19:50:53

img

В предыдущей статье я рассказал о том, как моделировать накопленные объемы сделок, а также простые анализы ценовых шоков. В этой статье мы продолжим анализ данных о торговых заказах.

Временные интервалы

Обычно предполагается, что время прибытия заказа соответствует процессу Пэпсон.Процесс ПарсанВ следующей статье я покажу, как это работает.

Скачать aggTrades 5 августа, в общей сложности 193193 сделки, очень преувеличено. Во-первых, сначала посмотрите на распределение платежей, и вы увидите негладкий локальный пик примерно в 100 мс и 500 мс, который, вероятно, вызван роботом, порученным Айсбергу, и это может быть одной из причин необычности дня.

Функция массы вероятности (PMF) для распределения Пэроса дается следующей формулой:

img

Среди них:

  • k - количество событий, которые нас интересуют.
  • λ - средняя частота событий в единичном времени (или единичном пространстве).
  • P ((k; λ) представляет собой вероятность того, что k событий случайно произойдут при условии данной средней вероятности λ.

В процессе парсанов интервал времени между событиями подчиняется индексовому распределению. Функция вероятности плотности индексового распределения (PDF) дается следующей формулой:

img

При сочетании результатов обнаружено, что ожидаемое отличие от распределения Папсона значительно больше, а процесс Папсона занижает частоту длительных интервалов и переоценивает частоту низких интервалов. (Распределение фактических интервалов ближе к скорректированному распределению Парето)

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

Статистические распределения количества случаев возникновения заказов в 1s, сравниваемые с распределением Пэпсона, также очень отчетливо отличаются. Распределение Пэпсона значительно недооценивает частоту возникновения маловероятных событий. Возможные причины:

  • Неконстантная вероятность: процесс Пэросона предполагает, что средняя вероятность событий в любом данном периоде времени является постоянной. Если эта гипотеза не соответствует действительности, то распределение данных будет иметь отклонение от распределения Пэросона.
  • Взаимодействие процессов: Еще одна основная гипотеза процессов Парсона заключается в том, что события независимы друг от друга. Если события в реальном мире влияют друг на друга, то их распределение может отклоняться от распределения Парсона.

То есть, в реальном окружении, частота, с которой происходят заказы, не является постоянной, требует обновления в режиме реального времени, и возникает стимулирующее действие, то есть больше заказов в фиксированное время стимулирует больше заказов. Это делает так, что стратегия не может фиксировать один параметр.

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

Обновление параметров в реальном времени

Анализ промежутков между заказами позволяет сделать вывод, что фиксированные параметры не подходят для реальных рыночных условий, и ключевые параметры описания рынка стратегии нуждаются в обновлении в режиме реального времени. Наиболее простым вариантом является скользящий средний показатель в скользящем окне. Ниже приведены средние значения частоты оплаты в течение 1 с и объема торговли в 1000 окнах соответственно.

На графике также можно понять, почему частота заказов так сильно отклоняется от распределения Пэпсона, хотя среднее количество заказов в секунду составляет всего 8,5 раз, в крайних случаях среднее количество заказов в секунду значительно отклоняется.

Здесь было обнаружено, что средние значения первых двух секунд прогнозируют наименьшую погрешность парадикса и намного лучше, чем простые средние значения.

result_df['order_count'][::10].rolling(1000).mean().plot(figsize=(10,5),grid=True);

img

result_df
order_count количество_сумма
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

Подведение итогов

В этой статье вкратце представлены причины отклонения от процесса отклонения от интервала времени заказа, в основном потому, что параметры меняются с течением времени. Для более точного прогнозирования рынка стратегии требуют выполнения прогнозов основных параметров рынка в режиме реального времени.


Больше