xeng 设计与实现
在金融市场交易中,我们可以获取两类行情:
- 基于订单、成交的逐笔行情
- 对订单薄进行切片得到的快照行情
我们可以利用以上数据复原订单薄「orderbook」。
利用 TtickByTick
利用 Snapshot
Talk is cheap
sliu:
这样啊,就是之前每一个没有trade的价位上,我们本来算了一个max(snap1_vol-snap2_vol,0)视作cxl,现在新加一个max(snap2_vol-snap1_vol,0)视作order吧
这样一来,假如一个价位的order从10到了20,那么我们就用一个10的order去消一下outstanding
Show me code
-
计算两个
snaps1
、snaps2
之间的vwap
-
设 $\Delta Volume = Volume_2 - Volume_1$
-
如果 $\Delta Volume = 0$,
sliu:
计算 cxl 的订单,刷新一下ob,然后用 cxl
噢!有一个点,我忽略了,如果完全没有Turnover,但是挂单超过了我们的outstanding,其实也应该撮合的
-
否则$\Delta Volume \neq 0$,需要计算
vwap
$$ \begin{align} vwap &= \frac{\Delta Turnover}{\Delta Volume} \newline &= \frac{Turnover_2 - Turnover_1}{Volume_2 - Volume_1}\end{align} $$
-
-
我们可以对比
vwap
与snaps1.ap1
,来判断这是主动买方向还是主动卖方向(用来提取snap1
的价格)。区分主动买/主动卖的目的,在于找到哪些是full_traded
,哪些是partial_traded
的情况-
if $vwap \gt snaps1.ap1$,判断为主动买,需要找到卖单序列(
snaps.ask_px
):full
:从snaps1.ask_px[0]
开始直到snaps1.ask_px[i] < vwap
part
:snaps1.ask_px[j] > vwap
且不在snap2.ask_px
里面的,从snaps1.ask_px[j] > vwap
开始处理,遇到snaps2.ask_px[j] >= snaps1.ask_px[i]
且snaps2.ask_qty[j] != 0
就停止搜索;如果没有找到,使用最后遇到的snaps2.ask_qty[j]
-
else if $snaps1.bp1 \lt vwap \lt snaps.ap1$,特殊情况,发现序列都是空的,使用
snap1.bp1
与snaps.ap1
,然后转化成第一种情况处理 -
else if $vwap \lt snaps1.bp1$,判断为主动卖,需要找到买单序列(
snaps1.bid_px
):full
:从snaps1.bid_px[i] < vwap
开始直到snaps1.bid_px[0]
part
:snaps1.ask_px[j] > vwap
且不在snap2.ask_px
里面的,从snaps1.bid_px[j] < vwap
开始处理,遇到snaps2.bid_px[j] <= snaps1.bid_px[i]
且snaps2.bid_qty[j] != 0
就停止搜索;如果没有找到,使用最后遇到的snaps2.bid_qty[j]
-
-
我们知道,
-
对于
full_trade
的序列,已经推算出trade
与cxl
的情况 (solve_equation
) -
但是对于
part_trade
的序列,我们还需要使用snaps2
上面的同一个价格档位的 qty 来计算从snaps1
变成snaps2
过程中发生的cxl_qty
-
标记为
part_snaps_qty_vec
,且记录1 2 3 4 5 6 7 8
if (part_snaps_qty_vec.empty()) { rsp.cxl_qty = std::max(qty_vec[i] - rsp.trade_qty, 0); } else { rsp.cxl_qty = std::max(qty_vec[i] - rsp.trade_qty - part_snaps_qty_vec[i], 0); }
-
-
这样,我们一共有
|
|
虚拟的 rsp
数据结构为
|
|
-
撮合
撮合的前半部分就是生成这些东西来和outstanding撮合 后半部分是我们自己的order进来,先和新ob撮合,生成rsp和outstanding撮合 如果完了还有剩的,就计算一个wait然后进入outstanding 那个时候的wait就是max{0, vol_1 - trade - cxl} + max{0, vol_2 - max{0, vol_1 - trade - cxl}} * q max{0, vol_1 - trade - cxl} + max{0, vol_2 - max{0, vol_1 - trade - cxl}} * q 里面其实 max{0, vol_2 - max{0, vol_1 - trade - cxl}} 就是你这里的order吧 lfang:leaves_qty 相当于表示上次还剩多少肯定排在我们订单前面,然后再用一个 q 的概率表示在新 snaps2 上面的订单排在前面的可能性 所以 wait_qty = rsp.leaves_qty + rsp.order_qty * q
Ref
- How to manage a local order book correctly
- Open a stream to wss://stream.binance.com:9443/ws/bnbbtc@depth.
- Buffer the events you receive from the stream.
- Get a depth snapshot from https://api.binance.com/api/v3/depth?symbol=BNBBTC&limit=1000 .
- Drop any event where
u
is <=lastUpdateId
in the snapshot. - The first processed event should have
U
<=lastUpdateId
+1 ANDu
>=lastUpdateId
+1. - While listening to the stream, each new event’s
U
should be equal to the previous event’su
+1. - The data in each event is the absolute quantity for a price level.
- If the quantity is 0, remove the price level.
- Receiving an event that removes a price level that is not in your local order book can happen and is normal.