Crypto Bot Binance + Telegram
Write your own alert bot for any type of trading or investing with C# in one day for free.
I’ve made a simple alert bot that tells me when to buy or sell with my investing strategy. It works like a charm and now I’m going to tell you how to do it by yourself.
If you haven’t read my research article about trading bots, here you go: https://stannotes.com/get-rich-with-trading-bots-3e033fc96f0b
Disclaimer: I hope that you’re familiar with the language you’re going to write the bot with. It’s an intermediate tutorial, not for beginners.
Step 1. Choose Trading Style
This is important. You have to choose what your alert bot has to do. We’re not writing an automatic trading system (I’ll write about it a bit later), but just a smart notifier.
We have the following simple trading styles:
- Daytrading. The great thing, that you have to review your telegram a few times a day and check your bot’s alerts, open your brokerage account to put an order, and not lose a chance to close an order. So this style is 50–50.
- Investing. Most a wonderful and beautiful style for the alert bot. I’ve chosen this way. It just tells you once a week or even a month (usually) to open order or not.
- Swing trading. Usually, it depends only on closing or not your order. It’s a similar style to investing, but you have to write your own exit strategy.
- S̶c̶a̶l̶p̶i̶n̶g̶. I won’t consider this style, but you know, it exists. As we’re writing alert bot, you won’t be able at most cases react too quickly and it’ll be a lose scenario at 95%
Step 2. Setup Environment
I see how many people use Python for developing their bots, but I have my experience in Game Development (mostly) and .Net Development. So it’s familiar for me to write code using C#. In fact, you may use any language, but examples of code I’ll show you with C#.
I’ll set up a console environment to put it on the server (how to deploy your bot on the server I’ll share in future posts, so stay tuned).
First things first. I’m going to select New Project in my Rider and set up the .Net Console Application.
Now we need to install a few dependencies from NuGet. I’ve chosen the following packages:
- Binance.Net — for fetching market data in real-time;
- Skender.Stock.Indicators — for the best way to convert market data into the strategy. It has great documentation though;
- Telegram.Bot — for notifying.
Now, this is the time to set up a telegram bot.
Step 3. Telegram Bot.
Find BotFather in Telegram and use it to create your brand new bot.
Just type /newbot to create a new bot, give it a great name and username. Then you’ll have your token, we’ll use it when start building our application.
Now, we’re well prepared to begin.
Step 3. Binance Key & Secret
Now we need to get our key & secret for application from Binance. You’ll have to have your Binance account ready and prepared. After logging in to your account, at the right top corner open up the profile menu and find “API Management” button. It’s available on this page at the time of writing: https://www.binance.com/en/my/settings/api-management
Inside the opened page find the input field “Label API”, type in some great name, and hit the “Create API” button.
You’ll see something like this below:
Copy Secret Key somewhere, as it will disappear and won’t be shown later! If you lost your secret key, you’ll have to create a new API key. We don’t need anything else from this point, so let’s go to the code!
Step 4. Basic Architecture
Here we go. Let’s start by writing a basic Binance service to allow fetching any market data for a given ticker name.
We need to create a new class, let’s call it BinanceService (as simple as we can imagine). Let it be a lazy singleton as we want to store only one instance at a time, it’s just only our bot, no one will use it.
public class BinanceService
{
private static readonly BinanceService Instance = new();
private BinanceClient _binanceClient = new(); public static BinanceService GetInstance() => Instance;
}
You can see that I use BinanceClient which is the Binance API’s main class, don’t forget to include the needed namespace (I won’t be posting namespaces here, to keep the guide as simple as possible, but make sure to add namespaces with your IDE).
Now, let’s define the “Initialize” method, to initialize credentials using key and secret from the previous step.
public void Initialize(string key, string secret)
{
BinanceClient.SetDefaultOptions(new BinanceClientOptions
{ApiCredentials = new ApiCredentials(key, secret)});
BinanceSocketClient.SetDefaultOptions(new BinanceSocketClientOptions
{ApiCredentials = new ApiCredentials(key, secret)});
}
Here we just set up API credentials for simple and socket clients (for streaming data).
Now we may set up another script for Telegram messaging. Let’s create another singleton and call it TelegramService, the structure is similar to the Binance service, so let’s just copy the same code and refactor it a little.
The final code is here:
public class TelegramService
{
private static readonly TelegramService Instance = new();
public static TelegramService GetInstance() => Instance;
public TelegramBotClient BotClient { get; set; }
public void Initialize(string key)
{
BotClient = new TelegramBotClient(key);
}
public async Task SendMessage(long accountId, string message)
{
await BotClient.SendTextMessageAsync(accountId, message, ParseMode.Markdown);
}
}
Here we have the same initialization way, create a new Client instance, which is TelegramBotClient. And a new method SendMessage, which will help us to send messages through the bot asynchronously, so that won’t prevent the analysis to continue.
Step 5. Alert Bot Algorithm
Here we’re going to implement our bot’s algorithm. Which is simply the strategy of our bot. Let’s take the simplest trading strategy of moving average reversal. It will trade on a 1-minute timeframe to show us the first results in a short period of time (swing trade would require at least a 1-hour timeframe).
The idea of the strategy is to add two smoothed moving averages (SMMA), with length properties of 21 and 200 respectively. The bot will send us signals when the lines are crossed.
At first, we have to read the latest data from the chosen ticker. As we need 200 candles for measuring the longest SMMA, we need at least 1000 (for getting a good result from high volatility and don’t miss those moves (1k 1m candles is about 16 hours). The guide for indicators you may found at the official website: https://daveskender.github.io/Stock.Indicators/indicators/
So let’s write a method called GetMinuteCandles(ticker, candlesAmount) in our BinanceService class.
Here we have two ways of implementing the method, first is to connect to the streaming data of Binance, second is to check it with a timer every N minutes (hours/days/etc.).
Streaming would check every tick of the market movement. It’s useful for scalping or momentum trading, but not for a day or swing trading (until we want to catch big moves or avoid high losses), anyways, as this is not a guide about writing a bot with limit and stop orders, we will use a timer to update data for the last 1 minute (or hour, depending on your chosen timeframe).
It’s not so optimized to get 100+ market candles every minute, but it’s ok for our goal, for more optimization you may want to use caching.
public async Task<IEnumerable<IBinanceKline>> GetMinuteCandles(string ticker, int candlesAmount)
{
var klines = await _binanceClient.UsdFuturesApi.ExchangeData.GetKlinesAsync(
ticker,
KlineInterval.OneMinute,
limit: candlesAmount);
return klines.Data;
}
Here we fill out a simple method GetKlinesAsync which will send API requests to the Binance futures (!) server. Select appropriate market (futures or spot) depending on your trading symbols. As I’m trading mostly on the futures market, I’ll choose this one.
In this method we fill following parameters:
1. Ticker or symbol, we send it as our method’s parameter;
2. Timeframe or kline interval, we use one minute in this example;
3. Limit is how many candles we want to get, we pass it from our method’s parameters.
Now, let’s implement another class and call it BinanceAlertBotService, which is actually our algorithm, implement the basic initialization as in previous services. We may want to create a method of starting the bot and passing the needed ticker in there. I’ll show you the simplified version where we pass the needed ticker through the console in real-time.
public class BinanceAlertBotService
{
private static readonly BinanceAlertBotService Instance = new();
public static BinanceAlertBotService GetInstance() => Instance;
private Timer _timer;
private long _accountId = 0; //YOUR_TELEGRAM_ACCOUNT_ID_HERE private List<string> _watchlist = new(); public void Start()
{
_timer = new Timer(async state => await Update(state), null, 0, 45000);
}
}
Just a simple initializer that goes every 45 seconds (to make sure we won’t skip any minute because of an internet connection reset or something).
Now, let’s define an Update method, which will call updating candles, receive two SMMA and detect their crossing based on previous data.
Here is the code:
private async Task Update(object state)
{
foreach (var symbol in _watchlist)
{
var candles = await BinanceService.GetInstance().GetMinuteCandles(symbol, 1000);
var quotes = candles.Select(candle => new Quote
{
Close = candle.ClosePrice,
Date = candle.CloseTime,
High = candle.HighPrice,
Low = candle.LowPrice,
Open = candle.OpenPrice,
Volume = candle.Volume
});
// Measure two SMMA's for current and previous candles
var smmaShortLast = quotes.GetSmma(21).Last().Smma;
var smmaShortPrevious = quotes.GetSmma(21).SkipLast(1).Last().Smma;
var smmaLongLast = quotes.GetSmma(200).Last().Smma;
var smmaLongPrevious = quotes.GetSmma(200).SkipLast(1).Last().Smma;
// Detect reversal
var isCurrentLong = smmaShortLast > smmaLongLast;
var isPreviousLong = smmaShortPrevious > smmaLongPrevious;
if (isCurrentLong != isPreviousLong)
{
await TelegramService.GetInstance().SendMessage(_accountId,
$"Reversal for {symbol}. **{(isCurrentLong ? "Long" : "Short")}**");
}
}
}
First, we convert the IBinanceKline list to the Quotes list (for passing to the Indicators plugin), then we measure SMMA’s and then detect reversal with sending an appropriate message to our telegram (_accountId is our private telegram id stored somewhere or passed directly).
Step 6. Final Touch
As we’re writing a bot, not just an alert system, we will be able to write messages through telegram directly to our bot.
Let’s define Telegram handlers for messages coming from messenger, distribute them between appropriate methods in our bot. We will implement a few methods for managing new symbols on the watchlist.
Add needed receiving method to Initialize of TelegramService:
BotClient.StartReceiving(new DefaultUpdateHandler(HandleUpdateAsync, HandleErrorAsync), null);
And additional methods for handling coming messages and errors:
private Task HandleErrorAsync(ITelegramBotClient botClient, Exception exception, CancellationToken cancellationToken)
{
if (exception is ApiRequestException apiRequestException)
Console.WriteLine("BOT ERROR: " + apiRequestException);
return Task.CompletedTask;
}
private Task HandleUpdateAsync(ITelegramBotClient botClient, Update update, CancellationToken cancellationToken)
{
var message = update.ChannelPost ?? update.Message;
if (message != null && !string.IsNullOrEmpty(message.Text))
{
var messageText = message.Text;
if (messageText.ToLower().StartsWith("add "))
BinanceAlertBotService.GetInstance().AddTicker(messageText.Replace("add ", ""));
else if (messageText.ToLower().StartsWith("remove "))
BinanceAlertBotService.GetInstance().RemoveTicker(messageText.Replace("remove ", ""));
else if (messageText.ToLower() == "tickers")
BinanceAlertBotService.GetInstance().ShowTickers();
}
return Task.CompletedTask;
}
In HandleUpdateAsync we’re looking for three commands, “add”, “remove” and “tickers”. The “Add” command will add a ticker to the watchlist, the “remove” command will remove a ticker, and the “tickers” will show the whole watchlist.
Corresponding methods for BinanceAlertBotService:
public async void AddTicker(string ticker)
{
_watchlist.Add(ticker);
await TelegramService.GetInstance().SendMessage(_accountId, "Added new ticker");
}
public async void RemoveTicker(string ticker)
{
_watchlist.Remove(ticker);
await TelegramService.GetInstance().SendMessage(_accountId, "Removed ticker");
}
public async void ShowTickers()
{
await TelegramService.GetInstance().SendMessage(_accountId, $"Tickers: \n{string.Join('\n', _watchlist)}");
}
And the last but not least, initialization in our Program class:
public class Program
{
private const string BinanceKey = "YOUR_BINANCE_KEY";
private const string BinanceSecret = "YOUR_BINANCE_SECRET";
private const string TelegramKey = "YOUR_TELEGRAM_KEY";
public static readonly ManualResetEvent ResetEvent = new(false);
static void Main(string[] args)
{
TelegramService.GetInstance().Initialize(TelegramKey);
BinanceService.GetInstance().Initialize(BinanceKey, BinanceSecret);
BinanceAlertBotService.GetInstance().Start();
ResetEvent.WaitOne(); // Wait for app closing
}
}
Conclusion
If we run our program, we may talk directly to our bot:
As soon as it gets to SMMA’s cross, we will get the next message:
The whole code you may check on my GitHub repo here: https://github.com/StanKryvenko/binance-alert-bot
Feel free to write your questions and subscribe to my social media:
Twitter: sgkryvenko
Instagram: stan.kryvenko
LinkedIn: sgkryvenko
Ten articles before and after
Monitoring Ethereum Wallets with Python & Telegram – Telegram Group
How I made +25% in few hours with the help of trading bot! – Telegram Group
How Telegram Makes Money? Telegrams New Plan to Generate Cash – Telegram Group
How to Install and Run the Crypto-Telegram Bot – Telegram Group
Using Github Actions, Python and Telegram to Get Ribeye Specials – Telegram Group
Confbot Open source. Hace un tiempo comencé a desarrollar… – Telegram Group
How to enable comments in Telegram channel – Telegram Group
TON history. Telegram’s blockchain project, the TON… – Telegram Group