量化戦略を実装する際に,多くの場合,並行実行は遅延提昇効率を低下させる.ヘッジロボットの場合,二つのコインの深さを取得する必要があります.
var depthA = exchanges[0].GetDepth()
var depthB = exchanges[1].GetDepth()
Rest APIのリクエストに遅延がある場合, 100ms と仮定すると, 2回の深さを取得する時間は実際には異なる.
JavaScriptには多くのスレッドがないため,Go関数が底辺に包まれていますが,設計メカニズムにより,実装は難しくなります.
var a = exchanges[0].Go("GetDepth")
var b = exchanges[1].Go("GetDepth")
var depthA = a.wait() //调用wait方法等待返回异步获取depth结果
var depthB = b.wait()
ほとんどの単純な場合,このように書くことは問題ではない.しかし,毎回のポリシーループでこのプロセスを繰り返すことに注意してください.中間変数 a,b は実際には一時的な補助です.また,もし私たちの同時作業が非常に多くなった場合,a とdepthA,b とdepthB の対応関係も記録する必要があります.私たちの同時作業が不確実である場合,状況はさらに複雑です.したがって,私たちは関数を実現したいです. Go を同時に書くとき,同時に変数を拘束し,同時実行の結果を返すとき,結果は自動的に変数に値付けされ,中間変数を省略し,プログラムを簡潔にします.
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}] //加入我们需要获取两个交易所的深度和账户,跟多的信息也可以放入,如订单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)
}
}
簡単な機能のみを実現するような回転が実際にコードの複雑さを大幅に簡素化している. プログラムが何を生成する必要があるかだけを気にする必要があり,作業者 (worker) プログラムによって自動的に並行して実行され,対応した結果が返されます. 柔軟性が非常に向上しています.
77924998草の神様,Python全体で
代理人紹介する
小草Pythonは,Goよりも便利で,独自の同期データベースを持っています.