Coding a Cryptocurrency Trading Bot that detects and buys new coins the moment they are listed on Binance
Have you noticed how many new coins tend to skyrocket temporarily the moment they are added to the Binance Exchange? Wouldn’t it be great if you could take advantage of that initial pump? This open source crypto trading bot that I’ve been working on aims to do just that. The bot scans the Binance exchance and buys a coin as soon as it’s been listed on Binance.
It’s fresh out of the oven so I’m pretty excited to see how it performs, and it comes with all the bells and whistles: from trailing stop loss to test mode and more.
Requirements for the Binance Trading Bot
- A Binance account (obviously)
- Some python skills
- A bit of time
Making a start
First things first, if you don’t have a Binance account, or would like to create a separate account to run the bot on, go ahead and create one here . You can use my referral link to get 5% off your trading fees. With a Binance account created, we’re going to Generate some API Keys.
To get your mainnet keys, navigate over your account, and click on API management.
On the API management page, give a label to your API key and click create API.
Once your key and secret have been generated make sure to save these, as you will only be shown the secret once. You’ll need to regenerate your keys if you haven’t saved the secret.
Now let’s give it the permissions that we require to run the bot on it. We’re only going to do Spot trading, so we only need to select Enable Reading and Enable Spot & Margin Trading.
Coding the crypto trading bot
First of all, I’ve open sourced the code and it’s available on GitHub, if you would like to have a look yourself or simply download the source. Keep on reading to understand how it works.
Install dependencies
pip install python-binance
pip install pyaml
The easiest way to do so is to launch your cmd/terminal and run the following commands using pip. Note that on Macs you may have to use pip3 instead.
Naturally, you need to have pip and python already installed on your machine.
Create credentials file
— -
# CLIENT DETAILS
binance_api: “BINANCE_API_KEY”
binance_secret: “BINANCE_SECRET”
Create a directory called auth and inside this directory create a new .yml file called auth.yml. Inside the file,, duplicate the exact format below and replace the dummy text with your Binance actual key and secret. The crypto trading bot will need those in order to place trade on the Binance exchange.
Create an authentication file
In the same directory, go ahead and create a new file called binance_auth.py we’re going to use this file to connect to the Binance client via the Binance API. The crypto trading bot needs access to the Binance API in order to place trades and read the account activity.
import yamlfrom binance.client import Client
from binance.exceptions import BinanceAPIExceptiondef load_binance_creds(file):
with open(file) as file:
auth = yaml.load(file, Loader=yaml.FullLoader)return Client(auth[‘binance_api’], auth[‘binance_secret’])
Create a config file
This is the file that tells our trading bot what to do, and how to trade. We’re going to create a few configurable options so that we can optimise our strategy. In the main directory (a level up from the auth directory) create a config.yml file like so:
Have a look at the comments for more details regarding each config option.
— -
TRADE_OPTIONS:
# In your pairing coin
QUANTITY: 15
# BTCUSDT will be bought for example
PAIRING: USDT
# How often to check for posts and run the script
# in minutes
RUN_EVERY: 0.3
# Test mode, set to false to use the live Binance account
TEST: True
#Stop loss in %
SL: 3
# Take profit in %
TP: 9
# Enable Trailing Stop Loss
ENABLE_TSL: True
# Trailing Stop in % from the current price
TSL: 0.5
# Trailing profit in % from the current price
TTP: 1
Load Config
Let’s create a file that will help us load the configuration that we just created and call it load_config.py
import yamldef load_config(file):
with open(file) as file:
return yaml.load(file, Loader=yaml.FullLoader)
Store orders
In order to be able to keep track of our orders and order details such as the price, time, volume and symbol, every trade we make must be logged in a local file. Your live trades will appear on the Binance reports, but test trades won’t, so a local file is the best way to keep track of test mode gains and losses. Go ahead and create a store_order.py file in the main directory The functions below will help us load and store both test and live trades.
import jsondef store_order(file, order):
“””
Save order into local json file
“””
with open(file, ‘w’) as f:
json.dump(order, f, indent=4)def load_order(file):
“””
Update Json file
“””
with open(file, “r+”) as f:
return json.load(f)
Create a trade client
The purpose of this file is to help perform two important operation for our crypto trading bot. Therefore it contains two functions that will be called in the main file. The first function will convert the volume of our paired coin to that of the coin we’re about to buy. If you remember the configuration options under the config file, you’ll recall an option called PAIRING. This tells our trading bot what to pair the base asset with. For example if pairing is set to USDT the bot will only place trades on coinUSDT (ie: BTCUSDT).
The first function ensures that the volume of the trade in USDT is converted to its equivalent in the base asset. For example 15USDT would convert to around 0.000330 BTC — and this is the value that Binance needs to know in order to automatically place a trade for us. The second function creates an order request with the symbol-pair, volume and side (BUY or SELL).
In the main directory, create a file called trade_client.py and define the two functions like so:
from auth.binance_auth import *client = load_binance_creds('auth/auth.yml')def convert_volume(coin, quantity, last_price):
"""Converts the volume given in QUANTITY from USDT to the each coin's volume"""try:
info = client.get_symbol_info(coin)
step_size = info['filters'][2]['stepSize']
lot_size = {coin:step_size.index('1') - 1}if lot_size[coin] < 0:
lot_size[coin] = 0except:
pass# calculate the volume in coin from QUANTITY in USDT (default)
volume = float(quantity / float(last_price))# define the volume with the correct step size
if coin not in lot_size:
volume = float('{:.1f}'.format(volume))else:
# if lot size has 0 decimal points, make the volume an integer
if lot_size[coin] == 0:
volume = int(volume)
else:
volume = float('{:.{}f}'.format(volume, lot_size[coin]))return volumedef create_order(coin, quantity, type):
"""
Creates simple buy order and returns the order
"""
return client.create_order(
symbol = coin,
side = type,
type = 'MARKET',
quantity = quantity
)
The reason our conversion function looks a little more complex than you would probably expect is because Binance is quite particular with the format of the volume order. For example, while BTCUSDT can have an accuracy of up to 6 decimal points, many other coins have different step-sizes. For instance the accuracy for a XRPUSDT trade is only 1 decimal point (ie: 1.1). Sending a request on XRPUSDT with any other format (1.1000) would return an error.
Coding the crypto trading bot logic
This is it, now that we have all the necessary infrastructure it’s time to write the buy and sell logic, and execute it.
Inside our main directory we’re going to create a main.py file. The first step is to import all the files we’ve created and any other dependencies. and define our Binance client like so:
from trade_client import *
from store_order import *
from load_config import *from datetime import datetime, time
import timeimport json
import os.path# loads local configuration
config = load_config('config.yml')
Next, we’re going to write two functions. One that will return a list of all the tradeable coins on Binance, and a second functions that will return the list once again and also compare any differences between the two lists. If new coins are found in the second list, we’ll return those too.
def get_all_coins():
"""
Returns all coins from Binance
"""
return client.get_all_tickers()def get_new_coins(all_coins):
"""
Returns new coins and the new coin list
"""
all_coins_recheck = get_all_coins()
return [new_coins for new_coins in all_coins_recheck if new_coins['symbol'] not in [coin['symbol'] for coin in all_coins]], all_coins_recheck
Ok now we need a function for our trading bot to return us the latest price for a coin on Binance.
def get_price(coin, pairing):
"""
Get the latest price for a coin
"""
return client.get_ticker(symbol=coin+pairing)['lastPrice']
At this point we have all the necessary functions to buy, sell, perform logic trades and store any trade data that we want locally. All that’s left now is to bring all this together in a logical manner and execute the script.
We’re going to define a main() function, where we’re going to start by performing sell checks, and the moving into buy checks. This last block of code is significantly longer than what we’ve seen above, so spend some time and study the comments and logic behind it.
def main():
"""
Sells, adjusts TP and SL according to trailing values
and buys new coins
"""
# store config deets
tp = config['TRADE_OPTIONS']['TP']
sl = config['TRADE_OPTIONS']['SL']
enable_tsl = config['TRADE_OPTIONS']['ENABLE_TSL']
tsl = config['TRADE_OPTIONS']['TSL']
ttp = config['TRADE_OPTIONS']['TTP']
pairing = config['TRADE_OPTIONS']['PAIRING']
qty = config['TRADE_OPTIONS']['QUANTITY']
frequency = config['TRADE_OPTIONS']['RUN_EVERY']
test_mode = config['TRADE_OPTIONS']['TEST']all_coins = get_all_coins()while True:# check if the order file exists and load the current orders
# basically the sell block and update TP and SL logic
if os.path.isfile('order.json'):
order = load_order('order.json')for coin in list(order):# store some necesarry trade info for a sell
stored_price = float(order[coin]['price'])
coin_tp = order[coin]['tp']
coin_sl = order[coin]['sl']
volume = order[coin]['volume']last_price = get_price(coin, pairing)# update stop loss and take profit values if threshold is reached
if float(last_price) > stored_price + (stored_price*coin_tp /100) and enable_tsl:
# increase as absolute value for TP
new_tp = float(last_price) + (float(last_price)*ttp /100)
# convert back into % difference from when the coin was bought
new_tp = float( (new_tp - stored_price) / stored_price*100)# same deal as above, only applied to trailing SL
new_sl = float(last_price) - (float(last_price)*tsl /100)
new_sl = float((new_sl - stored_price) / stored_price*100)# new values to be added to the json file
order[coin]['tp'] = new_tp
order[coin]['sl'] = new_sl
store_order('order.json', order)print(f'updated tp: {round(new_tp, 3)} and sl: {round(new_sl, 3)}')# close trade if tsl is reached or trail option is not enabled
elif float(last_price) < stored_price - (stored_price*sl /100) or float(last_price) > stored_price + (stored_price*tp /100) and not enable_tsl:try:# sell for real if test mode is set to false
if not test_mode:
sell = create_order(coin+pairing, coin['volume'], 'SELL')print(f"sold {coin} at {(float(last_price) - stored_price) / float(stored_price)*100}")# remove order from json file
order.pop(coin)
store_order('order.json', order)except Exception as e:
print(e)# store sold trades data
else:
if os.path.isfile('sold.json'):
sold_coins = load_order('sold.json')else:
sold_coins = {}if not test_mode:
sold_coins[coin] = sell
store_order('sold.json', sold_coins)
else:
sold_coins[coin] = {
'symbol':coin+pairing,
'price':last_price,
'volume':volume,
'time':datetime.timestamp(datetime.now()),
'profit': float(last_price) - stored_price,
'relative_profit': round((float(last_price) - stored_price) / stored_price*100, 3)
}store_order('sold.json', sold_coins)else:
order = {}# store new coins and rechecked coins list here
new_coins, all_coins_recheck = get_new_coins(all_coins)# the buy block and logic pass
if len(new_coins) > 0:all_coins = all_coins_recheck
print(f'New coins detected: {new_coins}')for coin in new_coins:# buy if the coin hasn't already been bought
if coin['symbol'] not in order:
print(f"Preparing to buy {coin['symbol']}")price = get_price(coin['symbol'], pairing)
volume = convert_volume(coin['symbol']+pairing, qty, price)try:
# Run a test trade if true
if config['TRADE_OPTIONS']['TEST']:
order[coin['symbol']] = {
'symbol':coin['symbol']+config['TRADE_OPTIONS']['PAIRING'],
'price':price,
'volume':volume,
'time':datetime.timestamp(datetime.now()),
'tp': tp,
'sl': sl
}print('PLACING TEST ORDER')# place a live order if False
else:
order[coin['symbol']] = create_order(coin['symbol']+config['TRADE_OPTIONS']['PAIRING'], volume, 'BUY')
order[coin['symbol']]['tp'] = tp
order[coin['symbol']]['sl'] = slexcept Exception as e:
print(e)else:
print(f"Order created with {volume} on {coin['symbol']}")store_order('order.json', order)
else:
print(f"New coin detected, but {coin['symbol']} is currently in portfolio")else:
print(f"No new coins detected, checking again in {frequency} minute(s)..")time.sleep(60*frequency)if __name__ == '__main__':
main()
And there you have it, you should now be able to buy new coins just as they are being listed on the Binance exchange with this neat crypto trading bot. Good luck!
Originally published at https://www.cryptomaton.org on August 15, 2021.