# Porting of deribit-api-python (https://github.com/deribit/deribit-api-python/blob/master/deribit_api.py) with some additions
#### HELPER FUNCTIONS ####
#' Helper function to send requests to the API. If private methods are used, provide corresponding API keys
#' @param keys list containing access and secret keys in the form: keys <- list(key = ACCESS_KEY, secret = ACCESS_SECRET)
#' @param action Action URI
#' @param data additional data(options) provided as list of vectors (of length one, typically)
#' use httr::with_verbose(rderibit::request(action = "/api/v1/private/cancel", keys = keys, data = list(orderId = "6306623820") ) ) to troubleshoot the connection to API
request <- function(keys = NULL, action, data = NULL, simplify = TRUE) {
# to set logger to DEBUG:
# futile.logger::flog.threshold(futile.logger::DEBUG, name = "rderibit")
futile.logger::flog.debug(keys, name = "rderibit")
# response = None
if (startsWith(action, "/api/v1/private/")) {
assertthat::assert_that(!is.null(keys$key), !is.null(keys$secret), msg = "Key or secret empty" )
apiSignature <- generate_signature(keys, action, data)
response <- httr::GET( httr::add_headers(.headers = c('x-deribit-sig' = apiSignature)),
url = paste0("https://www.deribit.com/", action),
query = data)
} else response <- httr::GET( url = paste0("https://www.deribit.com/", action), query = data )
if (simplify) {jsonlite::fromJSON(httr::content(response, "text", encoding = "UTF-8"), simplifyDataFrame = TRUE)
} else return(httr::content(response))
# TODO Add error handling for responses as in this Python example
# if response.status_code != 200:
# raise Exception("Wrong response code: {0}".format(response.status_code))
#
# json = response.json()
#
# if json["success"] == False:
# raise Exception("Failed: " + json["message"])
#
# if "result" in json:
# return json["result"]
# elif "message" in json:
# return json["message"]
# else:
# return "Ok"
}
generate_signature <- function(keys, action, data, nonceoverride = F) {
# added for debugging using API request generator
if (nonceoverride == FALSE) { nonce <- as.character( round(as.numeric(Sys.time())*1000) )
} else {
assertthat::assert_that(length(nonceoverride) == 1)
assertthat::is.count(nonceoverride)
nonce <- as.numeric(nonceoverride)
}
concat_param <- ""
if (!is.null(data)) {
assertthat::assert_that(typeof(data) == "list")
for (i in sort(names(data))) {
# the parameters (param1, param2, …) must be sorted alphabetically according to the parameters’ name
assertthat::assert_that(length(data[[i]]) > 0)
# if the X-th value (corresponding to the valueX) is of array type, for instance [’a’, ’b’, ’c’], the entries should be concatenated in a single string, i.e., the resulting valueX = ’abc’
concat_param <- paste0(concat_param, "&", i, "=", paste(data[[i]], collapse = '') )
}
}
string <- paste0("_=", nonce, "&_ackey=", keys$key, "&_acsec=", keys$secret, "&_action=", action, concat_param)
# set futile.logger::flog.threshold(futile.logger::DEBUG, name='rderibit') to see the debug messages
futile.logger::flog.debug(string, name = "rderibit")
# digest::digest() didnt' work, using openssl::sha256() instead
apiSignature <- paste0(keys$key, ".", nonce, ".", RCurl::base64(openssl::sha256(charToRaw(string))))
futile.logger::flog.debug(apiSignature, name = "rderibit")
return(apiSignature)
}
#### PUBLIC API ####
#' @export
getorderbook <- function(instrument, simplify = TRUE) {
return(request(action = "/api/v1/public/getorderbook", data = list(instrument = instrument), simplify = simplify))
}
#' @export
getinstruments <- function(simplify = TRUE) { return(request(action = "/api/v1/public/getinstruments", simplify = simplify))
}
#' @export
getcurrencies <- function(simplify = TRUE) { return(request(action = "/api/v1/public/getcurrencies", simplify = simplify))
}
#' @export
getsummary <- function(instrument) { return(request(action = "/api/v1/public/getsummary", data = list(instrument = instrument)))
}
#' @export
index <- function() { return(request(action = "/api/v1/public/index"))
}
#' @export
stats <- function() { return(request(action = "/api/v1/public/stats"))
}
#' Retrieve the latest trades that have occured for a specific instrument.
#' @param instrument string [optional], instrument name, example "BTC-28SEP18-3500-P" (or other items in rderibit::getinstruments()). Can as well be "all", "options", "futures", "BTC-THISWEEK", "BTC-NEXTWEEK"
#' @param startTimestamp timestamp of starting trade in milliseconds
#' @param endTimestamp timestamp of ending trade in milliseconds
#' @param startId – integer [optional], “since” tradeId, the server returns trades newer than that “since”.
#' @param endId - integer [optional], the server returns trades with tradeId smaller than the provided number.
#' @param startSeq relates to tradeSeq parameter
#' @param endSeq relates to tradeSeq parameter
#' @param count – integer [optional], count of trades returned (limitation: max. count is 100000, default 100)
#' @examples getlasttrades(instrument = "BTC-28SEP18-3500-P", startTimestamp = as.numeric(as.POSIXlt("2018-08-05 18:00:00 UTC"))*1000)
#'
#' @export
#'
getlasttrades <- function(instrument, count = NULL, startTimestamp = NULL, endTimestamp = NULL, startId = NULL,
endId = NULL, startSeq = NULL, endSeq = NULL, simplify = TRUE) {
options <- list(instrument = instrument)
if (!is.null(count))
options[['count']] <- count
if (!is.null(startTimestamp))
options[['startTimestamp']] <- startTimestamp
if (!is.null(endTimestamp))
options[['endTimestamp']] <- endTimestamp
if (!is.null(startId))
options[['startId']] <- startId
if (!is.null(endId))
options[['endId']] <- endId
if (!is.null(startSeq))
options[['startSeq']] <- startSeq
if (!is.null(endSeq))
options[['endSeq']] <- endSeq
return(request(action = "/api/v1/public/getlasttrades", data = options, simplify = simplify))
}
#### PRIVATE API ####
#' Get user account summary (authorization is required).
#' @param keys list containing access and secret keys in the form: keys <- list(key = ACCESS_KEY, secret = ACCESS_SECRET)
#' @examples rderibit::account(keys)
#' @export
account <- function(keys) { return (request(action = "/api/v1/private/account", keys = keys) ) }
#' Place a buy order in an instrument (authorization is required).
#' @param keys list containing access and secret keys in the form: keys <- list(key = ACCESS_KEY, secret = ACCESS_SECRET)
#' @examples rderibit::buy(keys, "BTC-28DEC18-8750-P", postOnly = T, quantity = 0.1, price = .005)
#' @export
buy <- function(keys, instrument, quantity, price, postOnly = FALSE, label= NULL) {
options <- list(
instrument = instrument,
quantity = quantity,
price = price )
if (!is.null(label))
options[['label']] <- label
if (postOnly == TRUE)
options[["postOnly"]] <- postOnly
return(request(keys = keys, action = "/api/v1/private/buy", data = options))
}
#' Places sell order for an instrument (authorization is required).
#' @param keys list containing access and secret keys in the form: keys <- list(key = ACCESS_KEY, secret = ACCESS_SECRET)
#' @examples rderibit::sell(keys, "BTC-28DEC18-8750-P", postOnly = T, quantity = 0.1, price = .005)
#' @export
sell <- function(keys, instrument, quantity, price, postOnly = FALSE, label= NULL) {
options <- list(
instrument = instrument,
quantity = quantity,
price = price )
if (!is.null(label))
options[['label']] <- label
if (postOnly == TRUE)
options[["postOnly"]] <- postOnly
return(request(keys = keys, action = "/api/v1/private/sell", data = options))
}
#' @export
cancel <- function(keys, orderId){ return(request(keys = keys, action = "/api/v1/private/cancel", data = list(orderId = orderId) ) )
}
#' Bulk cancel orders based on type or instrument
#' @param keys list containing access and secret keys in the form: keys <- list(key = ACCESS_KEY, secret = ACCESS_SECRET)
#' @param typeDef Cancel instructions. Can be "all", "options", "futures" or NULL. Will be ignored if instrument is not NULL
#' @param instrument string [optional], instrument name, example "BTC-28SEP18-3500-P" (or other items in rderibit::getinstruments()).
#' @examples cancelall(keys, "BTC-28DEC18-8750-P")
#' @export
cancelall <- function(keys, instrument = NULL, typeDef= NULL) {
if (is.null(typeDef) & is.null(instrument) ) {
warning("rderibit::cancelall(): Either typeDef or instrument should be defined. No request is sent, returning NULL")
return(NULL)
}
if ( !is.null(typeDef) & !is.null(instrument) ) {
warning("rderibit::cancelall(): As instrument is defined, input for typeDef is ignored")
options <- list(instrument = instrument)
} else if (!is.null(typeDef)) { options <- list(type = typeDef)
} else if (!is.null(instrument)) options <- list(instrument = instrument)
return(request(keys, "/api/v1/private/cancelall", data = options ) )
}
#' Change order parameters
#' @param keys list containing access and secret keys in the form: keys <- list(key = ACCESS_KEY, secret = ACCESS_SECRET)
#' @param orderId ID of the order to be changed
#' @param quantity New quantity
#' @param price New price
#' @export
edit <- function(keys, orderId, quantity, price) {
options < list(
orderId = orderId,
quantity = quantity,
price = price )
return(request(keys, "/api/v1/private/edit", data = options) )
}
#' Lists open orders
#' @param keys list containing access and secret keys in the form: keys <- list(key = ACCESS_KEY, secret = ACCESS_SECRET)
#' @param instrument (optional) Instrument name
#' @param orderId (optional)
#' @param simplify Boolean, defaults to TRUE
#' @export
getopenorders <- function(keys, instrument = NULL, orderId = NULL, simplify = TRUE) {
options <- list()
if (!is.null(instrument)) options[["instrument"]] <- instrument
if (!is.null(orderId)) options[["orderId"]] <- orderId
return(request(action = "/api/v1/private/getopenorders", keys = keys, data = options, simplify = simplify))
}
#' Lists open positions
#' @param keys list containing access and secret keys in the form: keys <- list(key = ACCESS_KEY, secret = ACCESS_SECRET)
#' @export
positions <- function(keys) { return (request(action = "/api/v1/private/positions", keys = keys) ) }
#' Outputs order history
#' @param keys list containing access and secret keys in the form: keys <- list(key = ACCESS_KEY, secret = ACCESS_SECRET)
#' @param count (optional) Length of the output
#' @param simplify bool, simplifies output to dataframe, defaults to TRUE
#' @export
orderhistory <- function(keys, count = NULL, simplify = TRUE) {
options <- list()
if (!is.null(count)) options[["count"]] <- count
return(request(action = "/api/v1/private/orderhistory", keys = keys, data = options, simplify = simplify))
}
#' Outputs trade history
#' @param keys list containing access and secret keys in the form: keys <- list(key = ACCESS_KEY, secret = ACCESS_SECRET)
#' @param instrument (optional) Instrument name
#' @param startTradeId (optional) startTradeId where output begins
#' @param count (optional) Length of the output
#' @param simplify bool, simplifies output to dataframe, defaults to TRUE
#' @export
tradehistory <- function(keys, instrument = "all", count = NULL, startTradeId = NULL, simplify = TRUE) {
options <- list(instrument = instrument)
if (!is.null(count)) options[["count"]] <- count
if (!is.null(startTradeId)) options[["startTradeId"]] <- startTradeId
return(request(action = "/api/v1/private/tradehistory", keys = keys, data = options, simplify = simplify))
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.