GET depth function
The binance_depth(api = “spot”, pair, quiet = TRUE) function takes as three arguments:
api
character (mandatory, default: spot): specify the api module to use. It can be:- spot: for Spot market;
- fapi: for Futures and Margin markets denominated in USD, denoted in the website by USD-M;
- dapi: for Futures and Margin markets denominated in the underlying asset, denoted in the website by COIN-M;
- eapi: for Options market.
pair
character (optional, default: BTCUSDT): the a trading pair available on Binance.com, for example BTCUSDT, ETHUSDT, ETHBTC.quiet
logical (mandatory, default: FALSE): if TRUE the function will not display messages and warnings.
Example: Spot (api)
# import depth data from binance
depth <- binance_depth(api = "spot", pair = "BTCUSDT", quiet = TRUE)
data <- dplyr::bind_rows(
tail(dplyr::filter(depth, side == "ASK"), n = 3), # best 3 ask
head(dplyr::filter(depth, side == "BID"), n = 3) # best 3 bid
)
format_kable(data, caption)
date | market | pair | side | price | quantity |
---|---|---|---|---|---|
2023-06-10 03:23:21 | spot | BTCUSDT | ASK | 26459.09 | 0.02288 |
2023-06-10 03:23:21 | spot | BTCUSDT | ASK | 26459.08 | 0.02138 |
2023-06-10 03:23:21 | spot | BTCUSDT | ASK | 26459.07 | 10.05993 |
2023-06-10 03:23:21 | spot | BTCUSDT | BID | 26459.06 | 1.66527 |
2023-06-10 03:23:21 | spot | BTCUSDT | BID | 26459.05 | 0.00946 |
2023-06-10 03:23:21 | spot | BTCUSDT | BID | 26459.01 | 0.03392 |
Example: Futures USD-M (fapi)
# import depth data from binance
depth_fapi <- binance_depth(api = "fapi", pair = "BTCUSDT", quiet = TRUE)
dplyr::bind_rows(
tail(dplyr::filter(depth_fapi, side == "ASK"), n = 3), # best 3 ask
head(dplyr::filter(depth_fapi, side == "BID"), n = 3) # best 3 bid
) %>%
format_kable(caption)
date | market | pair | side | price | quantity |
---|---|---|---|---|---|
2023-06-10 03:23:22 | usd-m | BTCUSDT | ASK | 26444.1 | 0.001 |
2023-06-10 03:23:22 | usd-m | BTCUSDT | ASK | 26444.0 | 0.016 |
2023-06-10 03:23:22 | usd-m | BTCUSDT | ASK | 26443.9 | 17.520 |
2023-06-10 03:23:22 | usd-m | BTCUSDT | BID | 26443.8 | 14.344 |
2023-06-10 03:23:22 | usd-m | BTCUSDT | BID | 26443.7 | 0.034 |
2023-06-10 03:23:22 | usd-m | BTCUSDT | BID | 26443.6 | 0.489 |
Example: Futures COIN-M (dapi)
# import depth data from binance
depth_dapi <- binance_depth(api = "dapi", pair = "BTCUSD_PERP", quiet = TRUE)
dplyr::bind_rows(
tail(dplyr::filter(depth_dapi, side == "ASK"), n = 3), # best 3 ask
head(dplyr::filter(depth_dapi, side == "BID"), n = 3) # best 3 bid
) %>%
format_kable(caption)
date | market | pair | side | price | quantity |
---|---|---|---|---|---|
2023-06-10 03:23:24 | coin-m | BTCUSD_PERP | ASK | 26451.0 | 926 |
2023-06-10 03:23:24 | coin-m | BTCUSD_PERP | ASK | 26450.9 | 3 |
2023-06-10 03:23:24 | coin-m | BTCUSD_PERP | ASK | 26450.7 | 17402 |
2023-06-10 03:23:24 | coin-m | BTCUSD_PERP | BID | 26450.6 | 425 |
2023-06-10 03:23:24 | coin-m | BTCUSD_PERP | BID | 26450.5 | 538 |
2023-06-10 03:23:24 | coin-m | BTCUSD_PERP | BID | 26450.4 | 55 |
Example: Options (eapi)
df_options <- binance_exchange_info(api = "eapi", pair = "BTCUSDT")
symbol <- filter(df_options, strikePrice == "27000.00000000")[1,]$symbol
df_options <- binance_exchange_info(api = "eapi", pair = "BTCUSDT")
symbol <- filter(df_options, as.numeric(strikePrice) == trunc(data$price[1]/1000)*1000)[1,]$symbol
# import depth data from binance
depth_eapi <- binance_depth(api = "eapi", pair = symbol, quiet = TRUE)
dplyr::bind_rows(
tail(dplyr::filter(depth_eapi, side == "ASK"), n = 3), # best 3 ask
head(dplyr::filter(depth_eapi, side == "BID"), n = 3) # best 3 bid
) %>%
format_kable(caption)
date | market | pair | side | price | quantity |
---|---|---|---|---|---|
2023-06-10 03:23:25 | options | BTC-230610-26000-C | ASK | 800 | 0.02 |
2023-06-10 03:23:25 | options | BTC-230610-26000-C | ASK | 660 | 0.05 |
2023-06-10 03:23:25 | options | BTC-230610-26000-C | ASK | 590 | 2.50 |
2023-06-10 03:23:25 | options | BTC-230610-26000-C | BID | 325 | 2.50 |
Example: Micro price and Imbalance
Denoting by:
- PBIDt: best BID price.
- PASKt: best ASK price.
- QBIDt: quantity as limit buy order at BID price.
- QASKt: quantity as limit sell order at ASK price.
The mid-price is computed as simple mean among the best BID-ASK price:
PMidt=PBIDt+PASKt2
The bid-ask spread is the mean distance among the best BID and ASK price:
St=PASKt−PBIDt2
The microprice is defined as weighted sum considering also the quantities H at the best BID-ASK:
PMicrot=PBIDt⋅QBIDt+PASKt⋅QASKtQBIDt+QASKt The order imbalance is defined as the proportion of quantity on the best BID with respect to all the quantities:
It=QBIDtQBIDt+QASKt - Gatheral and Oomen (2009)
# best ask and bid
bask <- tail(dplyr::filter(depth, side == "ASK"), n = 1)
bbid <- head(dplyr::filter(depth, side == "BID"), n = 1)
# compute mid-price
mid_price <- (bbid$price + bask$price)/2
# compute bid-ask spread
bid_ask_spread <- (bask$price - bbid$price)/2
# compute micro-price
micro_price <- (bbid$price*bbid$quantity + bask$price*bask$quantity)/(bbid$quantity + bask$quantity)
# compute order-imbalance
bid_imbalance <- (bbid$quantity)/(bask$quantity + bbid$quantity)*100
df_mp_example <- dplyr::tibble(
best_ask = bask$price,
ask = bask$quantity,
mid_price = mid_price,
micro_price = micro_price,
bid_ask_spread = bid_ask_spread,
imbalance = paste0(round(bid_imbalance,2), "%"),
bid = bbid$quantity,
best_bid = bbid$price)
colnames(df_mp_example) <- c("$P^{\\text{ASK}}_t$", "$\\text{ASK}$", "$P^{\\text{Mid}}_t$", "$P^{\\text{Micro}}_t$",
"$S_t$", "$I_t$", "$\\text{BID}$", "$P^{\\text{BID}}_t$")
df_mp_example %>%
format_kable(caption)
PASKt | ASK | PMidt | PMicrot | St | It | BID | PBIDt |
---|---|---|---|---|---|---|---|
26459.07 | 10.05993 | 26459.06 | 26459.07 | 0.005 | 14.2% | 1.66527 | 26459.06 |
Build an order-book from Depth
An order book is a table with three columns: - price: the price level - bid: the quantity that is on the buy side - ask: the quantity that is on the sell side
We have also added three more columns:
- buy: the quantity bought at that level
- sell: the quantity sold at that level
- net: the balance between buy and sell at that level, computed as net=buy−sell
OrderBook
The function OrderBook
has the purpose of structuring a
dataset in the same structure as this
Table.
OrderBook(data = depth, from = micro_price*0.99, to = micro_price*1.01, levels = 10, as_datatable = TRUE)
Example: Liquidity curve
# order by price (descending)
plot_data <- dplyr::arrange(depth, price)
# compute cumulated quantity
plot_data$cumQ <- cumsum(plot_data$quantity)
mp = c(x = micro_price, xend = micro_price,
y = 0, yend = plot_data$cumQ[which(plot_data$side == "ASK")[1]])
ggplot()+
geom_line(data = plot_data, aes(price, cumQ, color = side))+
geom_segment(aes(x = mp[1], xend = mp[2], y = mp[3], yend = mp[4]), linetype="dashed", color = "red")+
geom_point(aes(x = mp[1], y = mp[4]), size=2, color = "black")+
geom_label(aes(x = mp[1], y = mp[4] + mp[4]/10, label = round(micro_price, 2)), size=2, color = "black")+
scale_color_manual(values = c(ASK = "red", BID = "green"))+
labs(x = "Price", y = "Cumulated Quantity", color = "Side", caption = caption)+
theme(legend.position = "top")+
theme(axis.title = element_text(face = "bold"),
plot.title = element_text(face = "bold"),
axis.line = element_line(),
axis.text.x = element_text(angle = 0, face = "bold", size = 7),
axis.text.y = element_text(face = "bold"),
axis.title.x = element_text(face = "bold",size = 10),
axis.title.y = element_text(face = "bold", size = 10),
plot.subtitle = element_text(face = "italic"),
plot.caption = element_text(face = "italic"),
panel.grid.minor.x = element_blank(),
panel.grid.minor.y = element_blank(),
panel.grid.major.x = element_blank(),
panel.grid.major.y = element_blank(),
panel.border = element_blank(),
strip.background = element_blank(),
panel.background = element_blank(),
strip.text = element_text(angle = 0, face = "bold", size = 7),
legend.title = element_text(face = "bold", size = 11),
legend.text = element_text(face = "italic", size = 10),
legend.box.background = element_rect(),
legend.position = "top")
Example: Depth curve
# ASK orders
ask <- dplyr::filter(depth, side == "ASK")
ask <- dplyr::arrange(ask, price) # arrange by price (descending)
ask$cumQ <- cumsum(ask$quantity) # cumulated quantity
# BID orders
bid <- dplyr::filter(depth, side == "BID")
bid <- dplyr::arrange(bid, dplyr::desc(price)) # arrange by price (ascending)
bid$cumQ <- cumsum(bid$quantity) # cumulated quantity
plot_data <- dplyr::bind_rows(ask, bid)
mp = c(x = micro_price, xend = micro_price,
y = 0, yend = 0)
ggplot()+
geom_line(data = plot_data, aes(price, cumQ, color = side))+
geom_label(aes(x = mp[1], y = mp[4], label = round(micro_price, 2)), size=2, color = "black")+
scale_color_manual(values = c(ASK = "red", BID = "green"))+
labs(x = "Price", y = "Quantity", color = "Side", caption = caption)+
theme(legend.position = "top")+
theme(axis.title = element_text(face = "bold"),
plot.title = element_text(face = "bold"),
axis.line = element_line(),
axis.text.x = element_text(angle = 0, face = "bold", size = 7),
axis.text.y = element_text(face = "bold"),
axis.title.x = element_text(face = "bold",size = 10),
axis.title.y = element_text(face = "bold", size = 10),
plot.subtitle = element_text(face = "italic"),
plot.caption = element_text(face = "italic"),
panel.grid.minor.x = element_blank(),
panel.grid.minor.y = element_blank(),
panel.grid.major.x = element_blank(),
panel.grid.major.y = element_blank(),
panel.border = element_blank(),
strip.background = element_blank(),
panel.background = element_blank(),
strip.text = element_text(angle = 0, face = "bold", size = 7),
legend.title = element_text(face = "bold", size = 11),
legend.text = element_text(face = "italic", size = 10),
legend.box.background = element_rect(),
legend.position = "top")
Example: Quantile detection of supports and resitances
ask <- filter(depth, side == "ASK")
ob <- OrderBook(ask)
ob$ask <- ob$ask/sum(ob$ask)
ob$col <- ifelse(ob$ask > quantile(ob$ask, 0.8), "up", "dw")
ggplot(ob)+
geom_bar(data = ob, stat = "identity", aes(price, ask, fill = col), color = "black") +
geom_label(data = filter(ob, col == "up"), aes(price, ask, label = round(price)), color = "black") +
coord_flip()+
scale_x_continuous(breaks = round(ob$price))+
scale_fill_manual(values = c(up = "red", dw = "gray"))+
labs(x = "Price", y = "ASK Quantity", caption = caption)+
theme(axis.title = element_text(face = "bold"),
plot.title = element_text(face = "bold"),
axis.line = element_line(),
axis.text.x = element_text(angle = 0, face = "bold", size = 7),
axis.text.y = element_text(face = "bold"),
axis.title.x = element_text(face = "bold",size = 10),
axis.title.y = element_text(face = "bold", size = 10),
plot.subtitle = element_text(face = "italic"),
plot.caption = element_text(face = "italic"),
panel.grid.minor.x = element_blank(),
panel.grid.minor.y = element_blank(),
panel.grid.major.x = element_blank(),
panel.grid.major.y = element_blank(),
panel.border = element_blank(),
strip.background = element_blank(),
panel.background = element_blank(),
strip.text = element_text(angle = 0, face = "bold", size = 7),
legend.title = element_text(face = "bold", size = 11),
legend.text = element_text(face = "italic", size = 10),
legend.box.background = element_rect(),
legend.position = "none")
bid <- filter(depth, side == "BID")
ob <- OrderBook(bid)
ob$bid <- ob$bid/sum(ob$bid)
ob$col <- ifelse(ob$bid > quantile(ob$bid, 0.8), "up", "dw")
ggplot(ob)+
geom_bar(data = ob, stat = "identity", aes(price, bid, fill = col), color = "black") +
geom_label(data = filter(ob, col == "up"), aes(price, bid, label = round(price)), color = "black") +
labs(x = "Price", y = "BID Quantity", caption = caption)+
coord_flip()+
scale_x_continuous(breaks = round(ob$price))+
scale_fill_manual(values = c(up = "green", dw = "gray"))+
theme(axis.title = element_text(face = "bold"),
plot.title = element_text(face = "bold"),
axis.line = element_line(),
axis.text.x = element_text(angle = 0, face = "bold", size = 7),
axis.text.y = element_text(face = "bold"),
axis.title.x = element_text(face = "bold",size = 10),
axis.title.y = element_text(face = "bold", size = 10),
plot.subtitle = element_text(face = "italic"),
plot.caption = element_text(face = "italic"),
panel.grid.minor.x = element_blank(),
panel.grid.minor.y = element_blank(),
panel.grid.major.x = element_blank(),
panel.grid.major.y = element_blank(),
panel.border = element_blank(),
strip.background = element_blank(),
panel.background = element_blank(),
strip.text = element_text(angle = 0, face = "bold", size = 7),
legend.title = element_text(face = "bold", size = 11),
legend.text = element_text(face = "italic", size = 10),
legend.box.background = element_rect(),
legend.position = "none")