मात्रात्मक रणनीति को लागू करते समय, समवर्ती निष्पादन विलंबता को कम कर सकता है और कई मामलों में दक्षता में सुधार कर सकता है। हेजिंग रोबोट को उदाहरण के रूप में लेते हुए, हमें दो सिक्कों की गहराई प्राप्त करने की आवश्यकता है। अनुक्रम में निष्पादित कोड निम्नानुसार हैः
var depthA = exchanges[0].GetDepth()
var depthB = exchanges[1].GetDepth()
एक आराम एपीआई के अनुरोध में देरी होती है। यह मानते हुए कि यह 100ms है, गहराई प्राप्त करने का समय वास्तव में अलग है। यदि अधिक पहुंच की आवश्यकता है, तो देरी की समस्या अधिक प्रमुख हो जाएगी और रणनीति के कार्यान्वयन को प्रभावित करेगी।
जावास्क्रिप्ट में मल्टीथ्रेडिंग नहीं है, इसलिए इस समस्या को हल करने के लिए गो फ़ंक्शन को नीचे कैप्सूल किया गया है। हालांकि, डिजाइन तंत्र के कारण, कार्यान्वयन अपेक्षाकृत बोझिल है।
var a = exchanges[0].Go("GetDepth")
var b = exchanges[1].Go("GetDepth")
var depthA = a.wait() // Call the wait method to wait for the return of the depth result asynchronously
var depthB = b.wait()
अधिकांश सरल मामलों में, इस तरह से रणनीति लिखने में कुछ भी गलत नहीं है। हालांकि, यह ध्यान दिया जाता है कि इस प्रक्रिया को प्रत्येक रणनीति लूप के लिए दोहराया जाना चाहिए। मध्यवर्ती चर ए और बी केवल अस्थायी सहायक हैं। यदि हमारे पास बहुत सारे समवर्ती कार्य हैं, तो हमें ए और गहराईए, और बी और गहराईबी के बीच संबंधित संबंध रिकॉर्ड करने की आवश्यकता है। जब हमारे समवर्ती कार्य अनिश्चित होते हैं, तो स्थिति अधिक जटिल हो जाती है। इसलिए हम एक फ़ंक्शन को लागू करना चाहते हैंः जब समवर्ती रूप से जाओ लिखते हैं, तो एक ही समय में एक चर को बांधें, और जब समवर्ती ऑपरेशन का परिणाम वापस आता है, तो परिणाम स्वचालित रूप से चर को सौंपा जाएगा, मध्यवर्ती चर को समाप्त कर देता है और इस प्रकार कार्यक्रम को अधिक संक्षिप्त बनाता है। विशिष्ट कार्यान्वयन इस प्रकार हैः
function G(t, ctx, f) {
return {run:function(){
f(t.wait(1000), ctx)
}}
}
हम एक G फ़ंक्शन को परिभाषित करते हैं, जहां पैरामीटर t निष्पादित करने के लिए Go फ़ंक्शन है, ctx रिकॉर्डिंग प्रोग्राम संदर्भ है, और f विशिष्ट असाइनमेंट फ़ंक्शन है। आप बाद में फ़ंक्शन देखेंगे।
इस समय, समग्र प्रोग्राम फ्रेमवर्क को
var Info = [{depth:null, account:null}, {depth:null, account:null}] // If we need to obtain the depth and account of the two exchanges, more information can also be put in, such as order ID, status, etc.
var tasks = [ ] // Global list of tasks
function produce(){ // Issue various concurrent tasks
// The logic of task generation is omitted here, for demonstration purposes only.
tasks.push({exchange:0, ret:'depth', param:['GetDepth']})
tasks.push({exchange:1, ret:'depth', param:['GetDepth']})
tasks.push({exchange:0, ret:'sellID', param:['Buy', Info[0].depth.Asks[0].Price, 10]})
tasks.push({exchange:1, ret:'buyID', param:['Sell', Info[1].depth.Bids[0].Price, 10]})
}
function worker(){
var jobs = []
for(var i=0;i<tasks.length;i++){
var task = tasks[i]
tasks.splice(i,1) // Delete executed tasks
jobs.push(G(exchanges[task.exchange].Go.apply(this, task.param), task, function(v, task) {
Info[task.exchange][task.ret] = v // The v here is the return value of the concurrent Go function wait(), which can be experienced carefully.
}))
}
_.each(jobs, function(t){
t.run() // Execute all tasks concurrently here
})
}
function main() {
while(true){
produce() // Send trade orders
worker() // Concurrent execution
Sleep(1000)
}
}
ऐसा लगता है कि सर्कल में घूमने के बाद केवल एक सरल फ़ंक्शन को लागू किया गया है। वास्तव में, कोड की जटिलता बहुत सरल हो गई है। हमें केवल इस बात की परवाह करने की आवश्यकता है कि प्रोग्राम को क्या कार्य उत्पन्न करने की आवश्यकता है। कार्यकर्ता))) प्रोग्राम स्वचालित रूप से उन्हें समवर्ती रूप से निष्पादित करेगा और संबंधित परिणाम लौटाएगा। लचीलापन में बहुत सुधार हुआ है।