Type/to search
3
Follow
1503
Followers
Usando JavaScript para implementar execução simultânea de estratégias quantitativas - encapsulando funções Go
Discussions
Created 2019-06-29 11:24:57  Updated 2023-10-26 20:06:10
 3
 3017

img

Ao implementar estratégias quantitativas, em muitos casos, a execução simultânea pode reduzir a latência e melhorar a eficiência. Tomando o robô de hedge como exemplo, é necessário obter a profundidade de duas moedas. O código executado em sequência é o seguinte:

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

Há um atraso na solicitação de uma API de descanso. Suponha que seja 100 ms. Então o tempo para obter a profundidade duas vezes é realmente diferente. Se mais acesso for necessário, o problema de atraso será mais proeminente, afetando a execução da estratégia.

Como o JavaScript não possui multithreading, a função Go subjacente é encapsulada para resolver esse problema, mas devido ao seu mecanismo de design, a implementação é bastante complicada.

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

Na maioria dos casos simples, não há nada de errado em escrever a política dessa maneira. Mas observe que esse processo deve ser repetido toda vez que a estratégia for executada em loop, e as variáveis ​​intermediárias a e b são, na verdade, apenas auxílios temporários. Se tivermos muitas tarefas simultâneas, precisamos registrar a correspondência entre a e depthA, e b e depthB. Quando nossas tarefas simultâneas são incertas, a situação se torna mais complicada. Portanto, queremos implementar uma função: ao escrever simultaneidade Go, vincular uma variável ao mesmo tempo e, quando o resultado da execução simultânea for retornado, o resultado será automaticamente atribuído à variável, eliminando assim as variáveis ​​intermediárias e tornando o programa mais conciso. A implementação específica é a seguinte:

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

Definimos uma função G, onde o parâmetro t é a função Go a ser executada, ctx é o contexto do programa e f é a função para atribuição específica. Veremos essa função em ação em breve.

Neste ponto, a estrutura geral do programa pode ser escrita como um modelo "produtor-consumidor" (com algumas diferenças), onde os produtores emitem tarefas continuamente e os consumidores as executam concorrentemente. O código a seguir é apenas para demonstração e não envolve o programa. Execute a lógica.

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) } }

Parece que implementamos apenas uma função simples depois de passar por muitas etapas, mas, na verdade, a complexidade do código foi bastante simplificada. Precisamos apenas nos preocupar com quais tarefas o programa precisa gerar e o worker( ) o programa irá executá-los automaticamente simultaneamente e retornar os resultados correspondentes. A flexibilidade foi bastante melhorada.

Related Recommendations
Comment
All comments (3)

    草神,能不能整个Python的

    4 years ago

    python有自己的协程库,用着比Go方便

    4 years ago

    求介绍

    4 years ago
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)