hf
作者:杨几安
因子投资和时序模型的坑还没填完,这里又要开一个高频交易的新坑ORZ
这个系列的目的,正如文章名字所指明的,是一个高频交易的入门系列,从0开始介绍高频交易的名词、思路,最后在系列结尾的时候会分享几个我曾经用来赚钱的策略。
再次引用一下在因子投资那一期中的内容:
经济学家斯蒂芬·罗斯(Stephen Ross)于1976年提出的资产定价模型。它通过多因子模型解释资产收益,强调市场中不存在套利机会时,资产的预期收益可由多个系统性风险因子线性决定。
当市场中不存在套利机会的时候,因子投资收益稳定。当市场存在套利机会的时候,就是高频交易出手的时候了。
OrderBook
OrderBook,中文一般翻译为订单簿。然后根据这个行为是否成功发生,又可以分为quotes(报价)和Trades(交易)。
Quotes指的是市场上买卖双方提供的关于特定金融工具(如股票、期货、外汇等)的价格信息。这些信息通常包括最佳买价(Bid)、最佳卖价(Ask)、买卖双方的订单量等。
Trades记录了实际发生的交易,包括交易的价格、数量、时间戳等信息。
如果只是收集一只股票的orderbook,这个数据属于时序。如果同时收集了那一时刻所有股票的orderbook,则在使用上则归类为截面数据。
这两类数据是高频交易里最重要的数据,各位大神们通过这两种数据计算市场深度、市场情绪、评估交易成本等等。
大家所熟知的“卷”也是在OrderBook的处理过程,你比竞争对手早一点接收和处理完数据,就早一步下单。差1ms,就是赢钱和亏钱的区别。
所以有人就会去租与交易所在同一物理机房的机器做高频交易,以最大化降低时延的影响。
曾经我就有一个套利策略,本来稳定运行的很好,结果这个套利机会被别人也发现了,两个人就开始卷起来了。后来人越来越多,我的策略逐渐从盈利走向亏损,最后成交速度永远比不过别人,就只能怨自己菜,转而研究别的方向了。
一般来说,只有limit order(限价单)才会体现到Quotes上,因为如果做市价单一般会直接吃掉,进而体现在Trades,当然,如果极端情况下市场流动性不足,则market order也只能体现在quotes上。
更一般的,我们以maker 和 taker 来区分。
为市场注入流动性的,一般是maker。从市场中拿走流动性的,称之为taker。
作为一个交易所,当然希望更多的人来提供流动性,因此从交易费率上来说,maker的费率是远低于taker的。
甚至很多高频做市商的交易费率是负的。
接下来结合某所的 websocket stream 数据结构为例来介绍。
Trades
{
"e": "trade", // Event type
"E": 1672515782136, // Event time
"s": "BNBBTC", // Symbol
"t": 12345, // Trade ID
"p": "0.001", // Price
"q": "100", // Quantity
"T": 1672515782136, // Trade time
"m": true, // Is the buyer the market maker?
"M": true // Ignore
}
“e”: “trade”:表示事件类型为“交易”(trade)。 “E”: 1672515782136:表示事件的时间戳,通常是自Unix纪元(1970年1月1日)以来的毫秒数。 “s”: “BBTC”:表示交易的金融产品符号,这里是比特币(Bitcoin)。 “t”: 12345:表示交易的唯一标识符(ID)。 “p”: “0.001”:表示交易的价格,这里是0.001比特币。 “q”: “100”:表示交易的数量,这里是100单位的比特币。 “T”: 1672515782136:表示交易发生的具体时间戳。 “m”: true:表示是否是做市商(market maker)。如果是true,意味着这笔交易是做市商提供的流动性,如果是false,则表示是接受方(taker)。
这个就表示有一位maker的交易在1970年1月1日以0.001的价格成交了100btc。
然后按照你订阅的数据流的时效性,一般是5/10/20ms , 你都会收到如上的报文。编写你的交易策略对报文处理后做决策。
Quotes
很明显,trades一般就是拿大喇叭告诉你一声xxx成交了(莫名想起来缅北诈骗里的一个习俗,如果骗到人了就放50响礼炮,表示到手50万)
trades 就是干这个事情的。
一般做高频的会更加的关注quotes,因为它才包含了更多的市场信息。通常一个quotes会包含如下信息:
{
"lastUpdateId": 160, // Last update ID
"bids": [ // Bids to be updated
[
"0.0024", // Price level to be updated
"10" // Quantity
]
],
"asks": [ // Asks to be updated
[
"0.0026", // Price level to be updated
"100" // Quantity
]
]
}
如果你同时订阅了多个股票或者coin,他发给你的是一个聚合信息(aggStreams):
{
"e": "depthUpdate", // Event type
"E": 1672515782136, // Event time
"s": "BNBBTC", // Symbol
"U": 157, // First update ID in event
"u": 160, // Final update ID in event
"b": [ // Bids to be updated
[
"0.0024", // Price level to be updated
"10" // Quantity
]
],
"a": [ // Asks to be updated
[
"0.0026", // Price level to be updated
"100" // Quantity
]
]
}
与trades相比多了两个字段:b或者bid,a或者ask。
bid就是挂买单,有人愿意出价0.0024买入10单位的bnb。
ask就是挂卖单,有人愿意出价0.0026卖出100单位的bnb。
注意,我说的是“有人”,并不代表一个人。这10单位的bnb是交易所在处理完之后的结果,可能有1000个人下了2000单,它们的价格都是0.0024,最终体现在quotes上是这个结果。
而且,这个上边都是未成交的信息,成交的信息不体现在quotes,而是在Trades上。
所以也有可能是要以0.0024买入20单位,但是买到一半,市场上没有这个价格的了,因此体现了10单位在quotes上。
当然,这个信息在每个股民或者币民的交易app上也有展示,只不过这个是以api方式获取的高频数据。
在数据库中,未成交的报价长这个样子。
当你拿到这个quotes数据之后,关心的就是两个问题:
最优报价是多少?
满足我需求的价格下,深度depth是否满足?
还是用代码来说明,这里是我之前一个策略中写过的代码。
首先计算当前quotes中的交易深度是否能够满足我设置的阈值,以排除极端流动性不足的情况,如果流动性充足,我则以满足我要买的数量的阈值基础上,以比它低0.0005的价格做maker。
同样,我会以比它高0.0005的价格挂卖出单做maker。
提一句,这个价格就是你想买入或者卖出单best price,更严谨的话,是计算一个数学加权平均数。
def get_bothway_best_bid_and_ask(bids:list, asks:list,volumn_limit=3000)->Tuple[float,float]:
bid_vol,bid_price = 0,0
for [i,j] in bids:
bid_vol += float(j)
if bid_vol >= volumn_limit:
best_bid = float(i) - 0.0005
else:
best_bid = 9999999
ask_vol,ask_price = 0,0
for [i,j] in asks:
ask_vol += float(j)
if ask_vol >= volumn_limit:
best_ask= float+0.0005
else:
best_ask = -1
return best_bid,best_ask
maker 和 taker
无论是从上边的数据示例,还是我们的生活经验,好像市场上的bid 永远小于ask。他们两个之间总是存在一定的差距,比如上面0.0002。
这种状态是市场的稳态。
但是在极端情况,大量买单冲击,是会出现bid 大于ask的情况,这是市场的非稳态。更一般的,如果市场上突然出现大量taker,交易所来不及处理,是会出现bid=ask的。
因为在交易的时候,我们总会倾向于当下的最优价格,所以一般来说是以best bid 或者 best ask来成交的。
我们通常意义上的股票价格,比如茅台价格是1436,是指的当时的成交价格。
所以试想一下,如果有人以0.0024卖出了,那么股票价格就是0.0024,如果以0.0026买入了,股票价格就是0.0026。聪明的你已经想好怎么拉盘控盘了吧(doge
成交对市场的影响就是best bid 和 best ask 的差距进一步的加大。也就是说愿意买的人、和愿意卖的人之间的分歧进一步加大。体现在股价上,流动性不足的股票价格就是忽上忽下,不是连续的折现(因为gap太大了
交易所是靠手续费吃饭的,他们肯定不愿意看到这种情况,所以会引入做市商来缩小gap,提供流动性。
小测验:
你收到了如上的quotes时候,你选择以0.0024 的价格出售10个bnb,为了节约手续费,你选择的是limit order,请问你是maker 还是 taker?