Artikel ini membahas strategi perdagangan frekuensi tinggi, dengan penelitian fokus pada pemodelan volume perdagangan dan kejutan harga. Artikel ini mengusulkan model awal posisi paling optimal yang tergantung dengan menganalisis transaksi tunggal, kejutan harga interval tetap, dan efek transaksi pada harga. Model ini didasarkan pada pemahaman volume perdagangan dan kejutan harga, mencoba untuk menemukan posisi perdagangan optimal.
Pada artikel sebelumnya, kami menghasilkan ekspresi kemungkinan transaksi tunggal lebih besar dari nilai tertentu:
Kami juga peduli dengan distribusi volume transaksi dalam jangka waktu tertentu, yang secara intuitif harus terkait dengan jumlah transaksi dan frekuensi pesanan per transaksi. Di bawah ini data diproses dengan interval yang tetap.
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('HOOKUSDT-aggTrades-2023-01-27.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']
Menggabungkan transaksi satuan dengan interval 1s menjadi jumlah transaksi, menghilangkan bagian yang tidak terjadi, dan menyesuaikan dengan distribusi transaksi tunggal di atas, hasil yang terlihat lebih baik, menganggap semua transaksi dalam 1s sebagai satuan, masalah ini menjadi masalah yang telah diselesaikan. Tetapi ketika siklus diperpanjang (relatif terhadap frekuensi transaksi), kesalahan meningkat, dan penelitian menemukan bahwa kesalahan ini disebabkan oleh perbaikan distribusi Pareto sebelumnya. Ini menunjukkan bahwa ketika siklus diperpanjang, yang berisi lebih banyak transaksi tunggal, semakin banyak transaksi bergabung dan semakin dekat dengan distribusi Pareto, situasi ini harus dihapus.
df_resampled = buy_trades['quantity'].resample('1S').sum()
df_resampled = df_resampled.to_frame(name='quantity')
df_resampled = df_resampled[df_resampled['quantity']>0]
buy_trades
agg_trade_id | harga | jumlah | first_trade_id | last_trade_id | adalah_pembeli_pembuat | tanggal | waktu transaksi | interval | berbeda | |
---|---|---|---|---|---|---|---|---|---|---|
2023-01-27 00:00:00.161 | 1138369 | 2.901 | 54.3 | 3806199 | 3806201 | Tidak benar | 2023-01-27 00:00:00.161 | 1674777600161 | Tidak | 0.001 |
2023-01-27 00:00:04.140 | 1138370 | 2.901 | 291.3 | 3806202 | 3806203 | Tidak benar | 2023-01-27 00:00:04.140 | 1674777604140 | 3979.0 | 0.000 |
2023-01-27 00:00:04.339 | 1138373 | 2.902 | 55.1 | 3806205 | 3806207 | Tidak benar | 2023-01-27 00:00:04.339 | 1674777604339 | 199.0 | 0.001 |
2023-01-27 00:00:04.772 | 1138374 | 2.902 | 1032.7 | 3806208 | 3806223 | Tidak benar | 2023-01-27 00:00:04.772 | 1674777604772 | 433.0 | 0.000 |
2023-01-27 00:00:05.562 | 1138375 | 2.901 | 3.5 | 3806224 | 3806224 | Tidak benar | 2023-01-27 00:00:05.562 | 1674777605562 | 790.0 | 0.000 |
… | … | … | … | … | … | … | … | … | … | … |
2023-01-27 23:59:57.739 | 1544370 | 3.572 | 394.8 | 5074645 | 5074651 | Tidak benar | 2023-01-27 23:59:57.739 | 1674863997739 | 1224.0 | 0.002 |
2023-01-27 23:59:57.902 | 1544372 | 3.573 | 177.6 | 5074652 | 5074655 | Tidak benar | 2023-01-27 23:59:57.902 | 1674863997902 | 163.0 | 0.001 |
2023-01-27 23:59:58.107 | 1544373 | 3.573 | 139.8 | 5074656 | 5074656 | Tidak benar | 2023-01-27 23:59:58.107 | 1674863998107 | 205.0 | 0.000 |
2023-01-27 23:59:58.302 | 1544374 | 3.573 | 60.5 | 5074657 | 5074657 | Tidak benar | 2023-01-27 23:59:58.302 | 1674863998302 | 195.0 | 0.000 |
2023-01-27 23:59:59.894 | 1544376 | 3.571 | 12.1 | 5074662 | 5074664 | Tidak benar | 2023-01-27 23:59:59.894 | 1674863999894 | 1592.0 | 0.000 |
#1s内的累计分布
depths = np.array(range(0, 3000, 5))
probabilities = np.array([np.mean(df_resampled['quantity'] > depth) for depth in depths])
mean = df_resampled['quantity'].mean()
alpha = np.log(np.mean(df_resampled['quantity'] > mean))/np.log(2.05)
probabilities_s = np.array([((1+20**(-depth/mean))*depth/mean+1)**(alpha) for depth in depths])
plt.figure(figsize=(10, 5))
plt.plot(depths, probabilities)
plt.plot(depths, probabilities_s)
plt.xlabel('Depth')
plt.ylabel('Probability of execution')
plt.title('Execution probability at different depths')
plt.grid(True)
df_resampled = buy_trades['quantity'].resample('30S').sum()
df_resampled = df_resampled.to_frame(name='quantity')
df_resampled = df_resampled[df_resampled['quantity']>0]
depths = np.array(range(0, 12000, 20))
probabilities = np.array([np.mean(df_resampled['quantity'] > depth) for depth in depths])
mean = df_resampled['quantity'].mean()
alpha = np.log(np.mean(df_resampled['quantity'] > mean))/np.log(2.05)
probabilities_s = np.array([((1+20**(-depth/mean))*depth/mean+1)**(alpha) for depth in depths])
alpha = np.log(np.mean(df_resampled['quantity'] > mean))/np.log(2)
probabilities_s_2 = np.array([(depth/mean+1)**alpha for depth in depths]) # 无修正
plt.figure(figsize=(10, 5))
plt.plot(depths, probabilities,label='Probabilities (True)')
plt.plot(depths, probabilities_s, label='Probabilities (Simulation 1)')
plt.plot(depths, probabilities_s_2, label='Probabilities (Simulation 2)')
plt.xlabel('Depth')
plt.ylabel('Probability of execution')
plt.title('Execution probability at different depths')
plt.legend()
plt.grid(True)
Sekarang untuk distribusi jumlah transaksi yang terakumulasi dalam waktu yang berbeda, simpulkan rumus umum, dan sesuaikan dengan distribusi transaksi tunggal, tanpa menggunakan statistik terpisah setiap kali.
Di mana avg_interval menunjukkan interval rata-rata transaksi tunggal, dan avg_interval_T menunjukkan interval rata-rata interval yang perlu diperkirakan, yang dikatakan agak menyimpang. Jika kita ingin memperkirakan transaksi 1s, perlu memperkirakan interval rata-rata peristiwa transaksi yang terkandung dalam statistik 1s. Jika probabilitas pesanan yang tiba sesuai dengan distribusi Parsons, ini seharusnya dapat diperkirakan secara langsung, tetapi penyimpangan sebenarnya sangat besar, tidak dijelaskan di sini.
Perhatikan bahwa kemungkinan transaksi yang lebih besar dari nilai tertentu dalam interval waktu di sini dan kemungkinan transaksi yang sebenarnya berada di lokasi dalam kedalaman harus berbeda jauh, karena semakin lama waktu tunggu, semakin besar kemungkinan perubahan buku pesanan, dan transaksi juga menyebabkan perubahan kedalaman, sehingga kemungkinan transaksi di lokasi kedalaman yang sama berubah secara real-time seiring dengan pembaruan data.
df_resampled = buy_trades['quantity'].resample('2S').sum()
df_resampled = df_resampled.to_frame(name='quantity')
df_resampled = df_resampled[df_resampled['quantity']>0]
depths = np.array(range(0, 6500, 10))
probabilities = np.array([np.mean(df_resampled['quantity'] > depth) for depth in depths])
mean = buy_trades['quantity'].mean()
adjust = buy_trades['interval'].mean() / 2620
alpha = np.log(np.mean(buy_trades['quantity'] > mean))/0.7178397931503168
probabilities_s = np.array([((1+20**(-depth*adjust/mean))*depth*adjust/mean+1)**(alpha) for depth in depths])
plt.figure(figsize=(10, 5))
plt.plot(depths, probabilities)
plt.plot(depths, probabilities_s)
plt.xlabel('Depth')
plt.ylabel('Probability of execution')
plt.title('Execution probability at different depths')
plt.grid(True)
Data transaksi adalah harta karun, dan masih banyak data yang dapat digali. Kita harus sangat memperhatikan dampak pesanan terhadap harga, yang mempengaruhi posisi daftar strategi. Juga berdasarkan data agregat transact_time, perhitungkan selisih harga terakhir dan harga pertama, jika hanya ada satu pesanan, selisihnya adalah 0. Anehnya, ada juga sejumlah kecil hasil data negatif, seharusnya masalah urutan urutan data, tidak masuk ke dalam di sini.
Hasilnya menunjukkan bahwa persentase tidak menimbulkan benturan mencapai 77%, persentase 1 tik adalah 16,5%, 2 tik adalah 3,7%, 3 tik adalah 1,2%, dan lebih dari 4 tik adalah kurang dari 1%.
Jumlah transaksi yang menyebabkan perbedaan harga yang sesuai dihitung, menghilangkan kebohongan yang terlalu besar, dan pada dasarnya sesuai dengan hubungan linier, sekitar 1 tik untuk setiap 1000 volume yang menghasilkan fluktuasi harga.
diff_df = trades[trades['is_buyer_maker']==False].groupby('transact_time')['price'].agg(lambda x: abs(round(x.iloc[-1] - x.iloc[0],3)) if len(x) > 1 else 0)
buy_trades['diff'] = buy_trades['transact_time'].map(diff_df)
diff_counts = buy_trades['diff'].value_counts()
diff_counts[diff_counts>10]/diff_counts.sum()
0.000 0.769965
0.001 0.165527
0.002 0.037826
0.003 0.012546
0.004 0.005986
0.005 0.003173
0.006 0.001964
0.007 0.001036
0.008 0.000795
0.009 0.000474
0.010 0.000227
0.011 0.000187
0.012 0.000087
0.013 0.000080
Name: diff, dtype: float64
diff_group = buy_trades.groupby('diff').agg({
'quantity': 'mean',
'diff': 'last',
})
diff_group['quantity'][diff_group['diff']>0][diff_group['diff']<0.01].plot(figsize=(10,5),grid=True);
Harga shock dalam statistik 2s, yang berbeda adalah bahwa di sini akan ada negatif, tentu saja karena di sini hanya statistik pembayaran, posisi simetris akan lebih besar satu tik. Lanjutkan untuk mengamati hubungan antara transaksi dan shock, hanya statistik yang lebih besar dari 0 hasil, kesimpulan dan pesanan tunggal hampir sama, juga hubungan linear yang mendekati, setiap tik membutuhkan sekitar 2000 jumlah.
df_resampled = buy_trades.resample('2S').agg({
'price': ['first', 'last', 'count'],
'quantity': 'sum'
})
df_resampled['price_diff'] = round(df_resampled[('price', 'last')] - df_resampled[('price', 'first')],3)
df_resampled['price_diff'] = df_resampled['price_diff'].fillna(0)
result_df_raw = pd.DataFrame({
'price_diff': df_resampled['price_diff'],
'quantity_sum': df_resampled[('quantity', 'sum')],
'data_count': df_resampled[('price', 'count')]
})
result_df = result_df_raw[result_df_raw['price_diff'] != 0]
result_df['price_diff'][abs(result_df['price_diff'])<0.016].value_counts().sort_index().plot.bar(figsize=(10,5));
result_df['price_diff'].value_counts()[result_df['price_diff'].value_counts()>30]
0.001 7176
-0.001 3665
0.002 3069
-0.002 1536
0.003 1260
0.004 692
-0.003 608
0.005 391
-0.004 322
0.006 259
-0.005 192
0.007 146
-0.006 112
0.008 82
0.009 75
-0.007 75
-0.008 65
0.010 51
0.011 41
-0.010 31
Name: price_diff, dtype: int64
diff_group = result_df.groupby('price_diff').agg({ 'quantity_sum': 'mean'})
diff_group[(diff_group.index>0) & (diff_group.index<0.015)].plot(figsize=(10,5),grid=True);
Sebelumnya mencari volume transaksi yang diperlukan untuk perubahan tik, tetapi tidak akurat karena dibangun pada kasus yang mengasumsikan bahwa kejutan telah terjadi. Sekarang sebaliknya melihat kejutan harga yang disebabkan oleh perubahan perdagangan.
Di sini data disampel dalam 1s, satu langkah per 100 kuantitas, dan statistik perubahan harga dalam kisaran kuantitas ini; membuat beberapa kesimpulan yang lebih berharga:
Di antaranya,
df_resampled = buy_trades.resample('1S').agg({
'price': ['first', 'last', 'count'],
'quantity': 'sum'
})
df_resampled['price_diff'] = round(df_resampled[('price', 'last')] - df_resampled[('price', 'first')],3)
df_resampled['price_diff'] = df_resampled['price_diff'].fillna(0)
result_df_raw = pd.DataFrame({
'price_diff': df_resampled['price_diff'],
'quantity_sum': df_resampled[('quantity', 'sum')],
'data_count': df_resampled[('price', 'count')]
})
result_df = result_df_raw[result_df_raw['price_diff'] != 0]
df = result_df.copy()
bins = np.arange(0, 30000, 100) #
labels = [f'{i}-{i+100-1}' for i in bins[:-1]]
df.loc[:, 'quantity_group'] = pd.cut(df['quantity_sum'], bins=bins, labels=labels)
grouped = df.groupby('quantity_group')['price_diff'].mean()
grouped_df = pd.DataFrame(grouped).reset_index()
grouped_df['quantity_group_center'] = grouped_df['quantity_group'].apply(lambda x: (float(x.split('-')[0]) + float(x.split('-')[1])) / 2)
plt.figure(figsize=(10,5))
plt.scatter(grouped_df['quantity_group_center'], grouped_df['price_diff'],s=10)
plt.plot(grouped_df['quantity_group_center'], np.array(grouped_df['quantity_group_center'].values)/2e6-0.000352,color='red')
plt.xlabel('quantity_group_center')
plt.ylabel('average price_diff')
plt.title('Scatter plot of average price_diff by quantity_group')
plt.grid(True)
grouped_df.head(10)
jumlah_kelompok | harga_perbedaan | jumlah_kelompok_pusat | |
---|---|---|---|
0 | 0-199 | -0.000302 | 99.5 |
1 | 100-299 | -0.000124 | 199.5 |
2 | 200-399 | -0.000068 | 299.5 |
3 | 300-499 | -0.000017 | 399.5 |
4 | 400-599 | -0.000048 | 499.5 |
5 | 500-699 | 0.000098 | 599.5 |
6 | 600-799 | 0.000006 | 699.5 |
7 | 700-899 | 0.000261 | 799.5 |
8 | 800-999 | 0.000186 | 899.5 |
9 | 900-1099 | 0.000299 | 999.5 |
Dengan pemodelan volume transaksi dan model kasar dari volume transaksi yang sesuai dengan dampak harga, tampaknya dapat dihitung posisi optimum untuk daftar.
Pertama, tulislah pengembalian yang diharapkan yang sederhana, yaitu probabilitas pembayaran yang terkumpul lebih besar dari Q dalam 1s, dikalikan dengan pengembalian yang diharapkan (yaitu harga yang terjatuh):
Berdasarkan gambar, diharapkan hasil maksimal sekitar 2500 dan sekitar 2,5 kali lipat dari volume rata-rata transaksi. Artinya, pesanan jual harus tergantung di posisi 2500. Perlu ditekankan lagi bahwa volume transaksi dalam garis lintang mewakili 1s, tidak dapat secara sederhana sama dengan posisi kedalaman. Dan ini saat ini masih kekurangan data kedalaman yang penting, hanya berdasarkan spekulasi perdagangan.
Penemuan bahwa distribusi transaksi pada interval waktu yang berbeda adalah skala sederhana tentang distribusi transaksi tunggal. Juga berdasarkan kejutan harga dan probabilitas transaksi, model pengharapan pendapatan sederhana dibuat, dan hasilnya sesuai dengan harapan kami, jika jumlah transaksi yang dijual kecil, yang menunjukkan penurunan harga, diperlukan jumlah tertentu untuk ruang keuntungan, dan semakin besar volume transaksi, semakin rendah probabilitasnya, ada ukuran optimal di tengah, dan juga posisi yang strategis untuk mencari. Tentu saja, model ini masih terlalu sederhana, dan saya akan terus membahasnya di artikel berikutnya.
#1s内的累计分布
df_resampled = buy_trades['quantity'].resample('1S').sum()
df_resampled = df_resampled.to_frame(name='quantity')
df_resampled = df_resampled[df_resampled['quantity']>0]
depths = np.array(range(0, 15000, 10))
mean = df_resampled['quantity'].mean()
alpha = np.log(np.mean(df_resampled['quantity'] > mean))/np.log(2.05)
probabilities_s = np.array([((1+20**(-depth/mean))*depth/mean+1)**(alpha) for depth in depths])
profit_s = np.array([depth/2e6-0.000352 for depth in depths])
plt.figure(figsize=(10, 5))
plt.plot(depths, probabilities_s*profit_s)
plt.xlabel('Q')
plt.ylabel('Excpet profit')
plt.grid(True)
Ukuran ok 🐂🍺