Exploring the Binance API in Python - Part II: Recent and Historical Trades

Draft – work in progress.

Table of Contents

Latest Price

Get the price at which the latest trade was executed:

r = s.get("https://api.binance.com/api/v3/ticker/price", params=dict(symbol="ETHAUD"))

The content of r.json():

{
  "price": "3032.17000000",
  "symbol": "ETHAUD"
}

Average Price

Get the average price of trades in the last 5 minutes:

r = s.get("https://api.binance.com/api/v3/avgPrice", params=dict(symbol="ETHAUD"))

The content of r.json():

{
  "mins": 5,
  "price": "3038.63364133"
}

Recent Trades

Get details of the most recent trades.

r = s.get("https://api.binance.com/api/v3/trades",
          params=dict(symbol="ETHAUD", limit=500))
block = r.json()

This returns a list of dictionaries that contain details of the trade.

[
  {
    "id": 909049,
    "isBestMatch": true,
    "isBuyerMaker": false,
    "price": "3041.05000000",
    "qty": "0.68053000",
    "quoteQty": "2069.52575650",
    "time": 1619205370059
  },
  {
    "id": 909050,
    "isBestMatch": true,
    "isBuyerMaker": true,
    "price": "3034.11000000",
    "qty": "0.67985000",
    "quoteQty": "2062.73968350",
    "time": 1619205476103
  }
  (...)
]
>>> data = create_trades_frame(block)

where

def create_trades_frame(trades):

    frame = pd.DataFrame(trades) \
        .assign(time=lambda trade: pd.to_datetime(trade.time, unit="ms"),
                price=lambda trade: pd.to_numeric(trade.price),
                qty=lambda trade: pd.to_numeric(trade.qty),
                quoteQty=lambda trade: pd.to_numeric(trade.quoteQty))
    return frame
timeidpriceqtyquoteQtyisBuyerMakerisBestMatch
2021-04-23 17:39:09.8120009085512970.991.735415155.89FalseTrue
2021-04-23 17:39:13.8540009085522967.271.366684055.31FalseTrue
2021-04-23 17:39:15.0590009085532966.340.0094127.9133TrueTrue
2021-04-23 17:39:16.9480009085542965.440.339981008.19FalseTrue
2021-04-23 17:39:16.9490009085552965.440.909892698.22FalseTrue

Scatter plot

sns.scatterplot(x="time", y="price", marker="+", data=data)
Scatter plot (price vs. time) for the most recent 500 trades

Historical Trades

num_blocks = 100
limit = 500

blocks = []
blocks.append(block)
for i in range(num_blocks):
    from_id = block[0]["id"] - limit  # get first trade of previous block
    r = s.get("https://api.binance.com/api/v3/historicalTrades",
              params=dict(symbol="ETHAUD", limit=limit, fromId=from_id))
    block = r.json()
    blocks.append(block)

Let us chain together these blocks of trades. In other words, we wish to convert this list of blocks, where each block contains a list of trades, into a single “flat” list of trades.

>>> data = create_trades_frame(chain(*blocks))

where we import the chain function from itertools:

from itertools import chain

Scatter plot

sns.scatterplot(x="time", y="price", marker="x", s=0.5, alpha=0.2, data=data)
Scatter plot (price vs. time) for the most recent 100 x 500 = 50,000 trades

Open-High-Low-Close (OHLC) Data

data_ohlc = data.set_index("time").price.resample("30T").ohlc()
timeopenhighlowclose
2021-04-21 22:30:003079.113085.9530553074.12
2021-04-21 23:00:003071.993089.713039.443049.73
2021-04-21 23:30:003052.513096.033052.513065.93
2021-04-22 00:00:003066.543084.583012.323080.94
2021-04-22 00:30:003084.043133.273064.273132.16

Candlestick chart

mpf.plot(data_ohlc, type="candle", style="binance")
Candlestick chart for the most recent 100 x 500 = 50,000 trades

Volume Data

series_volume = data.set_index("time").quoteQty.resample("30T").sum()

Concatentate this together with the OHLC DataFrame:

frame = data_ohlc.assign(volume=series_volume)
timeopenhighlowclosevolume
2021-04-21 22:30:003079.113085.9530553074.12643973
2021-04-21 23:00:003071.993089.713039.443049.73848766
2021-04-21 23:30:003052.513096.033052.513065.93363078
2021-04-22 00:00:003066.543084.583012.323080.941.18854e+06
2021-04-22 00:30:003084.043133.273064.273132.16901508

Candlestick chart with volume

fig, (ax1, ax2) = plt.subplots(nrows=2, gridspec_kw=dict(height_ratios=[3, 1]))

mpf.plot(frame, type="candle", style="binance", volume=ax2, ax=ax1)
fig.autofmt_xdate()

plt.show()
Candlestick and Volume chart for the most recent 100 x 500 = 50,000 trades

Candlestick

We can also obtain summarize the data into a format suitable candlestick chart at server-side by directly calling the following endpoint:

r = s.get("https://api.binance.com/api/v3/klines",
          params=dict(symbol="ETHAUD", interval="4h"))

frame = pd.DataFrame(data=r.json(),
                     columns=["open_time",
                              "open",
                              "high",
                              "low",
                              "close",
                              "volume",
                              "close_time",
                              "quote_asset_volume",
                              "number_of_trades",
                              "taker_buy_base_asset_volume",
                              "taker_buy_quote_asset_volume",
                              "ignore"], dtype="float64") \
          .assign(open_time=lambda interval: pd.to_datetime(interval.open_time, unit="ms"),
                  close_time=lambda interval: pd.to_datetime(interval.close_time, unit="ms")) \
          .set_index("close_time")
Candlestick and Volume chart

If you don’t require fine-grained data on every single trade, then this might be more appropriate.


To receive updates on more posts like this, follow me on Twitter and GitHub!

Appendix

I - Import statements

import requests

import numpy as np
import pandas as pd

import matplotlib.pyplot as plt
import mplfinance as mpf
import seaborn as sns
Louis Tiao
Louis Tiao
PhD Candidate

Thanks for stopping by! Let’s connect – drop me a message or follow me:

comments powered by Disqus