{binance} Spot Trading: Market Orders

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.