নিবন্ধটি মূলত উচ্চ-ফ্রিকোয়েন্সি ট্রেডিং কৌশল নিয়ে আলোচনা করে, মূলত সমষ্টিগত ট্রেডিং মডেলিং এবং মূল্যের ধাক্কা নিয়ে গবেষণা করে। নিবন্ধটি একক লেনদেন, স্থির সময়ের দামের ধাক্কা এবং লেনদেনের দামের উপর প্রভাব বিশ্লেষণ করে একটি প্রাথমিক সর্বোত্তম প্যাচিং পজিশন মডেল উপস্থাপন করে। এই মডেলটি লেনদেনের পরিমাণ এবং মূল্যের ধাক্কা বোঝার উপর ভিত্তি করে সর্বোত্তম ট্রেডিং পজিশন খুঁজে বের করার চেষ্টা করে। মডেলের অনুমানগুলি গভীরভাবে আলোচনা করা হয় এবং মডেলের পূর্বাভাসের সাথে বাস্তব প্রত্যাশিত উপার্জনের তুলনা করে সর্বোত্তম প্যাচিং পজিশনগুলির প্রাথমিক মূল্যায়ন করা হয়।
পূর্ববর্তী পোস্টটি একক লেনদেনের পরিমাণ একটি নির্দিষ্ট মানের চেয়ে বেশি হওয়ার সম্ভাব্যতা প্রকাশ করেঃ
আমরা একটি নির্দিষ্ট সময়ের জন্য লেনদেনের পরিমাণের বিতরণ সম্পর্কেও উদ্বিগ্ন, যা স্বজ্ঞাতভাবে প্রতিটি লেনদেনের পরিমাণ এবং অর্ডার ফ্রিকোয়েন্সির সাথে সম্পর্কিত হওয়া উচিত। নীচে নির্দিষ্ট ব্যবধানে ডেটা প্রক্রিয়া করা হয়েছে। উপরে বর্ণিত হিসাবে এটির বিতরণটি অঙ্কিত করা হয়েছে।
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']
প্রতিটি লেনদেনের 1s ব্যবধানের সাথে একত্রিত করে লেনদেনের পরিমাণ, লেনদেন না করা অংশটি বাদ দিয়ে, এবং উপরের একক লেনদেনের বন্টনের সাথে সামঞ্জস্য করে, তুলনামূলকভাবে ভাল ফলাফল দেখা যায়, 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]
buy_trades
agg_trade_id | দাম | পরিমাণ | প্রথম_ট্রেড_আইডি | last_trade_id | is_buyer_maker | তারিখ | লেনদেনের সময় | অন্তরাল | ডিফ | |
---|---|---|---|---|---|---|---|---|---|---|
2023-01-27 00:00:00.161 | 1138369 | 2.901 | 54.3 | 3806199 | 3806201 | মিথ্যা | 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 | মিথ্যা | 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 | মিথ্যা | 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 | মিথ্যা | 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 | মিথ্যা | 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 | মিথ্যা | 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 | মিথ্যা | 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 | মিথ্যা | 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 | মিথ্যা | 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 | মিথ্যা | 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)
এখন বিভিন্ন সময়কালের উপর ভিত্তি করে ক্রয়-বিক্রয়ের জন্য একটি সাধারণ সূত্র সংকলন করুন এবং প্রতিটি সময়ে পৃথক পরিসংখ্যান ব্যবহার না করে একক ক্রয়-বিক্রয়ের জন্য একটি সাধারণ সূত্র সংকলন করুন। এখানে প্রক্রিয়াটি এড়িয়ে যান, সরাসরি সূত্রটি দিনঃ
যেখানে avg_interval একক লেনদেনের গড় ব্যবধানকে নির্দেশ করে, এবং avg_interval_T গড় ব্যবধানকে নির্দেশ করে যা অনুমান করা প্রয়োজন। যদি আমরা 1s এর লেনদেনের অনুমান করি, তবে পরিসংখ্যান 1s এর মধ্যে অন্তর্ভুক্ত লেনদেনের গড় ব্যবধানকে নির্দেশ করে। যদি অর্ডারটি পৌঁছানোর সম্ভাবনাটি পারসন বন্টনের সাথে সামঞ্জস্যপূর্ণ হয় তবে এটি সরাসরি অনুমান করা উচিত, তবে প্রকৃত বিচ্যুতিটি খুব বড়, এটি এখানে ব্যাখ্যা করা হবে না।
মনে রাখবেন যে এখানে একটি নির্দিষ্ট সময়ের ব্যবধানে একটি নির্দিষ্ট মানের চেয়ে বড় ট্রেডিংয়ের সম্ভাবনা এবং প্রকৃতপক্ষে গভীরতার মধ্যে অবস্থিত ট্রেডিংয়ের সম্ভাব্যতা আরও বড় পার্থক্য হওয়া উচিত, কারণ অপেক্ষা করার সময়টি দীর্ঘ হলে অর্ডার বুকের পরিবর্তনের সম্ভাবনা বেশি হয় এবং ট্রেডিংয়ের গভীরতাও পরিবর্তিত হয়, তাই একই গভীরতার অবস্থানের ট্রেডিংয়ের সম্ভাব্যতা ডেটা আপডেটের সাথে রিয়েল-টাইম পরিবর্তিত হয়।
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)
লেনদেনের ডেটা একটি সম্পদ, এবং খনির জন্য প্রচুর ডেটা রয়েছে। আমাদের অবশ্যই অর্ডারের দামের উপর প্রভাব ফেলতে হবে, যা কৌশলগত তালিকার অবস্থানকে প্রভাবিত করে। একইভাবে, transact_time সমষ্টিগত ডেটা অনুসারে, শেষ দাম এবং প্রথম দামের পার্থক্য গণনা করুন, যদি কেবলমাত্র একটি অর্ডার থাকে তবে পার্থক্যটি 0 হয়। আশ্চর্যজনকভাবে, একটি ছোট সংখ্যক ডেটা ফলাফলও নেতিবাচক, যা ডেটা স্যুটিংয়ের ক্রমানুসারে হওয়া উচিত। এখানে গভীরভাবে যেতে হবে না।
ফলাফলগুলি দেখায় যে কোনও ধাক্কা ছাড়াই 77%, 1 টি টিকের অনুপাত 16.5%, 2 টি টিক 3.7%, 3 টি টিক 1.2%, 4 টি টিক বা তার বেশি 1% এরও কম। এটি মূলত সূচকীয় ফাংশনের বৈশিষ্ট্যগুলির সাথে সামঞ্জস্যপূর্ণ, তবে ফিটিংটি সঠিক নয়।
প্রতিফলিত মূল্যের পার্থক্য সৃষ্টি করে এমন লেনদেনের পরিমাণকে পরিসংখ্যান করা হয়েছে, শকটির খুব বড় ভুলটি সরিয়ে ফেলা হয়েছে, মূলত একটি রৈখিক সম্পর্কের সাথে সামঞ্জস্যপূর্ণ, প্রায় প্রতি 1000 এর পরিমাণে 1 টি টিকের দামের উদ্বায়ী হয়। এটি প্রতি প্লেটের কাছাকাছি দামের জন্য একটি আনুমানিক পরিমাণের জন্যও বোঝা যায়।
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);
পরিসংখ্যান 2s এর মধ্যে দামের ধাক্কা, এখানে পার্থক্য হল যে এখানে নেতিবাচক হবে, অবশ্যই এখানে শুধুমাত্র পেমেন্ট পরিসংখ্যান করা হয়, তাই সিমপ্লেক্স অবস্থানটি একটি বড় টিক হবে। টিক এবং ধাক্কা সম্পর্কগুলি পর্যবেক্ষণ করা অব্যাহত রেখে, শুধুমাত্র পরিসংখ্যানগুলি 0 এর চেয়ে বড় ফলাফল, উপসংহার এবং একক আদেশের প্রায় একই, এবং প্রায়শই লিনিয়ার সম্পর্ক, প্রতিটি টিকের জন্য প্রায় 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));
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);
পূর্ববর্তীটি একটি টিক পরিবর্তনের জন্য প্রয়োজনীয় ট্রেড পরিমাণের সন্ধান করে, তবে এটি সঠিক নয়, কারণ এটি ধারণার ভিত্তিতে তৈরি করা হয়েছে যে ধাক্কা ইতিমধ্যে ঘটেছে; এখন বিপরীতভাবে, ট্রেড পরিমাণের দামের ধাক্কা দেখুন।
এখানে তথ্য 1s দ্বারা নমুনা করা হয়, প্রতি 100 ক্যাটাগরিতে 1 ধাপ দীর্ঘ, এবং এই ক্যাটাগরির মধ্যে দামের পরিবর্তন পরিসংখ্যান করা হয়।
যেখানে
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)
পরিমাণ_গ্রুপ | price_diff | 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 |
ট্রেড পরিমাণের মডেলিং এবং ট্রেড পরিমাণের দামের প্রভাবের সাথে সম্পর্কিত একটি রুক্ষ মডেলের সাহায্যে, এটি মনে হয় যে সর্বোত্তম হ্যান্ডলিং অবস্থানগুলি গণনা করা যায়। কিছু অনুমান করা ভাল, প্রথমে একটি দায়িত্বজ্ঞানহীন সর্বোত্তম মূল্য অবস্থান দেওয়া।
প্রথমে একটি সহজ প্রত্যাশিত আয় লিখুন, অর্থাৎ 1s এর মধ্যে Q এর চেয়ে বেশি অর্থ প্রদানের সম্ভাব্যতা, প্রত্যাশিত আয়তনের গুণে (যেমন, দামের ধাক্কা):
চিত্র অনুযায়ী, প্রত্যাশিত আয় সর্বোচ্চ প্রায় ২৫০০, যা গড় লেনদেনের প্রায় ২.৫ গুণ। অর্থাৎ, বিক্রয় আদেশটি ২৫০০ অবস্থানে থাকা উচিত। আবারও জোর দেওয়া দরকার যে, ক্রান্তীয় অক্ষের মধ্যে লেনদেনের পরিমাণ 1s এর প্রতিনিধিত্ব করে, এটি সহজভাবে গভীরতার অবস্থানের সাথে সমান হতে পারে না। এবং এটি বর্তমানে গুরুত্বপূর্ণ গভীরতার তথ্যের অভাবের সময়, কেবলমাত্র ট্রেডগুলির উপর ভিত্তি করে অনুমান করা হয়।
বিভিন্ন সময় ব্যবধানের মধ্যে ট্রেডিং বিতরণ পাওয়া যায় যে এটি একক ট্রেডিং বিতরণের একটি সহজ স্কেলিং। এছাড়াও, দামের ধাক্কা এবং লেনদেনের সম্ভাব্যতার উপর ভিত্তি করে একটি সহজ প্রত্যাশিত উপার্জন মডেল তৈরি করা হয়েছে, যার ফলাফল আমাদের প্রত্যাশার সাথে সামঞ্জস্যপূর্ণ, যদি বিক্রয় আদেশের পরিমাণ কম হয়, যা দামের পতনকে পূর্বাভাস দেয়, তবে লাভের জন্য একটি নির্দিষ্ট পরিমাণ প্রয়োজন।
#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)
ওক পরিমাণ 🐂🍺