Ketika menerapkan strategi kuantitatif, eksekusi bersamaan dapat mengurangi latensi dan meningkatkan efisiensi dalam banyak kasus.
var depthA = exchanges[0].GetDepth()
var depthB = exchanges[1].GetDepth()
Ada penundaan dalam meminta API istirahat. Dengan asumsi bahwa itu adalah 100ms, waktu untuk mendapatkan kedalaman sebenarnya berbeda. Jika lebih banyak akses diperlukan, masalah penundaan akan menjadi lebih menonjol dan mempengaruhi implementasi strategi.
JavaScript tidak memiliki multithreading, sehingga fungsi Go dikemas di bagian bawah untuk memecahkan masalah ini.
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()
Dalam kasus yang paling sederhana, tidak ada yang salah dengan menulis strategi dengan cara ini. Namun, perlu dicatat bahwa proses ini harus diulang untuk setiap loop strategi. Variabel perantara a dan b hanyalah bantuan sementara. Jika kita memiliki banyak tugas serentak, kita perlu mencatat hubungan yang sesuai antara a dan depthA, dan b dan depthB. Ketika tugas serentak kita tidak pasti, situasinya menjadi lebih kompleks. Oleh karena itu, kita ingin menerapkan fungsi: ketika menulis Go secara serentak, mengikat variabel pada saat yang sama, dan ketika hasil operasi serentak kembali, hasilnya akan secara otomatis diberikan kepada variabel, menghilangkan variabel perantara dan dengan demikian membuat program lebih ringkas. Implementasi spesifiknya adalah sebagai berikut:
function G(t, ctx, f) {
return {run:function(){
f(t.wait(1000), ctx)
}}
}
Kita mendefinisikan fungsi G, di mana parameter t adalah fungsi Go yang akan dijalankan, ctx adalah konteks program rekaman, dan f adalah fungsi penugasan spesifik.
Pada saat ini, kerangka kerja program secara keseluruhan dapat ditulis mirip dengan model
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)
}
}
Tampaknya hanya satu fungsi sederhana yang telah diimplementasikan setelah berputar-putar. Sebenarnya, kompleksitas kode telah disederhanakan. Kita hanya perlu peduli tentang tugas apa yang perlu dihasilkan program. Program worker() akan secara otomatis mengeksekusi mereka secara bersamaan dan mengembalikan hasil yang sesuai. Fleksibilitas telah meningkat banyak.