How to Build a Crypto Trading Bot for Binance (Using Python)
Binance and trading bots.
The world hasn’t seen a more iconic duo since Bert and Ernie. The legendary exchange has been flooded with automated trading bots of all kinds. Institutions and high net worth individuals are executing advanced algorithmic trading strategies while investors are automating their portfolio. It has become an exciting playground for builders.
Yet, there is still a lot to build. Only a fraction of the necessary services have been developed up until this point and there will be a lot of growth in the coming year.
If you want to get started participating in the development of trading bots, this is the best place to start. Throughout this article, we will teach you how to access market data from the exchange, connect to exchange accounts to read balance data, execute trades, chart candlesticks, and even connect to real-time websockets for ticker data.
There is a lot to cover, so let’s get started!
Getting Started
The following steps will break down the necessary components to begin programming your Binance Python scripts.
Installing Shrimpy Python
First, we will need to install the Shrimpy Python Library. The official Shrimpy Python GitHub can be found here.
Using Pip, you can quickly install the library using the following.
pip install shrimpy-python
Binance API Keys
In order to connect to the Binance exchange, we will need to generate a new API key through the exchange. This can be done by following the Binance API Key Help Article.
After you get to the step where you copy the API keys out of Binance, you can stop and store them in a secure place (instead of pasting them into the Shrimpy Portfolio Management Application). These keys will be used in our scripts by assigning them to a variable that we can pass into our client when it’s created.
exchange_public_key = '...'
exchange_secret_key = '...'
Shrimpy API Keys
After the exchange API keys have been created, we must also generate API keys for the Shrimpy Universal Crypto Trading APIs. These keys are generated by signing up for the Shrimpy Developer APIs then following the guide outlined here.
Once the keys have been created, store them in a secure location and use them in your Python scripts in the following way.
shrimpy_public_key = '...'
shrimpy_secret_key = '...'
Exchange Data
Getting accurate market data is the first step to creating a crypto trading bot that can execute strategies based on signals, market conditions, and price movements.
This is typically done using both live order book data and trade data. In the following sections, we will provide examples of how to collect both of these types of information through websockets and REST APIs.
Price Ticker
A price ticker is something that updates the price on a consistent basis in order to get the latest price of the asset on an exchange. The following examples will present a couple of examples of how to create and access price tickers.
A Simple Price Ticker
This example will provide a script for the most simple kind of price ticker. This ticker will use REST API calls to access pricing data on the exchange. This endpoint updates on a 1-minute interval, so that means the highest possible frequency for updating the ticker in this example is 1-minute.
import shrimpy
# Assign public and secret Shrimpy Master API Keys
shrimpy_public_key = '...'
shrimpy_secret_key = '...'
# Create the Shrimpy REST API client
client = shrimpy.ShrimpyApiClient(shrimpy_public_key, shrimpy_secret_key)
# Request the ticker for all assets on Binance
ticker = client.get_ticker('binance')
Websocket Price Ticker
More complex than the simple price ticker is the real-time websocket ticker. This ticker leverages the real-time websockets to stay updated with the latest price on the exchange.
Unlike the simple price ticker that is updated on a 1-minute interval, this price ticker will be updated instantly. As soon as the price changes on the exchange, the websocket will send the update and the new price will be received by this script to display.
import shrimpy
shrimpy_public_key = '...'
shrimpy_secret_key = '...'
# This is a sample handler, it simply prints the incoming message to the console
def error_handler(err):
print(err)
# This is a sample handler, it simply prints the incoming message to the console
def handler(msg):
print(msg['content'][0]['price'])
# Create the websocket client using the raw token retrieved by the REST API
api_client = shrimpy.ShrimpyApiClient(shrimpy_public_key, shrimpy_secret_key)
raw_token = api_client.get_token()
client = shrimpy.ShrimpyWsClient(error_handler, raw_token['token'])
# The subscription data for the websocket
subscribe_data = {
"type": "subscribe",
"exchange": "binance",
"pair": "eth-btc",
"channel": "trade"
}
# Start processing the Shrimpy websocket stream!
client.connect()
client.subscribe(subscribe_data, handler)
# Once complete, stop the client
client.disconnect()
Exchange Order Books
Precise order books on an exchange are used by traders and crypto bots to determine the exact order they would like to place on the exchange.
When placing orders, it is always beneficial to have real-time updates to the order book. That way you are always making decisions based on the most up-to-date information.
Simple Live Order Book Snapshot
The most simple way to get access to an exchange’s order books is to request the order book at the time you are going to place an order.
For example, if you want to execute a trade on the ETH/BTC trading pair, you can request to get the latest order book for this market by calling into the REST API.
import shrimpy
shrimpy_public_key = '...'
shrimpy_secret_key = '...'
# Create the API client for REST calls
client = shrimpy.ShrimpyApiClient(shrimpy_public_key, shrimpy_secret_key)
# Retrieve the live order book
orderbooks = client.get_orderbooks(
'binance', # exchange
'ETH', # base_symbol
'BTC', # quote_symbol
10 # limit
)
Websocket Live Order Book
In more advanced scenarios, it would be ideal to maintain a local copy of the order book that is updated in real-time through websockets. This can be done using the order book websocket available through the websocket APIs.
Connecting to the ETH/BTC pair would look something like the following example.
import shrimpy
shrimpy_public_key = '...'
shrimpy_secret_key = '...'
# This is a sample handler, it simply prints the incoming message to the console
def error_handler(err):
print(err)
# This is a sample handler, it simply prints the incoming message to the console
def handler(msg):
print(msg)
# Create the websocket client by getting the raw token.
api_client = shrimpy.ShrimpyApiClient(shrimpy_public_key, shrimpy_secret_key)
raw_token = api_client.get_token()
ws_client = shrimpy.ShrimpyWsClient(error_handler, raw_token['token'])
subscribe_data = {
"type": "subscribe",
"exchange": "binance",
"pair": "eth-btc",
"channel": "orderbook"
}
# Start processing the Shrimpy websocket stream!
ws_client.connect()
ws_client.subscribe(subscribe_data, handler)
# Once complete, stop the client
ws_client.disconnect()
Notice that this example does not describe how to manage the order book locally, but only how to access the data through the websocket. The organization of data would need to be done through custom code based on how you want to manage the books.
Essentially, managing the books will require a way to keep track of the current state of the book. That way you can insert new orders, update old orders, and delete orders as necessary based on the updates through the websocket.
Exchange Account Connectivity
In order to trade, we need access to an exchange account. This exchange account will be used to collect data on the available balances and execute the trading strategy.
Linking a Binance Account
Shrimpy provides a convenient user management system where you can link individual Binance accounts to users. Each user can maintain up to 20 exchange accounts. That way, all of your exchange accounts can be managed together.
Linking an exchange account to Shrimpy is a one-time event. That means once the account has been linked, Shrimpy will maintain the connection to the exchange for that account and not require re-linking in the future. You can always get your linked accounts by listing the accounts that have been connected to a user.
In this example, we will create our first user, then link the exchange account. Once you create your first user, you do not need to create another user again. You can always access your users by listing the users you have created.
# import required libraries
import shrimpy
# assign your Shrimpy Master API keys for later use
shrimpy_public_key = '...'
shrimpy_secret_key = '...'
# assign your exchange keys for which you wish to access the balance data
exchange_name = "binance"
exchange_public_key = '...'
exchange_secret_key = '...'
# create the Shrimpy client
client = shrimpy.ShrimpyApiClient(shrimpy_public_key, shrimpy_secret_key)
# create a user which will be linked to our exchange
create_user_response = client.create_user('The Shrimp Master')
user_id = create_user_response['id']
# link our first exchange so we can access balance data
link_account_response = client.link_account(
user_id,
exchange_name,
exchange_public_key,
exchange_secret_key
)
account_id = link_account_response['id']
Retrieving Binance Account Balances
As soon as the account has been linked, Shrimpy will begin collecting data from the exchange regarding the exchange account. This can take up to 5 seconds, so we recommend waiting a few seconds (only for the initial linkage) before using the next script to access the balance data for the exchange account that was linked.
After the data has been collected, Shrimpy will continuously update the balance as trades are executed, deposits or withdrawals are made, and other operations are done on the account.
In this example, we demonstrate how to retrieve the Binance account balance.
import shrimpy
# use your Shrimpy API public and private keys to create the client
shrimpy_public_key = '...'
shrimpy_secret_key = '...'
client = shrimpy.ShrimpyApiClient(shrimpy_public_key, shrimpy_secret_key)
# note: since we created a user in our last example script,
# we can just retrieve our list of users.
users = client.list_users()
first_user_id = users[0]['id']
# retrieve the accounts associated with this user
accounts = client.list_accounts(
first_user_id
)
first_account_id = accounts[0]['id']
# access balance data for the user account you previously created
balance = client.get_balance(
first_user_id, # user_id
first_account_id # account_id
)
Notice how we used the endpoints to “list users” and “list accounts”. If you already have the account and user IDs, you can simply input those values as well without retrieving them every time.
Executing a Trade on Binance
Exchanges can be complicated. Confusing documentation, inconsistent trading rules, and discrepancies across endpoints can cause the development process to be chaotic.
In the following examples, we will break down some of the most simple ways to execute trades on Binance. Without any complex logic, Shrimpy can help you execute an order on every major exchange in an identical way.
Simple Trade
The most simple way to execute a trade with Shrimpy is to use the “Create Trade” endpoint. All this endpoint requires is the relevant account IDs and the two assets you will trade “from” and “to”.
It will look something like the following.
create_trade_response = client.create_trade(
user_id, # The ID of the user
account_id, # The ID of the account linked to the user
from_symbol, # The asset you want to sell
to_symbol, # The asset you want to buy
from_native_amount # How much of the "from" asset you want to sell
)
The result is a simple way to buy and sell assets without worrying about the specifics of how the trades are executed. You don’t need to place individual limit orders, determine different trading pairs, or manually route the assets through different quote currencies. Shrimpy will take care of everything.
We can then put this endpoint to work by putting it into an example script. In this example, we will examine all of the assets you hold on the exchange. We will then iterate over the list of assets you own and sell all of them to a consolidation asset (in this case BTC).
STOP! Running this script will literally sell everything you own on the exchange and buy BTC. This is not a hypothetical script, this is a real example that executes real trades on your real exchange account. Don’t run the script if you don’t want to sell everything you own to Bitcoin.
import shrimpy
# Use your Shrimpy API public and private keys to create the client
shrimpy_public_key = '...'
shrimpy_secret_key = '...'
client = shrimpy.ShrimpyApiClient(shrimpy_public_key, shrimpy_secret_key)
# Note: since we created a user in our last example script,
# We can just retrieve our list of users.
users = client.list_users()
first_user_id = users[0]['id']
# Retrieve the accounts associated with this user
accounts = client.list_accounts(
first_user_id
)
first_account_id = accounts[0]['id']
# Access balance data for the user account you previously created
balance = client.get_balance(
first_user_id, # user_id
first_account_id # account_id
)
holdings = balance['balances']
# Select the asset for which you would like to consolidate
consolidation_symbol = 'BTC'
# Sell every asset besides the consolidation asset
for asset in holdings:
asset_symbol = asset['symbol']
asset_amount = asset['nativeValue']
if asset_symbol != consolidation_symbol:
print('Selling ' + str(asset_amount) + ' of ' + asset_symbol)
create_trade_response = client.create_trade(
first_user_id,
first_account_id,
asset_symbol,
consolidation_symbol,
asset_amount
)
Smart Order Routing
In the previous example, we did not use any intelligent routing. Essentially, Shrimpy will identify the “from” and “to” asset, then sell the “from” asset to BTC, then buy the “to” asset from BTC. This can be inefficient if there are alternative quote currencies that the asset could utilize.
In many cases, using the smart order routing option would be ideal. This simple flag tells Shrimpy to evaluate every possible route when deciding how we should trade the “from” asset and acquire the “to” asset.
import shrimpy
# Use your Shrimpy API public and private keys to create the client
shrimpy_public_key = '...'
shrimpy_secret_key = '...'
client = shrimpy.ShrimpyApiClient(shrimpy_public_key, shrimpy_secret_key)
# Note: since we created a user in our last example script,
# We can just retrieve our list of users.
users = client.list_users()
first_user_id = users[0]['id']
# Retrieve the accounts associated with this user
accounts = client.list_accounts(
first_user_id
)
first_account_id = accounts[0]['id']
# Access balance data for the user account you previously created
balance = client.get_balance(
first_user_id, # user_id
first_account_id # account_id
)
# Execute a market order
smart_order_response = client.create_trade(
first_user_id, # user_id
first_account_id, # account_id
'BTC', # from_symbol
'ETH', # to_symbol
'0.01' # amount of from_symbol
True # enable smart_routing
)
Notice how the only difference is the extra flag in the request for enabling smart routing and setting it to “True”.
Charting Candlesticks
Building an application with a user interface means we will need other components to illustrate the current state of the market to users. One example of data the user may wish to receive is candlestick charts.
Candlestick charts help traders decide when they should buy or sell an asset.
Shrimpy provides access to free endpoints for accessing real-time candlestick data. Every time a new trade is executed on the exchange, the candlesticks are updated in real-time. These candlesticks can then be polled on a regular interval in order to display them in the user interface in your application.
In the following example, we will poll the latest candlesticks for the ETH/BTC trading pair on the Binance exchange. This same endpoint can be used for every other major exchange, so there is no difference between using Binance and other exchanges.
import shrimpy
import plotly.graph_objects as go
shrimpy_public_key = '...'
shrimpy_secret_key = '...'
# Collect the historical candlestick data
client = shrimpy.ShrimpyApiClient(shrimpy_public_key, shrimpy_secret_key)
candles = client.get_candles(
'binance', # exchange
'ETH', # base_trading_symbol
'BTC', # quote_trading_symbol
'1d' # interval
)
dates = []
open_data = []
high_data = []
low_data = []
close_data = []
# Format the data to match the plotting library
for candle in candles:
dates.append(candle['time'])
open_data.append(candle['open'])
high_data.append(candle['high'])
low_data.append(candle['low'])
close_data.append(candle['close'])
# Plot the candlesticks
fig = go.Figure(data=[go.Candlestick(x=dates,
open=open_data, high=high_data,
low=low_data, close=close_data)])
fig.show()
Putting It All Together
There is only one thing left for us to do. That’s to put everything we’ve discussed so far together into a single script. This script will monitor the ticker for the BTC/USDT pair on Binance and execute a trade to sell all of your BTC when the value of BTC has gone above 10,000 USDT. This is a simple example of how you can combine the data from the websockets to execute a trading strategy.
import shrimpy
import time
shrimpy_public_key = '...'
shrimpy_secret_key = '...'
# Assign your exchange keys for which you wish to access the balance data
exchange_name = "binance"
exchange_public_key = '...'
exchange_secret_key = '...'
# Create the websocket client
api_client = shrimpy.ShrimpyApiClient(shrimpy_public_key, shrimpy_secret_key)
raw_token = api_client.get_token()
ws_client = shrimpy.ShrimpyWsClient(error_handler, raw_token['token'])
# Create a user which will be linked to our exchange
# Skip this step (or use the "list users" endpoint) if you've already created a user
create_user_response = api_client.create_user('The Shrimp Master')
user_id = create_user_response['id']
# Link our first exchange so we can access balance data
# Skip this step (or use the "list accounts" endpoint) if you've already linked an account
link_account_response = api_client.link_account(
user_id,
exchange_name,
exchange_public_key,
exchange_secret_key
)
account_id = link_account_response['id']
# Wait while Shrimpy collects data for the exchange account
# Only required the first time linking
time.sleep(5)
# Access balance data for the user account you previously created
balance = api_client.get_balance(
user_id, # user_id
account_id # account_id
)
btcAmount = 0
for asset in balance['balances']:
if asset['symbol'] = 'BTC':
btcAmount = asset['nativeValue']
# This is a sample handler, it simply prints the incoming message to the console
def error_handler(err):
print(err)
# This is a sample handler, it simply prints the incoming message to the console
def handler(msg):
price = msg['content'][0]['price']
if int(price) > 10000:
smart_order_response = api_client.create_trade(
user_id, # user_id
account_id, # account_id
'BTC', # from_symbol
'USDT', # to_symbol
btcAmount # amount of from_symbol
True # enable smart_routing
)
subscribe_data = {
"type": "subscribe",
"exchange": "binance",
"pair": "btc-usdt",
"channel": "trade"
}
# Start processing the Shrimpy websocket stream!
ws_client.connect()
ws_client.subscribe(subscribe_data, handler)
Conclusions
Armed with these scripts, it’s possible to build any number of exciting trading bots on Binance. As you explore more things about trading and the Shrimpy Trading APIs, you may find other useful endpoints, like the limit order endpoints. These give you finer control over the orders that you place on the exchange.
We encourage everyone to explore everything that we offer and make suggestions in our Developer Telegram. The cryptocurrency market is exciting and this is just the beginning of a new way to trade assets.
Shrimpy is an application for constructing custom cryptocurrency index funds, rebalancing, and managing a diverse portfolio of digital assets. Automate your portfolio by linking to any of the 16 crypto exchanges we support.
Shrimpy’s Universal Crypto Exchange APIs are designed for developers. Integrating with our unified APIs gives you instant access to uniform endpoints for trading, data collection, user management, and more across every major cryptocurrency exchange.
To access the complete Python and Node libraries, follow these links: