Order Types - A Trader's Guide to Backpack Exchange
TL;DR
Basic Order Types:
- Market Order - Execute immediately at best available price (fast, but price uncertain)
- Limit Order - Execute at your specified price or better (price guaranteed, fill not guaranteed)
Time-in-Force (how long your order stays active):
- GTC (Good-Til-Cancelled) - Stays on book until filled or cancelled
- IOC (Immediate-or-Cancel) - Fill what you can now, cancel the rest
- FOK (Fill-or-Kill) - All or nothing - fill completely or reject entirely
Execution Modifiers:
- Post-Only - Only maker orders (rejected if it would take liquidity)
- Reduce-Only - Only allows closing positions (won't increase exposure)
Trigger Orders:
- Stop-Loss - Triggers when price moves against you (limit losses)
- Take-Profit - Triggers when price moves in your favor (lock in gains)
Table of Contents
- Basic Order Types
- Time-in-Force
- Execution Modifiers
- Trigger Orders
- Order Lifecycle
- Common Mistakes & Gotchas
1. Basic Order Types
Market Order
What it does: Executes immediately at the best available price(s) in the order book.
When to use:
- You need to get in/out NOW (urgency matters more than price)
- High-liquidity markets where slippage is minimal
- Emergency exits from bad positions
Example:
Order Book State:
Asks: $100.10 (50), $100.20 (100), $100.30 (200)
Bids: $100.00 (50), $99.90 (100)
You: Market BUY 80 units
Result:
- 50 units filled at $100.10
- 30 units filled at $100.20
- Average price: $100.14 (not the "best" price!)Key characteristics:
- Always a taker (removes liquidity from book)
- No price guarantee - you get whatever is available
- Can specify quantity OR quote quantity (e.g., "buy $1000 worth")
- Higher fees than limit orders (taker fees)
Warning: In thin order books, market orders can experience significant slippage - the difference between expected and actual execution price.
How Market Orders Match (Book Walking)
Market orders "walk the book" - they consume liquidity starting from the best price and moving to worse prices until filled.
For a BUY order: Matches against asks, starting at the lowest ask (best for buyer), then moves UP.
For a SELL order: Matches against bids, starting at the highest bid (best for seller), then moves DOWN.
Order Book:
Asks: $100 (50), $101 (100), $102 (200) ← Sells waiting
Bids: $99 (50), $98 (100), $97 (200) ← Buys waiting
┌─────────────────────────────────────────────────────────┐
│ Market BUY 120 units │
├─────────────────────────────────────────────────────────┤
│ Step 1: Match $100 (best ask) │
│ → Fill 50 units @ $100 │
│ → 70 units remaining │
│ │
│ Step 2: Match $101 (next best ask) │
│ → Fill 70 units @ $101 │
│ → 0 units remaining │
│ │
│ Result: 120 units filled │
│ Avg price: (50×$100 + 70×$101) / 120 = $100.58 │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ Market SELL 120 units │
├─────────────────────────────────────────────────────────┤
│ Step 1: Match $99 (best bid) │
│ → Fill 50 units @ $99 │
│ → 70 units remaining │
│ │
│ Step 2: Match $98 (next best bid) │
│ → Fill 70 units @ $98 │
│ → 0 units remaining │
│ │
│ Result: 120 units filled │
│ Avg price: (50×$99 + 70×$98) / 120 = $98.42 │
└─────────────────────────────────────────────────────────┘Price-Time Priority: At each price level, orders are filled in the order they were placed (earlier orders first). The matching engine uses BTreeMap ordered by price, with order IDs (which are sequential) determining time priority within a price level.
Price Impact Protection
To prevent catastrophic slippage in thin order books, Backpack has price impact limits that stop market orders from penetrating too deep into the book.
How it works:
Configuration (per market):
max_impact_multiplier: 1.10 (10% above best ask for buys)
min_impact_multiplier: 0.90 (10% below best bid for sells)
Example - Market BUY with protection:
Best ask (first price): $100
Max allowed price: $100 × 1.10 = $110
Order Book Asks: $100 (10), $105 (10), $112 (1000)
You: Market BUY 500 units
Step 1: Fill 10 @ $100 ✓
Step 2: Fill 10 @ $105 ✓
Step 3: Try $112... BLOCKED! ($112 > $110 limit)
Result: Only 20 units filled, rest EXPIRED
Reason: PriceImpactFor BUY orders:
price must be ≤ first_price × max_impact_multiplierFor SELL orders:
price must be ≥ first_price × min_impact_multiplierWhy this exists:
- Prevents "fat finger" errors from wiping the entire book
- Protects against manipulation via thin liquidity
- Gives traders predictable worst-case slippage
What happens when triggered:
- Order is partially filled up to the impact limit
- Remaining quantity is expired with reason
PriceImpact - You receive a partial fill, not a rejection
Pro tip: If your market order is getting expired due to price impact, either:
- Use a limit order with your max acceptable price
- Split into smaller orders
- Wait for more liquidity
Limit Order
What it does: Executes only at your specified price or better.
When to use:
- You have a specific entry/exit price in mind
- Price matters more than timing
- You want to provide liquidity (make markets)
- You want lower fees (maker rebates)
Example:
Current market: $100
You: Limit BUY at $99.50 for 100 units
Scenarios:
A) Price stays at $100 → Order sits on book waiting
B) Price drops to $99.50 → Order fills at $99.50 or better
C) Price never reaches $99.50 → Order stays until you cancelKey characteristics:
- Can be maker (adds liquidity) or taker (takes liquidity)
- Price guaranteed - but fill is not guaranteed
- Maker orders earn rebates, taker orders pay fees
- Default time-in-force is GTC (stays on book)
Maker vs Taker:
Order Book: Best ask $100.10, Best bid $100.00
Limit BUY at $99.90 → MAKER (below best ask, goes on book)
Limit BUY at $100.20 → TAKER (above best ask, executes immediately)
Limit SELL at $100.20 → MAKER (above best bid, goes on book)
Limit SELL at $99.90 → TAKER (below best bid, executes immediately)When to Use Each
| Situation | Order Type | Why |
|---|---|---|
| Breaking news, need to exit NOW | Market | Speed > price |
| Setting a target entry price | Limit | Price precision |
| Market making / providing liquidity | Limit (Post-Only) | Earn rebates |
| Stop-loss execution | Market (trigger) | Guaranteed exit |
| Take-profit at specific level | Limit (trigger) | Price precision |
| DCA buying | Limit | Better average price |
| Closing a position urgently | Market | Certainty of exit |
2. Time-in-Force
Time-in-Force (TIF) determines how long your order remains active and what happens to unfilled portions.
GTC - Good-Til-Cancelled (Default)
What it does: Order stays on the book until completely filled or you cancel it.
When to use:
- You're willing to wait for your price
- Setting limit orders at support/resistance levels
- Building positions over time
Example:
You: Limit BUY 100 units at $95.00, GTC
Day 1: Price at $100, order sits on book
Day 2: Price at $98, still waiting
Day 3: Price drops to $95, 100 units filled!
Total time: 3 days waiting for your priceIOC - Immediate-or-Cancel
What it does: Fill whatever you can immediately, cancel the rest. Partial fills allowed.
When to use:
- You want execution now but don't want residual orders lingering
- Testing liquidity at a price level
- Avoiding stale orders on your account
Example:
Order Book Asks: $100 (50 units), $101 (100 units)
You: Limit BUY 80 units at $100, IOC
Result:
- 50 units filled at $100
- 30 units CANCELLED (no liquidity at $100)
- You got partial fill, rest is goneKey insight: IOC says "give me what's available NOW at my price, I don't want to wait."
FOK - Fill-or-Kill
What it does: Either fill the ENTIRE order immediately, or reject it completely. No partial fills.
When to use:
- All-or-nothing situations (hedging, arbitrage)
- You need exact position sizes
- Avoiding partial fills that leave you exposed
Example:
Order Book Asks: $100 (50 units), $101 (100 units)
Scenario A: FOK BUY 40 units at $100
→ 40 units filled (book has 50, we need 40 ✓)
Scenario B: FOK BUY 80 units at $100
→ Order REJECTED (book only has 50 at $100)
→ No partial fill, nothing happensKey insight: FOK says "I need exactly this much at this price, or forget it."
Comparison Table
| TIF | Partial Fill? | Unfilled Portion | Use Case |
|---|---|---|---|
| GTC | Yes | Stays on book | Patient trading |
| IOC | Yes | Cancelled | Immediate execution |
| FOK | No | Order rejected | All-or-nothing |
Memory Trick:
GTC = "I'll wait for my price" (patient)
IOC = "Now or never, but I'll take what I can get" (flexible)
FOK = "All or nothing" (strict)3. Execution Modifiers
Post-Only
What it does: Ensures your order is always a maker (adds liquidity). If your order would immediately match (become a taker), it's rejected.
When to use:
- Market making strategies
- You specifically want maker rebates
- Avoiding accidental taker fees
Example:
Order Book: Best ask $100.10, Best bid $100.00
Post-Only SELL at $100.05:
→ REJECTED! Would cross the spread and take from bids
→ Error: PostOnlyTaker
Post-Only SELL at $100.15:
→ Accepted! Goes on book above best ask
→ You're now a maker, earning rebates when filledCommon mistake: Setting post-only orders too aggressively. If your price would execute immediately, the order fails entirely.
Understanding the PostOnlyTaker Error
If you see the error "order would immediately match and take" (error code: PostOnlyTaker), it means your post-only order was rejected because it would have crossed the spread and taken liquidity.
Why does the exchange reject these orders?
Post-only is a promise: "I only want to be a maker." The exchange enforces this by checking if your order would immediately match:
Your order: Post-Only BUY at $100.50
Best ask: $100.40
What would happen WITHOUT post-only:
→ Your buy at $100.50 matches the $100.40 ask
→ You're a TAKER (removing liquidity)
→ You pay taker fees
What happens WITH post-only:
→ Exchange sees your order would immediately match
→ Rejects with PostOnlyTaker error
→ No order placed, no fees chargedWhy do traders want this?
Fee optimization - Makers often receive rebates; takers pay fees. A market maker placing thousands of orders wants to guarantee maker status.
Execution certainty - If you're quoting a price, you want that exact price or nothing. You don't want to accidentally sweep the book.
Strategy enforcement - Market making algorithms expect to rest on the book. An accidental taker fill can break position management logic.
How to fix it:
Adjust your price so your order rests on the book instead of crossing:
| Order Side | Must Be | Example |
|---|---|---|
| Post-only BUY | Below best ask | If best ask is $100.10, bid at $100.05 or lower |
| Post-only SELL | Above best bid | If best bid is $100.00, ask at $100.05 or higher |
Pro tip: If you're consistently getting PostOnlyTaker errors, your pricing logic may be too aggressive. Consider adding a buffer from the best price, or fetching fresh order book data before placing orders.
Reduce-Only
What it does: Order can only reduce (close) an existing position. Cannot open new positions or increase exposure.
When to use:
- Closing positions without accidentally flipping
- Stop-loss orders (you only want to exit, not reverse)
- Risk management to prevent over-exposure
Example:
Current Position: LONG 100 BTC
Reduce-Only SELL 50 BTC:
→ Accepted! Reduces position to 50 BTC
Reduce-Only SELL 150 BTC:
→ Only 100 BTC sold (reduced to 0)
→ Won't flip you SHORT
Without Reduce-Only SELL 150 BTC:
→ Sells 150 BTC
→ You're now SHORT 50 BTC (position flipped!)Key insight: Reduce-only prevents accidental position reversals and is automatically applied to all stop-loss/take-profit orders.
Important behavior: The engine tracks your reduce-only orders and ensures your total pending reduce-only quantity doesn't exceed your position size.
Self-Trade Prevention (STP)
What it does: Prevents your orders from matching against each other (useful for market makers running multiple strategies).
Options:
| Mode | Behavior |
|---|---|
| RejectTaker (default) | Incoming order is cancelled |
| RejectMaker | Resting order is cancelled |
| RejectBoth | Both orders cancelled |
| Allow | Self-trades permitted |
4. Trigger Orders
Trigger orders (stop-loss, take-profit) are conditional orders that only activate when a specified price is reached.
How Trigger Orders Work
Regular Limit Order:
Submit → Immediately on order book → Can be filled anytime
Trigger Order:
Submit → Stored separately (NOT on book) → Waits for trigger price
→ Trigger fires → Converts to regular order → Placed on bookKey insight: Trigger orders take a separate code path. They're stored in a TriggerOrders collection, not the main order book, until activated.
Stop-Loss
What it does: Triggers when price moves AGAINST your position. Limits downside.
For a LONG position:
You're LONG BTC at $100,000
Stop-Loss trigger at $95,000
Price drops to $95,000 → Stop triggers → Sells your position
Loss limited to ~5% instead of potentially moreFor a SHORT position:
You're SHORT BTC at $100,000
Stop-Loss trigger at $105,000
Price rises to $105,000 → Stop triggers → Buys to close
Loss limited to ~5%Take-Profit
What it does: Triggers when price moves IN FAVOR of your position. Locks in gains.
For a LONG position:
You're LONG BTC at $100,000
Take-Profit trigger at $110,000
Price rises to $110,000 → TP triggers → Sells your position
You lock in ~10% profitFor a SHORT position:
You're SHORT BTC at $100,000
Take-Profit trigger at $90,000
Price falls to $90,000 → TP triggers → Buys to close
You lock in ~10% profitTrigger Price vs Limit Price
When placing a trigger order, you specify:
- Trigger Price - When does the order activate?
- Limit Price (optional) - What price to execute at once triggered?
Trigger Order with Limit Price:
Trigger at $95,000, Limit at $94,500
→ When price hits $95,000: Creates a LIMIT SELL at $94,500
→ Guaranteed price of $94,500 or better
→ But might not fill if price gaps through!
Trigger Order without Limit Price (Stop-Market):
Trigger at $95,000, no limit
→ When price hits $95,000: Creates a MARKET SELL
→ Guaranteed fill
→ But price might be worse than $95,000 (slippage)Trade-off:
| Type | Fill Guarantee | Price Guarantee |
|---|---|---|
| Stop-Limit | No | Yes |
| Stop-Market | Yes | No |
Trigger Price Types
You can specify trigger prices in three ways:
| Type | Example | Use Case |
|---|---|---|
| Fixed | $95,000 | Most common - specific price level |
| Percentage | -5% | Trailing stops, dynamic targets |
| Relative | -$500 | Fixed dollar offset from reference |
Trigger Reference Price (TriggerBy)
What price does the system watch to fire your trigger?
| Option | Description | When to Use |
|---|---|---|
| LastPrice (default) | Most recent trade price | Standard trading |
| IndexPrice | Spot index (aggregated exchanges) | Avoid manipulation |
| MarkPrice | Fair price (index + basis) | Futures, avoid wicks |
Example of why this matters:
Scenario: Flash crash on Backpack only
LastPrice: Drops from $100,000 to $80,000 (bad data/manipulation)
IndexPrice: Stays at $99,000 (other exchanges stable)
MarkPrice: Stays at $99,500 (calculated fair value)
Your stop-loss at $95,000:
- TriggerBy=LastPrice → TRIGGERED (bad!)
- TriggerBy=IndexPrice → Safe (not triggered)
- TriggerBy=MarkPrice → Safe (not triggered)Pro tip: Use IndexPrice or MarkPrice for stop-losses to avoid getting stopped out by wicks or manipulation.
Trigger Quantity Options
You can also specify quantities dynamically:
| Type | Example | Behavior |
|---|---|---|
| Fixed | 1.5 BTC | Always this exact amount |
| Percentage | 50% | Percentage of current position |
Percentage is powerful for scaling out:
Position: 10 BTC
Take-Profit 1: Trigger $105k, Quantity 50% → Sells 5 BTC
Take-Profit 2: Trigger $110k, Quantity 100% → Sells remaining 5 BTCAutomatic Stop-Loss/Take-Profit Creation
When you place an order with SL/TP parameters, the system automatically creates the trigger orders when your main order fills:
Order: Buy 10 BTC at $100,000
- stop_loss_trigger_price: $95,000
- take_profit_trigger_price: $110,000
After fill:
1. You now own 10 BTC at $100,000
2. Stop-Loss created: Sell 10 BTC if price hits $95,000
3. Take-Profit created: Sell 10 BTC if price hits $110,000Important: These orders are created with reduce_only: true automatically, so they can only close your position.
5. Order Lifecycle
Order States
| State | Meaning | Terminal? |
|---|---|---|
| New | Order accepted, on book, unfilled | No |
| PartiallyFilled | Some quantity executed, remainder on book | No |
| Filled | Completely executed | Yes |
| Cancelled | Cancelled by user | Yes |
| Expired | Cancelled by system (IOC, FOK, insufficient margin, etc.) | Yes |
| TriggerPending | Trigger order waiting for price condition | No |
| TriggerFailed | Trigger couldn't activate (no position, etc.) | Yes |
State Machine Diagram
┌──────────────┐
│ SUBMIT │
└──────┬───────┘
│
┌────────────┼────────────┐
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────────┐
│ NEW │ │ EXPIRED │ │TRIGGER_PENDING│
└────┬─────┘ └──────────┘ └───────┬──────┘
│ │
┌────────┼────────┐ ┌────────┼────────┐
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐ ┌──────────┐ ┌────────────┐
│PARTIAL │ │FILLED │ │CANCELLED││ NEW │ │TRIGGER_FAIL│
│FILLED │ └────────┘ └────────┘ │(regular) │ └────────────┘
└───┬────┘ └──────────┘
│
├───────────┬───────────┐
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌──────────┐
│FILLED │ │CANCELLED│ │ EXPIRED │
└────────┘ └────────┘ └──────────┘Order Events
As orders progress through their lifecycle, events are emitted:
| Event | When |
|---|---|
| Accepted | Order reaches matching engine |
| Placed | Limit order rests on book (didn't fully fill) |
| Fill | Partial or complete execution |
| Cancelled | User-initiated cancellation |
| Expired | System-initiated cancellation with reason |
| TriggerPlaced | Trigger order registered |
| Triggered | Trigger condition met, order activated |
| TriggerFailed | Trigger couldn't fire (reason provided) |
Expiry Reasons
When an order is expired (not by you), here's why:
Margin/Funds:
InsufficientFunds- Not enough balanceInsufficientMargin- Would breach margin requirementsNegativeEquity- Account underwater
Order Validation:
PostOnlyTaker- Post-only order would take liquidityFillOrKill- FOK order couldn't fill completelyImmediateOrCancel- IOC unfilled portionSlippageToleranceExceeded- Price moved too far
Position/Risk:
ReduceOnlyNotReduced- Reduce-only order wouldn't reduce positionStopWithoutPosition- Trigger order for non-existent positionMaxStopOrdersPerPosition- Too many trigger ordersPositionLimit- Would exceed position limits
Market State:
OrderBookClosed- Market not accepting ordersPostOnlyMode- Market only accepting maker ordersInsufficientLiquidity- Not enough liquidity for market order
6. Common Mistakes & Gotchas
Mistake 1: Market Orders in Thin Books
Problem: Market order gets terrible fill due to slippage.
You expect: Buy at ~$100
Reality: $100 (10), $105 (10), $120 (80)
Your 100-unit market buy: Average price $116!Solution: Use limit orders, or check order book depth before market orders.
Mistake 2: Stop-Loss Below Current Price for Shorts
Problem: Placing stop-loss on wrong side.
You're SHORT at $100
Wrong: Stop-loss at $95 (that's take-profit territory!)
Right: Stop-loss at $105 (protects against price rising)Remember:
- LONG stop-loss = BELOW entry (price dropping hurts you)
- SHORT stop-loss = ABOVE entry (price rising hurts you)
Mistake 3: Stop-Market vs Stop-Limit in Fast Markets
Problem: Stop-limit doesn't fill during gap.
Your position: LONG at $100
Stop-limit: Trigger $95, Limit $94.50
Price gaps from $96 → $90 (fast crash)
Your limit order at $94.50 sits unfilled
You're still LONG as price continues to $80Solution: For stop-losses, consider stop-market (no limit price) if guaranteed exit matters more than price.
Mistake 4: Post-Only Rejected at Market Price
Problem: Post-only order keeps getting rejected.
Best ask: $100.10
Best bid: $100.00
You try: Post-Only SELL at $100.05
Result: Rejected (would cross spread)
You try: Post-Only SELL at $100.00
Result: Rejected (would match bids)
You need: Post-Only SELL at $100.15 or higherSolution: Post-only must be on YOUR side of the book:
- Post-only SELL → Above best ask
- Post-only BUY → Below best bid
Mistake 5: FOK with Insufficient Liquidity
Problem: FOK order fails because book can't fill entire size.
You need exactly 100 units
Book has: 50 at $100, 100 at $101
FOK BUY 100 at $100 → REJECTED (only 50 available)
IOC BUY 100 at $100 → Fills 50, cancels 50Solution: Use IOC if partial fills are acceptable, or increase your limit price for FOK.
Mistake 6: Reduce-Only with No Position
Problem: Reduce-only order fails because there's nothing to reduce.
Position: None (flat)
Order: Reduce-only SELL 10 BTC
Result: Order REJECTED or EXPIRED
Reason: ReduceOnlyNotReducedSolution: Only use reduce-only when you have an existing position to close.
Mistake 7: Trigger Orders Not Filling After Trigger
Problem: Trigger fires but order doesn't fill.
Stop-loss: Trigger $95, Limit $94.50
Price drops: $96 → $95 (trigger!) → $94 (below your limit)
Trigger fired, created limit order at $94.50
But price is now $94, no one wants to buy at $94.50
Order sits unfilledSolution:
- Use stop-market for guaranteed fills
- Set limit price with buffer (e.g., trigger $95, limit $94)
Mistake 8: TriggerBy=LastPrice During Volatility
Problem: Stop triggered by a wick, not real price movement.
Your stop: $95,000
Last price: Briefly touches $94,900 (1 trade, immediately bounces)
Index price: Never dropped below $98,000
Using TriggerBy=LastPrice: You got stopped out
Using TriggerBy=IndexPrice: You're still in the tradeSolution: Use IndexPrice or MarkPrice for stops in volatile conditions.
Quick Reference: Order Type Decision Tree
Need to execute NOW?
├─ YES: How important is exact fill size?
│ ├─ Must fill exactly: FOK
│ ├─ Partial OK: IOC or Market
│ └─ Don't care: Market
│
└─ NO: Are you providing liquidity?
├─ YES: Limit + Post-Only + GTC
└─ NO: Limit + GTC (most common)
Need to protect position?
├─ Limit losses: Stop-Loss
│ └─ Guaranteed exit? Stop-Market
│ └─ Better price? Stop-Limit
└─ Lock gains: Take-Profit
└─ Same considerations as StopSummary Table
| Order Type | Price Certainty | Fill Certainty | Best For |
|---|---|---|---|
| Market | None | High | Urgent exits |
| Limit GTC | High | Low | Patient entries |
| Limit IOC | High | Medium | Immediate execution, price cap |
| Limit FOK | High | Low | All-or-nothing |
| Limit Post-Only | High | Low | Market making |
| Stop-Market | Low | High | Guaranteed stop-loss |
| Stop-Limit | High | Low | Precise stop-loss |
| Take-Profit | High | Low | Locking gains |