Loading ...

基于数据回放功能开发的线性挂单流策略

Author: Hukybo, Created: 2019-12-13 17:13:07, Updated: 2019-12-16 10:30:14

前言

人们常说,交易是一门艺术,而艺术来源于灵感。所以今天想和大家分享一下,如何利用发明者量化数据回放功能,发掘自己的交易灵感。

交易的灵感和盘感

通常我们所说的灵感,是指人们在思维过程中瞬间产生富有创造性的状态。对于交易者来说,我们的大脑左半球完成了策略编写、资金配置、参数设置等一系列规则的制定。而那些交易灵感和盘感则来自于大脑右半球。

很多人都听过“盘感”这个词,这是一种说不清道不明的感觉,就像当前发生的事似曾相识。在交易时这种类似第六感的直觉,虽然未经过逻辑的推理和分析,但对行情未来走势的预感,会促使交易者做出买入或卖出的决策。

如何获取灵感

在外人看来,盘感一种玄之又玄,是一种无招胜有招的神秘天赋,有了它就可以立足于市场。其实盘感是一种大脑对主观交易经验的总结,是通过多年看盘,所领悟到的一种朦胧的预判式感觉。

虽然严格来讲,灵感不完全等于盘感,但相信大家经过市场千百次的锤炼,对市场有更深的认识,在策略开发时就会得心应手。所以要想获取这种天赋,要想开发出更多的交易策略,无他,唯手熟尔。只有通过大量交易,才能完善自己的交易系统。

但是国内商品期货和股票一天只有数个小时的交易时间,如果仅从实盘交易中提高自己的看盘经验,形成自己的盈利模式和交易规则,并在潜意识中训练自己的条件反射,就显得力不从心。除了要付出较长的时间成本外,大部分交易者还要承担资金亏损的成本。为了解决这个问题,发明者量化开发了数据回放功能。

如何使用数据回放

数据回放功能可以不受交易所交易时间限制进行训练,支持多种商品期货和数字货币品种,行情可以手动回放也可以自动回放,也能自由设定历史行情起止时间和回放速度。相对于其他软件普遍采用K线数据回放方式,发明者量化采用Tick级别的数据回放方式,真实接近实盘交易的回测环境,重现盘口价量数据,让交易者身临其境。

打开发明者量化的官网(fmz.com)注册并登录,然后点击控制中心的数据探索,即可呈现数据回放功能页面。其中共有四个选项框和一个选择按钮,首先点击选择按钮只显示支持实盘回放的品种,其次在左上方选择要回放的品种,然后在后面的两个选项框中选择数据的起止时间,接着选择数据的时间周期为实盘回放,最后点击最右边的Go按钮,即可开启数据回放功能。

img

在数据标签下面一共分为三块。左边是交易历史,这里按照时间顺序展示了所有已经成交的订单。中间是买卖各20档深度的盘口数据。右边则是数据回放的控制区域,在这里可以选择手动和自动数据回放方式,就像使用媒体播放器一样简单。

img

位置索引可以左右来回拖动游标,可以快速的选择数据回放的开始时间。

img

在最下方也可以通过右左移动游标控制数据的回放速度,以毫秒为时间单位,在数据回放时既能加速也能减速。

img

构建策略逻辑

尽管影响价格涨跌的因素非常多,包括:全球经济环境、国家宏观政策、相关产业政策、供需关系、国际事件、利率与汇率、通货膨胀与紧缩、市场心理、未知因素等等,但最后盘面上的价格却是多方与空方角逐后的结果。如果买的人多过卖的人,价格就会上涨;反之如果卖的人多过买的人,价格就会下跌。那么我们只需要分析价格,就可以做出一个交易策略。

通过发明者量化回放最近一个月币安交易所的btc_usdt交易对,我们发现在行情大涨和大跌时,Tick数据的订单薄多空双方的单量明显不对称。当行情大涨时多头的挂单量明显大于空头的挂单量;当行情大跌时空头的挂单量明显小于多头挂单量。那么我们是否可以根据订单薄中的挂单量来预测短时间内价格的涨跌呢?

答案是肯定的。

img img

我们可以通过收集深度Tick数据,计算多空双方的挂单量并加以对比,如果多空综合挂单量悬殊很大,就可能时潜在的买卖机会。比如当多头的挂单量是空头挂单量的N倍时,我们可以认为市场上大部分人都看多,未来短时间内价格上涨的概率就会增大;当空头的挂单量是多头的N倍时,我们可以认为市场大部分人都看空,未来短时间内价格下跌的概率就会增大。

编写交易策略

按照以上策略逻辑,开始用代码实现出来。依次打开:fmz.com网站 > 登录 > 控制中心 > 策略库 > 新建策略 > 点击右上角下拉菜单选择Python语言,开始编写策略。本策略作为教学抛砖引玉,所以我尽量把策略写的精简一些,注意看下面代码中的注释。

第一步:编写策略框架

# 策略主函数
def onTick():
    pass


# 程序入口
def main():
    while True:  # 进入无限循环模式
        onTick()  # 执行策略主函数
        Sleep(1000)  # 休眠1秒

我们编写策略时应该由大往小写,就像盖房子一样,先盖框架再盖墙面。在这个框架中,我们使用了两个函数,分别是:main函数和onTick函数。其中main函数是程序的入口,也就是说程序会从这里执行,然后进入无限循环模式,重复执行onTick函数。那么我们只需要把策略内容写到onTick函数中就可以了。

第二步:编写全局变量

vol_ratio_arr = []  # 多空挂单比率数组
mp = 0  # 虚拟持仓

之所以定义vol_ratio_arr为全局变量,因为我的策略需要收集一段Tick数据的多空挂单比率,如果我们把vol_ratio_arr变量放到onTick函数中,随着循环运行显然是不合理的,我们需要的是在循环模式中,当达到某个条件时才改变变量的值,最合理的方法是把这个变量放到循环的外面。

持仓管理是非常有必要的,因为它关系到买卖逻辑,一般情况下我们在现货交易中,是通过获取账户来计算持有的货币对。这里为了简化代码,直接定义一个全局虚拟持仓变量,来控制买卖逻辑。

第三步:计算当前多空比率

depth = exchange.GetDepth()  # 获取深度数据
asks = depth['Asks']  # 获取卖价数组
bids = depth['Bids']  # 获取买价数组
asks_vol = 0  # 所有卖价挂单
bids_vol = 0  # 所有买价挂单
for index, ask in enumerate(asks):  # 遍历卖价数组
    # 线性计算所有卖价挂单
    asks_vol = asks_vol + ask['Amount'] * (20 - index)
for index, bid in enumerate(bids):  # 遍历买价数组
    # 线性计算所有买价挂单
    bids_vol = bids_vol + bid['Amount'] * (20 - index)
bidask_ratio = bids_vol / asks_vol  # 计算多空比率

众所周知,数字货币通常是20档的深度数据,那么我们可以把多头和空头的挂单量累加起来就可以计算出多头与空头的比值,当这个值大于1时说明看多的人大于看空的人,预示着未来短时间内价格会上涨;当这个值小于1时说明看空的人大于看多的人,预示着未来短时间内价格会下跌。

但有一点是需要加以区分的,当挂单距离盘口越近,就说明看多或看空的意愿更强烈,比如挂在一档的买单肯定比挂在20档的买单看多意愿更强烈。因此我们在累加挂单时,需要用线性的方式把20档的挂单分别给与不同的权重,这样会更加合理。

第四步:线性计算一段时间内的多空比率

global vol_ratio_arr, mp  # 引入全局变量
vol_ratio_arr.insert(0, bidask_ratio)  # 把多空比率放到全局变量数组里面
if len(vol_ratio_arr) > 20:  # 如果数组超过指定长度
    vol_ratio_arr.pop()  # 删除最旧的元素
all_ratio = 0  # 临时变量,所有多空挂单比率
all_num = 0  # 临时变量,所有线性乘数
for index, vol_ratio in enumerate(vol_ratio_arr):  # 变量全局变量数组
    num = 20 - index  # 线性乘数
    all_num = all_num + num  # 线性乘数累加
    all_ratio = all_ratio + vol_ratio * num  # 所有多空挂单比率累加
ratio = all_ratio / all_num  # 线性多空挂单比率

把多头累加挂单除以空头累加挂单就可以得到多空比值,但这仅仅时一个Tick的数据,如果只用一个Tick数据,来决定买卖交易可能不是一个明智选择,因为在瞬息万变的行情中,一个Tick数据是没有说服力的。所以我们就需要收集一段固定的Tick数据,最后再通过线性计算出一个公允的数值。

第五步:下单交易

last_ask_price = asks[0]['Price']  # 最新卖一价,用于买入的价格
last_bid_price = bids[0]['Price']  # 最新买一价,用于卖出的价格
if mp == 0 and ratio > buy_threshold:  # 如果当前无持币,并且比率大于指定值
    exchange.Buy(last_ask_price, 0.01)  # 买入
    mp = 1  # 设置虚拟持仓的值
if mp == 1 and ratio < sell_threshold:  # 如果当前持币,并且比率小于指定值
    exchange.Sell(last_bid_price, 0.01)  # 卖出
    mp = 0  # 重置虚拟持仓的值

因为在下单时需要指定一个价格,所以我们在买入的时候,可以直接使用最新的卖一价;在卖出的时候,可以直接使用最新的买一价。最后在下单交易完毕,重置设置虚拟持仓的值。

结尾

以上就是基于数据回放功能开发的线性挂单流策略代码解析,如果你是交易初学者,数据回放功能可以零成本学习交易,缩短对交易的认知时间,实盘或模拟交易通常需要几年才会初见成效,在数据回放功能上用几周的时间就可以达到同样的效果,在不浪费时间的前提下,以最小化的损失学习交易。对于进阶的交易者,动态复盘可以帮助你分析自己以往的问题所在,验证和完善交易策略,提高交易者对策略的信心,并且可以帮助产生新的策略灵感。


More

Hukybo 这个只是简单介绍了原理,很多细节还需要优化,我目前回测也时亏损的,哈哈

XIANDONG79 在okex 上面 BTC 当季度期货尝试了几个小时,设置 persist_duration = 5 seconds, 这个 orderbook imbalance 的方法确实可以预测接下来几秒钟的价格变动方向,可是并不能造成收益。或许作者是超高频??