Website Logo
/ blog / components-of-a-market-making-bot

Components of a Market Making Bot

Introduction

I love software development. One of my favourite parts of building any somewhat large and complex blob of software is breaking the problem, with all of its complexity and requirements, into a bunch of smaller simple parts that work harmoniously together.

Knowing when to create a new component is sometimes clear and obvious. Other times it's hard and nigh-impossible to see without attempting to solve the problem first. Defining the 'scope' of a component - the 'bounds' of its interface - is like trying to define borders between countries on a map. Sometimes, as with Australia's border, it's relatively simple: "The whole island is one country!". But sometimes components are complex, and responsibilities blur between them, sparking endless debate about what should belong to what, more like the borders of India and Bangladesh.

Components often start simple, and grow and grow until they birth many more components that perform functionality whose necessity slowly reveals itself as niche edge-cases appear.

I enjoy thinking about the best way to separate things, because a loosely-coupled system lowers the cognitive load of working on a component and makes life easier. I also like to share how I compose these components (as I did in this post), because if you have an idea of the components required to solve a problem, that's a significant amount of the problem already solved.

A Market Maker Bot

One system I wrestled with all 2025 was a market making bot. I'm going to assume knowledge of limit order books for the rest of this piece, so if you don't know what they are, read up on them. In a nutshell, a market making bot is a computer program that can quickly post many limit orders in an order book so if people want to buy or sell something on an exchange, there is a seller/buyer waiting for them! How convenient! The reason someone might want to do this is because if you sell potatoes at $11 and buy them at $10, you can make a small profit from the difference in prices. Also, exchange fees are significantly smaller for maker orders than for taker orders - sometimes they're even negative! - so if you're looking to move into a position, it is more cost effective to use maker orders instead of taker orders.

In practice this "market making" is anything but simple, and "what price should something be?" is an unsolvable problem that has nerd-sniped millions of smart people throughout history, whose time may have potentially been better spent doing something else.

Additionally, since "trading" is a zero sum game, and there is only so much volume for market makers to compete for, nobody in the market making business ever spills the beans on the best way to do things. If you're doing something smart and it's making money, you don't share how you're doing it, otherwise your competition will copy you and you won't make money any more! Consequently, it feels like there is more secrecy in the trading industry than all others and I think that's a real shame.

I'm going to share a map of some of our components anyway. For a few reasons:

So with that out of the way, let's get on with the show:

The Components

I'm a visual learner, so here is a diagram showing a bunch of components, and arrows between them showing "data flow".

A draw.io diagram with a whole bunch of boxes and arrows between them.

Now let's explore the roles and responsibilities of these components one-by-one!

The Engine

The largest component of all, the "engine", is the giant component that contains all other components. The jobs of the engine are:

Initialisation alone is hard. You don't want to start placing orders before you can calculate the price you want to quote at. You might only know that price when you've connected to internal services and received your balances, limits, current prices, current volatility, etc, etc, etc. Initialisation will most likely have a critical order in which it occurs, because different components rely on others. These dependencies form a sort of graph!

It's also important to gracefully handle exceptions. Because there will be exceptions, and you should restart gracefully and send logs to wherever your logs are stored so they can be carefully analysed at a later date.

Now that I've talked about the engine, I've decided a sensible order to attack the remaining components is from left to right. These components will tell the tale of "how to calculate a price to quote at". I will leave the egress gateway and breakers till last.

Reference Pricer

A reference pricer is a module that gives you a price of some pair. For example, BTC:USDT = $100,000. How it gets this though, that'll depend on how you decide to do it! Here are some ideas for different types of ReferencePricers:

The two objectives of this module are:

1: Give you a price. 2: Be generic so it can be swapped out easily.

Price Graph

The job of the price graph is to:

Market Pricer

The job of the market pricer is to calculate the price of an asset in units of another asset. BTC in units of USDT for example. It might seem like a good idea to build this into the price graph at first glance, but there are many different ways calculate a market price. Do you prioritise prices from one exchange? Average them together? Something fancy with AI? Keeping the market pricer away from the price graph allows it to be tested, optimised, and swapped out separate to the price graph.

It's also critical that this run as fast as possible. You're going to be re-calculating the price you're interested in, every time any price changes. This can easily be many hundreds of times each second so you're going to want to benchmark and optimise it.

Perp Parameters

If you're market making any sort of cryptocurrency, you're probably trading perpetual futures (perps) as well as spot. After all, why trade bitcoin when we can trade pretend bitcoin with extra math to make life harder! As such, you're going to want another module that can use the price graph to calculate important information about these contracts like the basis and index offset. If you want to make funding rate trades, or react to events like exchanges exploding, you'll want access to these features.

Quote Model Manager

The jobs of the quote model manager are:

You might have different quote model managers that set different prices and quantities. For example you may want:

Quote Model

The "Quote Model" is a state machine that manages the state of a single quote. It receives generic messages from the ingress gateway, and sends generic messages to egress gateway.

Examples of generic messages you could receive:

Examples of generic messages you could send:

This is the heart of the trading engine where "what you could do" is decided. Consequently there are a bunch of fun design decisions that are made here. Things like:

Obviously it's important that this component perform correctly, but also the messaging protocol between the quote model and the ingress gateway is very important too. Different exchanges have different intricacies, and if you can make the quote model generic to work for as many as possible, that'll save a lot of work.

This component also manages the difference between "target" prices, and actual acceptable prices. Limit order books have both minimum tick sizes and minimum lot sizes. This means if your target price is $12.345, but the exchange only accepts orders at $12.34 and $12.35, you'll have to decide which of these to quote at.

Another duty of this component is to manage how closely the target price should be followed. How far should the current price deviate from the target price before you change the price of the order? The lower the allowed deviation, the more accurate your prices are, and the less chance you'll get picked off. But you'll send more messages, exhausting your rate limit which increases your chances of getting picked off when it actually matters! Another tough problem!

Also it's important that this component be fast, because if you want to quote 3 levels on each side of a price, you'll need 6 separate state machines!

Egress Gateway

This is where your exchange specific implementations of your custom gateway protocol will live. For each exchange you want to communicate with, you'll have to create, test, and wrestle any exchange-specific quirks into another egress gateway implementing your generic messaging interface.

Spread Model

The spread model is the first component that doesn't tightly lie in the critical path of the trading application. If you're market making, you're quoting on both sides of the price, and the difference between your buy and sell prices is the "spread". The job of the spread model is to answer the question: "How wide should the spread be?". This could be as simple as: "A constant 10 basis points!" but when the market is volatile and everyone else pulls back, you'll probably wish you were doing something fancier.

Limits and Deltas

Another critical piece of information you'll want is: "How much of asset X and Y do I have?", and "How much of asset X and Y do I want to have?". You'll probably want to store and update your balances in a central location, and your targets or limits are probably based off risk, or some trading strategy you want to implement. These are probably also stored in some other services that your bot will want to communicate with.

Breakers

Lastly, another nice feature for a trading bot to have is a simple on/off switch. It's turned on manually, and it's flicked off when breakers are tripped. Breakers can be tripped on any logic you want, but a fairly sensible starting point is "More than X dollars traded in Y time". This system can be connected to a paging system and external dashboards. Starting and stopping trading are very common actions, and you want to make them as easy as possible to perform.

Conclusion

Even the most complex systems can be broken down into a number of simple components!

I hope this information helps inform future decisions. It might give you fantastical ideas for new components, neat separation of responsibilities, or simply lead to the conclusion that building a decent trading system is a huge undertaking!