Exchange Liquidity Development (Market Making)
Liquidity is the market's readiness to execute an order without significant price change. An exchange without liquidity is dead: wide spread, deep impact, traders leaving to competitors. Market making is both art and engineering: constantly maintain two-sided quotes, hedge risks, and not lose money doing it.
What is Market Making
A market maker posts simultaneous bid (buy) and ask (sell) orders. Their earnings come from the spread between them. When trading against them, they take on inventory risk (a position in the asset).
Market Maker Book for BTC/USDT:
Ask $50,100 │ 0.5 BTC
Ask $50,050 │ 0.3 BTC
Mid $50,000 │
Bid $49,950 │ 0.3 BTC
Bid $49,900 │ 0.5 BTC
Spread = Ask_best - Bid_best = $50,050 - $49,950 = $100 (0.2%)
Market Making Bot Architecture
Basic Strategy
class MarketMaker:
def __init__(self, symbol: str, config: MMConfig):
self.symbol = symbol
self.spread_bps = config.spread_bps # half of spread in bps
self.order_size_base = config.order_size # base order size
self.num_layers = config.num_layers # quoting depth
self.layer_spacing_bps = config.layer_spacing # distance between levels
async def compute_quotes(self, mid_price: float) -> list[Quote]:
quotes = []
inventory_skew = self.calculate_inventory_skew()
for i in range(1, self.num_layers + 1):
# Shift quotes based on inventory
bid_offset_bps = self.spread_bps * i + inventory_skew
ask_offset_bps = self.spread_bps * i - inventory_skew
bid_price = mid_price * (1 - bid_offset_bps / 10000)
ask_price = mid_price * (1 + ask_offset_bps / 10000)
# Order size decreases at farther levels
size = self.order_size_base / i
quotes.append(Quote('buy', bid_price, size))
quotes.append(Quote('sell', ask_price, size))
return quotes
def calculate_inventory_skew(self) -> float:
"""
If we accumulate excess BTC (long inventory) —
shift quotes down: more aggressive ask, less aggressive bid.
This incentivizes the market to buy our BTC, rebalancing.
"""
target_inventory = 0 # neutral position
current_inventory = self.get_current_inventory()
inventory_deviation = current_inventory - target_inventory
# Skew proportional to deviation from neutral
skew = inventory_deviation * self.inventory_skew_factor
return max(-self.max_skew_bps, min(self.max_skew_bps, skew))
Hedging (Delta Hedging)
Market maker on internal exchange hedges position on external. If client bought 1 BTC from us — we buy 1 BTC on Binance to neutralize delta:
async def hedge_trade(self, trade: InternalTrade):
"""Hedge executed trade on external exchange"""
hedge_side = 'buy' if trade.side == 'sell' else 'sell'
# trade.side = what client did. If client bought — we sold → hedge with buy
await self.hedge_exchange.market_order(
symbol=self.symbol,
side=hedge_side,
quantity=trade.quantity
)
Execution Risk: between our trade with client and hedge on external exchange passes time (1-100ms). Price can shift. This is execution risk or hedging slippage — real P&L risk.
Inventory Management
Key metric: inventory skew — how much current position deviates from target (usually neutral).
def get_inventory_metrics(self) -> dict:
current_pos = self.get_position_btc() # positive = long, negative = short
pos_value_usd = current_pos * self.get_mid_price()
return {
"position_btc": current_pos,
"position_usd": pos_value_usd,
"max_inventory_usd": self.config.max_inventory_usd,
"utilization": abs(pos_value_usd) / self.config.max_inventory_usd,
"pnl_unrealized": self.calculate_unrealized_pnl(current_pos)
}
When inventory limits exceeded: strategy aggressively shifts quotes to reduce position, worst case — forced market order on external exchange.
Spread Determination
Spread Components
Minimum reasonable spread consists of:
Spread = Cost of carry + Expected adverse selection + Profit margin
Cost of carry = funding_rate × holding_period
Adverse selection = probability of trading against informed trader
Profit margin = desired return on volume
Adverse selection — hardest part. If trader trades against you with insider information (knows price will rise soon), you always lose. Empirically: in crypto, adverse selection higher at high volatility, before major events (Fed meetings, halvings).
Dynamic Spread
def calculate_dynamic_spread(self) -> float:
base_spread = self.config.base_spread_bps
# Widen spread at high volatility
volatility = self.get_realized_volatility_1h()
vol_multiplier = max(1.0, volatility / self.baseline_volatility)
# Widen before important events
event_factor = 1.5 if self.is_event_window() else 1.0
# Widen at low liquidity on hedge exchange
hedge_spread = self.get_hedge_exchange_spread()
hedge_factor = max(1.0, hedge_spread / self.baseline_hedge_spread)
return base_spread * vol_multiplier * event_factor * hedge_factor
Liquidity Provider Program
Incentivizing External Market Makers
Exchange can attract external market makers through fee rebate program:
| Tier | Maker volume/30d | Maker fee | Taker fee |
|---|---|---|---|
| Standard | < $1M | 0.10% | 0.15% |
| Market Maker 1 | $1M+ | -0.01% (rebate) | 0.10% |
| Market Maker 2 | $10M+ | -0.02% (rebate) | 0.08% |
| Market Maker 3 | $100M+ | -0.03% (rebate) | 0.06% |
Negative maker fee (rebate) means exchange pays market maker for each placed and executed order. Standard practice for attracting professional liquidity providers.
On-chain AMM Liquidity
For DEX or hybrid platforms, liquidity provided via LP positions in AMM pools. Difference in economics:
| Parameter | CEX Market Making | AMM LP |
|---|---|---|
| Price control | Full | Algorithmic |
| Impermanent loss | None (hedged) | Yes |
| Infrastructure requirements | Bot + API | Just transaction |
| Risk management | Active | Passive |
| Return | Higher (active) | Lower (passive) |
For serious trading volume, CEX market making incomparably more efficient than AMM LP. AMM works as backstop liquidity and for long-tail tokens without professional MMs.







