
Khi triển khai các chiến lược định lượng, trong nhiều trường hợp, thực hiện đồng thời có thể giảm độ trễ và cải thiện hiệu quả. Lấy robot phòng ngừa rủi ro làm ví dụ, cần phải có được độ sâu của hai đồng tiền. Mã được thực hiện theo trình tự như sau:
var depthA = exchanges[0].GetDepth()
var depthB = exchanges[1].GetDepth()
Có sự chậm trễ khi yêu cầu API nghỉ ngơi. Giả sử là 100ms. Khi đó, thời gian để có được độ sâu hai lần thực sự khác nhau. Nếu cần nhiều quyền truy cập hơn, vấn đề chậm trễ sẽ nổi bật hơn, ảnh hưởng đến việc thực hiện chiến lược.
Vì JavaScript không có đa luồng nên hàm Go cơ bản được đóng gói để giải quyết vấn đề này, nhưng do cơ chế thiết kế của nó nên việc triển khai khá phức tạp.
var a = exchanges[0].Go("GetDepth")
var b = exchanges[1].Go("GetDepth")
var depthA = a.wait() //调用wait方法等待返回异步获取depth结果
var depthB = b.wait()
Trong hầu hết các trường hợp đơn giản, không có gì sai khi viết chính sách theo cách này. Nhưng lưu ý rằng quá trình này phải được lặp lại mỗi lần chiến lược lặp lại và các biến trung gian a và b thực chất chỉ là giải pháp hỗ trợ tạm thời. Nếu chúng ta có nhiều tác vụ đồng thời, chúng ta cần ghi lại sự tương ứng giữa a và độ sâu A, và b và độ sâu B. Khi các tác vụ đồng thời của chúng ta không chắc chắn, tình hình trở nên phức tạp hơn. Do đó, chúng ta muốn triển khai một hàm: khi viết Go đồng thời, liên kết một biến cùng lúc và khi kết quả chạy đồng thời được trả về, kết quả sẽ tự động được gán cho biến, do đó loại bỏ các biến trung gian và làm cho chương trình dễ hiểu hơn. súc tích. Việc thực hiện cụ thể như sau:
function G(t, ctx, f) {
return {run:function(){
f(t.wait(1000), ctx)
}}
}
Chúng tôi định nghĩa hàm G, trong đó tham số t là hàm Go sẽ được thực thi, ctx là ngữ cảnh chương trình và f là hàm để gán cụ thể. Chúng ta sẽ sớm thấy chức năng này hoạt động.
Tại thời điểm này, khuôn khổ chương trình tổng thể có thể được viết dưới dạng mô hình “nhà sản xuất-người tiêu dùng” (với một số khác biệt). Nhà sản xuất liên tục đưa ra các tác vụ và người tiêu dùng thực hiện chúng đồng thời. Mã sau đây chỉ để trình diễn và không liên quan đến chương trình. Thực hiện logic.
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)
}
}
Có vẻ như chúng ta chỉ triển khai một hàm đơn giản sau khi trải qua nhiều bước, nhưng thực tế, độ phức tạp của mã đã được đơn giản hóa rất nhiều. Chúng ta chỉ cần quan tâm đến những tác vụ mà chương trình cần tạo ra và worker( ) chương trình sẽ tự động thực hiện chúng đồng thời và trả về kết quả tương ứng. Tính linh hoạt đã được cải thiện đáng kể.