币圈量化交易萌新看过来--带你走近币圈量化(代码片段)

K线骑士 K线骑士     2023-01-03     154

关键词:

上篇我们一起思考、设计了一个简单的多品种网格策略。接下来,我们继续在量化交易的道路上学习、前行。本篇我们来探讨更加复杂一点的策略设计-对冲策略的设计。本篇计划设计一个多品种的跨期对冲策略,说到跨期对冲策略熟悉期货交易的小伙伴们肯定都不陌生。对于萌新来说可能还并不了解这些概念,所以我们先简单讲解下跨期对冲的概念。

跨期对冲

跨期对冲简单说就是做多一个合约,做空一个合约,等待三种情况同时(多、空)平仓:

  • 做多的赚钱,做空的亏钱,赚的一头(俗语)比亏的一头(俗语)多的时候平仓,盈亏相抵之后会有一部分盈利。
  • 做多的亏钱,做空的赚钱,赚的一头比亏的一头多的时候平仓,…(同上)。
  • 做多的赚钱,做空的也赚钱,那还想啥!平仓!

其它情况就是浮亏了,扛着或者继续加仓。(由于差价波动比单边波动缓和的多,相对风险小些,注意仅仅是相对!)

设A1为合约A在1时刻的价格,设B1为合约B在1时刻的价格,此时做空A合约,做空价格A1,做多B合约,做多价格B1。
设A2为合约A在2时刻的价格,设B2为合约B在2时刻的价格,此时平仓A合约(平空),平空价格A2,平仓B合约(平多),平多价格B2。

1时刻的差价:A1 - B1 = X 
2时刻的差价:A2 - B2 = Y 
X - Y = A1 - B1 - (A2 - B2)
X - Y = A1 - B1 - A2 + B2
X - Y = A1 - A2 + B2 - B1

可以看到,A1 - A2 就是A合约平仓的盈利差价。
B2 - B1就是B合约平仓的盈利差价。只要这两个平仓总体是正数,即:A1 - A2 + B2 - B1 > 0 就是盈利的。也就是说只要X - Y > 0。
因为:X - Y = A1 - A2 + B2 - B1

得出结论,只要开仓时的差价X大于平仓时的差价Y就是盈利的(注意是做空A,做多B开仓,搞反了就是相反的了),当然这个是理论上的,实际上还要考虑手续费、滑点等因素。

由于数字货币交易所即有交割合约,也有永续合约。并且永续合约价格由于有资金费率的原因,价格始终和现货价格比较贴近。那么我们选择使用交割合约和永续合约对冲套利。交割合约选择一个较远期的合约,这样不用频繁设置对冲合约。

先搞个多品种差价统计热热身

对于基本原理熟悉了之后,可以不用急着动手写策略。先搞个差价统计,画画图,观察一下差价。一起来学习一下多品种策略画图。

我们基于OKEX合约来设计,在FMZ上画图十分简单,使用封装好的函数可以很轻松的画图,图表库是Highcharts。API文档上的画图函数说明:https://www.fmz.com/api#chart…

既然是多品种,首先在画图前要确定打印那些品种的差价。代码里先写两个数组,表示要做的合约。

var arrSwapContractType = ["BTC-USDT-SWAP", "LTC-USDT-SWAP", "ETH-USDT-SWAP", "ETC-USDT-SWAP"]   // 永续合约
var arrDeliveryContractType = ["BTC-USDT-210924", "LTC-USDT-210924", "ETH-USDT-210924", "ETC-USDT-210924"]  // 交割合约

根据这里设置的合约代码,初始化图表配置。这个图表配置肯定不能写死,因为你也不知道要做什么品种,做几个品种(这些是根据arrDeliveryContractType和arrSwapContractType的值确定的),所以图表配置由一个函数返回。

function createCfg(symbol) 
    var cfg = 
        extension: 
            // 不参于分组,单独显示,默认为分组 'group'
            layout: 'single', 
            // 指定高度,可以设置为字符串,"300px",设置数值300会自动替换为"300px"
            height: 300,      
            // 指定宽度占的单元值,总值为12
            col: 6
        ,
        title: 
            text: symbol
        ,
        xAxis: 
            type: 'datetime'
        ,
        series: [
            name: 'plus',
            data: []
        ]
    

    return cfg


function main() 
    // 声明arrCfg
    var arrCfg = []                                    // 声明一个数组,用来存放图表配置信息
    _.each(arrSwapContractType, function(ct)          // 迭代记录永续合约代码的数组,用合约名称XXX-USDT部分作为参数传给createCfg函数,构造图表配置信息,返回
        arrCfg.push(createCfg(formatSymbol(ct)[0]))    // createCfg返回的图表配置信息push进arrCfg数组
    )
    var objCharts = Chart(arrCfg)                      // 调用FMZ平台的图表函数Chart,创建图表控制对象objCharts
    objCharts.reset()                                  // 初始化图表内容
    
    // 以下省略.....

接下来我们来准备数据,我们使用OKEX合约的聚合行情接口:

USDT永续合约:

https://www.okex.com/api/v5/market/tickers?instType=SWAP

USDT交割合约:

https://www.okex.com/api/v5/market/tickers?instType=FUTURES

我们写一个函数来处理这两个接口的调用,把数据做成一种格式:

function getTickers(url) 
    var ret = []
    try 
        var arr = JSON.parse(HttpQuery(url)).data
        _.each(arr, function(ele) 
            ret.push(
                bid1: parseFloat(ele.bidPx),             // 买一价
                bid1Vol: parseFloat(ele.bidSz),          // 买一价的量
                ask1: parseFloat(ele.askPx),             // 卖一价
                ask1Vol: parseFloat(ele.askSz),          // 卖一价的量
                symbol: formatSymbol(ele.instId)[0],     // 格式成交易对
                type: "Futures",                         // 类型
                originalSymbol: ele.instId               // 原始合约代码
            )
        )
     catch (e) 
        return null 
    
    return ret 

再写一个函数处理下合约代码

function formatSymbol(originalSymbol) 
    var arr = originalSymbol.split("-")
    return [arr[0] + "_" + arr[1], arr[0], arr[1]]

剩下就是把获取到的数据迭代配对,计算差价,图表输出等。
这里测试的是次季度合约210924和永续合约的差价。
完整的代码:

// 临时参数
var arrSwapContractType = ["BTC-USDT-SWAP", "LTC-USDT-SWAP", "ETH-USDT-SWAP", "ETC-USDT-SWAP"]
var arrDeliveryContractType = ["BTC-USDT-210924", "LTC-USDT-210924", "ETH-USDT-210924", "ETC-USDT-210924"]
var interval = 2000

function createCfg(symbol) 
    var cfg = 
        extension: 
            // 不参于分组,单独显示,默认为分组 'group'
            layout: 'single', 
            // 指定高度,可以设置为字符串,"300px",设置数值300会自动替换为"300px"
            height: 300,      
            // 指定宽度占的单元值,总值为12
            col: 6
        ,
        title: 
            text: symbol
        ,
        xAxis: 
            type: 'datetime'
        ,
        series: [
            name: 'plus',
            data: []
        ]
    

    return cfg


function formatSymbol(originalSymbol) 
    var arr = originalSymbol.split("-")
    return [arr[0] + "_" + arr[1], arr[0], arr[1]]


function getTickers(url) 
    var ret = []
    try 
        var arr = JSON.parse(HttpQuery(url)).data
        _.each(arr, function(ele) 
            ret.push(
                bid1: parseFloat(ele.bidPx), 
                bid1Vol: parseFloat(ele.bidSz), 
                ask1: parseFloat(ele.askPx), 
                ask1Vol: parseFloat(ele.askSz), 
                symbol: formatSymbol(ele.instId)[0], 
                type: "Futures", 
                originalSymbol: ele.instId
            )
        )
     catch (e) 
        return null 
    
    return ret 


function main() 
    // 声明arrCfg
    var arrCfg = []
    _.each(arrSwapContractType, function(ct) 
        arrCfg.push(createCfg(formatSymbol(ct)[0]))
    )
    var objCharts = Chart(arrCfg)
    objCharts.reset()
    
    while (true) 
        // 获取行情数据        
        var deliveryTickers = getTickers("https://www.okex.com/api/v5/market/tickers?instType=FUTURES")
        var swapTickers = getTickers("https://www.okex.com/api/v5/market/tickers?instType=SWAP")
        if (!deliveryTickers || !swapTickers) 
            Sleep(2000)
            continue
        

        var tbl = 
            type : "table",
            title : "交割-永续差价",
            cols : ["交易对", "交割", "永续", "正对冲", "反对冲"],
            rows : []
        
        
        var subscribeDeliveryTickers = []
        var subscribeSwapTickers = []
        _.each(deliveryTickers, function(deliveryTicker) 
            _.each(arrDeliveryContractType, function(symbol) 
                if (deliveryTicker.originalSymbol == symbol) 
                    subscribeDeliveryTickers.push(deliveryTicker)
                
            )
        )
        _.each(swapTickers, function(swapTicker) 
            _.each(arrSwapContractType, function(symbol) 
                if (swapTicker.originalSymbol == symbol) 
                    subscribeSwapTickers.push(swapTicker)
                
            )
        )
        
        var pairs = []
        var ts = new Date().getTime()
        _.each(subscribeDeliveryTickers, function(deliveryTicker) 
            _.each(subscribeSwapTickers, function(swapTicker) 
                if (deliveryTicker.symbol == swapTicker.symbol) 
                    var pair = symbol: swapTicker.symbol, swapTicker: swapTicker, deliveryTicker: deliveryTicker, plusDiff: deliveryTicker.bid1 - swapTicker.ask1, minusDiff: deliveryTicker.ask1 - swapTicker.bid1
                    pairs.push(pair)
                    tbl.rows.push([pair.symbol, deliveryTicker.originalSymbol, swapTicker.originalSymbol, pair.plusDiff, pair.minusDiff])
                    for (var i = 0 ; i < arrCfg.length ; i++) 
                        if (arrCfg[i].title.text == pair.symbol) 
                            objCharts.add([i, [ts, pair.plusDiff]])
                                                
                                        
                
            )
        )

        LogStatus(_D(), "\\n`" + JSON.stringify(tbl) + "`")        
        Sleep(interval)
    

实盘运行

跑一会儿~

观察一下差价再说!

币圈量化交易萌新看过来--带你走近币圈量化(代码片段)

报错信息前几篇文章我们已经了解过所谓程序化、量化交易就是一个脚本程序根据从交易所获取到的数据,经过一系列的计算、判断、触发做出一些操作,操作交易所账户进行交易。这些获取数据、操作账户的行为都是... 查看详情

币圈量化交易萌新看过来--带你走近币圈量化(代码片段)

上篇文章我们讲解到了一个简单网格策略的交易逻辑分析,本篇我们继续来完成这个教学策略的设计。交易逻辑分析上篇文章我们说到,只要遍历网格每个网格线,判断当前价格上穿下穿网格线即可触发交易动作。但... 查看详情

币圈量化交易萌新看过来--带你走近币圈量化(代码片段)

上篇我们一起思考、设计了一个简单的多品种网格策略。接下来,我们继续在量化交易的道路上学习、前行。本篇我们来探讨更加复杂一点的策略设计-对冲策略的设计。本篇计划设计一个多品种的跨期对冲策略,说到跨... 查看详情

币圈量化交易萌新看过来--带你走近币圈量化(代码片段)

上一篇文章,我们一起设计了一个多品种的合约差价监控策略,本篇文章我们继续完善这个思路。来看一下这个思路是否可行,并且用OKEXV5的模拟盘跑一跑,验证一下策略设计。这些过程也是做数字货币程序化交... 查看详情

币圈量化交易萌新看过来--带你走近币圈量化(代码片段)

上篇我们一起动手做了一个简单的网格策略,本期文章我们把这个策略升级扩展,扩展成一个多品种现货网格策略,并让这个策略进行实战测试。目的并非要找到一个"圣杯",而是要从策略设计中探讨设计策... 查看详情

萌新看过来,你还学不懂vscode插件吗?(代码片段)

一、前言VSCode是微软家一个非常轻量化的编辑器,体量虽轻,但是却有异常强大的功能。原因在于VSCode许多强大功能都是基于插件实现的,IDE只提供一个最基本的框架和基本功能,我们需要使用插件来丰富和扩展它的功能。由于... 查看详情

ags量化机器人一一币圈最新消息

比特币一周涨幅达30%突破4万美元,多个巨头企业宣布加密领域新动作最近一周的加密市场呈现上涨态势,涨幅达到30%,多次突破4万美元。在长达两个月的震荡下行跌势下出现了一轮反弹,截至发文,比特币现... 查看详情

ags量化机器人一一币圈最新消息

比特币一周涨幅达30%突破4万美元,多个巨头企业宣布加密领域新动作最近一周的加密市场呈现上涨态势,涨幅达到30%,多次突破4万美元。在长达两个月的震荡下行跌势下出现了一轮反弹,截至发文,比特币现... 查看详情

量化交易机器人系统开发之机器人的用处

在数字货币市场迎来了新一轮的爆发期后,币圈投资者对数字货币的全球信息共识与共享的需求进一步加深。现在大家口中所说的量化交易机器人简单的说就是一种计算机软件程序,它可以是手机应用过端的程序,也... 查看详情

币圈交易说明(代码片段)

...要对数字货币的交易做一些介绍和解释,希望读者对币圈交易有初步了解,有过交易经验最好。如果你是刚刚接触数字货币,usdt和eth都是第一次听说,那么本文对你而言可能不是那么的浅显易懂。本文会先对现货... 查看详情

区块链量化交易策略相关问题解答系统搭建

...到现在也是有一段时间了,已经有很多的人成为了“币圈”的专业人士,但是还是有很多的投资者依旧是在摸索阶段,往往也会面对很多的问题,有句话就是“新手是1容易亏损的一部分人”,对于比特币投资... 查看详情

币圈名词解释之对冲搬砖

    对于刚入币圈的小白来说,知识匮乏是硬伤,要想在币圈有所建树,学习、不断的学习必不可少,本文和大家分享的就是币圈名词对冲搬砖相关内容,一起来看看吧。  对冲搬砖,原理是通过软件对各个交易... 查看详情

如何用python实现股票量化交易?(代码片段)

全文1.8w字,先带大家认识量化交易和量化回测框架,最后带你手把手实现第一个股票策略。目录一、量化交易简介量化交易(Quantitativetrading)量化交易分类量化交易历史量化交易项目做什么?二、量化回测框架介绍回... 查看详情

区块链开发币圈专业术语大全

区块链开发币圈专业术语大全币圈怎么赚钱啊?币圈怎么搬砖啊?币圈破发是什么意思?对于新入币圈的小伙伴经常会问一些这样的问题?下面就给大家带来了币圈专业术语大全,希望对新进币圈的小伙伴有所帮助。币圈是什么... 查看详情

ags量化机器人一一币圈最新消息

比特币一周涨幅达30%突破4万美元,多个巨头企业宣布加密领域新动作最近一周的加密市场呈现上涨态势,涨幅达到30%,多次突破4万美元。在长达两个月的震荡下行跌势下出现了一轮反弹,截至发文,比特币现... 查看详情

ccr炒币机器人:币圈macd技术形态认知,你不得不知到的知识

智能量化交易,机器人自动炒币,CCR炒币机器人、CCG合约机器人、FA外汇机器人huaniang7776一、MACD做多信号第一步:上升趋势中;第二步:MACD在0轴上方先死叉,后金叉,多单入场(如果金叉仍在零轴上信号更为准确)第三步:MACD再次出现死... 查看详情

简单讲解币圈的部分术语

有很多刚入币圈的伙伴也许对某些币圈的专业术语不太清楚,这致使他们无法有效地掌握某些投资的意见。IPFS阿飞会列举某些基本的专业术语当作1个参照,想让对刚入币圈的伙伴有所帮助。1、开盘价:当日的首笔交... 查看详情

易经量化交易系统1(代码片段)

易经量化交易系统是一个完整的量化交易平台,提供基于深度元强化学习的交易策略,并且具有一整套回测平台,可以用于策略研发和实盘操作。量化交易平台中,回测系统是一个关键的功能,易经量化交易... 查看详情