Licensed image from Adobe Stock

So we want to create a Telegram trading not, but where do we start? I guess the logical first step is explaining what Telegram is.

Register & Get Data

What is Telegram?

Telegram is a cloud-based messaging service renowned for its speed, security and generous features including one-to-one chats, large group “supergroups”, public channels, voice and video calls, and file sharing up to 2 GB. What really sets Telegram apart are its freely available, well-documented APIs: the Bot API for creating chatbots and mini-apps; the MTProto API and TDLib for building full-fledged third-party clients; and the Gateway API for sending verification codes. This openness has fostered a vibrant ecosystem of bots, custom clients and integrations without fees or restrictive approvals.

By contrast, WhatsApp and Viber limit developers to business-oriented offerings. WhatsApp’s proprietary Business API is only accessible through approved providers, requires paid templates and enforces strict session rules, while Viber’s RESTful Bot API permits only automated public accounts rather than custom apps or clients. In short, Telegram’s open, cost-free APIs give developers far more flexibility than the more controlled, enterprise-focused platforms of WhatsApp and Viber.

The first step is to download Telegram. For the purpose of this tutorial it doesn’t matter what platform you use. Whether you use the Desktop version or Mobile versions, it doesn’t matter.

Create a Telegram bot

At this stage, we are just creating a generic bot. We will be creating a trading bot but this is the first step you’ll do to create any bot. I like to use BotFather for this. Click on the link and click “Start Bot”.

You will need to send the message /newbot to BotFather and follow the prompts. You will need to give your bot a name. I used “EODHDAlerts” for example. You also need to assign a username to your bot. I used “eodhdalerts_bot”.

Make a note of your <YOUR_TOKEN>. You will need it in the next step. We will call it TELEGRAM_BOT_TOKEN in the config.py.

The next step to retrieve your Client ID is not a simple task! It catches a lot of people out. You won’t be able to retrieve the Client ID until you have sent at least one message to the bot. This is a crucial step which many miss which causes a lot of confusion. Open your bot, in my case https://t.me/eodhdalerts_bot.

**IMPORTANT** – Send at least one message to your newly created bot E.g. “hello”

Browse to https://api.telegram.org/botYOUR_TOKEN/getUpdates. Please note you need to put <YOUR_TOKEN> above instead of “YOUR_TOKEN” in bold in the URL. This will show you all the messages that have been sent to the bot. You need to make note of the “id” which we will use in the next section. We will call it TELEGRAM_CHAT_ID in the config.py.

Before you move onto the next section, make sure you have your token and client ID. This will be known as TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID in the config.py.

Key Features

When creating our Telegram trading bot we are looking at creating two core features…

  1. Demonised service that will retrieve and process historical market data using EODHD API’s historical data. As part of the processing, a trading strategy will be applied to the data identifying the buy and sell signals. When a buy or sell signal event happens the bot will send a message to the bot Telegram group letting the subscribers know they will probably want to place an order if they agree with the timing. Don’t place trades blindly. Use some common sense and your own analysis to before you carry out a trade action. We will refer to this feature as a “Push”, as in the bot is pushing data to the you.
  2. We will probably want a “Pull” as well. As in we sent a command to the bot via the Telegram channel. For example, a /get_price may be a helpful command.

This tutorial will explain how the bot framework will be setup and how to get the base functionality working. The following articles will delve deeper into more specialist Push and Pull functionality and features.

Open Source Project

I understand that EODHD API’s are interested in creating an open source project for this. I think it’s a great idea and a nice way to involve the community. When I created PyCryptoBot, over 50 volunteers contributed to the project from various backgrounds. Some were pure devs, some were skilled traders, some were just enthusiasts with great ideas. At one stage over 1000 people were speaking about the project around the clock. Hopefully this is the start of an exciting project. I’ve put the initial code for this project here.

The Code

I’m not going to explain all the code in low detail but highlight some important parts. Happy to receive feedback if there are any parts that could be explained in more detail but hopefully with some knowledge of Python, APIs, and EODHD APIs, you should be okay.

The first essential file to understand, which isn’t included in the repo, is the config.py. Create this file and include your EODHD_API_TOKEN (used to retrieve the historical data), TELEGRAM_BOT_TOKEN (which we extracted earlier), TELEGRAM_CHAT_ID (which we extracted earlier), and the other variables are parameters for the historical data processing and simple moving average (SMA) strategy.

# config.py

EODHD_API_TOKEN = "<REMOVED>"
TELEGRAM_BOT_TOKEN = "<REMOVED>"
TELEGRAM_CHAT_ID = "<REMOVED>"
DEFAULT_SYMBOL = "AAPL.MX"  # BTC-USD.CC 
DEFAULT_INTERVAL = "d"  # 1m, 5m, 1h, d, w, m
SHORT_WINDOW = 20
LONG_WINDOW = 50

The main file that runs is the bot.py. This is the daemon service that retrieves and processes the historical market data, sends messages to the bot channel, and received commands from the channel to execute. You will see below that I’ve created /start, /set_symbol, /set_internal, and /get_price to start with.

# bot.py

from telegram.ext import Updater, CommandHandler
from config import TELEGRAM_BOT_TOKEN
from handlers import start, set_symbol, set_interval, get_price, analyse_market
from telegram.ext import JobQueue


def main():
    updater = Updater(TELEGRAM_BOT_TOKEN)
    dp = updater.dispatcher

    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))

    job_queue: JobQueue = updater.job_queue
    job_queue.run_repeating(analyse_market, interval=60, first=0)

    updater.start_polling()
    updater.idle()


if __name__ == "__main__":
    main()

I’ve created a few classes using SOLID principles. DataFetcher in data_fetcher.py which handles the data retrieval from EODHD APIs, SMACrossoverStrategy in strategy.py which is a basic strategy to demonstrate the Telegram bot, TelegramNotifier in telegram_notifier.py which handles sending messages to the Telegram bot channel (“the Push“). The last file to mention is the handlers.py which isn’t a class but contains all the functions responsible for commands sent to the bot by users. It’s hopefully self explanatory what is happening below. This is a work in progress and will be build upon in future articles.

# handlers.py

from telegram import Update
from telegram.ext import CallbackContext
from config import DEFAULT_SYMBOL, DEFAULT_INTERVAL
from data_fetcher import DataFetcher
from strategy import SMACrossoverStrategy
from telegram_notifier import TelegramNotifier

symbol = DEFAULT_SYMBOL
interval = DEFAULT_INTERVAL


def start(update: Update, context: CallbackContext):
    update.message.reply_text("Welcome to the Trading Bot!")


def set_symbol(update: Update, context: CallbackContext):
    global symbol
    if context.args:
        symbol = context.args[0]
        update.message.reply_text(f"Symbol set to {symbol}")
    else:
        update.message.reply_text("Please provide a symbol.")


def set_interval(update: Update, context: CallbackContext):
    global interval
    if context.args:
        interval = context.args[0]
        update.message.reply_text(f"Interval set to {interval}")
    else:
        update.message.reply_text("Please provide an interval.")


def get_price(update: Update, context: CallbackContext):
    fetcher = DataFetcher(symbol, interval)
    price = fetcher.fetch_price()
    if price:
        update.message.reply_text(f"Current price of {symbol}: {price}")
    else:
        update.message.reply_text("Failed to fetch data.")


def analyse_market(context: CallbackContext):
    fetcher = DataFetcher(symbol, interval)
    data = fetcher.fetch_ohlc()
    if data.empty:
        return
    strategy = SMACrossoverStrategy(short_window=20, long_window=50)
    signals = strategy.generate_signals(data)
    latest_signal = signals["position"].iloc[-1]
    notifier = TelegramNotifier()

    if latest_signal == 1:
        notifier.send_message(f"Buy signal for {symbol}")
    elif latest_signal == -1:
        notifier.send_message(f"Sell signal for {symbol}")

Hopefully this has been a clear and useful introduction to the project. You should be able to clone the repo, and add the config.py, and it should just work.

If you have any ideas or suggestions where this project can go, or would like to contribute, do get in touch!

Do you enjoy our articles?

We can send new ones right to your email box