Writing crypto trading bot in Python with Telegram and ccxt

Maksim Avdyushkin
6 min readMay 22, 2018

--

Hello, this s my first ever programming blog post and I am super excited to post more in the future.

How it started

Recently I have been interested (read speculating) in shorting and longing crypto during highly volatile periods, which is pretty much every single day. I found it is time consuming to monitor price and then click buttons on the exchange, wait for the order to complete, and then create another one. I also found that mobile app for the exchange I am using sucks and it takes forever to place an order on the phone. I decided to create a simple bot that allows to do short and long trades using Telegram for interactions.

If you can not wait to get the code, here is the GitHub link

I personally only needed two operations:

  1. Short trade — sell holding currency at specified price and buy back when price drops
  2. Long trade — buy currency at specified price and sell it when price goes up

In addition, I decided to add two more: list open orders and show available balance

Set up telegram bot

I assume you already have Telegram account, otherwise go and create one. Now we can use https://web.telegram.org/ web interface to create our bot. Start a chat with BotFather and type /newbot. Follow instructions and record your token.

Getting API keys for exchange

Check your exchange documentation. You will need read and edit access to orders as well as read balance. I will be using bitfinex for this example. Record your secret and api keys.

Dependencies and design

I used Python 3.6, but I am sure you can adapt it to older versions and even to python 2. One of the great features in 3.6 is f-Strings and it is one of my favourite.

Many exchanges allow API access and there is a great library that allows to write the same code no matter what exchange is used. We are going to use that to implement our own exchange abstraction. Instead of implementing a specific logic for each exchange with different APIs we will use ccxt that will work for majority of exchanges (list of supported exchanges).

We will use python-telegram-bot for communicating with Telegram, reacting to chat messages, and scheduling trades.

There are only two dependencies:

$ pip install python-telegram-bot ccxt

Main classes that we need for the trading bot are:

  1. Exchange abstraction that allows to create orders, list orders, get the balance. This will be a wrapper for ccxt exchange
  2. Trade executor since we want short and long trades be executed automatically
  3. Telegram bot that will respond to requests

Coding the bot

Let’s start with project structure:

main.py
\config
\core
\model
\util

We will begin with a simple model. We will be doing long and short trades and both have a lot in common. Create a base class TradeDetails in \model:

And concrete LongTrade and ShortTrade respectively:

Next comes the exchange abstraction:

We then implement trade executor. The executor will take our exchange and timeout to check for order completion. When shorting we sell at set price and buy back when price drops to a certain level. For long it is the same in opposite order. I coded methods using asyncio coroutines so that waits don’t block:

For order waiting we will simply fetch order details and compare for status changes. Note that ccxt uses REST API for most exchanges. It is not as fast as WebSockets which some exchanges support. For this bot the speed is not that important.

Next comes the meat: Telegram bot. That was the most challenging part for me. The commands that we will aim for:

  1. List/cancel active orders
  2. Show free balance
  3. Create long or short trade

We also want to restrict our bot so it only reacts to your messages and someone else is not able to do trades using your exchange account.

The tricky part is to model the flow of questions for long and short trades:

  1. Choose short/long
  2. Enter coin name
  3. Enter amount
  4. Percent change
  5. Price per 1 unit
  6. Show confirmation
  7. Finally process trade

The steps for listing balance, showing active orders are more straight forward.

Let’s create telegrambot.py and add constants that we will use when writing handlers:

SELECTION = "selection"SHORT_TRADE = "short_trade"
LONG_TRADE = "long_trade"
OPEN_ORDERS = "open_orders"
FREE_BALANCE = "free_balance"
CANCEL_ORD = "cancel_order"
PROCESS_ORD_CANCEL = "process_ord_cancel"
COIN_NAME = "coin_select"
PERCENT_CHANGE = "percent_select"
AMOUNT = "amount"
PRICE = "price"
PROCESS_TRADE = "process_trade"CONFIRM = "confirm"
CANCEL = "cancel"
END_CONVERSATION = ConversationHandler.END

We can implement restrictions based on user_id by extending BaseFilter. Our bot needs to accept telegram token, id of allowed user and trade executor.

In _prepare() we will create all our handlers and attach it to dispatcher. We want to show basic options when we start chat with the bot:

InlineKeyboardButton allows us to show text options as , you might guess it, a keyboard. This is more intuitive than typing all commands. callback_data allows to pass additional data when button is pressed. show_options returns name of the next handler to continue conversation. Similar approach will be used for other handlers. We then implement processing of user selection. Here we mostly move from one question to another:

Lastly we build our conversation handler, set error hander, and add all handlers to the dispatcher.

We apply private filter to conversation entry point. Note that we pass user data, option that allows us to provide additional user_data argument to handlers. This ensures that bot maintains conversation state with all answers when it is passed from one handler to another.

We need run_async decorator to execute trades in background without blocking the bot from listening to new messages:

And here is formatter for order and balance display:

Finally, let’s create main.py and glue everything together:

We get our exchange keys, Telegram token and user id from secrets.txt, construct our core classes and start the bot. Create secrets.txt in config folder with following content:

# YOUR_API_KEY
# YOUR_SECRET
# YOUR_TELEGRAM_TOKEN
# YOUR_TELEGRAM_USER_ID

Now we are ready to try our bot in action!

Starting message
Long trade example

Full code on GitHub

Conclusion

This bot is more of a helper tool for someone who wants to simplify trading and have better experience using the phone. It is not a state of art algorithmic trading bot.

I’ve skipped a lot of things in this guide, but here are possible improvements:

  1. When doing a short trade fetch available balance and display it back, also show max value that user can short based on the balance
  2. Validation of created order before asking to execute it on the exchange. This was not an issue for me as the bot only reacting my private messages
  3. Adding TA indicators, signals to inform of best time to trade or to recommend whether the timing is good
  4. Keeping profit/loss and other statistics
  5. Having strategy to cancel order based on something like a timeout

If you enjoyed the story or found it useful click 👏 button. I am looking forward to share more interesting things I’ve been working on. Let me know in comments if you want to know more or to explore other topics in more details!

--

--

Maksim Avdyushkin

Software Engineer. Speed Learner. I love difficult challenges and elegant solutions