
I’ve implemented the backtesting functionality in the Telegram trading bot. To achieve this, I had to change the underlying architecture. Previously, the bot used the synchronous version of the python-telegram-bot library, but it now requires the asynchronous version. I have updated all the code accordingly to support this change.
Quick jump:
If you are installing the project for the first time, no additional steps are required. Installing the dependencies via requirements.txt using PIP will automatically retrieve the correct version. However, if you have previously installed an older version of the bot, you will need to upgrade. I have specified the required version explicitly within the requirements.txt file.
python-telegram-bot==20.7
apscheduler==3.10.4
numpy==1.26.3
If you try to install the pinned libraries using PIP, it will not automatically upgrade existing versions. You need to include the -U option to ensure they are updated.
EODHDAlerts % python3 -m pip install -r requirements.txt -U
Recap
Before we get into the coding, I thought it would be useful to provide a quick recap of where things currently stand.
The bot is started like this…
EODHDAlerts % python3 ./bot.py
INFO:root:Bot Started: Type /start in Telegram trading bot channel.
Bot Started: Type /start in Telegram trading bot channel.
INFO:apscheduler.scheduler:Adding job tentatively -- it will be properly scheduled when the scheduler starts
INFO:apscheduler.scheduler:Added job "analyse_market" to job store "default"
INFO:apscheduler.scheduler:Scheduler started
You will know it’s working if in your Telegram bot channel you see this when you send the /start command.

If you see “Welcome to the Trading Bot!”, it means that Python has successfully connected to Telegram, as that message is sent by the bot.
The bot has two main components: the push, which involves sending market data signals to the channel, and the pull, which handles receiving commands from Telegram users.
For the pull functionality, in bot.py you will see the following…
# Register all command handlers
dp.add_handler(CommandHandler("start", start))
dp.add_handler(CommandHandler("set_symbol", set_symbol))
dp.add_handler(CommandHandler("set_interval", set_interval))
dp.add_handler(CommandHandler("get_price", get_price))
dp.add_handler(CommandHandler("list_strategies", list_strategies))
dp.add_handler(CommandHandler("set_strategy", set_strategy))
dp.add_handler(CommandHandler("current_strategy", current_strategy))
These are the registered commands you can send to the bot from Telegram. They are all fairly self-explanatory, but I’ll demonstrate how they work. I’ve already shown you /start. Now let’s take a look at /set_symbol.

You can change the market to any of the EODHD API stock codes. Now let’s change the interval. I’m going to set it to a low value so I can try to generate a buy or sell signal to demonstrate how it works.

The Python bot console will show you what is happening in the background. At the moment, we are retrieving the Apple (AAPL.US) 1-minute intraday OHLCV data.

We are currently waiting for a market signal to trigger, but in the meantime, you can see the bot in action by requesting the current price for the selected symbol (market) using the /get_price command.

It was a bit tricky to demonstrate the bot in action, as I usually work on this over the weekend when the markets are closed. However, I did manage to catch a sell signal to show you. I also wanted to give you better visibility into what’s happening in the background, so I added a debug option. The command is called /debug.

If you look under the “Current price”, you’ll see that the last trading candle on Friday (yesterday) was a sell signal. I then enabled debug mode, and you can observe that the bot continues to indicate a sell signal every minute. However, this is only because no new data is coming in. I didn’t want the bot to be completely silent during this time, so with debug mode enabled, you can now see that although the last candle is still a sell, the bot recognises that it has already alerted you and therefore won’t take any further action.
Now for the part I’m excited to show you — the backtesting functionality.
I didn’t just want it to backtest your current strategy. I wanted to make it more generic to work on any of the supported options.
Backtesting
I’m going to show you how to list the currently supported strategies, and then run a backtest on the BTC-USD market using all of the available options.

It’s worth mentioning that I wouldn’t expect an SMA strategy on a 1-minute interval for Bitcoin to be profitable. This is purely to demonstrate the bot’s mechanics, not to showcase a winning strategy. That was the “sma” option — now let’s try the others.


Interestingly, I would have expected all the strategies to perform poorly using a 1-minute interval. However, the RSI14 strategy actually performed slightly better than a coin toss. It would be interesting to see whether applying this strategy to longer intervals might improve the win/loss ratio — I’ll leave that for you to experiment with.
It’s also worth pointing out that the bot does not currently factor in exchange fees. EODHD APIs are not tied to any specific exchange. A potential future enhancement could be to add a command allowing users to apply a buy and/or sell fee. This would make the backtest results more realistic, as many strategies that seem marginally profitable would actually result in a net loss once fees are accounted for.
The bot has been designed to be highly customisable. You can add any strategy, provided the dataset includes the required “position” and “signal” fields. More advanced logic can also be used to combine strategies, as long as the bot is able to interpret the resulting signals.
Hopefully I’ve made it clear how to add your own commands and handlers. If you think of any useful commands, you should find it straightforward to implement them.
As for next steps, adding persistence to the configuration would be useful. It would allow the bot to remember the selected market, strategy, and interval, and use them as defaults when it restarts.
Another potentially useful feature would be the ability to browse the markets supported by the EODHD API directly via Telegram. I’ve demonstrated examples using AAPL.US and BTC-USD.CC, but there are many more available. Adding a command to list the available markets could be an interesting and helpful enhancement.