DEV Community

Cover image for Trading Bot in C# — Part 1 — Basic Market Watching on Binance
Whale's Secret for Whale's Secret

Posted on • Edited on

Trading Bot in C# — Part 1 — Basic Market Watching on Binance

This blog post is part of a series on building a simple trading bot. In this blog post, we’ll cover how to connect to an exchange, get price data, and use a trading indicator to interpret that data. The next blog post will focus on adding a notification system, followed by a guide on executing trades based on the trading indicator.

Introduction

There are many forms of trading, each presenting unique opportunities and challenges. One question can be “What to trade?”. Here we have, for example, equities, commodities, currencies and crypto currencies. Then we may ask “How frequently?” and come out with scalping, day-trading, swing trading, positional trading. Another decision is to be made about the type of analysis to help us make decisions. Here we have technical analysis vs. fundamental analysis.

In this blog post and upcoming parts of the series, we will focus on automated crypto currency day-trading based on technical analysis. Today our bot we will just watch the market on the Binance exchange. Let’s get started!

Prerequisites

This blog post requires basic knowledge of .NET and the trading bot is written in C#. To communicate with Binance, we will use Whale’s Secret ScriptApiLib which translates exchanges’ APIs into nice and simple API for you.

Create New Console Application

Using command-line interface, a new console application can be set up using:

dotnet new console --name MarketWatcher
cd MarketWatcher
dotnet add package WhalesSecret.ScriptApiLib
Enter fullscreen mode Exit fullscreen mode

Alternatively, you can do the same in your IDE. In Visual Studio, you can create a console application like this:

  1. Open Visual Studio, and select Create a new project in the start window.
  2. In the Create a new project window, select C# from the language drop-down list. Choose Console App from the project types list.
  3. In the Configure your new project window, type or enter MarketWatcher in the Project name box, and then select Next.
  4. On the next screen with Additional information, you can leave everything as is and just hit Create.
  5. Install WhalesSecret.ScriptApiLib NuGet package by clicking Tools → NuGet Package Manager → Manage NuGet Packages for Solution and then searching for WhalesSecret.ScriptApiLib.

Connect to Binance

To make it simple, we start working only with market data in this blog post. This means that for now, you don’t need any account on Binance as the data is publicly available. If we were to create, for example, a new order, we would need an exchange account. However, our first aim is to simply connect to a Binance exchange server. In your Program.cs file, add the following code:

using WhalesSecret.ScriptApiLib;
using WhalesSecret.TradeScriptLib.API.TradingV1;
using WhalesSecret.TradeScriptLib.API.TradingV1.MarketData;
using WhalesSecret.TradeScriptLib.Entities;
using WhalesSecret.TradeScriptLib.Entities.MarketData;

await using ScriptApi scriptApi = await ScriptApi.CreateAsync();

Console.WriteLine("Initializing Binance exchange.");

// Initialize information about various exchange assets and coins.
await scriptApi.InitializeMarketAsync(ExchangeMarket.BinanceSpot);

Console.WriteLine("Connecting...");

// Connect to the exchange without API credentials to work with market data.
ConnectionOptions options = new(ConnectionType.MarketData);
await using ITradeApiClient tradeClient = await scriptApi.ConnectAsync(ExchangeMarket.BinanceSpot, options);
Console.WriteLine("Connection succeeded!");
Enter fullscreen mode Exit fullscreen mode

The program terminates immediately after connecting to a Binance server.

Get Historical Price Data

At every moment, a list of bids and a list of asks together represent an order book snapshot. In other words, an order book snapshot is a list of buy and sell orders and a trade occurs when an existing buy order is matched with a sell order or vice versa.

Binance order book example

If we were to store all order book snapshots in full, we would need a lot of disk space as order books get changed every time a new order is added to the order book, or removed, or modified, or when orders are matched and a trade occurs.

However, this section is about historical prices, so why are order book snapshots important? We wanted to make it clear that while price is generally a very simple concept, in trading, it might be less clear. Suppose that somebody tells you that the price of BTC/USDT is $80,000. What does it actually signify? There are at least three possible interpretations:

  • the top order book bid, or
  • the top order book ask, or
  • the last trade’s execution price.

In trading, when we talk about price we always mean the last trade’s execution price. It is also beneficial to think in terms of price ranges. Candlestick charts effectively illustrate this concept by visually representing the price range of an asset over specific time frames. For example, on March 2nd 2025, a candlestick chart with the 1-day granularity reveals that:

  • The price of the asset at the beginning of the trading period was $86,064. This is called opening price.
  • The price of the asset at the end of the trading period was $94,270. This is called closing price.
  • The highest price reached during the trading period was $95,000. This is called high price.
  • The lowest price reached during the trading period was $85,050. This is called low price.

It was a day with great price volatility. Remember that you cannot predict the future with certainty — i.e. probability is in play.

While candlestick charts are useful by giving better understanding of price changes, they do not account for order sizes. Suppose that the BTC/USDT order book contains the top bid price $80,000 but the top bidder wants to buy just 0.0001 BTC, and the next best bid is for $79,000. If you are a seller and you intend to sell 1 BTC, then you would not receive $80,000 but only about $79,000 or less. Costly detail!

However, since candlesticks only reflect the actual price that was reached on the market (i.e. not only price of bids and asks but actual executed trades), they are, in a sense, more real than prices taken from order books. Moreover, each candle comes with a volume information, that is the amount that was traded within the candle’s period.

Candlestick Subscription with RSI

We want to monitor the price data and compute an indicator, such as the relative-strength index (RSI), on top of it.

To do this, we will create a candlestick subscription, get historical candles, and consume new candlestick updates.

await using ICandlestickSubscription subscription = await tradeClient.CreateCandlestickSubscriptionAsync(SymbolPair.BTC_USDT);

// Get historical candlestick data for the last three days for 1-minute candles.
DateTime endTime = DateTime.Now;
DateTime startTime = endTime.AddDays(-3);

CandlestickData candlestickData = await tradeClient.GetCandlesticksAsync(SymbolPair.BTC_USDT, CandleWidth.Minute1, startTime, endTime);
Enter fullscreen mode Exit fullscreen mode

Afterwards, one can use the data to compute the RSI values which tell you if the market is overbought, oversold, or whether you should wait patiently on. We will use Skender.Stock.Indicators library for calculating the indicator.

// Compute RSI using Skender.Stock.Indicators.
// Add the package to the project using "dotnet add package Skender.Stock.Indicators".
// Add "using Skender.Stock.Indicators;" to the source file.
List<Quote> quotes = new();
foreach (Candle candle in candlestickData.Candles)
    quotes.Add(QuoteFromCandle(candle));

Candle lastClosedCandle = subscription.GetLatestClosedCandlestick(CandleWidth.Minute1);

Console.WriteLine();
Console.WriteLine($"Last closed candle: {lastClosedCandle}");

ReportRsi(quotes);

// Loop until the program is terminated using CTRL+C.
while (true)
{
    Console.WriteLine();
    Console.WriteLine("Waiting for the next closed candle...");

    try
    {
        lastClosedCandle = await subscription.WaitNextClosedCandlestickAsync(CandleWidth.Minute1);
    }
    catch (OperationCanceledException)
    {
        break;
    }

    Console.WriteLine($"New closed candle arrived: {lastClosedCandle}");
    quotes.Add(QuoteFromCandle(lastClosedCandle));
    ReportRsi(quotes);
}

static void ReportRsi(IEnumerable<Quote> quotes)
{
    IEnumerable<RsiResult> results = quotes.GetRsi();
    RsiResult lastRsi = results.Last();

    string interpretation = lastRsi.Rsi switch
    {
        < 30 => " (oversold!)",
        > 70 => " (overbought!)",
        _ => string.Empty
    };

    Console.WriteLine($"Current RSI: {lastRsi.Date} -> {lastRsi.Rsi}{interpretation}");
}

static Quote QuoteFromCandle(Candle candle)
{
    Quote quote = new()
    {
        Date = candle.Timestamp,
        Open = candle.OpenPrice,
        High = candle.HighPrice,
        Low = candle.LowPrice,
        Close = candle.ClosePrice,
        Volume = candle.BaseVolume,
    };

    return quote;
}
Enter fullscreen mode Exit fullscreen mode

Output can then look like this:

Last closed candle: [Timestamp=2025-03-15 09:36:00,OpenPrice=83821.35000000,HighPrice=83821.35000000,LowPrice=83811.74000000,ClosePrice=83811.74000000,BaseVolume=3.45983000,QuoteVolume=289993.96687040,IsClosed=True]
Current RSI: 15.03.2025 9:36:00 -> 52.24205443879027

Waiting for the next closed candle...
New closed candle arrived: [Timestamp=2025-03-15 09:37:00,OpenPrice=83811.75000000,HighPrice=83854.53000000,LowPrice=83811.74000000,ClosePrice=83851.98000000,BaseVolume=26.12462000,QuoteVolume=2190256.94452210,IsClosed=True]
Current RSI: 15.03.2025 9:37:00 -> 58.320544966728924
Enter fullscreen mode Exit fullscreen mode

The code listing is a bit more complicated as it requires a conversion from Whale’s Secret data format to Skender.Stock.Indicators. Alternatively, one can compute it in C# without a new dependency. Be it as it may, the code simply waits for a new closed candle, computes RSI value and presents an RSI verdict. If the market is overbought, you might consider decreasing your position and similarly you might want to increase your position if the market is oversold.

Conclusion

In this blog post, a simple trading bot in C# was implemented and it can connect to Binance for you. Then the bot can fetch historical price data which can drive your trading strategies. An example of computing RSI signal values was shown to consider a buy or sell when market conditions seem right.

Disclaimer: The information provided in this blog post should not be considered financial advice. Always conduct your own research and consider your personal circumstances before acting on any financial information.

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.