• 使用JavaScript实现量化策略并发执行


    本文代码和文章发在FMZ发明者比特币量化交易平台上:

    使用JavaScript实现量化策略并发执行--封装Go函数 - 发明者量化 https://www.fmz.com/digest-topic/3981

    在实现量化策略时,很多情况下,并发执行可以降低延时提升效率。以对冲机器人为例,需要获取两个币的深度,顺序执行的代码如下:

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

      

    请求一次rest API存在延时,假设是100ms,那么两次获取深度的时间实际上不一样,如果需要更多的访问,延时问题将会更突出,影响策略的执行。

    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()程序自动将他们并发执行,并返回相应的结果。灵活性提升了很多。

  • 相关阅读:
    Codeforces Round #336 (Div. 2) A. Saitama Destroys Hotel 模拟
    UVA 10341 二分搜索
    cscope 的使用
    2018年各大互联网前端面试题三(阿里)
    【前端统计图】hcharts实现堆叠柱形图(与后台数据交互)
    【前端统计图】echarts实现单条折线图
    【前端统计图】echarts实现简单柱状图
    css实现悬浮效果的阴影
    通过select下拉框里的value控制div显示与隐藏
    2018年各大互联网前端面试题四(美团)
  • 原文地址:https://www.cnblogs.com/botvsing/p/11106147.html
Copyright © 2020-2023  润新知