Functionality for working with spot trades is now available in {binance}
. In this post we’ll establish some background on spot trading and then explore some related functions.
Setup
First we’ll load the package.
library(binance)
packageVersion("binance")
[1] ‘0.0.3’
We’ll be using the Binance Testnet. This means that we need to change the base URL for the API and also specify a different set of credentials.
base_url("https://testnet.binance.vision/")
authenticate(
key = Sys.getenv("BINANCE_TESTNET_API_KEY"),
secret = Sys.getenv("BINANCE_TESTNET_API_SECRET")
)
Pairs and Spot Trades
Trading is the process of buying and selling assets, where in the current context those assets are cryptocurrencies. In a single trade you’d exchange an amount of one currency for the corresponding amount of another currency. The relative amounts of each currency involved in the transaction is determined by the market price (or spot price).
Trades always involve a pair of currencies and prices are always quoted for pairs. It doesn’t make sense to think about the price of a single cryptocurrency in isolation. It always needs to be compared to another cryptocurrency. For example, what is the price of BTC? Well, that depends on what you are using to purchase BTC. The price will be different if you are purchasing in USDT or ETH (or any other cryptocurrency for that matter).
Which pairs can we trade? Let’s see what currency pairs are available on the Binance Testnet.
market_exchange_symbols()
# A tibble: 20 × 5
symbol status base quote is_spot_trading_allowed
<chr> <chr> <chr> <chr> <lgl>
1 BNBBUSD TRADING BNB BUSD TRUE
2 BTCBUSD TRADING BTC BUSD TRUE
3 ETHBUSD TRADING ETH BUSD TRUE
4 LTCBUSD TRADING LTC BUSD TRUE
5 TRXBUSD TRADING TRX BUSD TRUE
6 XRPBUSD TRADING XRP BUSD TRUE
7 BNBUSDT TRADING BNB USDT TRUE
8 BTCUSDT TRADING BTC USDT TRUE
9 ETHUSDT TRADING ETH USDT TRUE
10 LTCUSDT TRADING LTC USDT TRUE
11 TRXUSDT TRADING TRX USDT TRUE
12 XRPUSDT TRADING XRP USDT TRUE
13 BNBBTC TRADING BNB BTC TRUE
14 ETHBTC TRADING ETH BTC TRUE
15 LTCBTC TRADING LTC BTC TRUE
16 TRXBTC TRADING TRX BTC TRUE
17 XRPBTC TRADING XRP BTC TRUE
18 LTCBNB TRADING LTC BNB TRUE
19 TRXBNB TRADING TRX BNB TRUE
20 XRPBNB TRADING XRP BNB TRUE
So there are twenty pairs, all of which are currently available for spot trading (their status is TRADING
). There are vastly more pairs on the Binance mainnet.
Each pair consists of two cryptocurrencies, the base and the quote. For example, the BTCUSDT pair has BTC as the base and USDT as the quote. What does this mean? Well, let’s look at the corresponding price information.
market_price_ticker() %>% arrange(symbol) %>% mutate(price = round(price, 6))
# A tibble: 20 × 2
symbol price
<chr> <dbl>
1 BNBBTC 0.0025
2 BNBBUSD 389.52
3 BNBUSDT 517.1
4 BTCBUSD 51421.87
5 BTCUSDT 60607.26
6 ETHBTC 0.575063
7 ETHBUSD 3957.53
8 ETHUSDT 1600
9 LTCBNB 0.3847
10 LTCBTC 0.0098
11 LTCBUSD 183
12 LTCUSDT 185.04
13 TRXBNB 0.000218
14 TRXBTC 0.000004
15 TRXBUSD 0.10216
16 TRXUSDT 0.14338
17 XRPBNB 0.002377
18 XRPBTC 0.000019
19 XRPBUSD 1.1338
20 XRPUSDT 0.8491
Suppose you wanted to buy 1 BTC. If you were going to pay for that in BUSD then it would cost you 51421.87 BUSD. If, however, you were paying in USDT then it would cost you 60607.26 USDT. In either of these cases you’d be making a buy trade, either buying BTCBUSD (trading BUSD for BTC) or BTCUSDT (trading USDT for BTC).
Does this mean that it’s only possible to purchase BTC with BUSD or USDT? Nope. BTC features in other pairs too, like ETHBTC and XRPBTC. If you had ETH and you wanted to buy BTC then you’d make a sell trade on ETHBTC (selling ETH for BTC). Likewise, if you had XRP, then you could sell on XRPBTC. In this case the price works the other way around: 1 ETH would get you 0.575063 BTC, while 1 XRP would sell for 0.000019 BTC.
The base is the asset which you are buying or selling and the quote is the other asset which you will be paying or receiving.
🚨 The prices on the Binance testnet differ dramatically from the real prices on the Binance mainnet.
Initial Account Balance
Before we start trading, let’s check on our spot account balance on the testnet.
spot_account_balances()
# A tibble: 7 × 3
asset free locked
<chr> <dbl> <dbl>
1 BNB 980. 0
2 BUSD 12234. 0
3 ETH 147. 0
4 LTC 500 0
5 TRX 472872. 6000
6 USDT 10524. 0
7 XRP 50500 0
Plenty of (fictional) coins to play with.
Making Trades
Market orders are trades which are executed at the current market price.
Let’s buy 1 ETH paying with USDT. Use the generic spot_new_order()
function and specify "MARKET"
order type. The effective price for the transaction will be the current ETHUSDT market price.
(ethusdt_mkt <- spot_new_order(order_type = "MARKET", symbol = "ETHUSDT", side = "BUY", quantity = 1))
# A tibble: 1 × 11
symbol order_id transact_time price orig_qty exec_qty status time_in_force type side fills
<chr> <int> <dttm> <dbl> <dbl> <dbl> <chr> <chr> <chr> <chr> <list>
1 ETHUSDT 454759 2021-11-01 06:16:42 0 1 1 FILLED GTC MARKET BUY <tibble [4 × 5]>
The status of the transaction is FILLED
, meaning that the entire amount requested was bought. This is also reflected in the fact that the executed quantity (exec_qty
) matches the original quantity (orig_qty
).
The price
column is empty. Why? Because there is often not an unique price associated with the trade. We can see the details in the fills
element.
ethusdt_mkt$fills
[[1]]
# A tibble: 4 × 5
price qty commission commissionAsset tradeId
<chr> <chr> <chr> <chr> <int>
1 1556.42000000 0.33410000 0.00000000 ETH 10954
2 1557.34000000 0.13228000 0.00000000 ETH 10955
3 1557.96000000 0.06547000 0.00000000 ETH 10956
4 1600.00000000 0.46815000 0.00000000 ETH 10957
There was some slippage in this transaction. Although we asked to buy 1 ETH, there wasn’t sufficient volume available at the market price. So we got some ETH at a price of 1556.42 USDT, but in order to fill the order we got the rest at higher prices. Price slippage is a necessary evil of making market trades.
Now let’s sell some TRX and purchase BUSD. We’ll use the specific spot_new_market_order()
function to avoid having to specify the order_type
parameter.
(trxbusd_mkt <- spot_new_market_order(symbol = "TRXBUSD", side = "SELL", quantity = 1000))
# A tibble: 1 × 11
symbol order_id transact_time price orig_qty exec_qty status time_in_force type side fills
<chr> <int> <dttm> <dbl> <dbl> <dbl> <chr> <chr> <chr> <chr> <list>
1 TRXBUSD 1544 2021-11-01 06:31:18 0 1000 1000 FILLED GTC MARKET SELL <tibble [1 × 5]>
trxbusd_mkt$fills
[[1]]
# A tibble: 1 × 5
price qty commission commissionAsset tradeId
<chr> <chr> <chr> <chr> <int>
1 0.10153000 1000.00000000 0.00000000 BUSD 602
In this case all 1000 TRX was sold at the same price of 0.10153000 BUSD.
Updated Account Balance
We should see the results of these two trades in our account balance.
spot_account_balances()
# A tibble: 7 × 3
asset free locked
<chr> <dbl> <dbl>
1 BNB 980. 0
2 BUSD 12335. 0
3 ETH 148. 0
4 LTC 500 0
5 TRX 471872. 6000
6 USDT 8924. 0
7 XRP 50500 0
The balance of ETH has increased from 147 to 148 (because we bought 1 ETH using USDT) and the balance of USDT has dropped accordingly. The balance of TRX has dropped by 1000 (because we sold 1000 TRX for BUSD) and the balance of BUSD has increased.
Listing Trades
We can review our trading history using spot_trades_list()
. This will include the two trades above (identify using the order_id
column) as well as some other historical trades.
spot_trades_list("ETHUSDT")
# A tibble: 11 × 12
symbol time id order_id price qty quote_qty commission commission_asset side
<chr> <dttm> <int> <int> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
1 ETHUSDT 2021-10-29 05:12:10 9701 411314 1678.66 0.1 167.866 0 ETH BUY
2 ETHUSDT 2021-10-29 06:42:55 9735 411345 1600 0.01 16 0 ETH BUY
3 ETHUSDT 2021-10-29 06:42:55 9736 411345 1600 0.09 144 0 ETH BUY
8 ETHUSDT 2021-10-30 04:42:07 9962 421351 1468.91 0.1 146.891 0 ETH BUY
4 ETHUSDT 2021-10-30 06:27:41 10003 427922 1418.91 0.16872 239.39850 0 ETH BUY
5 ETHUSDT 2021-10-30 06:27:42 10004 427922 1418.91 0.00989 14.033020 0 ETH BUY
6 ETHUSDT 2021-10-30 06:27:42 10005 427922 1418.91 0.32075 455.11538 0 ETH BUY
7 ETHUSDT 2021-10-30 06:27:46 10008 427922 1418.91 0.00762 10.812094 0 ETH BUY
9 ETHUSDT 2021-11-01 06:16:42 10954 454759 1556.42 0.3341 519.99992 0 ETH BUY
10 ETHUSDT 2021-11-01 06:16:42 10955 454759 1557.34 0.13228 206.00494 0 ETH BUY
11 ETHUSDT 2021-11-01 06:16:42 10956 454759 1557.96 0.06547 101.99964 0 ETH BUY
spot_trades_list("TRXBUSD")
# A tibble: 25 × 12
symbol time id order_id price qty quote_qty commission commission_asset side
<chr> <dttm> <int> <int> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
1 TRXBUSD 2021-10-30 05:51:20 562 1500 0.10153 1000 101.53 0 BUSD SELL
22 TRXBUSD 2021-11-01 06:31:18 602 1544 0.10153 1000 101.53 0 BUSD SELL
What’s Next
In the next post we’ll take a look at market liquidity and how this affects your ability to trade.