Sumber dimuat naik... memuat...

Berfikir tentang strategi perdagangan frekuensi tinggi ((2)

Penulis:Rumput, Dicipta: 2023-08-04 16:14:27, Dikemas kini: 2024-11-10 18:48:22

img

Artikel ini membincangkan strategi dagangan frekuensi tinggi, dengan tumpuan kepada pemodelan jumlah dagangan yang terkumpul dan kejutan harga. Artikel ini mengemukakan model kedudukan tunggal yang paling optimal berdasarkan analisis transaksi tunggal, kejutan harga selang tetap dan kesan dagangan pada harga. Model ini berdasarkan pemahaman mengenai jumlah dagangan dan kejutan harga untuk mencari kedudukan dagangan yang paling optimum.

Pemodelan pengangkutan yang terkumpul

Artikel sebelumnya menghasilkan ungkapan kebarangkalian transaksi tunggal yang lebih besar daripada nilai tertentu:

img

Kami juga mengambil berat tentang pembahagian jumlah transaksi dalam jangka masa tertentu, yang secara intuitif harus berkaitan dengan jumlah transaksi dan kekerapan pesanan setiap kali; di bawah ini, data diproses mengikut selang masa yang tetap; dan seperti di atas, gambarkan pembahagian itu.

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 setiap selang 1s menjadi jumlah transaksi, membuang bahagian yang tidak berlaku, dan menyesuaikan dengan peredaran transaksi tunggal di atas, hasil yang lebih baik dapat dilihat, menganggap semua transaksi dalam 1s sebagai satu, masalah ini menjadi masalah yang telah diselesaikan. Tetapi apabila kitaran ditarik (berbanding dengan kekerapan urus niaga), kesalahan meningkat, dan kajian mendapati bahawa kesalahan ini disebabkan oleh penyempurnaan pembahagian Pareto sebelumnya. Ini menunjukkan bahawa apabila kitaran ditarik, yang mengandungi lebih banyak transaksi tunggal, semakin banyak gabungan transaksi yang semakin mendekati pembahagian Pareto, keadaan ini perlu dikeluarkan penyempurnaan.

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 kuantiti first_trade_id last_trade_id is_buyer_maker tarikh masa urus niaga Jangkaan berbeza
2023-01-27 00:00:00.161 1138369 2.901 54.3 3806199 3806201 Tidak betul 2023-01-27 00:00:00.161 1674777600161 NaN 0.001
2023-01-27 00:00:04.140 1138370 2.901 291.3 3806202 3806203 Tidak betul 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 betul 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 betul 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 betul 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 betul 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 betul 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 betul 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 betul 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 betul 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)

png

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)

png

Sekarang untuk pembahagian jumlah urus niaga yang terkumpul dalam masa yang berbeza, ringkasan formula umum, yang disesuaikan dengan pembahagian urus niaga tunggal, tanpa menggunakan statistik yang berasingan setiap kali.

img

Di mana avg_interval menunjukkan selang purata transaksi tunggal, dan avg_interval_T menunjukkan selang purata selang yang diperlukan untuk dianggarkan, dikatakan agak melingkar. Jika kita mahu menganggarkan selang 1s, kita perlu menganggarkan selang purata peristiwa yang terkandung dalam selang 1s. Jika kemungkinan pesanan tiba sesuai dengan pembahagian Parsons, ini sepatutnya dapat dianggarkan secara langsung, tetapi kesesuaian sebenar sangat besar, tidak dijelaskan di sini.

Perhatikan di sini bahawa kebarangkalian transaksi yang lebih besar daripada nilai tertentu dalam satu selang masa dan kebarangkalian transaksi yang sebenarnya berada di lokasi dalam kedalaman harus berbeza jauh, kerana semakin lama masa menunggu, semakin besar kemungkinan perubahan buku pesanan, dan transaksi juga menyebabkan perubahan kedalaman, jadi kebarangkalian transaksi di lokasi yang sama dalam kedalaman berubah secara langsung dengan kemas kini 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)

png

Harga transaksi tunggal terhempas

Data urus niaga adalah harta karun, dan masih banyak data yang boleh digali. Kita harus sangat memperhatikan kesan pesanan terhadap harga, yang mempengaruhi kedudukan senarai strategi. Juga berdasarkan data agregat transact_time, mengira perbezaan harga terakhir dan harga pertama, jika hanya ada satu pesanan, perbezaannya adalah 0.

Hasilnya menunjukkan peratusan tidak menyebabkan kejutan sebanyak 77%, peratusan 1 tik adalah 16.5%, 2 tik adalah 3.7%, 3 tik adalah 1.2%, dan lebih daripada 4 tik adalah kurang daripada 1%.

Jumlah dagangan yang menyebabkan perbezaan harga yang sepadan telah dikira, menghilangkan kepalsuan yang terlalu besar, dan pada dasarnya sesuai dengan hubungan linear, kira-kira satu pergerakan harga bagi setiap 1000 jumlah yang menyebabkan 1 tik.

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

png

kejutan harga berkala tetap

Harga kejutan dalam statistik 2s, yang berbeza di sini adalah bahawa akan ada negatif, tentu saja kerana di sini hanya statistik pembayaran, kedudukan simetris akan lebih besar daripada satu tik. Teruskan melihat hubungan perdagangan dan kejutan, hanya statistik yang lebih besar daripada 0 hasil, kesimpulan dan pesanan tunggal hampir sama, juga hubungan linear yang hampir, setiap tik memerlukan jumlah sekitar 2000.

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

png

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

png

kejutan harga transaksi

Sebelum ini, jumlah transaksi yang diperlukan untuk perubahan tik dikehendaki, tetapi tidak tepat kerana ia dibina pada keadaan yang menganggap kejutan telah berlaku; kini sebaliknya melihat kejutan harga yang disebabkan oleh pertukaran.

Di sini, data disampel mengikut 1s, satu langkah setiap 100 kuantiti, dan perubahan harga dalam jumlah ini dikira; membuat beberapa kesimpulan yang agak berharga:

  1. Apabila jumlah pesanan di bawah 500, perubahan harga yang dijangkakan adalah penurunan, yang sesuai dengan jangkaan, selepas semua, pesanan jual juga mempengaruhi harga.
  2. Apabila jumlah dagangan rendah, ia sesuai dengan hubungan linear, iaitu jumlah dagangan yang lebih besar, kenaikan harga yang lebih besar.
  3. Jumlah transaksi yang lebih besar, perubahan harga yang lebih besar, yang sering mewakili harga yang terputus, harga yang mungkin kembali selepas terputus, ditambah dengan pengambilan sampel pada selang masa yang tetap, menyebabkan ketidakstabilan data.
  4. Perhatian harus diberikan kepada bahagian atas grafik titik-titik, iaitu bahagian di mana jumlah urus niaga sepadan dengan kenaikan harga.
  5. Bagi pasangan ini sahaja, beri hubungan kepada perubahan harga yang disebabkan oleh jumlah urus niaga dalam bentuk kasar:

img

Di antaranya, C mewakili perubahan harga, dan Q mewakili jumlah pembelian dan transaksi.

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)

png

grouped_df.head(10)
kuantiti_kumpulan harga_perbezaan quantity_group_center
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

Kedudukan pertama yang paling baik

Dengan pemodelan yang kasar terhadap jumlah urus niaga dan jumlah urus niaga yang sepadan dengan kejutan harga, nampaknya boleh dihitung kedudukan yang paling optimum.

  1. Andaikan harga selepas kejutan kembali ke nilai asal (yang tentu saja tidak mungkin, memerlukan analisis semula perubahan harga selepas kejutan)
  2. Misalkan jumlah transaksi dan kekerapan pesanan dalam tempoh ini adalah seperti yang dijangkakan (ini juga tidak tepat, di sini anggaran digunakan untuk nilai sehari, dan transaksi mempunyai fenomena pengumpulan yang jelas).
  3. Sekiranya hanya satu pesanan dijual berlaku dalam masa simulasi, maka penempatan akan dilakukan.
  4. Jika anda menganggap bahawa selepas pesanan selesai, ada pembayaran lain yang terus menaikkan harga, terutama apabila jumlahnya sangat rendah, kesan ini diabaikan di sini, dengan hanya menganggap bahawa akan kembali.

Pertama, tulis hasil yang dijangkakan yang mudah, iaitu kebarangkalian pembayaran yang terkumpul lebih besar daripada Q dalam 1s, dikalikan dengan kadar pulangan yang dijangkakan (iaitu harga kejutan):

img

Berdasarkan imej, jangkaan keuntungan maksimum adalah kira-kira 2500 dan kira-kira 2.5 kali ganda jumlah purata dagangan. Maksudnya, pesanan jual harus digantung di kedudukan 2500. Perlu ditekankan sekali lagi bahawa jumlah dagangan dalam kisaran 1s tidak dapat disamakan dengan kedudukan kedalaman. Dan ini pada masa ini masih kekurangan data kedalaman yang penting, hanya berdasarkan spekulasi dagangan.

Ringkasan

Dijumpai bahawa pembahagian jumlah dagangan pada selang masa yang berbeza adalah skala sederhana mengenai pembahagian jumlah dagangan tunggal. Juga berdasarkan kejutan harga dan kebarangkalian dagangan, model pendapatan yang diharapkan sederhana dibuat. Hasil model ini sesuai dengan jangkaan kami, jika jumlah dagangan yang dijual kecil, yang menunjukkan penurunan harga, ruang keuntungan diperlukan untuk jumlah tertentu, dan jumlah dagangan yang lebih besar semakin rendah kebarangkalian, terdapat saiz yang paling baik di tengah-tengah, dan juga strategi mencari kedudukan gantung. Sudah tentu, model ini masih terlalu mudah, artikel seterusnya, saya akan terus membincangkannya.

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

png


Lebih lanjut

Ukuran ok 🐂🍺