Market making
Someone has to be willing to buy when you want to sell and sell when you want to buy. That's a market maker: it always shows a price on both sides and earns the difference. This page explains the economics, the risks, and two engineering bugs Prayog's own market maker had.
1. What a market maker does
It keeps quotes on both sides of the book: a bid (the price it will buy at) and an ask (the price it will sell at), usually several levels deep. Anyone who wants to trade right now can trade with it. It provides liquidity; the people who trade against it take liquidity.
Exchanges want market makers because a market with no one quoting is a market where nobody can trade. Many venues have formal programmes with obligations (quote a minimum size within a maximum spread for most of the day) and fee rebates in return.
2. A business example: the currency exchange booth
An airport currency booth shows two prices for dollars: "We buy at 82.10, we sell at 83.90". It doesn't care which way you trade; it earns ₹1.80 on every dollar that goes in and comes back out. Its risks:
- If everyone sells dollars to it and no one buys, it ends the day holding a pile of dollars (inventory). If the rupee strengthens overnight, those dollars are worth less.
- So when the pile grows, it lowers both prices: buying dollars less eagerly and selling them more cheaply until the pile shrinks (skew).
- If a customer knows something the booth doesn't ("the rate is about to jump"), the booth loses on that trade (adverse selection).
3. The spread pays
Buy at the bid, sell at the ask, keep the difference. If the market maker quotes 1,507.20 / 1,507.45 and both sides fill, it earns ₹0.25 per share. With thousands of round trips a day, tiny spreads add up. Competition between market makers pushes spreads down, which is good for everyone else.
4. Inventory risk and skew
Fills don't arrive in pairs. A run of sells against the market maker leaves it long, exposed to the price falling. The standard response is to move both quotes against the inventory:
center = fair_value - skew × inventory
bid = center - half_spread
ask = center + half_spread
Long inventory lowers the center: the ask becomes more attractive (inventory goes out), the bid less attractive (less comes in). A hard limit stops it adding to a position at all past a maximum.
5. Adverse selection
Noise traders trade for their own reasons; against them the market maker earns the spread. Informed traders trade because they know the price is about to move; they buy just before it rises. Every fill against an informed trader is a loss. The market maker's spread must cover its losses to informed flow, which is why spreads widen when news is likely (a volatile scenario) and why fast price updates matter.
6. Try it
A fair value wanders. A market maker quotes around it with your settings; traders arrive at random. Some are informed: they know where fair value will be a moment later. Watch the profit and the inventory.
Try: raise informed traders to 50% with a 1-tick spread (profit turns negative: they only trade when they know you're wrong); then widen the spread until it covers them. Set skew to 0 and watch the inventory wander; raise it and inventory stays near zero.
7. Engineering traps we hit
Crossing your own quotes
When fair value rises, both quotes move up. If the bid moves first, it can briefly sit at or above the market maker's own old ask. The exchange's self-trade prevention cancels it. In Prayog's first live run this happened 798 times in a few minutes and left the book one-sided. The fix: move the side that steps away from the market first (asks up before bids up; bids down before asks down), and skip a quote that would still reach your own opposite order until the next step.
Trusting your own bookkeeping
The exchange sends the REST answer ("order 5621 resting") and the private-feed fill for that order at the same moment; the network decides which arrives first. A bot that ignores fills for order ids it hasn't recorded yet will think it still has an order that has already filled. The fix: reconcile every couple of seconds against the exchange's list of your open orders, and treat that list as the truth.
8. Prayog's market maker
| Setting | calm | volatile |
|---|---|---|
| Half spread | 2 ticks | 4 ticks |
| Levels per side | 3, 2 ticks apart | 3, 3 ticks apart |
| Size per level | 4 lots of 10 shares | 3 lots |
| Skew | 0.5 tick per lot | 1 tick per lot |
| Inventory cap | 60 lots | 40 lots |
It quotes around a hidden fair value (a mean-reverting random walk with jumps), so it behaves as if informed about the long-run price; noise and momentum traders trade against it. Code: services/agents/src/prayog_agents/agents.py (MarketMaker) and quoting.py (the pure quoting rules, unit-tested).
9. Questions
Isn't a market maker just front-running?
No. Front-running is trading ahead of a client's order using knowledge of that order, which is illegal. A market maker posts prices publicly and anyone may trade against them; it takes the risk of being on the wrong side.
Why do market makers cancel so many orders?
Every time fair value moves, stale quotes become a free option for faster traders. Updating them (cancel and replace, or modify) is how a market maker avoids being picked off. In Prayog's run, modifies outnumber new orders roughly 8 to 1.