3
Подписаться
1444
Подписчики

Использование JavaScript для реализации параллельного выполнения количественных стратегий — инкапсуляция функций Go

Создано: 2019-06-29 11:24:57, Обновлено: 2023-10-26 20:06:10
comments   3
hits   2797

Использование JavaScript для реализации параллельного выполнения количественных стратегий — инкапсуляция функций Go

При реализации количественных стратегий во многих случаях одновременное выполнение может сократить задержку и повысить эффективность. Взяв в качестве примера хеджирующего робота, необходимо получить глубину двух монет. Код, выполняемый в последовательности, выглядит следующим образом:

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

При запросе REST API есть задержка. Предположим, что она составляет 100 мс. Тогда время получения глубины дважды на самом деле отличается. Если требуется больше доступа, проблема задержки будет более заметной, что повлияет на выполнение стратегии.

Поскольку 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 и глубиной A, а также b и глубиной B. Когда наши параллельные задачи неопределенны, ситуация становится более сложной. Поэтому мы хотим реализовать функцию: при написании параллельного кода 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( ) программа автоматически выполнит их одновременно и вернет соответствующие результаты. Гибкость значительно улучшена.