::install_github("hfshr/bitmexr") remotes
bitmexr: An R client for BitMEX cryptocurrency exchange.
How bitmexr came to be.
While writing my previous post, I was surprised to find that there was no R related package for the cryptocurrency exchange BitMEX. While cryptocurrency itself is a somewhat niche area, BitMEX is one of the largest and most popular exchanges, so I had assumed someone would have already put together something in R for accessing data through BitMEX’s API. As I could find no such package, I drew inspiration from the few ‘crypto’ related packages that do exist, and set about creating a package that would provide a R users with a set of tools to obtain historic trade data from the exchange..
BitMEX has a very detailed API that allows users to perform essentially every action possible on the site through the API. This ranges from simple queries about historic price data through to executing trades on the platform. Initially, I just wanted the package to be able to easily access historic data for research purposes, however it would be relatively straightforward to implement additional features such as executing trades through the API.
And like that, bitmexr
was born…
Currently you can install bitmexr
from github, but hopefully the package will be on CRAN soon.
bitmexr
bitmexr
is a relatively simple package that enables the user to obtain data about trades that have been executed on the exchange. The API supports trade data to be returned in two forms:
Individual trade data
- Details about individual trades that have taken place on the exchange
Bucketed trade data
- A summarised form of individual trade data where individual trades have been “bucketed” into one of the following time intervals; 1-minute, 5-minute, 1-hour or 1-day.
To access this data, bitmexr
has two core functions:
trades()
for individual trade data
library(bitmexr)
library(dplyr)
library(rmarkdown)
library(knitr)
library(tidyquant)
library(purrr)
library(gganimate)
trades(symbol = "XBTUSD", count = 5) %>%
select(-trdMatchID) %>% # unique trade identifier, not particularly interesting
kable()
timestamp | symbol | side | size | price | tickDirection | grossValue | homeNotional | foreignNotional |
---|---|---|---|---|---|---|---|---|
2022-03-13 20:18:49 | XBTUSD | Sell | 400 | 38710.0 | ZeroMinusTick | 1033324 | 0.0103332 | 400 |
2022-03-13 20:18:49 | XBTUSD | Sell | 200 | 38710.0 | ZeroMinusTick | 516662 | 0.0051666 | 200 |
2022-03-13 20:18:49 | XBTUSD | Sell | 100 | 38710.0 | MinusTick | 258331 | 0.0025833 | 100 |
2022-03-13 20:18:49 | XBTUSD | Sell | 100 | 38713.5 | MinusTick | 258308 | 0.0025831 | 100 |
2022-03-13 20:18:49 | XBTUSD | Sell | 100 | 38715.5 | MinusTick | 258294 | 0.0025829 | 100 |
bucket_trades()
for bucketed trade data
bucket_trades(symbol = "XBTUSD", count = 5, binSize = "1d") %>%
kable()
timestamp | symbol | open | high | low | close | trades | volume | vwap | lastSize | turnover | homeNotional | foreignNotional |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2022-03-13 | XBTUSD | 38714.5 | 39480.0 | 38645.5 | 38794.0 | 63987 | 377767900 | 39060.82 | 1400 | 9.671287e+11 | 9671.287 | 377767900 |
2022-03-12 | XBTUSD | 39418.0 | 40245.5 | 38239.0 | 38714.5 | 141479 | 979194400 | 39062.35 | 1700 | 2.506753e+12 | 25067.534 | 979194400 |
2022-03-11 | XBTUSD | 41954.5 | 42037.0 | 38420.0 | 39418.0 | 181394 | 1351599500 | 39651.86 | 6500 | 3.408674e+12 | 34086.744 | 1351599500 |
2022-03-10 | XBTUSD | 38723.5 | 42596.5 | 38641.5 | 41954.5 | 167006 | 1079137900 | 41338.54 | 200 | 2.610491e+12 | 26104.907 | 1079137900 |
2022-03-09 | XBTUSD | 37967.0 | 39381.0 | 37857.0 | 38723.5 | 156917 | 1087892900 | 38651.68 | 3700 | 2.814608e+12 | 28146.078 | 1087892900 |
These functions allow the user to quickly return historic trade/price data that have been executed on the exchange.
map_* variants
In addition to the core functions, the packages contains map_* variants of each function. These functions were implemented to address two restrictions within the API:
- The maximum number of rows per API call is limited to 1000
- The API is limited to 30 requests within a 60 second period
The map_* functions are useful for when the data you wanted to return is greater than the 1000 row limit, but you want to avoid running in to the request limit (too many request timeouts may lead to an IP for up to one week).
For example, say you want to get hourly bucketed trade data from the 2019-01-01 to 2020-01-01.
bucket_trades(startTime = "2019-01-01",
endTime = "2020-01-01",
binSize = "1h",
symbol = "XBTUSD") %>%
filter(timestamp == max(timestamp)) %>%
select(timestamp) %>%
kable()
timestamp |
---|
2019-02-11 15:00:00 |
The first 1000 rows have only returned data up until 2019-02-11. To obtain the rest of the data, you would need to pass in this start date and run the function again, repeating this process until you had the desired time span of data.
This is where the map_* variants come in handy.
map_bucket_trades(start_date = "2019-01-01",
end_date = "2020-01-01",
binSize = "1h",
symbol = "XBTUSD",
verbose = FALSE) %>%
paged_table()