Guide · 9 min read

Market-making, done honestly.

A market maker gets paid to bear inventory risk in exchange for the spread. Most retail bots that call themselves "market makers" are actually one-sided directional bets in disguise. This guide covers the mechanics that make the difference.

You'll learn

How to estimate fair value from a public order book, how to skew quotes against inventory, when to widen or pull, and how to measure whether you're actually earning the spread.

1. Fair value

The midpoint is a lazy fair value. A better estimate is the microprice: weighted midpoint that leans toward the deeper side of the book, because that side is harder to move.

def microprice(bid, ask, bid_size, ask_size):
    total = bid_size + ask_size
    if total == 0:
        return (bid + ask) / 2
    return (bid * ask_size + ask * bid_size) / total

2. Quoting with inventory skew

The core discipline: push your quote away from any inventory you already hold, so fills push you back toward flat instead of doubling you down. Long inventory → lower both bid and ask; short inventory → raise both.

def quotes(fair, inventory, target_spread=0.02, skew=0.001):
    skewed_mid = fair - skew * inventory
    half = target_spread / 2
    return skewed_mid - half, skewed_mid + half

3. Adverse-selection defense

You get filled most often exactly when you don't want to be. Defenses that actually work:

  • — Widen the spread when short-term realized volatility jumps.
  • — Cancel and reprice on any print larger than N × average trade size.
  • — Refuse to quote in the last minutes before an event resolves.
  • — Cap the number of consecutive fills on the same side before flattening.

4. Measuring spread capture

Track two P&L streams separately: the spread you capture at the moment of each fill (fill price minus mid at fill time), and the mark-to-market on inventory you carry. A healthy maker has consistently positive spread capture and roughly zero-mean inventory P&L over time.

# On every fill:
spread_pnl += (fill_price - mid_at_fill) * side_sign * size
# On every tick:
inventory_pnl = position * (mid - avg_entry_price)

5. Sizing and kill switches

  • — Cap notional per market and total notional across the book.
  • — Set a max inventory position beyond which you only quote the flattening side.
  • — Hard daily loss kill that cancels all quotes and flattens inventory.

6. Frequently asked questions

Do I need to be faster than everyone else to market-make?
On the fastest venues, yes — retail cannot win a latency race against colocated firms. On thinner venues like Polymarket or Kalshi, discipline around inventory, quoting cadence, and adverse selection matters far more than microseconds.
How do I know if I'm actually capturing spread?
Split your P&L into two components: spread captured (edge relative to mid at fill time) and inventory P&L (mark-to-market on unfilled leans). Healthy market makers earn positive spread and roughly break even on inventory.
What kills a market-making bot?
Adverse selection — getting filled only when the market is about to move against you. Defenses include widening quotes into volatility, canceling on large trade prints, and refusing to quote near event resolution.
How does this fit into ScriptSamurai's forward-test?
The same deterministic fill model that scores directional bots also scores makers: resting orders match when the shared book crosses them. Your Sharpe, drawdown, and win rate are computed the same way — which is why disciplined making tends to rank well.

Built one? Prove it in the dojo.