Pikiran tentang Strategi Perdagangan Frekuensi Tinggi (5)

Penulis:Lydia, Dibuat: 2023-08-10 15:57:27, Diperbarui: 2023-09-12 15:51:54

img

Pikiran tentang Strategi Perdagangan Frekuensi Tinggi (5)

Dalam artikel sebelumnya, berbagai metode untuk menghitung harga tengah diperkenalkan, dan harga tengah direvisi diusulkan.

Data yang Dibutuhkan

Kami membutuhkan data aliran pesanan dan data kedalaman untuk sepuluh tingkat teratas buku pesanan, yang dikumpulkan dari perdagangan langsung dengan frekuensi pembaruan 100ms. demi kesederhanaan, kami tidak akan menyertakan pembaruan real-time untuk harga penawaran dan permintaan. untuk mengurangi ukuran data, kami hanya menyimpan 100.000 baris data kedalaman dan memisahkan data pasar tik-by-tik ke kolom individu.

Dalam [1]:

from datetime import date,datetime
import time
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import ast
%matplotlib inline

Dalam [2]:

tick_size = 0.0001

Dalam [3]:

trades = pd.read_csv('YGGUSDT_aggTrade.csv',names=['type','event_time', 'agg_trade_id','symbol', 'price', 'quantity', 'first_trade_id', 'last_trade_id',
       'transact_time', 'is_buyer_maker'])

Dalam [4]:

trades = trades.groupby(['transact_time','is_buyer_maker']).agg({
    'transact_time':'last',
    'agg_trade_id': 'last',
    'price': 'first',
    'quantity': 'sum',
    'first_trade_id': 'first',
    'last_trade_id': 'last',
    'is_buyer_maker': 'last',
})

Dalam [5]:

trades.index = pd.to_datetime(trades['transact_time'], unit='ms')
trades.index.rename('time', inplace=True)
trades['interval'] = trades['transact_time'] - trades['transact_time'].shift()

Dalam [6]:

depths = pd.read_csv('YGGUSDT_depth.csv',names=['type','event_time', 'transact_time','symbol', 'u1', 'u2', 'u3', 'bids','asks'])

Dalam [7]:

depths = depths.iloc[:100000]

Dalam [8]:

depths['bids'] = depths['bids'].apply(ast.literal_eval).copy()
depths['asks'] = depths['asks'].apply(ast.literal_eval).copy()

Dalam [9]:

def expand_bid(bid_data):
    expanded = {}
    for j, (price, quantity) in enumerate(bid_data):
        expanded[f'bid_{j}_price'] = float(price)
        expanded[f'bid_{j}_quantity'] = float(quantity)
    return pd.Series(expanded)
def expand_ask(ask_data):
    expanded = {}
    for j, (price, quantity) in enumerate(ask_data):
        expanded[f'ask_{j}_price'] = float(price)
        expanded[f'ask_{j}_quantity'] = float(quantity)
    return pd.Series(expanded)
# Apply to each line to get a new df
expanded_df_bid = depths['bids'].apply(expand_bid)
expanded_df_ask = depths['asks'].apply(expand_ask)
# Expansion on the original df
depths = pd.concat([depths, expanded_df_bid, expanded_df_ask], axis=1)

Dalam [10]:

depths.index = pd.to_datetime(depths['transact_time'], unit='ms')
depths.index.rename('time', inplace=True);

Dalam [11]:

trades = trades[trades['transact_time'] < depths['transact_time'].iloc[-1]]

Lihatlah distribusi pasar di 20 tingkat ini. sesuai dengan harapan, dengan lebih banyak pesanan yang ditempatkan semakin jauh dari harga pasar. selain itu, pesanan beli dan penjualan hampir simetris.

Dalam [14]:

bid_mean_list = []
ask_mean_list = []
for i in range(20):
    bid_mean_list.append(round(depths[f'bid_{i}_quantity'].mean(),0))
    ask_mean_list.append(round(depths[f'ask_{i}_quantity'].mean(),0))
plt.figure(figsize=(10, 5))
plt.plot(bid_mean_list);
plt.plot(ask_mean_list);
plt.grid(True)

Keluar[14]:

img

Menggabungkan data kedalaman dengan data transaksi untuk memfasilitasi evaluasi akurasi prediksi. Memastikan bahwa data transaksi lebih lambat dari data kedalaman. Tanpa mempertimbangkan latensi, langsung menghitung rata-rata kesalahan kuadrat antara nilai yang diprediksi dan harga transaksi yang sebenarnya. Ini digunakan untuk mengukur akurasi prediksi.

Dari hasil, kesalahan adalah yang tertinggi untuk nilai rata-rata harga bid dan ask (mid_price). Namun, ketika diubah ke harga mid_weighted, kesalahan segera berkurang secara signifikan. Peningkatan lebih lanjut diamati dengan menggunakan harga mid_weighted yang disesuaikan. Setelah menerima umpan balik tentang hanya menggunakan I ^ 3 / 2, itu diperiksa dan ditemukan bahwa hasilnya lebih baik. Setelah refleksi, ini mungkin karena frekuensi peristiwa yang berbeda. Ketika I dekat dengan -1 dan 1, ini mewakili peristiwa probabilitas rendah. Untuk memperbaiki untuk peristiwa probabilitas rendah ini, akurasi memprediksi peristiwa frekuensi tinggi terkompromikan. Oleh karena itu, untuk memprioritaskan peristiwa frekuensi tinggi, beberapa penyesuaian dilakukan (parameter ini murni trial-and-error dan memiliki signifikansi praktis terbatas dalam perdagangan langsung).

img

Hasilnya telah sedikit meningkat. Seperti yang disebutkan dalam artikel sebelumnya, strategi harus mengandalkan lebih banyak data untuk prediksi. Dengan ketersediaan data transaksi pesanan yang lebih dalam dan lebih luas, peningkatan yang diperoleh dari fokus pada buku pesanan sudah lemah.

Di [15]:

df = pd.merge_asof(trades, depths, on='transact_time', direction='backward')

Di [17]:

df['spread'] = round(df['ask_0_price'] - df['bid_0_price'],4)
df['mid_price'] = (df['bid_0_price']+ df['ask_0_price']) / 2
df['I'] = (df['bid_0_quantity'] - df['ask_0_quantity']) / (df['bid_0_quantity'] + df['ask_0_quantity'])
df['weight_mid_price'] = df['mid_price'] + df['spread']*df['I']/2
df['adjust_mid_price'] = df['mid_price'] + df['spread']*(df['I'])*(df['I']**8+1)/4
df['adjust_mid_price_2'] = df['mid_price'] + df['spread']*df['I']*(df['I']**2+1)/4
df['adjust_mid_price_3'] = df['mid_price'] + df['spread']*df['I']**3/2
df['adjust_mid_price_4'] = df['mid_price'] + df['spread']*(df['I']+0.3)*(df['I']**4+0.7)/3.8

Dalam [18]:

print('Mean value     Error in mid_price:', ((df['price']-df['mid_price'])**2).sum())
print('Error of pending order volume weighted mid_price:', ((df['price']-df['weight_mid_price'])**2).sum())
print('The error of the adjusted mid_price:', ((df['price']-df['adjust_mid_price'])**2).sum())
print('The error of the adjusted mid_price_2:', ((df['price']-df['adjust_mid_price_2'])**2).sum())
print('The error of the adjusted mid_price_3:', ((df['price']-df['adjust_mid_price_3'])**2).sum())
print('The error of the adjusted mid_price_4:', ((df['price']-df['adjust_mid_price_4'])**2).sum())

Keluar[18]:

Nilai rata-rata Kesalahan di harga pertengahan: 0.0048751924999999845 Kesalahan volume order yang sedang menunggu dengan nilai rata-rata harga: 0.0048373440193987035 Kesalahan harga pertengahan yang disesuaikan: 0,004803654771638586 Kesalahan dari rata-rata rata-rata harga yang disesuaikan: 0.004808216498329721 Kesalahan dari rata-rata rata-rata harga_3: 0.004794984755260528 Kesalahan dari rata-rata rata-rata harga yang disesuaikan: 0,0047909595497071375

Pertimbangkan Tingkat Kedua Kedalaman

Kita dapat mengikuti pendekatan dari artikel sebelumnya untuk memeriksa rentang yang berbeda dari parameter dan mengukur kontribusinya terhadap harga pertengahan berdasarkan perubahan harga transaksi.

Menggunakan pendekatan yang sama untuk tingkat kedua kedalaman, kita menemukan bahwa meskipun efeknya sedikit lebih kecil daripada tingkat pertama, itu masih signifikan dan tidak boleh diabaikan.

Berdasarkan kontribusi yang berbeda, kami memberikan bobot yang berbeda untuk tiga tingkat parameter ketidakseimbangan ini. Dengan memeriksa metode perhitungan yang berbeda, kami mengamati penurunan lebih lanjut dalam kesalahan prediksi.

Dalam [19]:

bins = np.linspace(-1, 1, 50)
df['change'] = (df['price'].pct_change().shift(-1))/tick_size
df['I_bins'] = pd.cut(df['I'], bins, labels=bins[1:])
df['I_2'] = (df['bid_1_quantity'] - df['ask_1_quantity']) / (df['bid_1_quantity'] + df['ask_1_quantity'])
df['I_2_bins'] = pd.cut(df['I_2'], bins, labels=bins[1:])
df['I_3'] = (df['bid_2_quantity'] - df['ask_2_quantity']) / (df['bid_2_quantity'] + df['ask_2_quantity'])
df['I_3_bins'] = pd.cut(df['I_3'], bins, labels=bins[1:])
df['I_4'] = (df['bid_3_quantity'] - df['ask_3_quantity']) / (df['bid_3_quantity'] + df['ask_3_quantity'])
df['I_4_bins'] = pd.cut(df['I_4'], bins, labels=bins[1:])
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(8, 5))


axes[0][0].plot(df.groupby('I_bins')['change'].mean())
axes[0][0].set_title('I')
axes[0][0].grid(True)

axes[0][1].plot(df.groupby('I_2_bins')['change'].mean())
axes[0][1].set_title('I 2')
axes[0][1].grid(True)

axes[1][0].plot(df.groupby('I_3_bins')['change'].mean())
axes[1][0].set_title('I 3')
axes[1][0].grid(True)

axes[1][1].plot(df.groupby('I_4_bins')['change'].mean())
axes[1][1].set_title('I 4')
axes[1][1].grid(True)
plt.tight_layout();

Keluar[19]:

img

Dalam [20]:

df['adjust_mid_price_4'] = df['mid_price'] + df['spread']*(df['I']+0.3)*(df['I']**4+0.7)/3.8
df['adjust_mid_price_5'] = df['mid_price'] + df['spread']*(0.7*df['I']+0.3*df['I_2'])/2
df['adjust_mid_price_6'] = df['mid_price'] + df['spread']*(0.7*df['I']+0.3*df['I_2'])**3/2
df['adjust_mid_price_7'] = df['mid_price'] + df['spread']*(0.7*df['I']+0.3*df['I_2']+0.3)*((0.7*df['I']+0.3*df['I_2'])**4+0.7)/3.8
df['adjust_mid_price_8'] = df['mid_price'] + df['spread']*(0.7*df['I']+0.2*df['I_2']+0.1*df['I_3']+0.3)*((0.7*df['I']+0.3*df['I_2']+0.1*df['I_3'])**4+0.7)/3.8

Di [21]:

print('The error of the adjusted mid_price_4:', ((df['price']-df['adjust_mid_price_4'])**2).sum())
print('The error of the adjusted mid_price_5:', ((df['price']-df['adjust_mid_price_5'])**2).sum())
print('The error of the adjusted mid_price_6:', ((df['price']-df['adjust_mid_price_6'])**2).sum())
print('The error of the adjusted mid_price_7:', ((df['price']-df['adjust_mid_price_7'])**2).sum())
print('The error of the adjusted mid_price_8:', ((df['price']-df['adjust_mid_price_8'])**2).sum())

Keluar[21]:

Kesalahan dari rata-rata rata-rata harga yang disesuaikan: 0,0047909595497071375 Kesalahan harga_tengah_terakreditasi_5: 0.0047884350488318714 Kesalahan harga_tengah_terakreditasi 6: 0,0047778319053133735 Kesalahan dari rata-rata rata-rata harga yang disesuaikan: 0,004773578540592192 Kesalahan harga_tengah_terakreditasi_8: 0,004771415189297518

Mempertimbangkan Data Transaksi

Data transaksi secara langsung mencerminkan luasnya posisi panjang dan pendek. Lagi pula, transaksi melibatkan uang riil, sementara penempatan pesanan memiliki biaya yang jauh lebih rendah dan bahkan dapat melibatkan penipuan yang disengaja. Oleh karena itu, ketika memprediksi harga pertengahan, strategi harus berfokus pada data transaksi.

Dalam hal bentuk, kita dapat mendefinisikan ketidakseimbangan jumlah pesanan rata-rata yang tiba sebagai VI, dengan Vb dan Vs mewakili jumlah rata-rata pesanan beli dan jual dalam interval waktu satuan, masing-masing.

img

Hasilnya menunjukkan bahwa jumlah kedatangan dalam jangka waktu singkat memiliki dampak yang paling signifikan pada prediksi perubahan harga. Ketika VI berada antara 0,1 dan 0,9, itu berkorelasi negatif dengan harga, sementara di luar kisaran ini, itu berkorelasi positif dengan harga. Ini menunjukkan bahwa ketika pasar tidak ekstrem dan terutama berosilasi, harga cenderung kembali ke rata-rata. Namun, dalam kondisi pasar ekstrem, seperti ketika ada sejumlah besar pesanan beli yang melampaui pesanan jual, sebuah tren muncul. Bahkan tanpa mempertimbangkan skenario probabilitas rendah ini, mengasumsikan hubungan linier negatif antara tren dan VI secara signifikan mengurangi prediksi kesalahan harga tengah. Koefisien a mewakili bobot hubungan ini dalam persamaan.

img

Dalam [22]:

alpha=0.1

Dalam [23]:

df['avg_buy_interval'] = None
df['avg_sell_interval'] = None
df.loc[df['is_buyer_maker'] == True, 'avg_buy_interval'] = df[df['is_buyer_maker'] == True]['transact_time'].diff().ewm(alpha=alpha).mean()
df.loc[df['is_buyer_maker'] == False, 'avg_sell_interval'] = df[df['is_buyer_maker'] == False]['transact_time'].diff().ewm(alpha=alpha).mean()

Dalam [24]:

df['avg_buy_quantity'] = None
df['avg_sell_quantity'] = None
df.loc[df['is_buyer_maker'] == True, 'avg_buy_quantity'] = df[df['is_buyer_maker'] == True]['quantity'].ewm(alpha=alpha).mean()
df.loc[df['is_buyer_maker'] == False, 'avg_sell_quantity'] = df[df['is_buyer_maker'] == False]['quantity'].ewm(alpha=alpha).mean()

Di [25]:

df['avg_buy_quantity'] = df['avg_buy_quantity'].fillna(method='ffill')
df['avg_sell_quantity'] = df['avg_sell_quantity'].fillna(method='ffill')
df['avg_buy_interval'] = df['avg_buy_interval'].fillna(method='ffill')
df['avg_sell_interval'] = df['avg_sell_interval'].fillna(method='ffill')

df['avg_buy_rate'] = 1000 / df['avg_buy_interval']
df['avg_sell_rate'] =1000 / df['avg_sell_interval']

df['avg_buy_volume'] = df['avg_buy_rate']*df['avg_buy_quantity']
df['avg_sell_volume'] = df['avg_sell_rate']*df['avg_sell_quantity']

Di [26]:

df['I'] = (df['bid_0_quantity']- df['ask_0_quantity']) / (df['bid_0_quantity'] + df['ask_0_quantity'])
df['OI'] = (df['avg_buy_rate']-df['avg_sell_rate']) / (df['avg_buy_rate'] + df['avg_sell_rate'])
df['QI'] = (df['avg_buy_quantity']-df['avg_sell_quantity']) / (df['avg_buy_quantity'] + df['avg_sell_quantity'])
df['VI'] = (df['avg_buy_volume']-df['avg_sell_volume']) / (df['avg_buy_volume'] + df['avg_sell_volume'])

Dalam [27]:

bins = np.linspace(-1, 1, 50)
df['VI_bins'] = pd.cut(df['VI'], bins, labels=bins[1:])
plt.plot(df.groupby('VI_bins')['change'].mean());
plt.grid(True)

Keluar[27]:

img

Dalam [28]:

df['adjust_mid_price'] = df['mid_price'] + df['spread']*df['I']/2
df['adjust_mid_price_9'] = df['mid_price'] + df['spread']*(-df['OI'])*2
df['adjust_mid_price_10'] = df['mid_price'] + df['spread']*(-df['VI'])*1.4

Dalam [29]:

print('The error of the adjusted mid_price:', ((df['price']-df['adjust_mid_price'])**2).sum())
print('The error of the adjusted mid_price_9:', ((df['price']-df['adjust_mid_price_9'])**2).sum())
print('The error of the adjusted mid_price_10:', ((df['price']-df['adjust_mid_price_10'])**2).sum())

Keluar[29]:

Kesalahan harga pertengahan yang disesuaikan: 0,0048373440193987035 Kesalahan dari rata-rata harga_9 yang disesuaikan: 0.004629586542840461 Kesalahan harga_tengah_10 yang disesuaikan: 0,004401790287167206

Harga Pertengahan yang Komprehensif

Dengan mempertimbangkan bahwa data ketidakseimbangan buku pesanan dan data transaksi berguna untuk memprediksi harga pertengahan, kita dapat menggabungkan kedua parameter ini bersama-sama. Penugasan bobot dalam hal ini sewenang-wenang dan tidak memperhitungkan kondisi batas. Dalam kasus ekstrem, harga pertengahan yang diprediksi mungkin tidak jatuh antara harga penawaran dan harga permintaan. Namun, selama kesalahan prediksi dapat dikurangi, rincian ini tidak terlalu mengkhawatirkan.

Pada akhirnya, kesalahan prediksi dikurangi dari 0,00487 menjadi 0,0043. Pada titik ini, kita tidak akan menggali lebih dalam topik. Masih ada banyak aspek yang harus dijelajahi ketika datang untuk memprediksi harga pertengahan, karena pada dasarnya memprediksi harga itu sendiri. Semua orang didorong untuk mencoba pendekatan dan teknik mereka sendiri.

Di [30]:

#Note that the VI needs to be delayed by one to use
df['CI'] = -1.5*df['VI'].shift()+0.7*(0.7*df['I']+0.2*df['I_2']+0.1*df['I_3'])**3 

Di [31]:

df['adjust_mid_price_11'] = df['mid_price'] + df['spread']*(df['CI'])
print('The error of the adjusted mid_price_11:', ((df['price']-df['adjust_mid_price_11'])**2).sum())

Keluar[31]:

Kesalahan dari rataan harga_11 yang disesuaikan: 0,0043001941412563575

Ringkasan

Artikel ini menggabungkan data kedalaman dan data transaksi untuk lebih meningkatkan metode perhitungan harga pertengahan. Hal ini memberikan metode untuk mengukur akurasi dan meningkatkan akurasi prediksi perubahan harga. Secara keseluruhan, parameter tidak ketat dan hanya untuk referensi. Dengan harga pertengahan yang lebih akurat, langkah selanjutnya adalah melakukan backtesting menggunakan harga pertengahan dalam aplikasi praktis.


Lebih banyak