यह लेख मुख्य रूप से उच्च आवृत्ति ट्रेडिंग रणनीतियों पर केंद्रित है, जिसमें संचयी लेनदेन मॉडलिंग और मूल्य झटके पर ध्यान केंद्रित किया गया है। यह लेख एकल लेनदेन, निश्चित अंतराल पर मूल्य झटके और लेनदेन के मूल्य पर प्रभाव का विश्लेषण करके एक प्रारंभिक इष्टतम लटकन स्थिति मॉडल प्रस्तुत करता है। यह मॉडल लेनदेन मात्रा और मूल्य झटके की समझ के आधार पर इष्टतम लेनदेन स्थिति खोजने का प्रयास करता है। मॉडल की धारणाओं पर गहन चर्चा की जाती है, और मॉडल के अनुमानित वास्तविक और अपेक्षित लाभों का तुलना करके इष्टतम लटकन स्थिति का प्रारंभिक मूल्यांकन किया जाता है।
पिछले आलेख में एक एकल लेनदेन के लिए एक निश्चित मूल्य से अधिक होने की संभावना का एक अभिव्यक्ति हैः
हम एक समय के लिए लेनदेन के वितरण के बारे में भी चिंतित हैं, और यह सहज रूप से प्रत्येक लेनदेन और ऑर्डर की आवृत्ति से संबंधित होना चाहिए। नीचे डेटा को एक निश्चित अंतराल के अनुसार संसाधित किया गया है। ऊपर दिए गए तरीके से इसके वितरण को चित्रित किया गया है।
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 | मूल्य | मात्रा | first_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 | ना. | 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% तक पहुंच गया है, एक टिक का अनुपात 16.5% है, दो टिक का 3.7% है, तीन टिक का 1.2% है, और चार टिक से अधिक का 1% से कम है। यह मूल रूप से सूचकांक फ़ंक्शन की विशेषताओं के अनुरूप है, लेकिन फिट नहीं है।
यह आंकड़ा उस लेनदेन की मात्रा को बताता है जो एक समान मूल्य अंतर का कारण बनता है, जो बहुत अधिक झुकाव को हटा देता है, जो मूल रूप से रैखिक संबंधों के अनुरूप है, लगभग हर 1000 मात्रा में 1 टिक की कीमत में उतार-चढ़ाव का कारण बनता है। यह भी समझा जा सकता है कि प्रत्येक डिश के पास कीमतों के लिए लटकने की मात्रा औसतन लगभग 1000 है।
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 मात्रा में एक कदम की लंबाई, और इस मात्रा के भीतर कीमतों में बदलाव का आंकलन किया गया है; कुछ अधिक मूल्यवान निष्कर्ष निकाले गए हैंः
इनमें से,
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)
मात्रा_समूह | मूल्य_अंतर | मात्रा_समूह_केंद्र | |
---|---|---|---|
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 से अधिक है, अपेक्षित लाभ दर (यानी धक्का देने वाले मूल्य) से गुणा करेंः
इमेज के अनुसार, अपेक्षित लाभ अधिकतम लगभग 2500 के आसपास है, जो कि औसत लेनदेन की मात्रा के लगभग 2.5 गुना है। यानी, बिक्री के आदेश को 2500 की स्थिति में लटका दिया जाना चाहिए। यह फिर से जोर देने की आवश्यकता है कि क्षैतिज अक्ष के भीतर लेनदेन की मात्रा 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)
ओक मात्रा 🐂🍺