How to code your own crypto trading bot using Python (GitHub repo included)

CyberPunkMetalHead
8 min readApr 15, 2021

--

In the following article I will be showing you how to build your first automated cryptocurrency trading algorithm, as well as the resources that you will require. I will also post a link to the GitHub Repo at the end of the article, so you can grab the code without copy-pasting from here.

What is a cryptocurrency trading bot?

Trading bots, or trading algorithms are programs designed to automatically place trading positions on your behalf, and operate on a series of pre-define parameters. These parameters can also be referred to as the logic which drives buy or sell signals of the bot. In the stock market world, the use of trading bots is referred to as High Frequency Trading and usually require access to low-latency data centres in order to compete in an already over-saturated market.

By comparison, the Crypto market is much younger and due to the blockchain, there are less barriers to entry when it comes to creating a bot which can compete against the bigger players in the market.

Why you should consider building one?

  • We are in a unique position to learn the early movements of the crypto-market with no barriers, and all of the tools at our disposal.
  • The crypto market never sleeps — it operates 24/7. A crypto trading algorithm can help fill in the gaps for you.
  • No emotions — personally the biggest reason for myself. I am all too familiar with buying high and selling low.
  • It’s a great learning experience and introduces you the world of algo trading.
  • It’s cool.

Defining parameters

For this example, our bot will be trading Bitcoin automatically if the price has increased by more than 3% in the last 10 minutes.

We will have a stop loss of 5% and take profit of 8%.

Later on, you can choose to further optimise your bot and include additional features such as trailing stop loss and close signals — but for now we’ll keep it simple.

Identifying a test platform

Your next goal should be finding a platform that allows you to open a demo account. Demo accounts provide you with “fake” or virtual currency that you can use to test your bot with. You don’t want to give it your own money before you have a good understanding on how it performs. Most crypto trading bots in Python will require multiple amends and testing phases before you can even consider backing it up with actual money, so it’s important to start off with a platform that enables you to test your bot in a safe environment.

My recommendation is to start with MetaTrader5. MT5 is a free-to-use platform that which allows you to perform technical analysis, trading operations and best of all — it integrates well with Python! It’s important to note that MT5 is not a broker, but a platform that allows you to chose which broker you would like to use.

Binance can also be used for algorithmic cryptocurrency trading, however the set-up process for the test environment is a task in and of itself and this will be covered this in a future blog post. For the purpose of building and testing your cryptocurrency bot, MT5 will serve you well, so long as you pick the right broker.

There are only a handful of Brokers that support both MT5 and cryptocurrency trading, but after some research I came across one that suited my needs quite well. XBTFX has the most crypto-currency trading pairs available on MT5, so it was naturally the best choice. As we will only be testing (at least in the beginning), we’re not too concerned with the fees and commissions.

Once you’ve downloaded and installed MT5, head over to File and select “Open an Account”. Search for XBTFX, select it and press next.

If you’ve signed up to XBTFX using the referral link above, you will have to Connect with an existing trade account. Otherwise select “Open a demo account to trade virtual money without risk”. Take note of the user ID given to you — you will need this in Python.

Setting up your crypto bot environment

First you will need to install the MetaTrader5 module using pip. So fire up your console (cmd if you’re on Windows) and type in the following commands:

pip install MetaTrader5pippip install — upgrade MetaTrader5

In your Python file, you need to connect to your new demo account. You can do this by adding the following code in. More in-depth explanation on the code of this bot is available in my YouTube video.

from datetime import datetime
from itertools import count
import time
import MetaTrader5 as mt5CRYPTO = 'BTCUSD'# Price threshold (percentage)
PRICE_THRESHOLD = 3
# Stop loss (percentage)
STOP_LOSS = 5
# Take profit (percentage)
TAKE_PROFIT = 8
# Replace in line 113 to choose between a BUY or SELL order
BUY = mt5.ORDER_TYPE_BUY
SELL = mt5.ORDER_TYPE_SELL
ORDER_TYPE = BUY
# connect to the trade account without specifying a password and a server
mt5.initialize()
# account number in the top left corner of the MT5 terminal window
# the terminal database password is applied if connection data is set to be remembered
account_number = 555
authorized = mt5.login(account_number)
if authorized:
print(f'connected to account #{account_number}')
else:
print(f'failed to connect at account #{account_number}, error code: {mt5.last_error()}')

Have a look at the PRICE_THRESHOLD, STOP_LOSS, TAKE_PROFT and ORDER_TYPE variables.

These are your configuration options that allow you to set different parameters for the bot.

The ORDER_TYPE variable allows you to switch from a BUY order to a SELL order for additional testing. As mentioned the Edit above, some people wanted to test how the bot would perform if it sells right after a spike instead of buying.

Next, we want to store the account’s equity inside a global variable. This will enable you to specify later how much % of your equity should go in every trade. For this bot, we’ll stick to 5% of your available equity per trade.

# store the equity of your account
account_info = mt5.account_info()
if account_info is None:
raise RuntimeError('Could not load the account equity level.')
else:
equity = float(account_info[10])

Importing data

Now that the inital set-up is in place we need to import and store the dataset that we’ll be working from. As we’re only interested in price of the last two 10 minute candles, we’ll only import 1 day’s worth of data. Other crypto trading bots may require a much larger dataset to work from.

We’ll use 3 functions — one where we define the dates for our dataset, another where we import the data and a third function for the latest bid and ask prices.

def get_dates() contains several global variables that will need to be accessed in other functions.

def get_dates():
"""Use dates to define the range of our dataset in the `get_data()`."""
today = datetime.today()
utc_from = datetime(year=today.year, month=today.month, day=today.day - 1)
return utc_from, datetime.now()

def get_data() will import our data in 10 minute candle timeframes:

def get_data():
"""Download one day of 10 minute candles, along with the buy and sell prices for bitcoin."""
utc_from, utc_to = get_dates()
return mt5.copy_rates_range('BTCUSD', mt5.TIMEFRAME_M10, utc_from, utc_to)

def get_prices()

def get_current_prices():
"""Return current buy and sell prices."""
current_buy_price = mt5.symbol_info_tick("BTCUSD")[2]
current_sell_price = mt5.symbol_info_tick("BTCUSD")[1]
return current_buy_price, current_sell_price

Defining the logic and placing a BUY order

Now that our data is imported, we can check whether the price has increased by more than 3% in the last 10 minutes by defining a simple equation in the difference variable. Positions will inform our crypto trading algorithm if there is another active trade placed on BTCUSD.

This next block of code is longer than the previous ones and has thus been broken down into smaller chunks, to allow for explanations where relevant. Please note that it is part of the same function so please apply the name indentation when copying it over to your editor.

Defining the main variables and performing the logic check

Logic check

The logic check is quite straightforward — the crypto bot will check if the difference is greater than 3, sleep for 8 seconds and then check again. During my testing it turned out that sometimes there can be a temporary spike up, followed by an immediate correction.

This in turn triggered the bot to open a trade and almost instantly hit the stop loss.

Feel free to test and adjust the duration of the time.sleep(8).

def trade():
"""Determine if we should trade and if so, send requests to MT5."""
utc_from, utc_to = get_dates()
candles = get_data()
current_buy_price, current_sell_price = get_current_prices()
# calculate the % difference between the current price and the close price of the previous candle
difference = (candles['close'][-1] - candles['close'][-2]) / candles['close'][-2] * 100
# used to check if a position has already been placed
positions = mt5.positions_get(symbol=CRYPTO)
orders = mt5.orders_get(symbol=CRYPTO)
symbol_info = mt5.symbol_info(CRYPTO)
# perform logic check
if difference > PRICE_THRESHOLD :
print(f'dif 1: {CRYPTO}, {difference}')
# Pause for 8 seconds to ensure the increase is sustained
time.sleep(8)
# calculate the difference once again
candles = mt5.copy_rates_range(CRYPTO, mt5.TIMEFRAME_M10, utc_from, utc_to)
difference = (candles['close'][-1] - candles['close'][-2]) / candles['close'][-2] * 100
if difference > PRICE_THRESHOLD:
print(f'dif 2: {CRYPTO}, {difference}')
price = mt5.symbol_info_tick(CRYPTO).bid
print(f'{CRYPTO} is up {str(difference)}% in the last 5 minutes opening BUY position.')
# prepare the trade request
if not mt5.initialize():
raise RuntimeError(f'MT5 initialize() failed with error code {mt5.last_error()}')
# check that there are no open positions or orders
if len(positions) == 0 and len(orders) < 1:
if symbol_info is None:
print(f'{CRYPTO} not found, can not call order_check()')
mt5.shutdown()
# if the symbol is unavailable in MarketWatch, add it
if not symbol_info.visible:
print(f'{CRYPTO} is not visible, trying to switch on')
if not mt5.symbol_select(CRYPTO, True):
print('symbol_select({}}) failed, exit', CRYPTO)
#this represents 5% Equity. Minimum order is 0.01 BTC. Increase equity share if retcode = 10014
lot = float(round(((equity / 20) / current_buy_price), 2))

# define stop loss and take profit
if ORDER_TYPE == BUY:
sl = price - (price * STOP_LOSS) / 100
tp = price + (price * TAKE_PROFIT) / 100
else:
sl = price + (price * STOP_LOSS) / 100
tp = price - (price * TAKE_PROFIT) / 100

request = {
'action': mt5.TRADE_ACTION_DEAL,
'symbol': CRYPTO,
'volume': lot,
'type': ORDER_TYPE,
'price': price,
'sl': sl,
'tp': tp,
'magic': 66,
'comment': 'python-buy',
'type_time': mt5.ORDER_TIME_GTC,
'type_filling': mt5.ORDER_FILLING_IOC,
}
# send a trading request
result = mt5.order_send(request)
# check the execution result
print(f'1. order_send(): by {CRYPTO} {lot} lots at {price}')
if result.retcode != mt5.TRADE_RETCODE_DONE:
print(f'2. order_send failed, retcode={result.retcode}')
#print the order result - anything else than retcode=10009 is an error in the trading request.
print(f'2. order_send done, {result}')
print(f' opened position with POSITION_TICKET={result.order}')
else:
print(f'BUY signal detected, but {CRYPTO} has {len(positions)} active trade')
else:
pass
else:
if orders or positions:
print('Buying signal detected but there is already an active trade')
else:
print(f'difference is only: {str(difference)}% trying again...')

Putting it all together

The script above will work yes — but it will only execute once! Which doesn’t help very much. Luckily, automating this is rather easy. Just add the snippet below and you’re good to go.

if __name__ == '__main__':
print('Press Ctrl-C to stop.')
for i in count():
trade()
print(f'Iteration {i}')

You should now have a functioning cryptocurrency algorithmic trading bot that detects sharp spikes in Bitcoin price. Give it a test and, please comment with your results and ideas for improvements!

Considerations

During my testing it turned out that the trading bot underperformed on bitcoin, however it actually performed quite well on XLM.

The main limitation that I came across is the lack of a viable exit strategy, so if you can think one, please share it with me.

Additional Resources

If you found this article useful please subscribe and share this article!

--

--

CyberPunkMetalHead
CyberPunkMetalHead

Written by CyberPunkMetalHead

x3 Top Writer and co-founder of Algo Trading Platform AESIR. I write about crypto, trading, tech and coding.

No responses yet