Loading ...

数字货币量化交易策略交易所配置详解

Author: 小小梦, Created: 2019-09-02 09:39:59, Updated: 2019-09-09 11:51:20

数字货币量化交易策略交易所配置详解

初学数字货币量化交易策略设计时,经常有各种各样的策略需求,不论用那种语言,那种平台,都会遇到各种不同情况的策略设计需求。例如有时候需要多品种轮动,有时候需要多平台对冲,有时候又需要不同品种行情并发等等。下面我们就一起分享下策略需求实现时的一些设计经验。 学习平台依然使用发明者量化交易平台(https://www.fmz.com),市场选择为数字货币市场。

  • 「多币种」策略设计

    此类需求情况多为需要编写一个多品种趋势策略,多品种网格策略等,需要针对策略逻辑,用不同的交易对行情迭代执行。 通常这样设计:

    function Process (symbol) {
        exchange.IO("currency", symbol)
        var ticker = _C(exchange.GetTicker)
        Log("已经切换交易对,按照策略逻辑处理交易对 :", symbol, "行情:", ticker)
        // ...
        // ..
        // .
    }  
    
    function main(){
        var symbols = ["BTC_USDT", "LTC_USDT", "ETH_USDT"]
        while (true) {
            for (var i = 0 ; i < symbols.length; i++) {
                Process(symbols[i])
                Sleep(500)
            }
        }
    }
    

    我们给机器人配置: img

    img

    可以看到,这样就实现了在机器人上配置一个交易所对象,切换交易对,获取不同交易对的行情,进行多品种行情,在一种策略逻辑下执行。 可以看到,三种我们定义的交易对:BTC_USDT,LTC_USDT,ETH_USDT ,在循环中依次迭代获取行情,获取行情后,就可以具体对于行情检测,触发策略设计好的交易逻辑。

    有的同学可能会提出:“我不喜欢切换交易对,感觉有点麻烦,策略这样设计也不清晰”。 确实也有其它的设计办法,就是下面我们介绍的另一种方式。

  • 同一个交易所账户给机器人配置多个交易所对象

    通过多个交易所对象来获取不同交易对的行情数据,迭代策略逻辑中执行。 例如这样配置机器人:给机器人配置三个交易所对象,交易对分别设置为 BTC_USDT , LTC_USDT , ETH_USDT 。 img

    名字是 「OKEX现货V3测试」的交易所对象,在控制中心,交易所配置页面: img 已经配置好了。

    代码修改一下,因为这次我们给机器人添加了多个交易所对象,分别是交易对为 BTC_USDT 、LTC_USDT、ETH_USDT 的交易所对象。

    function Process (e) {
        var ticker = _C(e.GetTicker)
        Log("交易所", e.GetName(), "按照策略逻辑处理交易对 :", e.GetCurrency(), "行情:", ticker)
        // ...
        // ..
        // .
    }  
    
    function main(){
        while (true) {
            for (var i = 0 ; i < exchanges.length; i++) {
                Process(exchanges[i])
                Sleep(500)
            }
        }
    }
    

    运行机器人: img

    以上讲述的例子,无论是切换交易对,还是添加一个配置账户的多个不同交易对的交易所对象。 都只是使用一个交易所账号配置(使用一个配置好的交易所)。那么如何在一个策略中使用多个交易所账号呢?

  • 使用多个交易所账户的策略

    某些策略例如,多交易所跨市对冲,单交易所内多账户策略等。

    • 多个交易所配置,但是是不同的交易所。 img 例如,我在控制中心->交易所->添加交易所 页面,配置了2个交易所。 我在策略中就可以访问这两个交易所配置的账户的资产信息。

      img

      function main(){
          Log(exchanges[0].GetAccount())    // 打印第一个 交易所对象的账户资产信息,即火币期货 这个交易所的资产信息。
          Log(exchanges[1].GetAccount())    // ... 打印Bit-Z这个交易所的资产信息
      }
      

      当然我也可以,给一个交易所添加第二个、第三个账户的交易所配置。

    • 多个交易所配置,是相同的交易所。

      例如我们再添加一个火币期货的账号。 img

      可以看到,这样就配置了两个「火币期货」交易所的账号。

      img

      在创建策略时,机器人的 「修改配置」 选项中就又出现了一个火币期货交易所对象以供选择。

      img

      比如这样可以让两个账户一个做先卖后买网格策略(向上),一个做先买后卖网格策略(向下)。

      通过上面这两个例子

      这里讲下机器人上配置多个交易所对象 和 「同一个交易所账户给机器人配置多个交易所对象」的区别:

      这个猛地一看和上面讲解的「同一个交易所账户给机器人配置多个交易所对象」例子有些类似,但是是有区别的。 区别在于上面讲的例子是一个交易所配置,即:

      img

      在机器人配置交易所对象时,始终用的都是: img 这个配置。

      只不过是添加交易所对象时,交易对设置不同而已。 如果调用 GetAccount 函数,始终访问的都是同一个账户的资产信息。

      然而: img 这样配置的两个火币期货交易所对象,虽然都是火币期货,代表的却是不同的交易所账户。

  • 巧用交易所配置,让数字货币期货策略设计更加简单。

    有时候在做数字货币合约对冲的策略时,为了抓住转瞬即逝的交易机会,很多场景需要并发下单。但是因为合约不同,需要在获取行情,下单操作时切换到对应的合约。在使用 exchange.Go 函数并发执行下单函数或者获取行情时,由于有同步的问题,并不是很快。并且这样切换合约的设计也让逻辑显得不是那么简洁。那有没有更好的办法呢?

    当然有办法!我们可以按照上文中讲的「同一个交易所账户给机器人配置多个交易所对象」给机器人添加两个交易所对象。 img 然后还是使用 这个交易所配置,再添加一个交易所对象。 这时会弹出一个提示框! img 一个交易所账户配置,不能添加相同币种、交易对的交易所对象。

    这样怎么办?看来是不能让策略机器人用两个交易所对象,并且让交易所对象上绑定的是一个交易所账号了码? 还是有办法的!

    我们在「控制中心」->「交易所」,再添加一个 OKEX 期货交易所配置。

    img

    配置好以后点击保存。

    img

    「划重点」这样我们就有了两个交易所配置,但是使用的是同一个 API KEY 配置信息。

    img

    这样带来的好处是什么呢? 当然是编写策略时,设计就很简单啦!

    function main(){
        exchanges[0].SetContractType("quarter")        // 设置第一个添加的交易所对象 当前的合约为季度合约
        exchanges[1].SetContractType("this_week")      // 设置第二个添加的交易所对象,当前的合约为当周合约
        
        while (true) {
            var beginTime = new Date().getTime()       // 记录这次获取行情时起始的时间戳。
            var rA = exchanges[0].Go("GetTicker")      // 创建并发 线程去获取 第一个交易所对象,也就是季度合约的行情数据。
            var rB = exchanges[1].Go("GetTicker")      // 创建并发 线程去获取 第二个交易所对象,也就是当周合约的行情数据。
            
            var tickerA = rA.wait()                    // 并发的两个线程各自执行自己的任务,这里等待获取数据,A 等待时,B任务也在执行。
            var tickerB = rB.wait()                    // 所以这里看似是顺序执行,实际在底层是并发的。只不过获取的时候是顺序先获取A,在获取B。
            var endTime = new Date().getTime()         // 记录并发获取两个合约行情结束时的时间戳。
            
            if (tickerA && tickerB) {                  // 如果获取的数据没有问题,执行以下逻辑。
                var diff = tickerA.Last - tickerB.Last // 计算差价
                $.PlotLine("diff", diff)               // 使用画线类库把差价画在图表上。
                if (diff > 500) {                      // 如果差价大于500, 对冲套利(当然设置500 的差价是比较大的,很少见。)
                    // 对冲
                    rA = exchanges[0].Go("Sell", tickerA.Buy, 1)     // 并发线程创建 季度合约下卖单
                    rB = exchanges[1].Go("Buy", tickerB.Sell, 1)     // 并发线程创建 当周合约下买单
                    
                    var idA = rA.wait()           // 等待 返回下单结果,返回的是订单ID
                    var idB = rB.wait()           // ...
                }
                
                // ...
            }
            
            LogStatus(_D(), "并发获取两个合约行情耗时:", endTime - beginTime, "毫秒。")    // 显示在状态栏上时间,以便知道程序在执行。
            Sleep(500)
        }
    }
    

    这样设计策略是不是感觉简单了许多,思路清晰了许多。

    实盘运行: img

    可以看到,每次并发获取两个合约的行情,只耗时50毫秒左右。


More

bwxiaok 棒,这个很有帮助!