Use JavaScript to implement a quantification policy while running the Go function in a wrapper.

Author: The grass, Created: 2019-06-29 11:24:57, Updated: 2023-10-26 20:06:10

img

When implementing a quantification strategy, in many cases, concurrent execution can reduce the efficiency of the delayed boost. For example, a hedge robot requires the depth of two coins, and the sequence of execution code is as follows:

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

Once a request for rest API is delayed, assuming 100ms, then the time taken to obtain depth twice is actually different, and if more access is required, the delay problem will be more prominent, affecting the execution of the policy.

JavaScript does not have many threads, so the bottom-up Go function solves this problem, but it is more cumbersome to implement due to the design mechanism.

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

In most simple cases, writing a policy like this is not a problem. But note that each policy loop repeats this process, and the intermediate variables a and b are actually only temporary auxiliaries. If we have a very large number of concurrent tasks, we also need to record the corresponding relationship between a and depthA, b, and depthB. The situation is more complex when our concurrent tasks are uncertain.

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

We define a G function, where the argument t is the Go function to be executed, ctx is the context of the recording program, and f is the function with the specific assignment.

In this case, the overall programming framework can be written as similar to the producer-consumer model (with some differences), where the producer continuously issues tasks and the consumer executes them simultaneously, while the code is only a demonstration and does not involve the execution logic of the program.

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

It seems that a loop only achieves a simple function, in fact greatly simplifies the complexity of the code, we only need to worry about what tasks the program needs to produce, and the worker () program automatically executes them simultaneously and returns the corresponding results. Flexibility is greatly improved.


Related

More

77924998Grasshopper, can you do the whole Python?

RegentI want to introduce myself.

The grassPython has its own syntax library, which is easier to use than Go.