Type/to search
3
Follow
1505
Followers
उच्च आवृत्ति ट्रेडिंग रणनीतियों पर विचार (2)
HFT
Created 2023-08-04 16:14:27  Updated 2024-11-10 18:48:22
 1
 3792

img

लेख में मुख्य रूप से उच्च आवृत्ति ट्रेडिंग रणनीतियों पर चर्चा की गई है, तथा संचयी मात्रा मॉडलिंग और मूल्य झटकों पर ध्यान केंद्रित किया गया है। यह शोधपत्र कीमतों पर एकल लेनदेन, निश्चित अंतराल मूल्य झटकों और लेनदेन मात्रा के प्रभाव का विश्लेषण करके एक प्रारंभिक इष्टतम ऑर्डर प्लेसमेंट मॉडल का प्रस्ताव करता है। यह मॉडल मात्रा और मूल्य झटकों की समझ के आधार पर इष्टतम ट्रेडिंग स्थिति खोजने का प्रयास करता है। मॉडल की मान्यताओं पर गहराई से चर्चा की गई है, तथा वास्तविक और मॉडल-पूर्वानुमानित अपेक्षित रिटर्न की तुलना करके इष्टतम ऑर्डर प्लेसमेंट का प्रारंभिक आकलन किया गया है।

संचयी वॉल्यूम मॉडलिंग

पिछले लेख में एकल लेनदेन की मात्रा के एक निश्चित मान से अधिक होने की संभाव्यता अभिव्यक्ति प्राप्त की गई थी:

img

हम एक समयावधि में ट्रेडिंग वॉल्यूम के वितरण के बारे में भी चिंतित हैं, जो सहज रूप से प्रत्येक लेनदेन की मात्रा और ऑर्डर आवृत्ति से संबंधित होना चाहिए। इसके बाद, डेटा को निश्चित अंतराल पर संसाधित किया जाता है। इसका वितरण ऊपर बताए अनुसार दर्शाइए।

python
from datetime import date,datetime import time import pandas as pd import numpy as np import matplotlib.pyplot as plt %matplotlib inline
python
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']

हर 1 सेकंड में ट्रांजेक्शन वॉल्यूम को मर्ज करें, उस हिस्से को हटा दें जहां कोई ट्रांजेक्शन नहीं हुआ है, और फिट करने के लिए ऊपर दिए गए सिंगल ट्रांजेक्शन के वितरण का उपयोग करें। यह देखा जा सकता है कि परिणाम बेहतर है। यदि 1 सेकंड के भीतर सभी ट्रांजेक्शन को सिंगल ट्रांजेक्शन माना जाता है, तो यह समस्या बन जाती है यह एक हल हो चुकी समस्या बन गई है। हालाँकि, जब चक्र लंबा हो जाता है (लेनदेन आवृत्ति के सापेक्ष), तो त्रुटि बढ़ जाती है, और शोध में पाया गया है कि यह त्रुटि पिछले पेरेटो वितरण सुधार अवधि के कारण होती है। इसका मतलब यह है कि जैसे-जैसे चक्र लंबा होता जाता है और इसमें अधिक व्यक्तिगत लेन-देन शामिल होते हैं, कई लेन-देन का संयोजन पेरेटो वितरण के करीब पहुंच जाता है। इस मामले में, सुधार अवधि को हटा दिया जाना चाहिए।

python
df_resampled = buy_trades['quantity'].resample('1S').sum() df_resampled = df_resampled.to_frame(name='quantity') df_resampled = df_resampled[df_resampled['quantity']>0]
python
buy_trades
agg_trade_idpricequantityfirst_trade_idlast_trade_idis_buyer_makerdatetransact_timeintervaldiff
2023-01-27 00:00:00.16111383692.90154.338061993806201False2023-01-27 00:00:00.1611674777600161NaN0.001
2023-01-27 00:00:04.14011383702.901291.338062023806203False2023-01-27 00:00:04.14016747776041403979.00.000
2023-01-27 00:00:04.33911383732.90255.138062053806207False2023-01-27 00:00:04.3391674777604339199.00.001
2023-01-27 00:00:04.77211383742.9021032.738062083806223False2023-01-27 00:00:04.7721674777604772433.00.000
2023-01-27 00:00:05.56211383752.9013.538062243806224False2023-01-27 00:00:05.5621674777605562790.00.000
.................................
2023-01-27 23:59:57.73915443703.572394.850746455074651False2023-01-27 23:59:57.73916748639977391224.00.002
2023-01-27 23:59:57.90215443723.573177.650746525074655False2023-01-27 23:59:57.9021674863997902163.00.001
2023-01-27 23:59:58.10715443733.573139.850746565074656False2023-01-27 23:59:58.1071674863998107205.00.000
2023-01-27 23:59:58.30215443743.57360.550746575074657False2023-01-27 23:59:58.3021674863998302195.00.000
2023-01-27 23:59:59.89415443763.57112.150746625074664False2023-01-27 23:59:59.89416748639998941592.00.000
python
#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

python
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

अब हमने विभिन्न समयों पर संचित ट्रेडिंग वॉल्यूम के वितरण के लिए एक सामान्य सूत्र का सारांश तैयार किया है, तथा इसे फिट करने के लिए एकल लेनदेन के वितरण का उपयोग किया है, तथा प्रत्येक बार उन्हें अलग से गिनने की आवश्यकता नहीं है। यहां हम प्रक्रिया को छोड़ देते हैं और सीधे सूत्र देते हैं:

img

उनमें से, avg_interval एकल लेनदेन के बीच औसत अंतराल का प्रतिनिधित्व करता है, और avg_interval_T उन अंतरालों के औसत अंतराल का प्रतिनिधित्व करता है जिनका अनुमान लगाने की आवश्यकता है। यह थोड़ा भ्रमित करने वाला है। यदि हम 1 सेकंड के लेनदेन समय का अनुमान लगाना चाहते हैं, तो हमें 1 सेकंड के भीतर लेनदेन वाले घटनाओं के बीच औसत अंतराल की गणना करनी होगी। यदि किसी ऑर्डर के आने की संभावना पॉइसन वितरण के अनुरूप है, तो इसका सीधे अनुमान लगाना संभव होना चाहिए, लेकिन वास्तविक विचलन बड़ा है, इसलिए मैं इसे यहां स्पष्ट नहीं करूंगा।

ध्यान दें कि एक निश्चित अंतराल के भीतर वॉल्यूम के एक निश्चित मूल्य से अधिक होने की संभावना गहराई में उस स्थिति में लेनदेन की वास्तविक संभावना से काफी भिन्न होनी चाहिए, क्योंकि प्रतीक्षा समय जितना लंबा होगा, ऑर्डर बुक होने की संभावना उतनी ही अधिक होगी गहराई में परिवर्तन होता है, इसलिए डेटा अपडेट होने पर समान गहराई की स्थिति में लेनदेन की संभावना वास्तविक समय में बदल जाती है।

python
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

एकल लेनदेन मूल्य प्रभाव

लेन-देन संबंधी डेटा एक खजाना है, और अभी भी बहुत सारा डेटा निकाला जाना बाकी है। हमें कीमतों पर ऑर्डर के प्रभाव पर बारीकी से ध्यान देना चाहिए, जो रणनीति में लंबित ऑर्डर की नियुक्ति को प्रभावित करता है। इसी तरह, transact_time कुल डेटा के आधार पर, अंतिम कीमत और पहली कीमत के बीच अंतर की गणना करें। यदि केवल एक ऑर्डर है, तो अंतर 0 है। अजीब बात यह है कि अभी भी कुछ संख्या में डेटा परिणाम नकारात्मक हैं। यह डेटा व्यवस्था के क्रम में एक समस्या होनी चाहिए, इसलिए मैं यहाँ इस पर बात नहीं करूँगा।

परिणाम दर्शाते हैं कि बिना प्रभाव वाले लोगों का अनुपात 77% जितना अधिक है, 1 टिक का अनुपात 16.5% है, 2 टिक का अनुपात 3.7% है, 3 टिक का अनुपात 1.2% है, और 4 से अधिक टिक का अनुपात 1% से कम है . यह मूलतः घातांकीय फ़ंक्शन की विशेषताओं के अनुरूप है, लेकिन फिटिंग सटीक नहीं है।

संबंधित मूल्य अंतर का कारण बनने वाले लेनदेन की मात्रा की गणना की गई, और बहुत बड़े प्रभाव के कारण होने वाली विकृति को हटा दिया गया। यह मूल रूप से रैखिक संबंध के अनुरूप है, और लगभग हर 1,000 वॉल्यूम 1 टिक के मूल्य में उतार-चढ़ाव का कारण बनता है। इसे ऐसे भी समझा जा सकता है कि प्रत्येक मूल्य के निकट लंबित ऑर्डरों की औसत संख्या लगभग 1,000 है।

python
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)
python
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
python
diff_group = buy_trades.groupby('diff').agg({ 'quantity': 'mean', 'diff': 'last', })
python
diff_group['quantity'][diff_group['diff']>0][diff_group['diff']<0.01].plot(figsize=(10,5),grid=True);

png

नियमित अंतराल पर मूल्य में उतार-चढ़ाव

2 सेकंड के भीतर कीमत के प्रभाव की गणना करें। यहाँ अंतर यह है कि नकारात्मक मूल्य होंगे। बेशक, चूँकि यहाँ केवल खरीद ऑर्डर गिने जाते हैं, इसलिए सममित स्थिति एक टिक बड़ी होगी। ट्रेडिंग वॉल्यूम और प्रभाव के बीच संबंध का निरीक्षण करना जारी रखें, और केवल 0 से अधिक परिणामों की गणना करें। निष्कर्ष एकल ऑर्डर के समान है, जो एक अनुमानित रैखिक संबंध भी है। प्रत्येक टिक के लिए लगभग 2000 वॉल्यूम की आवश्यकता होती है।

python
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]
python
result_df['price_diff'][abs(result_df['price_diff'])<0.016].value_counts().sort_index().plot.bar(figsize=(10,5));

png

python
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
python
diff_group = result_df.groupby('price_diff').agg({ 'quantity_sum': 'mean'})
python
diff_group[(diff_group.index>0) & (diff_group.index<0.015)].plot(figsize=(10,5),grid=True);

png

मात्रा का मूल्य प्रभाव

टिक परिवर्तन के लिए आवश्यक आयतन की गणना पहले की गई थी, लेकिन यह सटीक नहीं है क्योंकि यह इस धारणा पर आधारित है कि प्रभाव पहले ही घटित हो चुका है। अब आइए ट्रेडिंग वॉल्यूम के कारण मूल्य पर पड़ने वाले प्रभाव पर नजर डालें।

यहां डेटा को 1 सेकंड पर नमूना लिया जाता है, जिसमें 100 मात्राएं 1 चरण के रूप में होती हैं, और इस मात्रा सीमा के भीतर मूल्य परिवर्तन की गणना की जाती है। कुछ मूल्यवान निष्कर्ष निकाले गए:

  1. जब खरीद मात्रा 500 से नीचे होती है, तो अपेक्षित मूल्य परिवर्तन नीचे होता है, जो कि अपेक्षित है क्योंकि मूल्य को प्रभावित करने वाले विक्रय आदेश भी होते हैं।
  2. जब ट्रेडिंग वॉल्यूम कम होता है, तो यह एक रैखिक संबंध का अनुसरण करता है, अर्थात, ट्रेडिंग वॉल्यूम जितना अधिक होता है, कीमत में उतनी ही अधिक वृद्धि होती है।
  3. खरीद ऑर्डर वॉल्यूम जितना बड़ा होगा, कीमत में बदलाव उतना ही अधिक होगा, जो अक्सर कीमत में एक ब्रेकथ्रू को दर्शाता है। ब्रेकथ्रू के बाद, कीमत वापस आ सकती है। निश्चित अंतराल पर सैंपलिंग के साथ, डेटा अस्थिर है।
  4. स्कैटर प्लॉट के ऊपरी भाग पर ध्यान दिया जाना चाहिए, अर्थात वह भाग जहां वॉल्यूम मूल्य वृद्धि के अनुरूप होता है।
  5. केवल इस ट्रेडिंग जोड़ी के लिए, मात्रा और मूल्य परिवर्तन के बीच संबंध का एक मोटा संस्करण दिया गया है:

img

उनमें से, "सी" मूल्य में परिवर्तन का प्रतिनिधित्व करता है और "क्यू" खरीद आदेश मात्रा का प्रतिनिधित्व करता है।

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

python
grouped_df.head(10)
quantity_groupprice_diffquantity_group_center
00-199-0.00030299.5
1100-299-0.000124199.5
2200-399-0.000068299.5
3300-499-0.000017399.5
4400-599-0.000048499.5
5500-6990.000098599.5
6600-7990.000006699.5
7700-8990.000261799.5
8800-9990.000186899.5
9900-10990.000299999.5

प्रारंभिक इष्टतम ऑर्डर स्थिति

ट्रेडिंग वॉल्यूम के मॉडलिंग और मूल्य प्रभाव के अनुरूप ट्रेडिंग वॉल्यूम के एक मोटे मॉडल के साथ, ऐसा लगता है कि इष्टतम ऑर्डर स्थिति की गणना की जा सकती है। आइये कुछ धारणाएं बनाएं और एक गैर-जिम्मेदार इष्टतम मूल्य स्थिति दें।

  1. मान लीजिए कि आघात के बाद कीमत अपने मूल मूल्य पर वापस आ जाती है (यह निश्चित रूप से असंभव है और आघात के बाद मूल्य में हुए परिवर्तनों का पुनः विश्लेषण आवश्यक है)
  2. मान लें कि इस अवधि के दौरान ट्रेडिंग वॉल्यूम और ऑर्डर आवृत्ति का वितरण पूर्व निर्धारित आवश्यकताओं को पूरा करता है (यह भी गलत है, क्योंकि अनुमान के लिए एक दिन का मूल्य उपयोग किया जाता है, और लेनदेन में स्पष्ट क्लस्टरिंग होती है)।
  3. मान लें कि सिमुलेशन समय के दौरान केवल एक विक्रय आदेश होता है और फिर स्थिति बंद हो जाती है।
  4. यह मानते हुए कि ऑर्डर निष्पादित होने के बाद, कीमत को बढ़ाने के लिए अन्य खरीद ऑर्डर जारी हैं, खासकर जब वॉल्यूम बहुत कम है। इस प्रभाव को यहाँ अनदेखा किया जाता है और यह मान लिया जाता है कि यह वापस आ जाएगा।

सबसे पहले, एक सरल अपेक्षित प्रतिफल लिखें, अर्थात, 1 सेकंड के भीतर संचयी खरीद आदेश Q से अधिक होने की संभावना, जिसे अपेक्षित प्रतिफल दर (अर्थात, प्रभाव मूल्य) से गुणा किया जाता है:

img

ग्राफ के अनुसार, अपेक्षित रिटर्न अधिकतम 2500 के आसपास है, जो औसत ट्रेडिंग वॉल्यूम का लगभग 2.5 गुना है। इसका मतलब यह है कि विक्रय आदेश 2500 पर रखा जाना चाहिए। इस बात पर पुनः जोर दिया जाना चाहिए कि क्षैतिज अक्ष 1 सेकंड के भीतर ट्रेडिंग वॉल्यूम को दर्शाता है और इसे केवल गहराई की स्थिति के साथ नहीं जोड़ा जा सकता है। और यह ऐसे समय में है जब अभी भी बहुत महत्वपूर्ण गहन डेटा का अभाव है, और यह केवल ट्रेडों पर आधारित अटकलों पर आधारित है।

संक्षेप

यह पाया गया है कि विभिन्न समय अंतरालों पर मात्रा वितरण, एकल लेनदेन के मात्रा वितरण का एक सरल मापन है। हमने मूल्य झटकों और लेनदेन की संभावना के आधार पर एक सरल अपेक्षित रिटर्न मॉडल भी बनाया है। इस मॉडल के परिणाम हमारी अपेक्षाओं के अनुरूप हैं। यदि बिक्री ऑर्डर की मात्रा कम है, तो यह मूल्य में गिरावट का संकेत देता है। एक निश्चित मात्रा में वॉल्यूम की आवश्यकता होती है लाभ मार्जिन है, और लेन-देन की मात्रा जितनी बड़ी होगी, लाभ मार्जिन उतना ही अधिक होगा। संभावना जितनी बड़ी होगी, यह उतना ही कम होगा। बीच में एक इष्टतम आकार है, जो ऑर्डर प्लेसमेंट की स्थिति भी है जिसे रणनीति तलाश रही है। बेशक, यह मॉडल अभी भी बहुत सरल है। अगले लेख में, मैं इस पर गहराई से चर्चा जारी रखूंगा।

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

Related Recommendations
Comment
All comments (1)

    🐂🍺

    3 years ago
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)