TWAP - Time-Weighted Average Price Execution
TL;DR
- TWAP splits a large order into smaller slices executed at regular time intervals, reducing market impact
- How it works: You specify a total quantity, duration, and interval. The system calculates
interval_count = duration / intervalandinterval_quantity = quantity / interval_count, then places a market order each interval - Slippage protection enforces a maximum price deviation per slice: either percent-based (0.01%--9.99%) or tick-size-based (1--10,000 ticks from the best price). If slippage is exceeded, the entire strategy cancels
- Randomization mode adds up to +/-20% variance to each slice quantity, making your execution pattern harder to detect. The final interval is adjusted to hit the exact total
- Auto-cancellation triggers on slippage exceeded, insufficient funds/margin, insufficient liquidity, liquidation risk, and other error conditions
- Supported on both spot and perpetual markets with optional reduce-only and auto-borrow/auto-lend modifiers
- Use case: You want to buy or sell a large position over minutes or hours without moving the market against yourself
1. What Is TWAP and Why Use It?
Time-Weighted Average Price (TWAP) is an execution algorithm that breaks a large order into equal-sized slices and executes them at fixed time intervals. The goal is to achieve an average execution price close to the market's time-weighted average over the execution window.
The Problem: Market Impact
When you place a single large market order, you "walk the book" -- consuming liquidity at progressively worse prices. A 100 SOL market buy might look like this:
Single Market Order: Buy 100 SOL
Order Book Asks:
$150.00 (20 SOL) ← filled
$150.05 (30 SOL) ← filled
$150.15 (25 SOL) ← filled
$150.40 (25 SOL) ← filled
Result: 100 SOL filled, average price $150.14
Slippage from best ask: $0.14 per SOL = 0.093%
Total extra cost: $14.00That 0.09% might seem small, but on a $1M order it is $930 of slippage. Worse, other participants see the price spike and front-run you, pushing costs even higher.
The TWAP Solution
Instead of one large order, TWAP spreads execution over time:
TWAP: Buy 100 SOL over 10 minutes, 1-minute intervals
Minute 1: Buy 10 SOL at market → filled @ $150.01
Minute 2: Buy 10 SOL at market → filled @ $149.98
Minute 3: Buy 10 SOL at market → filled @ $150.05
Minute 4: Buy 10 SOL at market → filled @ $150.02
Minute 5: Buy 10 SOL at market → filled @ $149.95
Minute 6: Buy 10 SOL at market → filled @ $150.08
Minute 7: Buy 10 SOL at market → filled @ $150.00
Minute 8: Buy 10 SOL at market → filled @ $150.03
Minute 9: Buy 10 SOL at market → filled @ $149.97
Minute 10: Buy 10 SOL at market → filled @ $150.01
Average price: $150.01Each 10 SOL slice barely moves the book. The order book has time to replenish liquidity between slices. Your average price reflects the true market price over the window, not a one-time liquidity hole.
When TWAP Makes Sense
| Situation | Use TWAP? | Why |
|---|---|---|
| Large order relative to book depth | Yes | Splits impact across time |
| Position exit over hours | Yes | Avoids signaling a dump |
| Small order, deep book | No | Single market order is fine |
| Time-sensitive exit (liquidation risk) | No | Need immediate execution |
| Volatile market, unclear direction | Maybe | TWAP gives you average price, but market may trend against you |
2. How Backpack's TWAP Works
Backpack implements TWAP as a scheduled strategy -- a server-side algorithm that runs in the exchange's execution engine. You submit the strategy once, and the system manages slicing, scheduling, and order placement automatically.
Architecture Overview
┌─────────────────────────────────────────────────────────┐
│ Your API Request │
│ POST /api/v1/strategy (quantity, duration, interval) │
└──────────────────────────┬──────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Validation Layer │
│ - Parameter bounds check │
│ - Interval divides duration evenly │
│ - Slippage tolerance valid │
│ - Account has sufficient funds/margin │
└──────────────────────────┬──────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Strategy Crank │
│ Runs every 500ms, checks all active strategies │
│ │
│ For each strategy: │
│ 1. Is it time for the next slice? │
│ 2. Calculate slice quantity (with randomization?) │
│ 3. Place market order with slippage tolerance │
│ 4. Record fill, advance to next interval │
│ 5. If final interval → execute remaining quantity │
└──────────────────────────┬──────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Matching Engine │
│ Market order fills against the order book │
│ Slippage tolerance enforced as a limit price │
└─────────────────────────────────────────────────────────┘The Execution Crank
The strategy crank is a background process that polls every 500 milliseconds. On each tick, it checks all active TWAP strategies and determines if any are due for their next slice. This means your interval timing has up to 500ms of jitter -- an order scheduled at t=60s might execute at t=60.0s to t=60.5s. This jitter is negligible for the minute-scale intervals TWAP typically uses.
3. Parameters
When creating a TWAP strategy, you provide the following parameters:
Required Parameters
| Parameter | Type | Description |
|---|---|---|
| symbol | string | Trading pair (e.g., SOL_USDC, BTC_USDC_PERP) |
| side | string | Bid (buy) or Ask (sell) |
| quantity | decimal | Total quantity to execute in base asset units |
| duration | integer | Total execution window in seconds |
| interval | integer | Time between slices in seconds |
| slippageTolerance | object | Maximum allowed price deviation per slice |
Slippage Tolerance (one of two formats)
Percent-based:
{
"slippageTolerance": {
"percent": "0.50"
}
}Allowed range: 0.01% to 9.99%. Each slice's market order is capped at a price that is percent% worse than the best available price at the time of execution.
Tick-size-based:
{
"slippageTolerance": {
"ticks": 5
}
}Allowed range: 1 to 10,000 ticks. Each slice's market order is capped at the best price plus (or minus, for sells) the specified number of tick increments for that market.
Optional Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| randomizedIntervalQuantity | boolean | false | Enable +/-20% randomization on slice quantities |
| reduceOnly | boolean | false | Only reduce an existing position (perp markets) |
| autoBorrow | boolean | false | Borrow assets if needed (spot, requires margin) |
| autoLend | boolean | false | Lend proceeds automatically |
4. The Math: Interval Slicing
TWAP divides your order into evenly sized slices using straightforward arithmetic.
Core Formulas
interval_count = duration / interval
interval_quantity = quantity / interval_countConstraint: duration must be evenly divisible by interval. If duration = 600s and interval = 90s, the request is rejected because 600 / 90 = 6.67 (not a whole number).
Worked Example
Parameters:
quantity = 100 SOL
duration = 600 seconds (10 minutes)
interval = 60 seconds (1 minute)
Calculation:
interval_count = 600 / 60 = 10
interval_quantity = 100 / 10 = 10 SOL
Execution Plan:
Slice 1 at t=0:00 → Market buy 10 SOL
Slice 2 at t=1:00 → Market buy 10 SOL
Slice 3 at t=2:00 → Market buy 10 SOL
Slice 4 at t=3:00 → Market buy 10 SOL
Slice 5 at t=4:00 → Market buy 10 SOL
Slice 6 at t=5:00 → Market buy 10 SOL
Slice 7 at t=6:00 → Market buy 10 SOL
Slice 8 at t=7:00 → Market buy 10 SOL
Slice 9 at t=8:00 → Market buy 10 SOL
Slice 10 at t=9:00 → Market buy 10 SOL
─────────────────
Total: 100 SOL over 10 minutesThe first slice executes immediately when the strategy starts (t=0). The last slice executes at duration - interval (t=9:00 in this example), so the entire execution completes within the specified duration window.
Another Example: Short Duration, Tight Intervals
Parameters:
quantity = 5 BTC
duration = 120 seconds (2 minutes)
interval = 30 seconds
Calculation:
interval_count = 120 / 30 = 4
interval_quantity = 5 / 4 = 1.25 BTC
Execution Plan:
Slice 1 at t=0:00 → Market sell 1.25 BTC
Slice 2 at t=0:30 → Market sell 1.25 BTC
Slice 3 at t=1:00 → Market sell 1.25 BTC
Slice 4 at t=1:30 → Market sell 1.25 BTC
─────────────────────
Total: 5 BTC over 2 minutes5. Randomization Mode
By default, every slice is exactly interval_quantity. This creates a predictable, detectable pattern: the same quantity hitting the market at the same interval. Sophisticated participants can detect this and front-run your remaining slices.
How Randomization Works
When randomizedIntervalQuantity is enabled, each slice quantity is randomly adjusted by up to +/-20% from the base interval_quantity:
randomized_quantity = interval_quantity * (1 + random(-0.20, +0.20))Worked Example with Randomization
Parameters:
quantity = 100 SOL, duration = 600s, interval = 60s
randomizedIntervalQuantity = true
interval_quantity = 10 SOL
Randomization range: 8.0 SOL to 12.0 SOL per slice
Possible Execution:
Slice 1: 10.0 SOL (first slice, no randomization)
Slice 2: 11.4 SOL (+14%)
Slice 3: 8.3 SOL (-17%)
Slice 4: 11.9 SOL (+19%)
Slice 5: 9.1 SOL ( -9%)
Slice 6: 10.8 SOL ( +8%)
Slice 7: 8.6 SOL (-14%)
Slice 8: 11.2 SOL (+12%)
Slice 9: 9.5 SOL ( -5%)
──────────────────────────
Subtotal: 90.8 SOL (after 9 slices)
Slice 10: 9.2 SOL ← Exact remainder to hit 100 SOL total
──────────────────────────
Total: 100.0 SOL ✓The Final Interval Rule
The final slice always executes the exact remaining quantity, regardless of randomization. This guarantees that you get your full requested quantity. If randomized slices happened to run slightly above or below the expected cumulative total, the last slice compensates.
Why Randomize?
Without randomization: With randomization:
Volume Volume
│ │
│ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ │ ██ ██
│ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ │ ██ ██ ██ ██ ██ ██
│ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ │ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
└────────────────────────────── └──────────────────────────────
1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10
Interval Interval
Pattern: Obvious Pattern: Harder to detectRandomization makes your TWAP less vulnerable to front-running by other participants who monitor for repetitive execution patterns.
6. Slippage Protection
Each slice in a TWAP strategy is a market order, but market orders can fill at arbitrarily bad prices if the book is thin. Slippage tolerance acts as a safety net: it converts each market order into a limit order at the worst acceptable price.
Percent-Based Slippage
For a buy order with percent: 0.50 (0.50% tolerance):
best_ask = $150.00
max_buy_price = $150.00 * (1 + 0.0050) = $150.75
The slice's market order becomes: Limit BUY at $150.75
→ Fills at $150.00-$150.75 (whatever is available)
→ If the book is empty below $150.75, partial fill or no fillFor a sell order with percent: 0.50:
best_bid = $150.00
min_sell_price = $150.00 * (1 - 0.0050) = $149.25
The slice's market order becomes: Limit SELL at $149.25
→ Fills at $149.25-$150.00Valid range: 0.01% to 9.99%. Values outside this range are rejected at submission time.
Tick-Size-Based Slippage
Tick-based slippage uses the market's minimum price increment (tick size) instead of a percentage.
For a buy order on SOL_USDC (tick size = $0.01) with ticks: 5:
best_ask = $150.00
max_buy_price = $150.00 + (5 * $0.01) = $150.05
The slice's market order becomes: Limit BUY at $150.05For a sell order with ticks: 5:
best_bid = $150.00
min_sell_price = $150.00 - (5 * $0.01) = $149.95
The slice's market order becomes: Limit SELL at $149.95Valid range: 1 to 10,000 ticks.
Comparison: Percent vs Tick-Size
| Aspect | Percent-Based | Tick-Size-Based |
|---|---|---|
| Scales with price | Yes (0.5% of $100 = $0.50; 0.5% of $100,000 = $500) | No (5 ticks always = 5 * tick_size) |
| Best for | Assets at varying price levels | Precise control on a single market |
| Intuition | "I accept up to X% worse" | "I accept up to N price levels worse" |
| Risk on volatile assets | Scales proportionally | Fixed absolute limit |
What Happens When Slippage Is Exceeded
If a slice cannot fill within the slippage tolerance, the entire TWAP strategy is cancelled -- not just the one slice. This is a deliberate safety design: if market conditions have deteriorated enough that a single slice cannot execute within tolerance, continuing to place more slices is likely to result in poor fills.
Slice 5 of 10: Buy 10 SOL
best_ask = $155.00 (market moved sharply)
tolerance = 0.50%
max_price = $155.78
Order book asks: $156.00 (all liquidity above tolerance)
→ Slice fails: SlippageToleranceExceeded
→ Entire strategy cancelled
→ Slices 6-10 will NOT execute
→ You have 40 SOL filled from slices 1-47. Auto-Cancellation Reasons
A TWAP strategy can be cancelled by the user at any time, but the system will also automatically cancel the strategy if it encounters conditions that make continued execution unsafe or impossible.
Cancellation Reasons
| Reason | Description | What to Do |
|---|---|---|
| SlippageToleranceExceeded | A slice could not fill within your specified tolerance | Widen tolerance or wait for calmer conditions |
| InsufficientFunds | Account lacks the balance to fund the next slice | Deposit more funds or reduce remaining quantity |
| InsufficientMargin | Next slice would breach margin requirements (perp) | Add collateral or reduce position size |
| InsufficientLiquidity | Order book is empty or too thin for the slice | Wait for deeper liquidity |
| Liquidation | Account is at risk of or undergoing liquidation | Address margin health immediately |
| UserCancelled | You manually cancelled the strategy via API or UI | N/A |
Partial Completion
When a strategy is auto-cancelled, all slices that already filled remain filled. Cancellation stops future slices but does not reverse past executions. Your resulting position reflects however many slices completed successfully.
Example: 10-slice TWAP, cancelled after slice 6
Slices 1-6: Filled (60 SOL purchased)
Slices 7-10: Not executed
Your position: 60 SOL (not 0, not 100)
Strategy status: Cancelled (reason: SlippageToleranceExceeded)8. Practical Examples
Example 1: Large Spot Buy
You want to accumulate 500 SOL without spiking the price.
Strategy:
symbol: SOL_USDC
side: Bid (buy)
quantity: 500 SOL
duration: 1800 seconds (30 minutes)
interval: 180 seconds (3 minutes)
slippageTolerance: { percent: "1.00" }
randomizedIntervalQuantity: true
Calculation:
interval_count = 1800 / 180 = 10
interval_quantity = 500 / 10 = 50 SOL per slice
Execution (randomized):
t=0:00 Buy ~50 SOL (first slice, exact)
t=3:00 Buy ~42 SOL
t=6:00 Buy ~58 SOL
t=9:00 Buy ~47 SOL
...
t=27:00 Buy [remainder] SOL ← exact amount to total 500
Each slice:
- Checks best ask price
- Sets limit price = best_ask * 1.01
- Fills up to that price
- If cannot fill → strategy cancelsExample 2: Perp Position Exit with Reduce-Only
You are long 20 BTC on the perpetual market and want to unwind over an hour without signaling a large sell.
Strategy:
symbol: BTC_USDC_PERP
side: Ask (sell)
quantity: 20 BTC
duration: 3600 seconds (1 hour)
interval: 300 seconds (5 minutes)
slippageTolerance: { ticks: 10 }
reduceOnly: true
Calculation:
interval_count = 3600 / 300 = 12
interval_quantity = 20 / 12 = 1.667 BTC per slice
Key behavior:
- reduceOnly ensures the strategy can only close your long, never flip short
- If your position is closed early (e.g., by a separate order), the strategy
will cancel because reduce-only has nothing to reduce
- tick-based slippage: each sell can go up to 10 ticks below best bidExample 3: Quick Execution with Tight Slippage
You want to sell 1,000 USDC worth of a token quickly but still split it up.
Strategy:
symbol: TOKEN_USDC
side: Ask (sell)
quantity: 10,000 TOKEN
duration: 60 seconds (1 minute)
interval: 10 seconds
slippageTolerance: { percent: "0.10" }
Calculation:
interval_count = 60 / 10 = 6
interval_quantity = 10,000 / 6 = 1,666.67 TOKEN per slice
Note: With tight 0.10% tolerance on a 10-second interval, any sudden spread
widening will cancel the strategy. This configuration favors liquid markets.9. TWAP vs Regular Orders: When to Use Each
Decision Framework
Order Size vs Book Depth:
Order < 5% of top-of-book depth
└─ Single market or limit order is fine
Order = 5-20% of top-of-book depth
└─ Consider TWAP if you can wait
└─ Limit order works if you're patient
Order > 20% of top-of-book depth
└─ TWAP strongly recommended
└─ Single market order will suffer significant slippageComparison Table
| Factor | Market Order | Limit Order | TWAP |
|---|---|---|---|
| Speed | Instant | Uncertain | Gradual (minutes to hours) |
| Price certainty | None | Exact price | Average over time window |
| Market impact | High for large orders | None (passive) | Low (spread across time) |
| Execution guarantee | High | Low | Moderate (can be cancelled) |
| Complexity | None | None | Must choose duration, interval, tolerance |
| Best for | Small/urgent orders | Price-sensitive entries | Large orders in size |
| Risk | Slippage | Never fills | Partial fill if cancelled; market trends against you |
When NOT to Use TWAP
- Emergency exits: If you are being liquidated or need to exit now, a market order is faster and simpler.
- Illiquid markets: If the order book is consistently thin, TWAP slices will each struggle with slippage. A single limit order at your target price may be more effective.
- Trending markets: TWAP gives you the average price. If the market is trending strongly against you (rising when you are buying), you will get progressively worse fills. A single immediate execution could be cheaper.
- Very small orders: If your order is small relative to available liquidity, the overhead of a TWAP strategy is unnecessary.
10. Spot and Perpetual Market Support
TWAP works on both spot and perpetual futures markets on Backpack, with slightly different behaviors and options for each.
Spot Markets
On spot markets, TWAP places actual buy or sell orders for the underlying asset:
- Buying: Each slice purchases base asset (e.g., SOL) using quote asset (e.g., USDC). You need sufficient quote balance or auto-borrow enabled.
- Selling: Each slice sells base asset for quote asset. You need sufficient base balance.
- autoBorrow: If enabled, the system borrows the needed asset from the lending pool if your balance is insufficient for a slice. Interest accrues on borrowed amounts. See Borrow & Lend for details.
- autoLend: If enabled, proceeds from sell slices are automatically lent to the lending pool to earn interest.
Perpetual Markets
On perpetual markets, TWAP opens or closes futures positions:
- Buying (Bid): Each slice goes long or reduces a short position.
- Selling (Ask): Each slice goes short or reduces a long position.
- reduceOnly: When enabled, the strategy can only reduce an existing position. It will not open a new position or flip your side. If the position is fully closed before the strategy completes, the remaining slices are cancelled.
- Margin: Each slice requires sufficient margin. If margin becomes insufficient mid-execution, the strategy auto-cancels.
Feature Matrix
| Feature | Spot | Perpetual |
|---|---|---|
| Buy / Sell | Yes | Yes (Long / Short) |
| Slippage tolerance | Yes | Yes |
| Randomization | Yes | Yes |
| Reduce-only | No | Yes |
| Auto-borrow | Yes | No |
| Auto-lend | Yes | No |
| Margin requirements | No (balance-based) | Yes |
| Funding rate impact | No | Yes (for longer durations) |
11. API Reference
Create a TWAP Strategy
POST /api/v1/strategyRequest body:
{
"symbol": "SOL_USDC",
"side": "Bid",
"quantity": "100",
"duration": 600,
"interval": 60,
"slippageTolerance": {
"percent": "0.50"
},
"randomizedIntervalQuantity": false,
"reduceOnly": false,
"autoBorrow": false,
"autoLend": false
}Get Strategy Status
GET /api/v1/strategy/:strategyIdReturns the current state of the strategy, including how many slices have executed, the quantity filled so far, and the current status (active, completed, or cancelled with reason).
Cancel a Strategy
DELETE /api/v1/strategy/:strategyIdImmediately stops the strategy. Slices already filled are not reversed. Remaining slices will not execute.
12. Risks and Edge Cases
Price Trending Against You
TWAP is not an opinion on direction -- it gives you the average price over time. If the market moves strongly against you during execution, TWAP will dutifully fill at worse and worse prices:
Scenario: Buying 100 SOL over 10 minutes while SOL rallies
Slice 1: Buy 10 @ $150.00
Slice 2: Buy 10 @ $150.50
Slice 3: Buy 10 @ $151.20
...
Slice 10: Buy 10 @ $155.00
Average: $152.50
If you had bought all 100 at once: ~$150.20
TWAP cost you an extra $2.30/SOL = $230 totalThis is the fundamental trade-off: TWAP protects against impact but exposes you to drift. It works best in range-bound or mean-reverting markets.
Partial Fills and Cancellation
If the strategy cancels partway through, you are left with a partial position. Plan for this:
- On perp markets, a partial long/short position still requires margin and is subject to liquidation.
- On spot markets, you may hold a partial base asset position that you did not intend to hold indefinitely.
Thin Order Books
If the order book is consistently thin, many slices may fail slippage checks, leading to early cancellation. Check the order book depth for your target market before starting a TWAP. A good rule of thumb: each slice quantity should be less than the typical top-of-book depth on the side you are trading.
Crank Timing
The strategy crank runs every 500ms. For very short intervals (e.g., 10 seconds), the 500ms polling cycle introduces minimal jitter. For intervals of 1 second or less (not recommended), the jitter could be significant relative to the interval.
Summary
TWAP is Backpack's execution algorithm for splitting large orders into time-distributed slices. The key mechanics:
- You define the total quantity, execution window (duration), and slice frequency (interval)
- The system calculates
interval_count = duration / intervaland places one market order per interval - Slippage tolerance protects each slice from filling at unacceptable prices (percent-based or tick-based)
- Randomization (optional) varies slice sizes by +/-20% to disguise your execution pattern
- Auto-cancellation halts the strategy if any slice encounters an error condition (slippage, funds, margin, liquidity, liquidation)
- Partial fills are kept -- cancellation stops future slices but does not reverse past ones
Use TWAP when your order is large relative to available liquidity and you can afford to execute over minutes or hours. Use regular market or limit orders when speed matters more than impact, or when your order is small enough that slippage is negligible.