मैंने लेख में एक बैकटेस्टिंग इंजन जारी किया
सबसे पहले, ऐतिहासिक के-लाइन क्या है? एक के-लाइन डेटा में चार कीमतें शामिल हैंः उच्चतम मूल्य, उद्घाटन मूल्य, सबसे कम मूल्य और समापन मूल्य, प्रारंभ समय, अंत समय और अंतराल व्यापार मात्रा। अधिकांश मात्रात्मक प्लेटफार्मों और फ्रेमवर्क को के-लाइन के आधार पर बैकटेस्ट किया जाता है, और एफएमजेड क्वांट प्लेटफॉर्म टिक स्तर बैकटेस्टिंग भी प्रदान करता है। के-लाइन बैकटेस्टिंग की गति बहुत तेज है, और यह ज्यादातर मामलों में कोई समस्या नहीं है, लेकिन बहुत गंभीर दोष भी हैं, विशेष रूप से मल्टी-वेरिएटी रणनीति और उच्च आवृत्ति बैकटेस्टिंग की रणनीति, जो शायद ही सही निष्कर्ष निकाल सकती है।
सबसे पहले, यह समय की बात है। के-लाइन डेटा के उच्चतम और निम्नतम मूल्य का समय नहीं दिया गया है, इसलिए यह विचार करने के लिए अनावश्यक है, लेकिन सबसे महत्वपूर्ण उद्घाटन और समापन मूल्य उद्घाटन और समापन स्थिति के समय नहीं हैं। भले ही ट्रेडिंग किस्में अप्रचलित हों, वे अक्सर दस सेकंड से अधिक समय तक कारोबार नहीं की जाती हैं। जब हम बहु-विविधता रणनीतियों का बैकटेस्ट करते हैं, तो हम अक्सर डिफ़ॉल्ट रूप से मानते हैं कि उनकी उद्घाटन और समापन कीमतें समान हैं, जो समापन मूल्य बैकटेस्टिंग का आधार भी है।
दो किस्मों के मध्यस्थता को बैकटेस्ट करने के लिए मिनट-लाइन का उपयोग करने की कल्पना करें। उनके बीच का अंतर आमतौर पर 10 युआन होता है। अब यह पाया जाता है कि 10:01 पर, अनुबंध ए का समापन मूल्य 100 युआन है, अनुबंध बी का समापन मूल्य 112 युआन है, और अंतर 12 युआन है। इसलिए रणनीति हेजिंग शुरू करती है। एक निश्चित समय पर, अंतर वापस आ जाता है, और रणनीति 2 युआन रिटर्न लाभ कमाती है।
हालांकि, वास्तविक स्थिति हो सकती है कि 10:00:45 पर, अनुबंध ए ने 100 युआन का लेनदेन उत्पन्न किया, और फिर कोई लेनदेन नहीं हुआ। अनुबंध बी ने 10:00:58 पर 112 युआन का लेनदेन उत्पन्न किया। 10:01 पर, दोनों कीमतें मौजूद नहीं थीं। इस समय शुरुआती मूल्य क्या था? और हेजिंग कितना अंतर प्राप्त कर सकता है? हम नहीं जानते। एक संभावित स्थिति यह है कि 10:00:58 पर, अनुबंध ए का एक खरीदने और बेचने का रुझान 101.9-102.1 है, और 2 युआन का कोई प्रसार नहीं है, जो हमारी रणनीति अनुकूलन को बहुत भ्रामक बना देगा।
दूसरा मैचमेकिंग है। असली मैचमेकिंग पहले कीमत और समय है। यदि खरीदार एक बिक्री मूल्य से अधिक है, तो वह आमतौर पर एक बिक्री मूल्य पर लेनदेन समाप्त करेगा, अन्यथा, वह ऑर्डर बुक में प्रवेश करेगा और इंतजार करेगा। यह स्पष्ट है कि के-लाइन डेटा में एक बेचने या खरीदने की कीमत नहीं है, जो विस्तार के स्तर पर मिलान का अनुकरण करने में असमर्थ है।
अंतिम है बाजार पर रणनीति के लेनदेन का प्रभाव। यदि यह एक छोटा फंड बैकटेस्ट है, तो प्रभाव छोटा होगा। हालांकि, यदि ट्रेडिंग मात्रा एक बड़े अनुपात के लिए जिम्मेदार है, तो इसका बाजार पर प्रभाव पड़ेगा। लेनदेन तुरंत पूरा होने पर न केवल मूल्य स्लिप बिंदु बड़ा होगा, बल्कि यदि आपका खरीद आदेश बैकटेस्ट में पूरा हो जाता है, तो यह वास्तव में अन्य मूल व्यापारियों के लेनदेन को रोकता है जो खरीदना चाहते हैं, जिसका बाजार पर तितली प्रभाव प्रभाव पड़ेगा। हालांकि, इस प्रभाव को मात्रात्मक रूप से निर्धारित नहीं किया जा सकता है, और यह केवल अनुभव से कहा जा सकता है कि उच्च आवृत्ति व्यापार केवल छोटे धनराशि को समायोजित कर सकता है।
एफएमजेड वास्तविक बॉट स्तर बैकटेस्टिंग प्रदान करता है, जो वास्तविक ऐतिहासिक 20-स्तर गहराई, वास्तविक समय सेकंड टिक, लेनदेन द्वारा लेनदेन और अन्य डेटा प्राप्त कर सकता है, और इसके आधार पर यह वास्तविक बॉट प्लेबैक फ़ंक्शन बनाया है (https://www.fmz.com/m/database) इस प्रकार के बैकटेस्ट माप में बड़ी मात्रा में डेटा और धीमी गति है, जिसका उपयोग केवल दो दिनों के लिए किया जा सकता है। अपेक्षाकृत उच्च आवृत्ति वाली रणनीतियों के लिए या सख्त समय निर्णय की आवश्यकता होती है, वास्तविक बॉट बैकटेस्टिंग आवश्यक है। एफएमजेड द्वारा एकत्र किए गए ट्रेडिंग जोड़े और समय बहुत लंबे नहीं हैं, लेकिन 70 बिलियन से अधिक ऐतिहासिक डेटा हैं। वर्तमान मिलान तंत्र यह है कि यदि खरीद आदेश एक बिक्री आदेश से बड़ा है, तो यह मात्रा को देखे बिना तुरंत पूरी तरह से मेल खाएगा, और यदि खरीद आदेश एक बिक्री आदेश से कम है, तो यह मिलान कतार में प्रवेश करेगा। यह बैकटेस्टिंग तंत्र के-लाइन बैकटेस्टिंग की पहली दो समस्याओं को हल करता है, लेकिन यह अभी भी अंतिम समस्या को हल नहीं कर सकता है। और क्योंकि डेटा की मात्रा बहुत बड़ी है, बैकटेस्टिंग गति और समय सीमा सीमित है।
के-लाइन के बारे में बहुत कम जानकारी है, और गहराई भी गलत हो सकती है। हालांकि, एक प्रकार का डेटा बाजार का वास्तविक लेनदेन इरादा है, जो सबसे वास्तविक लेनदेन इतिहास को दर्शाता है - यानी, लेनदेन द्वारा लेनदेन। इस पेपर में, मैं ऑर्डर प्रवाह के आधार पर एक उच्च-आवृत्ति बैकटेस्टिंग प्रणाली का प्रस्ताव करूंगा, जो वास्तविक बॉट स्तर पर बैकटेस्टिंग में डेटा की मात्रा को बहुत कम करेगा, और कुछ हद तक, बाजार पर ट्रेडिंग वॉल्यूम के प्रभाव का अनुकरण करेगा।
मैंने पिछले 5 दिनों के लेनदेन द्वारा लेनदेन डाउनलोड किया है
[['XTZ', 1590981301905, 2.905, 0.4, 'False\n'],
['XTZ', 1590981303044, 2.903, 3.6, 'True\n'],
['XTZ', 1590981303309, 2.903, 3.7, 'True\n'],
['XTZ', 1590981303738, 2.903, 238.1, 'True\n'],
['XTZ', 1590981303892, 2.904, 0.1, 'False\n'],
['XTZ', 1590981305250, 2.904, 0.1, 'False\n'],
['XTZ', 1590981305643, 2.903, 197.3, 'True\n'],
डेटा एक दो आयामी सूची है, जिसे लेनदेन के समय द्वारा सॉर्ट किया गया है। विशिष्ट अर्थ हैंः प्रजाति का नाम, लेनदेन की कीमत, लेनदेन का समय टिकट, लेनदेन की मात्रा, और क्या बिक्री आदेश सक्रिय रूप से निष्पादित किया गया है। खरीद और बिक्री दोनों हैं। प्रत्येक लेनदेन में खरीदार और विक्रेता शामिल हैं। यदि खरीदार एक बाजार निर्माता है और विक्रेता एक सक्रिय लेनदेन लेने वाला है, तो अंतिम डेटा सच होगा।
सबसे पहले, लेन-देन की दिशा के अनुसार, हम बाजार में एक खरीद और एक बेचने के बारे में सटीक अनुमान लगा सकते हैं। यदि यह एक सक्रिय बिक्री आदेश है, तो इस समय एक खरीद की कीमत लेनदेन की कीमत है। यदि यह एक सक्रिय खरीद आदेश है, तो एक बेचने की कीमत लेनदेन की कीमत है। यदि कोई नया लेनदेन है, तो हम नई शुरुआती स्थिति को अपडेट करेंगे। यदि यह अपडेट नहीं किया गया है, तो अंतिम परिणाम बरकरार रहेगा। उपरोक्त डेटा के अंतिम क्षण को लॉन्च करना आसान है। एक खरीद की कीमत 2.903 है और एक बेचने की कीमत 2.904 है।
ऑर्डर प्रवाह के अनुसार, इसे इस तरह से मेल खा सकता हैः एक खरीद ऑर्डर को उदाहरण के रूप में लें, कीमत कीमत है, और ऑर्डर मात्रा राशि है। इस समय, एक खरीदें और एक बिक्री एक शुरुआती स्थिति क्रमशः बोली और पूछें। यदि कीमत पूछने से कम और बोली से अधिक है, तो इसे पहले निर्माता के रूप में आंका जाएगा, और मैचमेकिंग को प्राथमिकता दी जा सकती है। फिर ऑर्डर के जीवनकाल के दौरान कीमत से कम या बराबर लेनदेन की कीमत वाले सभी लेनदेन इस आदेश के साथ मेल खाएंगे (यदि कीमत बोली से कम या बराबर है, तो लेनदेन को प्राथमिकता नहीं दी जा सकती है, और कीमत से कम लेनदेन की कीमत वाले ऑर्डर इस आदेश के साथ मेल खाएंगे) । मैचमेकिंग मूल्य मूल्य है, और लेनदेन की मात्रा लेनदेन द्वारा लेनदेन की मात्रा है, जब तक कि लेनदेन पूरी तरह से बंद नहीं हो जाता है या लेनदेन रद्द नहीं हो जाता है। यदि अंतर अधिक है, तो इसे लेने वाले के रूप में माना जाएगा। इस तरह की रणनीति लेनदेन के दौरान लेनदेन की कीमत से कम या लेनदेन के बाद के आदेश के साथ मेल खाने के लिए प्रोत्साहित करती है।
इस मैचमेकिंग की समस्या को देखना आसान है। यदि ऑर्डर एक टेकर है, तो वास्तविक स्थिति यह है कि लेनदेन तुरंत किया जा सकता है, बजाय इसके कि एक नया ऑर्डर मिलान करने के लिए प्रतीक्षा करें। सबसे पहले, हमने बाजार में सूचीबद्ध ऑर्डर की संख्या पर विचार नहीं किया। भले ही डेटा थे, लेनदेन के प्रत्यक्ष निर्णय ने गहराई को बदल दिया है और बाजार को प्रभावित किया है। नए ऑर्डर पर आधारित मैचमेकिंग इतिहास में वास्तविक ऑर्डर के साथ आपके ऑर्डर को बदलने के बराबर है, जो किसी भी मामले में बाजार की लेनदेन मात्रा सीमा से अधिक नहीं होगा, और अंतिम लाभ बाजार द्वारा उत्पन्न अधिकतम लाभ से अधिक नहीं हो सकता है। मैचमेकिंग तंत्र का कुछ हिस्सा ऑर्डर की लेनदेन मात्रा को भी प्रभावित करता है, जिससे रणनीति के रिटर्न पर प्रभाव पड़ता है, जो रणनीतिक रूप से रणनीति को दर्शाता है। कोई पारंपरिक बैकटेस्टिंग नहीं होगी, जहां फंड की राशि दोगुनी हो जाती है तो आपके ऑर्डर की मात्रा दोगुनी हो जाती है।
कुछ छोटे विवरण भी हैं। यदि किसी ऑर्डर की खरीद मूल्य खरीद एक मूल्य के बराबर है, तो अभी भी एक निश्चित संभावना है कि ऑर्डर खरीद एक मूल्य पर मेल खाएगा। ऑर्डर की प्राथमिकता और लेनदेन की संभावना पर विचार करने की आवश्यकता है, जो अधिक जटिल है, और इसे यहां विचार नहीं किया जाएगा।
एक्सचेंज ऑब्जेक्ट्स शुरुआत में परिचय को संदर्भित कर सकते हैं, मूल रूप से अपरिवर्तित। केवल मेकर और टेकर कमीशन के बीच का अंतर जोड़ा जाता है, और बैकटेस्टिंग की गति अनुकूलित होती है। मैचमेकिंग कोड मुख्य रूप से नीचे पेश किया गया है।
symbol = 'XTZ'
loop_time = 0
intervel = 1000 #The sleep time of the strategy is 1000ms
init_price = data[0][2] #Initial price
e = Exchange([symbol],initial_balance=1000000,maker_fee=maker_fee,taker_fee=taker_fee,log='') #Initialize the exchange
depth = {'ask':data[0][2], 'bid':data[0][2]} #depth
order = {'buy':{'price':0,'amount':0,'maker':False,'priority':False,'id':0},
'sell':{'price':0,'amount':0,'maker':False,'priority':False,'id':0}} #Order
for tick in data:
price = int(tick[2]/tick_sizes[symbol])*tick_sizes[symbol] #Transaction price
trade_amount = tick[3] #Number of transactions
time_stamp = tick[1] #Transaction timestamp
if tick[4] == 'False\n':
depth['ask'] = price
else:
depth['bid'] = price
if depth['bid'] < order['buy']['price']:
order['buy']['priority'] = True
if depth['ask'] > order['sell']['price']:
order['sell']['priority'] = True
if price > order['buy']['price']:
order['buy']['maker'] = True
if price < order['sell']['price']:
order['sell']['maker'] = True
#Order network delay can also be used as one of the matching conditions, which is not considered here
cond1 = order['buy']['priority'] and order['buy']['price'] >= price and order['buy']['amount'] > 0
cond2 = not order['buy']['priority'] and order['buy']['price'] > price and order['buy']['amount'] > 0
cond3 = order['sell']['priority'] and order['sell']['price'] <= price and order['sell']['amount'] > 0
cond4 = not order['sell']['priority'] and order['sell']['price'] < price and order['sell']['amount'] > 0
if cond1 or cond2:
buy_price = order['buy']['price'] if order['buy']['maker'] else price
e.Buy(symbol, buy_price, min(order['buy']['amount'],trade_amount), order['buy']['id'], order['buy']['maker'])
order['buy']['amount'] -= min(order['buy']['amount'],trade_amount)
e.Update(time_stamp,[symbol],{symbol:price})
if cond3 or cond4:
sell_price = order['sell']['price'] if order['sell']['maker'] else price
e.Sell(symbol, sell_price, min(order['sell']['amount'],trade_amount), order['sell']['id'], order['sell']['maker'])
order['sell']['amount'] -= min(order['sell']['amount'],trade_amount)
e.Update(time_stamp,[symbol],{symbol:price})
if time_stamp - loop_time > intervel:
order = get_order(e,depth,order) #Trading logic, not given here
loop_time += int((time_stamp - loop_time)/intervel)*intervel
कुछ विवरण ध्यान देने योग्य हैंः
-1. जब कोई नया लेन-देन होता है, तो हमें पहले ऑर्डर मिलाना चाहिए, और फिर नवीनतम मूल्य के अनुसार ऑर्डर देना चाहिए।
-2. प्रत्येक आदेश में दो विशेषताएं होती हैंः निर्माता
अंत में, हम वास्तविक बैकटेस्टिंग चरण तक पहुँचते हैं। यहां, हम यह देखने के लिए एक सबसे क्लासिक ग्रिड रणनीति का बैकटेस्ट करने जा रहे हैं कि क्या इसने अपेक्षित प्रभाव प्राप्त किया है। रणनीति सिद्धांत यह है कि हर बार जब कीमत 1% बढ़ जाती है, तो हम शॉर्ट पोजीशन ऑर्डर का एक निश्चित मूल्य रखेंगे (अन्यथा, हम लॉन्ग पोजीशन ऑर्डर रखेंगे), और हम खरीद ऑर्डर और बिक्री ऑर्डर की गणना करेंगे और उन्हें पहले से लंबित करेंगे। कोड जारी नहीं किया जाएगा। सभी कोड को फ़ंक्शन में कैप्सूल करें।Grid ('XTZ ', 100,0.31000, maker_fee=-0.00002, taker_fee=0.0003)
मापदंड हैंः ट्रेडिंग जोड़ी, मूल्य विचलन 1% के साथ होल्डिंग वैल्यू, ऑर्डर घनत्व 0.3%, एमएस का स्लीप इंटरवल, लंबित ऑर्डर कमीशन और टेकर कमीशन।
पिछले 5 दिनों से एक्सटीजेड बाजार में झटका लगा हुआ है, जो कि ग्रिड रणनीति के लिए बहुत उपयुक्त है।
हम पहले रिटर्न पर विभिन्न पदों के प्रभाव का बैकटेस्ट करेंगे। पारंपरिक बैकटेस्टिंग तंत्र द्वारा मापा गया रिटर्न निश्चित रूप से पदों की वृद्धि के साथ आनुपातिक रूप से बढ़ेगा।
e1 = Grid('XTZ',100,0.3,1000,maker_fee=-0.00002,taker_fee=0.0003)
print(e1.account['USDT'])
e2 = Grid('XTZ',1000,0.3,1000,maker_fee=-0.00002,taker_fee=0.0003)
print(e2.account['USDT'])
e3 = Grid('XTZ',10000,0.3,1000,maker_fee=-0.00002,taker_fee=0.0003)
print(e3.account['USDT'])
e4 = Grid('XTZ',100000,0.3,1000,maker_fee=-0.00002,taker_fee=0.0003)
print(e4.account['USDT'])
कुल चार समूहों को 100, 1000, 10000 और 100000 की स्थिति मानों के साथ बैकटेस्ट किया गया और कुल बैकटेस्टिंग समय 1.3 सेकंड था। परिणाम इस प्रकार हैंः
{'realised_profit': 28.470993031132966, 'margin': 0.7982662957624465, 'unrealised_profit': 0.0104554474048441, 'total': 10000028.481448, 'leverage': 0.0, 'fee': -0.3430967859046398, 'maker_fee': -0.36980249726699727, 'taker_fee': 0.026705711362357405}
{'realised_profit': 275.63148945320177, 'margin': 14.346335829979132, 'unrealised_profit': 4.4382117331794045e-14, 'total': 10000275.631489, 'leverage': 0.0, 'fee': -3.3102045933457784, 'maker_fee': -3.5800688964477048, 'taker_fee': 0.2698643031019274}
{'realised_profit': 2693.8701498889504, 'margin': 67.70120400534114, 'unrealised_profit': 0.5735269329348516, 'total': 10002694.443677, 'leverage': 0.0001, 'fee': -33.984021415250744, 'maker_fee': -34.879233866850974, 'taker_fee': 0.8952124516001403}
{'realised_profit': 22610.231198585603, 'margin': 983.3853688758861, 'unrealised_profit': -20.529965947304365, 'total': 10022589.701233, 'leverage': 0.002, 'fee': -200.87094000385412, 'maker_fee': -261.5849078470078, 'taker_fee': 60.71396784315319}
यह देखा जा सकता है कि अंतिम प्राप्त लाभ क्रमशः स्थिति मूल्य का 28.4%, 27.5%, 26.9% और 22.6% है। यह वास्तविक स्थिति के अनुरूप भी है। स्थिति का मूल्य जितना अधिक होगा, आदेश का मूल्य उतना ही अधिक होगा, और आंशिक लेनदेन होने की अधिक संभावना होगी। आदेश की राशि के सापेक्ष अंतिम प्राप्त रिटर्न छोटा होगा। नीचे दिया गया चित्र क्रमशः 100 और 10000 के स्थिति मूल्यों के साथ सापेक्ष रिटर्न की तुलना दिखाता हैः
हम बैकटेस्ट की वापसी पर विभिन्न मापदंडों के प्रभाव को भी बैकटेस्ट कर सकते हैं, जैसे लंबित ऑर्डर घनत्व, नींद का समय और कमीशन। उदाहरण के रूप में नींद का समय लें, इसे 100ms में बदलें, 1000ms के नींद के समय की तुलना करें, और रिटर्न का निरीक्षण करें। बैकटेस्टिंग परिणाम इस प्रकार हैंः
{'realised_profit': 29.079440803790423, 'margin': 0.7982662957624695, 'unrealised_profit': 0.0104554474048441, 'total': 10000029.089896, 'leverage': 0.0, 'fee': -0.3703702128662524, 'maker_fee': -0.37938946377435134, 'taker_fee': 0.009019250908098965}
लाभ थोड़ा बढ़ गया है। इसका कारण यह है कि रणनीति के लिए केवल एक समूह के आदेश लंबित हैं, और कुछ आदेश उतार-चढ़ाव वाली कीमत नहीं प्राप्त कर सकते हैं क्योंकि उनके पास बदलने का समय नहीं है। कम नींद का समय इस समस्या में सुधार करता है। यह ग्रिड रणनीति में लंबित बहु-समूह के आदेशों के महत्व को भी दर्शाता है।
इस पेपर में ऑर्डर फ्लो के आधार पर एक नई बैकटेस्टिंग प्रणाली का प्रस्ताव है, जो आंशिक रूप से ऑर्डर लंबित, ऑर्डर लेने, आंशिक लेनदेन और देरी जैसी मिलान स्थिति का अनुकरण कर सकती है, आंशिक रूप से रिटर्न पर रणनीतिक फंड मात्रा के प्रभाव को दर्शाती है, और उच्च आवृत्ति रणनीतियों और हेजिंग रणनीतियों के लिए इसका महत्वपूर्ण संदर्भ मूल्य है। उच्च परिशुद्धता बैकटेस्टिंग रणनीति मापदंडों के अनुकूलन के लिए दिशा इंगित करती है। इसे दीर्घकालिक वास्तविक बॉट परीक्षणों द्वारा भी सत्यापित किया गया है। और बैकटेस्ट के लिए आवश्यक डेटा की मात्रा अच्छी तरह से नियंत्रित है, और बैकटेस्ट गति भी बहुत तेज है।