Bei der Implementierung von Quantitative Strategien kann in vielen Fällen die gleichzeitige Ausführung die Effizienzverzögerung reduzieren. Bei einem Hedgebot zum Beispiel ist es notwendig, die Tiefe von zwei Münzen zu erlangen, und die Reihenfolge der Ausführung ist folgende:
var depthA = exchanges[0].GetDepth()
var depthB = exchanges[1].GetDepth()
Wenn eine Request-Rest-API eine Verzögerung aufweist, die vorausgesetzt wird, dass 100 ms ist, dann ist die Zeit für die Erfassung der Tiefe bei den beiden Anfragen in der Tat unterschiedlich. Wenn mehr Zugriffe erforderlich sind, wird das Verzögerungsproblem stärker hervortreten und die Ausführung der Strategie beeinträchtigen.
Da JavaScript nicht mehrere Themen hat, löst die Go-Funktion das Problem, aber aufgrund der Design-Mechanik ist die Implementierung schwerwiegend.
var a = exchanges[0].Go("GetDepth")
var b = exchanges[1].Go("GetDepth")
var depthA = a.wait() //调用wait方法等待返回异步获取depth结果
var depthB = b.wait()
In den meisten einfachen Fällen ist es nicht problematisch, eine solche Strategie zu schreiben. Beachten Sie jedoch, dass der Prozess bei jeder Strategie-Lippe wiederholt wird, wobei die Zwischenvariablen a und b eigentlich nur temporär unterstützend sind. Wenn wir sehr viele Parallelvorgaben haben, müssen wir zusätzlich die Wechselbeziehungen zwischen a und depthA, b und depthB aufzeichnen, was die Situation komplizierter macht, wenn unsere Parallelvorgaben unsicher sind. Daher möchten wir eine Funktion realisieren:
function G(t, ctx, f) {
return {run:function(){
f(t.wait(1000), ctx)
}}
}
Wir definieren eine G-Funktion, bei der der Parameter t die zu ausführende Go-Funktion ist, ctx der Kontext des Aufzeichnungsprogramms und f die Funktion, der die spezifische Zuordnung zugewiesen wird.
Das gesamte Programm-Framework kann dann ähnlich wie das Hersteller-Verbraucher-Modell geschrieben werden (mit einigen Unterschieden), bei dem der Hersteller ständig Aufgaben ausgibt, die der Verbraucher gleichzeitig ausführt, wobei der Code lediglich eine Demonstration ist und nicht die Logik der Durchführung des Programms beinhaltet.
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)
}
}
Es sieht so aus, als ob ein Kreis nur eine einfache Funktion realisiert, was die Komplexität des Codes erheblich vereinfacht hat. Wir müssen uns nur darum kümmern, welche Aufgaben ein Programm erzeugen muss.
77924998Grasshopper, kannst du die ganze Python
RegentIch möchte mich vorstellen.
Das GrasPython hat seine eigene Synchronous Library, die einfacher zu verwenden ist als Go.