Skip to content
4 changes: 4 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ export(usdm_v1_premium_index)
export(usdm_v1_time)
export(usdm_v2_account)
export(usdm_v2_position_risks)
export(usdm_v1_trades)
export(usdm_um_trades)
export(usdm_um_new_order)
export(usdm_um_open_orders)
importFrom(assertive,assert_is_numeric)
importFrom(data.table,"%chin%")
importFrom(data.table,":=")
Expand Down
26 changes: 13 additions & 13 deletions R/binance.R
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
BINANCE <- list(
BASE = list(
SPOT = 'https://api.binance.com',
USDM = 'https://fapi.binance.com'
USDM = 'https://papi.binance.com'
),
SPOT = list(
TIMEINFORCE = c('GTC', 'IOC', 'FOK'),
Expand All @@ -15,7 +15,7 @@ BINANCE <- list(
"MAX_NUM_ORDERS", "MAX_NUM_ALGO_ORDERS",
"MIN_NOTIONAL", "PERCENT_PRICE"),
TIMEINFORCE = c('GTC', 'IOC', 'FOK', 'GTX'),
POSITION_SIDE = c('LONG', 'SHORT'),
POSITION_SIDE = c('BOTH', 'LONG', 'SHORT'),
TYPE = c('LIMIT', 'MARKET',
'STOP', 'STOP_MARKET',
'TAKE_PROFIT', 'TAKE_PROFIT_MARKET',
Expand Down Expand Up @@ -798,24 +798,24 @@ binance_new_order <- function(symbol, side, type, time_in_force, quantity, price
quantity <= filters[filterType == 'LOT_SIZE', maxQty])
# work around the limitation of %% (e.g. 200.1 %% 0.1 = 0.1 !!)
quot <- (quantity - filters[filterType == 'LOT_SIZE', minQty]) / filters[filterType == 'LOT_SIZE', stepSize]
stopifnot(abs(quot - round(quot)) < 1e-10)
stopifnot(abs(quot - round(quot)) < 1)

if (type == 'MARKET') {
stopifnot(quantity >= filters[filterType == 'MARKET_LOT_SIZE', minQty],
quantity <= filters[filterType == 'MARKET_LOT_SIZE', maxQty])
# work around the limitation of %% (e.g. 200.1 %% 0.1 = 0.1 !!)
quot <- (quantity - filters[filterType == 'MARKET_LOT_SIZE', minQty]) / filters[filterType == 'MARKET_LOT_SIZE', stepSize]
stopifnot(abs(quot - round(quot)) < 1e-10)
stopifnot(abs(quot - round(quot)) < 1)

if (isTRUE(filters[filterType == 'MIN_NOTIONAL', applyToMarket])) {
if (filters[filterType == 'MIN_NOTIONAL', avgPriceMins] == 0) {
if (isTRUE(filters[filterType == 'NOTIONAL', applyToMarket])) {
if (filters[filterType == 'NOTIONAL', avgPriceMins] == 0) {
ref_price <- binance_ticker_price(symbol)$price
} else {
ref_price <- binance_avg_price(symbol)
stopifnot(ref_price$mins == filters[filterType == 'MIN_NOTIONAL', avgPriceMins])
stopifnot(ref_price$mins == filters[filterType == 'NOTIONAL', avgPriceMins])
ref_price <- ref_price$price
}
stopifnot(ref_price * quantity >= filters[filterType == 'MIN_NOTIONAL', minNotional])
stopifnot(ref_price * quantity >= filters[filterType == 'NOTIONAL', minNotional])
}
}

Expand All @@ -830,19 +830,19 @@ binance_new_order <- function(symbol, side, type, time_in_force, quantity, price
stopifnot(abs(quot - round(quot)) < 1e-10)
}

if (filters[filterType == 'PERCENT_PRICE', avgPriceMins] == 0) {
if (filters[filterType == 'NOTIONAL', avgPriceMins] == 0) {
ref_price <- binance_ticker_price(symbol)$price
} else {
ref_price <- binance_avg_price(symbol)
stopifnot(ref_price$mins == filters[filterType == 'PERCENT_PRICE', avgPriceMins])
stopifnot(ref_price$mins == filters[filterType == 'NOTIONAL', avgPriceMins])
ref_price <- ref_price$price
}
stopifnot(
price >= ref_price * filters[filterType == 'PERCENT_PRICE', multiplierDown],
price <= ref_price * filters[filterType == 'PERCENT_PRICE', multiplierUp]
price >= ref_price * filters[filterType == 'PERCENT_PRICE_BY_SIDE', 'askMultiplierDown'],
price <= ref_price * filters[filterType == 'PERCENT_PRICE_BY_SIDE', 'askMultiplierUp']
)

stopifnot(price * quantity >= filters[filterType == 'MIN_NOTIONAL', minNotional])
stopifnot(price * quantity >= filters[filterType == 'NOTIONAL', minNotional])

params$price = price
}
Expand Down
126 changes: 111 additions & 15 deletions R/usdm.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ usdm_query <- function(endpoint, ...) {
#' @export
#' @return "OK" string on success
usdm_v1_ping <- function() {
res <- usdm_query("/fapi/v1/ping")
res <- usdm_query("/papi/v1/ping")
if (is.list(res) & length(res) == 0) {
res <- "OK"
}
Expand All @@ -21,7 +21,7 @@ usdm_v1_ping <- function() {
#' @export
#' @return \code{POSIXct}
usdm_v1_time <- function() {
res <- usdm_query("/fapi/v1/time")$serverTime
res <- usdm_query("/dapi/v1/time")$serverTime
res <- as_timestamp(res / 1e3)
res
}
Expand All @@ -31,7 +31,7 @@ usdm_v1_time <- function() {
#' @export
#' @importFrom jsonlite fromJSON
usdm_v1_exchange_info <- function() {
res <- usdm_query("/fapi/v1/exchangeInfo", content_as = "text")
res <- usdm_query("/papi/v1/exchangeInfo", content_as = "text")
res <- fromJSON(res)
res$serverTime <- as_timestamp(res$serverTime / 1e3)
res$rateLimits <- as.data.table(res$rateLimits)
Expand Down Expand Up @@ -76,7 +76,7 @@ usdm_v1_premium_index <- function(symbol) {
params$symbol <- symbol
}

res <- usdm_query("/fapi/v1/premiumIndex", params = params)
res <- usdm_query("/dapi/v1/premiumIndex", params = params)

if (missing(symbol)) {
res <- rbindlist(res)
Expand All @@ -97,7 +97,7 @@ usdm_v1_premium_index <- function(symbol) {
res[, time := as_timestamp(time)]
}

#' Open new order on the Binance USDM account
#' Open new order on the Binance Coin-m account
#'
#' This function serves as a low level entry for order classes.
#' Do not use it directly.
Expand All @@ -122,8 +122,8 @@ usdm_v1_new_order <- function(symbol,
...
)

order <- usdm_query(
"/fapi/v1/order",
order <- usdm_query(
"/papi/v1/cm/order",
method = "POST",
params = params,
sign = TRUE
Expand All @@ -132,7 +132,42 @@ usdm_v1_new_order <- function(symbol,
as.data.table(order)
}

#' Get all open orders of a symbol on USDM.
#' Open new order on the Binance USDM account
#'
#' This function serves as a low level entry for order classes.
#' Do not use it directly.
#'
#' @param symbol string
#' @param side enum
#' @param position_side enum
#' @param type enum
#' @param ... list
#' @return data.table
#' @export
usdm_um_new_order <- function(symbol,
side = BINANCE$SIDE,
position_side = BINANCE$USDM$POSITION_SIDE,
type = BINANCE$USDM$TYPE,
...) {
params <- list(
symbol = symbol,
side = match.arg(side),
positionSide = match.arg(position_side),
type = match.arg(type),
...
)

order <- usdm_query(
"/papi/v1/um/order",
method = "POST",
params = params,
sign = TRUE
)

as.data.table(order)
}

#' Get all open orders of a symbol on Coin-M.
#'
#' Get all open orders on a symbol. Careful when accessing this with no symbol.
#' Weight: 1 for a single symbol; 40 when the symbol parameter is omitted.
Expand All @@ -148,14 +183,39 @@ usdm_v1_open_orders <- function(symbol) {
}

order <- usdm_query(
"/fapi/v1/openOrders",
"/papi/v1/cm/openOrders",
params = params,
sign = TRUE
)

rbindlist(order)
}

#' Get all open orders of a symbol on USDM.
#'
#' Get all open orders on a symbol. Careful when accessing this with no symbol.
#' Weight: 1 for a single symbol; 40 when the symbol parameter is omitted.
#'
#' @param symbol optional string
#' @return data.table
#' @export
usdm_um_open_orders <- function(symbol) {
params <- list()

if (!missing(symbol)) {
params$symbol <- symbol
}

order <- usdm_query(
"/papi/v1/um/openOrders",
params = params,
sign = TRUE
)

rbindlist(order)
}


#' Get positions of a symbol or all symbols on USDM.
#' @param symbol optional string
#' @return data.table
Expand All @@ -169,13 +229,49 @@ usdm_v2_position_risks <- function(symbol) {

rbindlist(
usdm_query(
"/fapi/v2/positionRisk",
"/dapi/v2/positionRisk",
params = params,
sign = TRUE
)
)
}

#' Trade list (sp)
#' @return data.table
#' @export
usdm_v1_trades <- function(symbol) {
params <- list()

if (!missing(symbol)) {
params$symbol <- symbol
}

rbindlist(
usdm_query(
"/papi/v1/cm/userTrades",
sign = TRUE
)
)
}

#' Trade list USDM (sp)
#' @return data.table
#' @export
usdm_um_trades <- function(symbol) {
params <- list()

if (!missing(symbol)) {
params$symbol <- symbol
}

rbindlist(
usdm_query(
"/papi/v1/um/userTrades",
sign = TRUE
)
)
}

#' Convert columns of positions into numeric.
#' @param positions data.table
#' @return data.table
Expand All @@ -198,7 +294,7 @@ convert_position_risks <- function(positions) {
#' @return list
#' @export
usdm_v2_account <- function() {
account <- usdm_query("/fapi/v2/account", sign = TRUE)
account <- usdm_query("/dapi/v2/account", sign = TRUE)
account$assets <- rbindlist(account$assets)
account$positions <- rbindlist(account$positions)
account
Expand All @@ -216,7 +312,7 @@ usdm_v1_change_initial_leverage <- function(symbol, leverage) {
)

usdm_query(
"/fapi/v1/leverage",
"/dapi/v1/leverage",
method = "POST",
params = params,
sign = TRUE
Expand All @@ -236,7 +332,7 @@ usdm_v1_change_margin_type <- function(symbol,
)

usdm_query(
"/fapi/v1/marginType",
"/dapi/v1/marginType",
method = "POST",
params = params,
sign = TRUE
Expand All @@ -255,7 +351,7 @@ usdm_v1_cancel_order_by_id <- function(symbol, order_id) {
)

order <- usdm_query(
"/fapi/v1/order",
"/dapi/v1/order",
method = "DELETE",
params = params,
sign = TRUE
Expand All @@ -276,7 +372,7 @@ usdm_v1_cancel_order_by_client_order_id <- function(symbol, client_order_id) {
)

order <- usdm_query(
"/fapi/v1/order",
"/dapi/v1/order",
method = "DELETE",
params = params,
sign = TRUE
Expand Down