zoukankan      html  css  js  c++  java
  • 使用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()程序自动将他们并发执行,并返回相应的结果。灵活性提升了很多。

  • 相关阅读:
    java操作生成jar包 和写入jar包
    jboss配置jndi连接池
    windows 域的LDAP查询相关举例
    LDAP error Code 及解决方法
    HDU 6417
    CF1299D Around the World
    codechef Chef and The Colored Grid
    Educational Codeforces Round 82 (Rated for Div. 2)
    CF1237F Balanced Domino Placements
    CF1254E Send Tree to Charlie
  • 原文地址:https://www.cnblogs.com/botvsing/p/11106147.html
Copyright © 2011-2022 走看看