Trading
Rebate Capture and Maker-Taker Economics: How Fee Tiers Drive Routing Decisions
The math behind maker-taker fee structures, VIP tier optimization, post-only order economics, and how fee-adjusted mid price should drive your venue routing decisions at scale.
I personally optimize my Binance fee tier. I hold BNB for the 25% discount. I use post-only orders on my maker strategies. At my trading scale, the difference between VIP1 and VIP3 is not noise - it’s a material factor in whether a strategy is profitable.
At Akuna Capital, where I worked on systematic trading infrastructure for exchange-maker strategies, we were at Binance VIP9 across multiple trading accounts. The fee engineering team spent serious effort on fee structure optimization - not because fees are theoretically interesting, but because at the volumes Akuna was running, a single basis point difference in effective fees was worth hundreds of thousands of dollars per month.
This post is the one I wish I’d had before I spent months learning fee optimization by trial and error.
The Maker-Taker Model
Every major crypto exchange charges fees based on whether you “make” or “take” liquidity:
Maker: Your order rests on the order book and gets filled when someone else trades against it. You add liquidity to the market, which reduces bid-ask spread and improves price discovery. Exchanges reward this by paying you a rebate (negative fee) at high VIP tiers.
Taker: Your order immediately crosses the spread and fills against resting orders. You remove liquidity from the market. Exchanges charge you a fee for this.
The economic logic is sound: exchanges make money on the spread between maker and taker fees, and they want to incentivize market makers to post tight two-sided quotes to attract taker order flow.
For a strategy that never makes markets, taker fees are just a cost of business. For any strategy that sometimes or always posts resting limit orders, maker rebates are a revenue source. This is not a minor distinction.
Binance VIP Tier Structure
Binance calculates your VIP tier based on your 30-day trading volume AND your BNB holdings. Both matter - holding BNB without volume doesn’t qualify you for top tiers, and high volume without BNB holding misses the discount.
USDT-Margined Futures (USDT-M) - Binance VIP Tiers:
| VIP Tier | 30d Volume Req | Maker Fee | Taker Fee |
|---|---|---|---|
| Regular | < $1M | 0.020% | 0.040% |
| VIP1 | $1M+ | 0.016% | 0.040% |
| VIP2 | $5M+ | 0.014% | 0.035% |
| VIP3 | $20M+ | 0.012% | 0.032% |
| VIP4 | $100M+ | 0.010% | 0.030% |
| VIP5 | $500M+ | 0.008% | 0.027% |
| VIP6 | $1B+ | 0.006% | 0.025% |
| VIP7 | $2B+ | 0.004% | 0.022% |
| VIP8 | $4B+ | 0.002% | 0.020% |
| VIP9 | $8B+ | -0.010% (rebate) | 0.017% |
At VIP9, maker orders earn a 0.01% rebate - meaning Binance pays you 100,000 in maker volume. At Akuna’s scale, this was a meaningful incoming revenue stream.
Note that “Maker Fee” at lower tiers is still a cost (you pay), just lower than the taker fee. The rebate only appears at VIP9 on USDT-M futures.
The Math: Why Fee Tiers Matter at Scale
Let’s do the actual arithmetic. Assume a firm doing $10M per day in USDT-M futures with a 60% maker / 40% taker fill ratio (a reasonably good maker-focused strategy).
Daily maker volume: 4M
VIP3 fees (0.012% maker, 0.032% taker):
- Maker cost: 720
- Taker cost: 1,280
- Total daily fee: $2,000
VIP9 fees (-0.010% maker, 0.017% taker):
- Maker rebate: 600 (received)
- Taker cost: 680
- Net daily fee: $80 (net positive: more taker cost than maker rebate, but nearly break-even)
The difference: 80/day at VIP9 = 700,800/year.
For the firm at 700K annually. This is not a footnote - it’s a significant factor in whether certain strategies are viable at all.
Now scale to $100M daily volume (still modest for a dedicated market-making operation):
VIP9 at $100M/day (60/40 maker/taker split):
- Maker rebate: 6,000 received
- Taker cost: 6,800 paid
- Net: $800/day in net costs
VIP5 at $100M/day (same split):
- Maker cost: 4,800 paid (VIP5 maker = 0.008%, still a cost not rebate)
- Taker cost: 10,800 paid
- Net: $15,600/day in net costs
Difference: 800 = 5.4M/year difference. At this scale, fee tier optimization is a strategy in itself.
Post-Only Orders: The Maker Guarantee
A post-only order is a limit order that will only execute if it would be placed on the order book as a maker - if the market has moved such that your limit price would cross and fill as a taker, the exchange rejects the order rather than filling it as a taker.
Why this matters: at VIP5 with 0.008% maker rate, a strategy that can achieve >80% maker fill rate is dramatically more economical than the same strategy submitting market orders.
The calculus:
- Post-only order at $80,000 for BTC:
- If fills as maker: pay 0.008% = 8,000 notional) - or a rebate at VIP9
- If rejected (market moved through): no fill, no cost - need to resubmit
The trade-off of post-only: fill rate decreases. In fast-moving markets, your limit price becomes stale quickly, and post-only orders get rejected frequently. For market-making strategies, this is acceptable - you’d rather not fill as a taker than pay taker fees. For directional strategies with urgency, post-only can cause you to miss moves.
Practical guidance for post-only strategy design:
- Use post-only for passive resting orders (entries at your fair value bid/offer)
- Never use post-only for stop-loss orders (you need guaranteed fills there)
- In fast markets, have a “market urgency” flag that disables post-only and accepts taker fees when your edge exceeds the fee cost
BNB Discount: The Hidden Fee Lever
Holding BNB in your Binance account gives a 25% discount on trading fees across spot and futures. This is applied automatically if you opt in and maintain sufficient BNB balance.
The break-even calculation: If you’re paying 10M volume), a 25% discount saves 182,500/year. The opportunity cost of holding BNB instead of USDT is roughly the difference between BNB’s return and the risk-free rate - but the fee savings alone might justify the position.
For infrastructure engineers, BNB balance management requires:
- BNB balance monitoring: If your BNB balance drops below the threshold Binance requires for fee payment, the discount fails silently and you start paying full rate
- BNB auto-purchase: Some professional accounts automate BNB purchases to maintain the discount - build this into your operations layer
- Fee currency tracking: Your PnL accounting must correctly model the fee as paid in BNB (at the BNB/USDT rate at time of trade), not in USDT directly
def binance_effective_fee_rate(
base_fee: float,
use_bnb: bool = True,
bnb_discount: float = 0.25,
) -> float:
"""Calculate effective fee rate after BNB discount."""
if use_bnb:
return base_fee * (1 - bnb_discount)
return base_fee
# Example: VIP3 maker with BNB
# Base rate: 0.012%
# After 25% BNB discount: 0.012% × 0.75 = 0.009%
eff_maker = binance_effective_fee_rate(0.00012, use_bnb=True)
print(f"Effective maker rate: {eff_maker:.5%}") # 0.00900%
The Fee-Adjusted Mid Price: The Routing Decision Function
When you have positions to execute and multiple venues are available, the routing decision should not be “which venue has the best price?” It should be “which venue has the best fee-adjusted price?”
The fee-adjusted mid price is:
Fee-Adjusted Mid (maker) = Mid Price - Expected Maker Rebate (or + Maker Cost)
Fee-Adjusted Mid (taker) = Mid Price + Expected Taker Fee
For a buy order on USDT-M futures at VIP3 (maker 0.012%, taker 0.032%):
- Market mid: $80,000
- If I post a limit buy (maker): effective cost = 80,009.60
- If I market order (taker): effective cost = 80,025.60
For the same trade on Bybit at VIP3 equivalent (maker 0.010%, taker 0.060%):
- Market mid: $80,005 (Bybit is slightly different from Binance)
- If I post (maker): 80,013.00
- If I market (taker): 80,053.00
Routing decision (maker orders):
- Binance fee-adjusted: $80,009.60
- Bybit fee-adjusted: $80,013.00
- Winner: Binance (even though Bybit spot price is closer to our target)
Routing decision (taker/market orders):
- Binance fee-adjusted: $80,025.60
- Bybit fee-adjusted: $80,053.00
- Winner: Binance by a larger margin (Bybit’s high taker fees make it expensive for market orders)
Here’s a Python fee calculator that automates this reasoning:
from dataclasses import dataclass
from enum import Enum
class VIPTier(Enum):
REGULAR = "regular"
VIP1 = "vip1"
VIP2 = "vip2"
VIP3 = "vip3"
VIP4 = "vip4"
VIP5 = "vip5"
VIP6 = "vip6"
VIP7 = "vip7"
VIP8 = "vip8"
VIP9 = "vip9"
# Binance USDT-M futures fee schedule (as of early 2026)
# (maker_rate, taker_rate) - positive = cost, negative = rebate
BINANCE_USDTM_FEES = {
VIPTier.REGULAR: (0.0002, 0.0004),
VIPTier.VIP1: (0.00016, 0.0004),
VIPTier.VIP2: (0.00014, 0.00035),
VIPTier.VIP3: (0.00012, 0.00032),
VIPTier.VIP4: (0.0001, 0.0003),
VIPTier.VIP5: (0.00008, 0.00027),
VIPTier.VIP6: (0.00006, 0.00025),
VIPTier.VIP7: (0.00004, 0.00022),
VIPTier.VIP8: (0.00002, 0.0002),
VIPTier.VIP9: (-0.0001, 0.00017), # Maker is a rebate at VIP9
}
@dataclass
class VenueConfig:
name: str
mid_price: float
vip_tier: VIPTier
use_bnb: bool = False
# Fee schedule: (maker, taker) as fractions (positive = cost, negative = rebate)
maker_rate: float = 0.0
taker_rate: float = 0.0
def __post_init__(self):
maker, taker = BINANCE_USDTM_FEES.get(self.vip_tier, (0.0002, 0.0004))
if self.use_bnb:
maker = maker * 0.75 if maker > 0 else maker * 1.25 # BNB adjusts cost, not rebate direction
taker = taker * 0.75
self.maker_rate = maker
self.taker_rate = taker
def fee_adjusted_cost(
venue: VenueConfig,
side: str, # "BUY" or "SELL"
order_type: str, # "MAKER" or "TAKER"
quantity: float,
) -> dict:
"""
Calculate the fee-adjusted all-in cost for a trade.
Returns:
dict with gross_cost, fee_amount, net_cost, and fee_adjusted_price
"""
rate = venue.maker_rate if order_type == "MAKER" else venue.taker_rate
notional = venue.mid_price * quantity
# Fee: positive = we pay, negative = we receive (rebate)
fee_amount = notional * rate
if side == "BUY":
# Buying: gross cost = price × qty, net = gross + fee
net_cost = notional + fee_amount
fee_adjusted_price = venue.mid_price * (1 + rate)
else:
# Selling: gross revenue = price × qty, net = gross - fee
net_cost = notional - fee_amount
fee_adjusted_price = venue.mid_price * (1 - rate)
return {
"venue": venue.name,
"order_type": order_type,
"mid_price": venue.mid_price,
"gross_notional": notional,
"fee_rate": rate,
"fee_amount_usd": fee_amount,
"net_cost_usd": net_cost,
"fee_adjusted_price": fee_adjusted_price,
}
def best_venue_for_trade(
venues: list[VenueConfig],
side: str,
order_type: str,
quantity: float,
) -> tuple[VenueConfig, dict]:
"""
Given multiple venue options, find the best fee-adjusted price.
For BUY: minimize fee_adjusted_price (lower = better)
For SELL: maximize fee_adjusted_price (higher = better)
"""
results = [
(venue, fee_adjusted_cost(venue, side, order_type, quantity))
for venue in venues
]
if side == "BUY":
best = min(results, key=lambda x: x[1]["fee_adjusted_price"])
else:
best = max(results, key=lambda x: x[1]["fee_adjusted_price"])
return best
# Example: comparing venues for a 1 BTC buy as maker order
venues = [
VenueConfig("Binance-VIP3", mid_price=80000, vip_tier=VIPTier.VIP3, use_bnb=True),
VenueConfig("Binance-VIP3-noBNB", mid_price=80000, vip_tier=VIPTier.VIP3, use_bnb=False),
VenueConfig("Binance-VIP9", mid_price=80005, vip_tier=VIPTier.VIP9, use_bnb=False),
]
best_venue, best_result = best_venue_for_trade(venues, "BUY", "MAKER", 1.0)
print(f"\nBest venue: {best_result['venue']}")
print(f"Fee-adjusted price: ${best_result['fee_adjusted_price']:,.2f}")
print(f"Fee amount: ${best_result['fee_amount_usd']:.2f} ({'rebate' if best_result['fee_amount_usd'] < 0 else 'cost'})")
How This Breaks in Production
Mistake 1: Not including fee in the PnL calculation from the start. I’ve seen strategy backtests that assumed zero fees or flat 0.04% taker fees. The actual fee impact, especially at high taker rates and sub-VIP tiers, can convert a marginally profitable strategy into a losing one. Model fees accurately from day one.
Mistake 2: Letting VIP tier calculation drift. Binance recalculates your VIP tier every day at midnight UTC based on trailing 30-day volume. If you don’t track your own volume, you might assume you’re at VIP5 when you’ve actually dropped to VIP3 because volume was low last month. Build a daily volume tracking dashboard and alert when tier status changes.
Mistake 3: Using market orders when limit orders would work. For any trade that is not urgently time-sensitive, using post-only limit orders at or near the bid/ask saves the entire maker-taker spread. The difference between 0.04% taker and 0.02% maker (with BNB discount) is 0.02% per trade - across thousands of daily trades, this compounds dramatically.
Mistake 4: Not accounting for fee currency. BNB fees are paid in BNB, not USDT. Your accounting system needs to track your BNB balance, BNB price at time of fee payment, and the USDT-equivalent cost. A spike in BNB price at high trading volume can make a profitable trading day look worse in BNB terms.
Mistake 5: Single-venue mentality. The routing decision is always multi-venue. Bybit, OKX, and Binance all have different fee structures and different liquidity profiles. The “best venue” changes by instrument, by time of day, and by order type. Build multi-venue fee modeling from the start.
Fee optimization is not glamorous. It’s not the interesting part of trading infrastructure. But it’s often the difference between a strategy that generates alpha in backtesting and one that actually makes money in production. The market is too competitive for margin to survive ignorance of your own cost structure.
Continue Reading
Enjoyed this?
Get one deep infrastructure insight per week.
Free forever. Unsubscribe anytime.
You're in. Check your inbox.