Menggunakan JavaScript untuk mengimplementasikan kebijakan kuantifikasi pada saat yang sama untuk menjalankan fungsi Go yang terbungkus dengan kerucut

Penulis:Rumput, Dibuat: 2019-06-29 11:24:57, Diperbarui: 2023-10-26 20:06:10

img

Dalam banyak kasus, pelaksanaan bersamaan dapat mengurangi efisiensi peningkatan waktu saat menerapkan strategi kuantitatif. Sebagai contoh, untuk robot hedging, perlu mendapatkan kedalaman dua koin, kode yang dijalankan secara berurutan adalah sebagai berikut:

var depthA = exchanges[0].GetDepth()
var depthB = exchanges[1].GetDepth()

Permintaan satu kali rest API mengalami keterlambatan, misalkan 100 ms, maka waktu untuk mendapatkan kedalaman dua kali sebenarnya berbeda, dan masalah keterlambatan akan lebih menonjol jika diperlukan lebih banyak kunjungan, yang mempengaruhi pelaksanaan kebijakan.

JavaScript tidak memiliki banyak thread, sehingga fungsi Go yang terbungkus di bawahnya memecahkan masalah ini, tetapi implementasinya lebih rumit karena mekanisme desainnya.

var a = exchanges[0].Go("GetDepth")
var b = exchanges[1].Go("GetDepth")
var depthA = a.wait() //调用wait方法等待返回异步获取depth结果 
var depthB = b.wait()

Dalam kebanyakan kasus sederhana, menulis kebijakan dengan cara ini tidak masalah. Namun, perhatikan bahwa setiap siklus kebijakan harus mengulangi proses ini, dan variabel tengah a, b sebenarnya hanya bantuan sementara. Jika kita memiliki banyak tugas paralel, kita juga harus mencatat hubungan antara a dan depthA, b, dan depthB, dan situasinya lebih rumit ketika tugas paralel kita tidak pasti. Oleh karena itu, kita ingin menerapkan fungsi: ketika menulis Go secara bersamaan, mengikat variabel pada saat yang sama, dan ketika hasil dari operasi paralel dikembalikan, hasilnya secara otomatis memberikan nilai kepada variabel, sehingga menghilangkan variabel tengah, sehingga program menjadi lebih sederhana. Secara khusus, kita dapat menerapkan:

function G(t, ctx, f) {
    return {run:function(){
        f(t.wait(1000), ctx)
    }}
}

Kita mendefinisikan sebuah fungsi G di mana parameter t adalah fungsi Go yang akan dijalankan, ctx adalah konteks pada program catatan, dan f adalah fungsi yang diberikan nilai tertentu.

Dalam hal ini, kerangka kerja program secara keseluruhan dapat ditulis sebagai mirip dengan model kerangka kerja produsen-konsumen (dengan beberapa perbedaan), di mana produsen terus-menerus mengeluarkan tugas, konsumen mengeksekusi mereka secara bersamaan, sementara kode hanya untuk demonstrasi dan tidak melibatkan logika eksekusi program.

var Info = [{depth:null, account:null}, {depth:null, account:null}] //加入我们需要获取两个交易所的深度和账户,跟多的信息也可以放入,如订单Id,状态等。
var tasks = [ ] //全局的任务列表

function produce(){ //下发各种并发任务
  //这里省略了任务产生的逻辑,仅为演示
  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) //删掉已执行的任务
        jobs.push(G(exchanges[task.exchange].Go.apply(this, task.param), task, function(v, task) {
                    Info[task.exchange][task.ret] = v //这里的v就是并发Go函数wait()的返回值,可以仔细体会下
                }))
    }
    _.each(jobs, function(t){
            t.run() //在这里并发执行所有任务
        })
}
function main() {
    while(true){
        produce()         // 发出交易指令
        worker()        // 并发执行
        Sleep(1000)
    }
}

Sepertinya berputar-putar hanya mencapai fungsi sederhana, sebenarnya sangat menyederhanakan tingkat kompleksitas kode, kita hanya perlu peduli dengan tugas apa yang harus dihasilkan oleh program, dan program worker akan secara otomatis mengeksekusi mereka secara bersamaan dan mengembalikan hasil yang sesuai.


Berkaitan

Lebih banyak

77924998Grasshopper, apakah Anda bisa menggunakan seluruh Python?

RegentPerkenalkan diri

RumputPython memiliki perpustakaan sendiri, lebih mudah digunakan daripada Go.