Những suy nghĩ về các chiến lược giao dịch tần số cao (2)

Tác giả:Lydia., Tạo: 2023-08-04 17:17:30, Cập nhật: 2023-09-12 15:50:31

img

Những suy nghĩ về các chiến lược giao dịch tần số cao (2)

Mô hình hóa tổng số giao dịch

Trong bài viết trước, chúng tôi đã rút ra một biểu thức cho xác suất của một số lượng giao dịch duy nhất lớn hơn một giá trị nhất định.

img

Chúng tôi cũng quan tâm đến sự phân bố số lượng giao dịch trong một khoảng thời gian, mà trực quan nên liên quan đến số lượng giao dịch cá nhân và tần suất lệnh. Dưới đây, chúng tôi xử lý dữ liệu trong khoảng thời gian cố định và vẽ sự phân bố của nó, tương tự như những gì đã được thực hiện trong phần trước.

Trong [1]:

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

Trong [2]:

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']

Chúng tôi kết hợp các số tiền giao dịch riêng lẻ trong khoảng thời gian 1 giây để có được số tiền giao dịch tổng hợp, trừ các giai đoạn không có hoạt động giao dịch. Sau đó, chúng tôi điều chỉnh số tiền tổng hợp này bằng cách sử dụng phân bố bắt nguồn từ phân tích số lượng giao dịch duy nhất đã đề cập trước đó. Kết quả cho thấy sự phù hợp tốt khi xem xét mỗi giao dịch trong khoảng thời gian 1 giây như một giao dịch duy nhất, giải quyết vấn đề hiệu quả. Tuy nhiên, khi khoảng thời gian được kéo dài so với tần suất giao dịch, chúng tôi quan sát thấy sự gia tăng các lỗi. Nghiên cứu thêm cho thấy lỗi này là do thời gian điều chỉnh được giới thiệu bởi phân phối Pareto. Điều này cho thấy rằng khi thời gian kéo dài và bao gồm nhiều giao dịch riêng lẻ hơn, sự tổng hợp của nhiều giao dịch tiếp cận phân bố Pareto chặt chẽ hơn, đòi hỏi phải loại bỏ thời gian điều chỉnh.

Trong [3]:

df_resampled = buy_trades['quantity'].resample('1S').sum()
df_resampled = df_resampled.to_frame(name='quantity')
df_resampled = df_resampled[df_resampled['quantity']>0]

Trong [4]:

# Cumulative distribution in 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)

Ra khỏi [1]:

img

Trong [5]:

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]) # No amendment

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)

Ra khỏi [5]:

img

Bây giờ tóm tắt một công thức chung cho việc phân phối số tiền giao dịch tích lũy cho các khoảng thời gian khác nhau, sử dụng việc phân phối số tiền giao dịch duy nhất để phù hợp, thay vì tính riêng mỗi lần.

img

Ở đây, avg_interval đại diện cho khoảng thời gian trung bình của các giao dịch đơn lẻ, và avg_interval_T đại diện cho khoảng thời gian trung bình của khoảng thời gian cần được ước tính. Nó có thể nghe có vẻ hơi khó hiểu. Nếu chúng ta muốn ước tính số tiền giao dịch trong 1 giây, chúng ta cần tính khoảng thời gian trung bình giữa các sự kiện chứa giao dịch trong vòng 1 giây. Nếu xác suất đến của các lệnh theo phân phối Poisson, nó nên được ước tính trực tiếp. Tuy nhiên, trong thực tế, có một độ lệch đáng kể, nhưng tôi sẽ không chi tiết về nó ở đây.

Lưu ý rằng xác suất số tiền giao dịch vượt quá một giá trị cụ thể trong một khoảng thời gian nhất định và xác suất thực tế giao dịch ở vị trí đó trong độ sâu nên khá khác nhau. Khi thời gian chờ tăng, khả năng thay đổi trong sổ lệnh tăng, và giao dịch cũng dẫn đến thay đổi độ sâu. Do đó, xác suất giao dịch ở cùng một vị trí độ sâu thay đổi trong thời gian thực khi dữ liệu được cập nhật.

Trong [6]:

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)

Ra ngoài[6]:

img

Tác động của giá thương mại duy nhất

Dữ liệu giao dịch rất có giá trị, và vẫn còn rất nhiều dữ liệu có thể được khai thác. Chúng ta nên chú ý rất nhiều đến tác động của các đơn đặt hàng lên giá cả, vì điều này ảnh hưởng đến vị trí của chiến lược. Tương tự, tổng hợp dữ liệu dựa trên thời gian giao dịch, chúng ta tính toán sự khác biệt giữa giá cuối cùng và giá đầu tiên. Nếu chỉ có một đơn đặt hàng, sự khác biệt giá là 0.

Kết quả cho thấy tỷ lệ giao dịch không gây ra bất kỳ tác động nào là cao đến 77%, trong khi tỷ lệ giao dịch gây ra sự biến động giá 1 tick là 16,5%, 2 tick là 3,7%, 3 tick là 1,2%, và hơn 4 tick là dưới 1%.

Số lượng giao dịch gây ra chênh lệch giá tương ứng cũng được phân tích, loại trừ các biến dạng do tác động quá mức. Nó cho thấy một mối quan hệ tuyến tính, với khoảng 1 dấu hiệu biến động giá do mỗi 1000 đơn vị số tiền. Điều này cũng có thể được hiểu là trung bình khoảng 1000 đơn vị đơn đặt hàng được đặt gần mỗi mức giá trong sổ đơn đặt hàng.

Trong [7]:

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)

Trong [8]:

diff_counts = buy_trades['diff'].value_counts()
diff_counts[diff_counts>10]/diff_counts.sum()

Ra khỏi[8]:

img

Trong [9]:

diff_group = buy_trades.groupby('diff').agg({
    'quantity': 'mean',
    'diff': 'last',
})

Trong [10]:

diff_group['quantity'][diff_group['diff']>0][diff_group['diff']<0.01].plot(figsize=(10,5),grid=True);

Ra khỏi[10]:

img

Tác động giá trong khoảng thời gian cố định

Chúng ta hãy phân tích tác động giá trong khoảng thời gian 2 giây. Sự khác biệt ở đây là có thể có giá trị âm. Tuy nhiên, vì chúng ta chỉ xem xét lệnh mua, tác động đến vị trí đối xứng sẽ cao hơn một dấu chấm. Tiếp tục quan sát mối quan hệ giữa số lượng giao dịch và tác động, chúng ta chỉ xem xét kết quả lớn hơn 0.

Trong [11]:

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]

Trong [12]:

result_df['price_diff'][abs(result_df['price_diff'])<0.016].value_counts().sort_index().plot.bar(figsize=(10,5));

Ra khỏi [1]:

img

Trong [23]:

result_df['price_diff'].value_counts()[result_df['price_diff'].value_counts()>30]

Ra khỏi [23]:

img

Trong [14]:

diff_group = result_df.groupby('price_diff').agg({ 'quantity_sum': 'mean'})

Trong [15]:

diff_group[(diff_group.index>0) & (diff_group.index<0.015)].plot(figsize=(10,5),grid=True);

Ra khỏi [1]:

img

Tác động giá của số lượng thương mại

Trước đây, chúng tôi đã xác định số lượng giao dịch cần thiết cho một thay đổi dấu chấm, nhưng nó không chính xác vì nó dựa trên giả định rằng tác động đã xảy ra.

Trong phân tích này, dữ liệu được lấy mẫu mỗi 1 giây, với mỗi bước đại diện cho 100 đơn vị số lượng. sau đó chúng tôi tính toán sự thay đổi giá trong phạm vi số lượng này. đây là một số kết luận có giá trị:

  1. Khi số tiền đặt hàng mua dưới 500, sự thay đổi giá dự kiến là giảm, điều này là mong đợi vì cũng có các lệnh bán ảnh hưởng đến giá.
  2. Ở số lượng giao dịch thấp hơn, có một mối quan hệ tuyến tính, có nghĩa là số lượng giao dịch càng lớn, giá cả tăng càng lớn.
  3. Khi số tiền đặt hàng mua tăng lên, sự thay đổi giá trở nên quan trọng hơn. Điều này thường chỉ ra sự đột phá giá, sau đó có thể giảm xuống. Ngoài ra, việc lấy mẫu khoảng thời gian cố định làm tăng sự bất ổn dữ liệu.
  4. Điều quan trọng là phải chú ý đến phần trên của biểu đồ phân tán, tương ứng với sự gia tăng giá với số lượng giao dịch.
  5. Đối với cặp giao dịch cụ thể này, chúng tôi cung cấp một phiên bản thô của mối quan hệ giữa số lượng giao dịch và thay đổi giá.

img

Trong đó C đại diện cho sự thay đổi về giá và Q đại diện cho số tiền đặt hàng mua.

Trong [16]:

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]

Trong [24]:

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

Trong [25]:

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)

Ra ngoài[25]:

img

Trong [19]:

grouped_df.head(10)

Ra khỏi [1]: ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

img

Đặt đơn đặt hàng tối ưu sơ bộ

Với mô hình hóa số lượng giao dịch và mô hình sơ bộ về tác động giá tương ứng với số lượng giao dịch, có vẻ như có thể tính toán đặt lệnh tối ưu.

  1. Giả sử rằng giá sẽ trở lại giá trị ban đầu sau tác động (điều này rất khó có thể và sẽ yêu cầu phân tích thêm về sự thay đổi giá sau tác động).
  2. Giả sử rằng sự phân bố số lượng giao dịch và tần suất lệnh trong thời gian này tuân theo một mô hình đã được đặt trước (đó cũng không chính xác, vì chúng tôi đang ước tính dựa trên dữ liệu một ngày và giao dịch cho thấy hiện tượng cụm rõ ràng).
  3. Giả sử chỉ có một lệnh bán xảy ra trong thời gian mô phỏng và sau đó được đóng.
  4. Giả sử rằng sau khi lệnh được thực hiện, có các lệnh mua khác tiếp tục đẩy giá lên, đặc biệt là khi số tiền rất thấp.

Chúng ta hãy bắt đầu bằng cách viết một lợi nhuận mong đợi đơn giản, đó là xác suất các lệnh mua tích lũy vượt quá Q trong vòng 1 giây, nhân với tỷ lệ lợi nhuận mong đợi (tức là tác động giá).

img

Dựa trên biểu đồ, lợi nhuận tối đa dự kiến là khoảng 2500, gấp khoảng 2,5 lần số tiền giao dịch trung bình. Điều này cho thấy lệnh bán nên được đặt ở vị trí giá 2500. Điều quan trọng cần nhấn mạnh là trục ngang đại diện cho số tiền giao dịch trong vòng 1 giây và không nên được coi là tương đương với vị trí độ sâu. Ngoài ra, phân tích này dựa trên dữ liệu giao dịch và thiếu dữ liệu độ sâu quan trọng.

Tóm lại

Chúng tôi đã phát hiện ra rằng việc phân phối số lượng giao dịch ở các khoảng thời gian khác nhau là một quy mô đơn giản của việc phân phối số lượng giao dịch cá nhân. Chúng tôi cũng đã phát triển một mô hình lợi nhuận mong đợi đơn giản dựa trên tác động giá và xác suất giao dịch. Kết quả của mô hình này phù hợp với mong đợi của chúng tôi, cho thấy nếu số lượng lệnh bán thấp, nó cho thấy giá giảm, và một số lượng nhất định là cần thiết cho tiềm năng lợi nhuận. xác suất giảm khi số lượng giao dịch tăng, với kích thước tối ưu ở giữa, đại diện cho chiến lược đặt hàng tối ưu. Tuy nhiên, mô hình này vẫn quá đơn giản. Trong bài viết tiếp theo, tôi sẽ đi sâu hơn vào chủ đề này.

Trong [20]:

# Cumulative distribution in 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)

Ra khỏi [1]:

img


Thêm nữa