There are a few issues with the way you are approaching placing an order using binanceR. Unlike Binance itself, you cannot specify what percentage of your wallet you want to spend on a crypto, rather you have to calculate the exact amount of the crypto. This is very simple and done as follows:
#Fetching the current price of crypto of interest
curr_price <- binance_ticker_price("WAVEBTC")
curr_price <- curr_price$price
#Fetch your wallet balances
avail_btc <- binance_balances()
avail_btc <- filter(avail_btc, asset == "BTC")
avail_btc <- as.numeric(avail_usdt$free)
#Calculate possible coin quantity
buy_quantity<- avail_btc/curr_price
In this case we used all our available wallet crypto (100%+/-) to calculate the amount of crypto we want to buy, i.e. the quantity. You can select less of your wallet by dividing what you need (i.e 50% of wallet avail_btc/2).
#Reduce quantity of coins by 0.5% to avoid insufficient balance error NBNB!!
calc_price <- function(price, growth) {
new_price <- (price*growth)+price
return(new_price)
}
buy_quantity <- calc_price(buy_quantity, -0.005)
There are ways to condense the process, but step-wise is better for troubleshooting in my opinion.
Now that we have established the correct quantity, we can place an order:
binance_new_order("WAVEBTC",
side = "BUY",
type = "LIMIT",
quantity = buy_quantity,
price = b_price,
time_in_force = "GTC",
test = FALSE)
But we get the very annoying error: Error in binance_new_order("WAVEBTC", side = "BUY", type = "LIMIT", quantity = buy_quant, : abs(quot - round(quot)) < 1e-10 is not TRUE
This happens because all coins have limits on the size of the quantity OR price that you want to pass to Binance. I am not sure, but Binance sorts this out for you, which is why you never encounter this there. For example: WAVEBTC will accept a quantity of 3.2234 but not 3.223456, you see the additional two decimals... You can manually try to guess the correct format of the quantity or price, but for automation is a pain.
The solution is simple but not obvious. I had to go to the source code for binanceR and find the sections where the errors are generated. Here they are for quantity and price respectively:
#Price
quot <- (price - filters[filterType == 'PRICE_FILTER', minPrice]) / filters[filterType == 'PRICE_FILTER', tickSize]
stopifnot(abs(quot - round(quot)) < 1e-10)
#Quantity
quot <- (buy_quantity - filters[filterType == 'LOT_SIZE', minQty]) / filters[filterType == 'LOT_SIZE', stepSize]
stopifnot(abs(quot - round(quot)) < 1e-10)
These pieces of code basically checks if there is any unwanted decimals to your quantity or price. If we run this on an example using "ONTUSDT" you will see that if we use a buy_quantity of 332.44543 and calculate quot, we get a value of 33243.54. If we run stopifnot(abs(quot - round(quot)) < 1e-10) we get the error. But why? What is the value of abs(quot - round(quot): 0.457 which does not meet the error code criteria and which is why we get an error. If we change the buy_quantity to 332.44 we do not get an error message because our abs(quot - round(quot) value is 0. This is the key to the solution!
What we need to do is determine what the "correct" number of decimals are for our coins in question. For this we are going to use a simple function to calculate decimal positions for numbers and/or characters (you will see why):
decimalplaces <- function(x) {
if (class(x)=="character") {
x<-gsub("(.*)(\\.)|([0]*$)","",x)
nchar(x)
} else if (abs(x - round(x)) > .Machine$double.eps^0.5) {
nchar(strsplit(sub('0+$', '', as.character(x)), ".", fixed = TRUE)[[1]][[2]])
} else {
return(0)
}
}
Next we need to fetch the filters used by these pieces of code to determine if our quantities or prices are correct:
filters <- binance_filters("WAVEBTC")
Now we need to reformat the equation for quot so that we calculate the unknown quantity which will look like this (remember we want a quot of value 0):
quantity <- (quot*filters[filterType == 'LOT_SIZE', stepSize])+filters[filterType == 'LOT_SIZE', minQty])
#Remember to change quot to 0
quantity <- (0*filters[filterType == 'LOT_SIZE', stepSize])+filters[filterType == 'LOT_SIZE', minQty])
#Since anything * by 0 = 0, our final equation is:
quantity <- filters[filterType == 'LOT_SIZE', minQty]
Again using "ONTUSDT" as an example, the quantity value will be 0.01. This is the number of decimals your buy_quantity needs to be. So simply:
#Sometimes the value will be in scientific notation, so we convert it which creates a character string and this is why the decimalplaces function accommodates numbers and character strings.
t <- format(quantity, scientific = FALSE)
dec <- decimalplaces(t)
buy_quantity<- round(buy_quantity, digits = dec)
NB! Follow the same process for your price!
If we use buy_quantity in the error code, you will see that we do not get an error message and placing an order works!
binance_new_order("WAVEBTC",
side = "BUY",
type = "LIMIT",
quantity = buy_quantity,
price = b_price,
time_in_force = "GTC",
test = TRUE)
Good luck and trade safely!