From 255367b1d33536215efc654faf4b65b89b0f4488 Mon Sep 17 00:00:00 2001 From: serkor1 <77464572+serkor1@users.noreply.github.com> Date: Fri, 10 Nov 2023 15:14:19 +0100 Subject: [PATCH] Added Bitmart Support We know support Bitmart. Kraken seems to be bugged. Needs a fix --- R/api_bitmart.R | 450 +++++++++++++++++++++++++++++++++++++++++ R/api_kraken.R | 31 ++- R/availableExchanges.R | 2 +- R/helper.R | 39 +++- R/sysdata.rda | Bin 7340 -> 18305 bytes 5 files changed, 507 insertions(+), 15 deletions(-) create mode 100644 R/api_bitmart.R diff --git a/R/api_bitmart.R b/R/api_bitmart.R new file mode 100644 index 00000000..8d431c70 --- /dev/null +++ b/R/api_bitmart.R @@ -0,0 +1,450 @@ +# script: scr_bitmart +# date: 2023-10-03 +# author: Serkan Korkmaz, serkor1@duck.com +# objective: These functions +# script start; + +# available intervals in bitmart; +bitmartIntervals <- function(futures, interval, all = FALSE) { + + # this funtion serves two purposes + # + # 1) listing all available + # intervals + # + # 2) extracting chosen intervals + # for the remainder of this script. + # + # This step is unnessary for some of + # the REST APIs like bitmart, but it provides + # a more streamlined programming structure + + allIntervals <- data.frame( + cbind( + labels = c( + '1m', + '3m', + '5m', + '15m', + '30m', + '1h', + '2h', + '4h', + '6h', + '12h', + '1d', + '3d', + '1w' + ), + values = c( + 1, + 3, + 5, + 15, + 30, + 60, + 120, + 240, + 360, # + 720, + 1440, + 4320, + 10000 + ) + ) + ) + + + # if all; then this function + # has been called by availableIntervals + # and will return all available intervals + + + if (all) { + + interval <- allIntervals$labels + + } else { + + # 1) locate the chosen interval + # from the list + indicator <- grepl( + pattern = paste0('^', interval), + ignore.case = FALSE, + x = allIntervals$labels + ) + + if (sum(indicator) == 0) { + + rlang::abort( + message = c( + paste0(interval, ' were not found.'), + 'v' = paste('Valid intervals:', paste(allIntervals$labels,collapse = ', ')) + ), + # disable traceback, on this error. + trace = rlang::trace_back() + ) + + } + + # 2) extract the interval + # from the list + interval <- allIntervals[indicator,]$values + } + + + return( + interval + ) + +} + + + + + + +# baseURL; +bitmartUrl <- function( + futures = TRUE +) { + + # 1) define baseURL + # for each API + baseUrl <- base::ifelse( + test = futures, + yes = 'https://api-cloud.bitmart.com', + no = 'https://api-cloud.bitmart.com' + ) + + # 2) return the + # baseURL + return( + baseUrl + ) + +} + + + + +# tickers; +bitmartTickers <- function( + futures = TRUE +) { + + # 1) extract endpoint + # based on futres + endPoint <- base::ifelse( + test = futures, + yes = '/contract/public/details', + no = '/spot/v1/symbols' + ) + + # 2) GET response + # using baseUrl + # and internal endpoint + # defined here + response <- httr::GET( + url = baseUrl( + source = 'bitmart', + futures = futures + ), + path = endPoint + ) + + # 3) parse response + response <- jsonlite::fromJSON( + txt = httr::content( + x = response, + as = 'text', + encoding = 'UTF-8' + ) + )$data + + if (futures) { + + response <- response$symbol$symbol + + } else { + + response <- response$symbols + + } + # 4) subset by + # currently tradable + # tickers and extract + # the symbols as a character + # vector + # response <- subset( + # x = response$symbols, + # grepl( + # pattern = 'trading', + # ignore.case = TRUE, + # x = response$symbols$status + # ) + # )$symbol + + + # 5) return the + # vector + return( + response + ) + +} + + +# endpoint +bitmartEndpoint <- function( + futures = TRUE +) { + + # 1) construct endpoint url + endPoint <- base::ifelse( + test = futures, + yes = '/contract/public/kline', + no = '/spot/quotation/v3/lite-klines' + ) + + # 2) return endPoint url + return( + endPoint + ) +} + + + +# parameters; +bitmartParams <- function( + futures, + ticker, + interval, + from = NULL, + to = NULL +) { + + # 1) construct baseparametes + # conditional on marketEndpoint + # ie. wether its futures, or spotmarket + if (futures) { + + getParams <- list( + symbol = ticker, + step = constructInterval( + source = 'bitmart', + futures = futures, + interval = interval + ), + start_time = as.numeric( + as.POSIXct( + Sys.Date() - 1, + origin = '1970-01-01' + ) + ), + end_time = as.numeric( + as.POSIXct( + Sys.Date(), + origin = '1970-01-01' + ) + ) + ) + + } else { + + getParams <- list( + symbol = ticker, + step = constructInterval( + source = 'bitmart', + futures = futures, + interval = interval + ) + ) + + } + + # 2) add startTime and endTime + # on the parameter list if not + # null + # + # NOT: Its all UTC, in a future + # update this should be depending on + # choice, and user system. + if (!is.null(from) & !is.null(to)) { + + getParams$after <- format( + as.numeric( + as.POSIXct( + from, + tz = 'UTC' + ) + ), + scientific = FALSE + ) + + + + getParams$before <- format( + as.numeric( + as.POSIXct( + to, + tz = 'UTC' + ) + ), scientific = FALSE + ) + + } + + # 3) return parameters + return( + getParams + ) + +} + + +# get prices; +bitmartQuote <- function( + futures, + interval, + ticker, + from = NULL, + to = NULL +) { + + # function information + # + # + # This function fetches the + # the data + + # 1) GET request + response <- httr::GET( + url = baseUrl( + source = 'bitmart', + futures = futures + ), + # NOTE: Cant connect + # to bitmart with this + # httr::use_proxy( + # url = '141.11.158.172', + # port = 8080 + # ), + path = endPoint( + source = 'bitmart', + futures = futures + ), + query = getParams( + source = 'bitmart', + futures = futures, + ticker = ticker, + interval = interval, + from = from, + to = to + ) + ) + + + # 2) parse response + response <- jsonlite::fromJSON( + txt = httr::content( + x = response, + as = 'text', + encoding = 'UTF-8' + ) + )$data + + + + # 3) format response + # accordingly + + # 3.1) set column + # names + if (futures) { + + column_names <- c( + 'Low', + 'High', + 'Open', + 'Close', + 'Volume' + ) + + # 3.2) format + # dates + index <- as.POSIXct( + as.numeric(response[,6]), + origin = '1970-01-01', + tz = 'UTC' + ) + + # 3.3) extract needed + # columns from the response + response <- response[,1:5] + colnames(response) <- column_names + + # 3.4) convert all values + # to numeric + response <- apply( + response, + c(1,2), + as.numeric + ) + + + + + + + } else { + + + column_names <- c( + 'Open', + 'High', + 'Low', + 'Close', + 'Volume' + ) + + # 3.2) format + # dates + index <- as.POSIXct( + as.numeric(response[,1]), + origin = '1970-01-01', + tz = 'UTC' + ) + + + # 3.3) extract needed + # columns from the response + response <- response[,c(2:5,7)] + colnames(response) <- column_names + + # 3.4) convert all values + # to numeric + response <- apply( + response, + c(1,2), + as.numeric + ) + + + + } + + + return( + list( + index = index, + quote = response + ) + ) + +} + + + +# script end; + diff --git a/R/api_kraken.R b/R/api_kraken.R index f5ba7169..b645e6a0 100644 --- a/R/api_kraken.R +++ b/R/api_kraken.R @@ -375,8 +375,18 @@ krakenQuote <- function( ) ), query = list( - from = from, - to = to + from = as.numeric( + as.POSIXct( + from, + tz = 'UTC' + ) + ), + to = as.numeric( + as.POSIXct( + to, + tz = 'UTC' + ) + ) ) ) @@ -426,6 +436,7 @@ krakenQuote <- function( } + # 3) format response # accordingly @@ -442,15 +453,27 @@ krakenQuote <- function( # 3.2) format # dates index <- as.POSIXct( - as.numeric(response[,1]), + as.numeric(response[,1])/ifelse(futures, 1000, 1), origin = '1970-01-01', tz = 'UTC' ) + if (futures) { + + idx <- c(2:6) + + } else { + + idx <- c(2:5, 7) + + } + + + # 3.3) extract needed # columns from the response - response <- response[,c(2:5, 7)] + response <- response[,idx] colnames(response) <- column_names # 3.4) convert all values diff --git a/R/availableExchanges.R b/R/availableExchanges.R index a69ed510..4325be1b 100644 --- a/R/availableExchanges.R +++ b/R/availableExchanges.R @@ -22,7 +22,7 @@ availableExchanges <- function(){ rlang::inform( message = c( 'i' = c('Available exchanges'), - 'v' = paste(c('binance', 'kucoin', 'kraken'), collapse = ', ') + 'v' = paste(c('binance', 'kucoin', 'kraken', 'bitmart'), collapse = ', ') ) ) diff --git a/R/helper.R b/R/helper.R index 5bab6792..ef83f6dd 100644 --- a/R/helper.R +++ b/R/helper.R @@ -77,10 +77,13 @@ convert_date <- function( } + + + # generate data; # this data is for the purpose of presenting # and error-testing -generate_data <- function(exchanges = c('binance', 'kucoin')) { +generate_data <- function(exchanges = c('binance', 'kucoin', 'kraken', 'bitmart')) { markets <- c( 'spot', 'futures' @@ -92,6 +95,8 @@ generate_data <- function(exchanges = c('binance', 'kucoin')) { seq_along(exchanges), function(x) { + # determine tickers: + # First is SPOT, second is FUTURES if (x == 1) { # Binance @@ -105,6 +110,18 @@ generate_data <- function(exchanges = c('binance', 'kucoin')) { } + if (x == 3) { + + ticker <- c('ATOMUSDT', 'PF_ATOMUSD') + + } + + if (x == 4) { + + ticker <- c('ATOM_USDT', 'ATOMUSDT') + + } + # for each exchange # we collect futures @@ -113,16 +130,22 @@ generate_data <- function(exchanges = c('binance', 'kucoin')) { seq_along(markets), function(y) { + message( + paste( + 'ticker:', ticker[y], 'market:', markets[y], 'exchange:', exchanges[x]) + ) Sys.sleep(2) + + # Collect data quote <- getQuote( ticker = ticker[y], source = exchanges[x], futures = ifelse(markets[y] == 'futures', TRUE, FALSE), interval = '15m', - from = '2023-10-01', - to = '2023-10-02' + from = '2023-11-01', + to = '2023-11-03' ) # quote$exchange <- x @@ -158,13 +181,9 @@ generate_data <- function(exchanges = c('binance', 'kucoin')) { } -# internalTest <- generate_data() -# usethis::use_data( -# internalTest, -# internal = TRUE, -# overwrite = TRUE -# -# ) + + + convertIndicator <- function(indicator) { diff --git a/R/sysdata.rda b/R/sysdata.rda index c305ce118004de96322f3ca43e309ce8012c86f4..2d473cbab749a00a7e81fe0c36c8a1b3daff1996 100644 GIT binary patch literal 18305 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 QJm3Epaz!{$kib41x$$t3U;qFB literal 7340 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