TWAP
TWAP orders split one total size across time. Market TWAPs run on Hyperliquid (up to 24h) or by Borsa on your device or in the cloud (up to 30 days); Limit ALO TWAPs always run on Borsa. Full mechanics, fees, edge cases.
A TWAP (Time-Weighted Average Price) order takes one total size and spreads it across a duration as a series of smaller fills. The Execution toggle in the TWAP panel picks Market or Limit (ALO). For Market, Run by picks who sends the slices: Hyperliquid or Borsa.
Two Modes
Market, run by Hyperliquid
Native to Hyperliquid. The exchange's twapOrder action takes total size + minutes + randomization flag, and the exchange itself slices and submits IOC takers internally over the duration. The duration is capped at 24 hours by the exchange, and the TWAP is visible on-chain.
Market, run by Borsa
Same goal, but Borsa sends one IOC limit per slice on its own schedule, so there is no TWAP trace on-chain. The duration can be up to 30 days. Where it runs follows your default run location in Settings (Cloud strategies → Default run location), and the Run by button names it:
- Borsa, this device: runs in this browser. Keep the tab open (you can switch to other tabs or apps).
- Borsa Cloud: runs on Borsa Cloud 24/7 with the browser closed. If the cloud can't take the run, it falls back to this device and tells you why.
Limit (ALO)
A passive-maker TWAP. Borsa rests a single ALO limit at the best bid (buy) or ask (sell), cancels/reposts on an interval as the book moves, and advances to the next chunk when the current one fills. It always runs on Borsa, on this device or on Borsa Cloud, following the same default run location.
Borsa-run TWAPs (Market run by Borsa, and Limit ALO) appear in the Strategies tab, not the TWAP tab. See Strategies.
Execution Model: Market, Run by Hyperliquid
Wire format
{
type: "twapOrder",
twap: {
a: <asset_id>,
b: <isBuy>,
s: <total size>,
r: <reduceOnly>,
m: <minutes>,
t: <randomize boolean>
}
}
One request. The exchange returns a twapId. From then on, all slices fire server-side and appear in the TWAP activity tab. You cancel the whole TWAP via twapCancel.
Pacing
The exchange decides slice size and timing. The total minutes you set is the wall-clock duration. Randomization, when enabled, applies a small (≈30%) jitter to slice timing and size.
Trigger and terminate prices
Two optional fields ride along in the same action as details: { t, s }:
- Trigger price (optional): the TWAP stays dormant on-chain and activates when the mark price reaches this level. Above or below is inferred from the current price. Leave it empty (Start now) to start immediately.
- Max buy price (optional) / Min sell price (optional): an on-chain terminate price. The exchange permanently ends the TWAP when the mark price crosses it (buys above, sells below). It does not pause and resume.
Minimum
Hyperliquid enforces $10 per minute total notional. So a 30-minute TWAP needs at least $300 total, a 60-minute at least $600, and so on. The UI rejects sub-minimum configs.
Execution Model: Market, Run by Borsa
Borsa runs a single async loop per active TWAP.
Per slice:
- Wait until
nextChunkTime. - Read current mid from the WS cache.
- Build an IOC limit at
mid × (1 ± 5%)forchunkSize(with jitter if randomize on). With a price bound set, the IOC limit never crosses it. - POST as a single-order action.
- Record fill into the strategy execution history.
- Set
nextChunkTime = now + intervalSeconds × jitter. - Loop until
totalSizeis reached or you cancel.
Pacing has two modes:
- Duration: one slice every 30 seconds across the duration, fewer if a slice would fall below $10:
numChunks = min(floor(minutes × 60 / 30), floor(totalSize × midPrice / MIN_ORDER_VALUE_USD))
chunkSize = totalSize / numChunks
intervalSeconds = (minutes × 60) / numChunks
- Frequency: you set the spacing (every N seconds or minutes) or Fastest (the next order sends the instant the previous one fills), and split the size by Orders (a count) or Order size (size per order). The count is still capped so each slice is at least $10.
The panel summary shows the resulting number of orders, size per order and runtime before you submit.
Max buy price (optional) / Min sell price (optional) is a hard price bound here: slices pause while the market is beyond it and resume when price comes back. Fills never cross it, but the full size may take longer, or never complete, if the market runs away.
The executor persists progress per-strategy so a page reload resumes from the last-completed chunk.
Execution Model: Limit ALO
This is more complex. Borsa runs a single async loop that posts and modifies one ALO limit at a time, advancing as fills happen.
Per tick:
- Read the book quote (best bid / best ask) from the L2 book WS subscription.
- Compute target price: best ± offsetPct (default 0%, i.e. exactly at the best). Apply optional
priceCapto never cross past a user-defined ceiling/floor. - If a resting ALO already exists at a stale price, send
modifywith the new price (preserves cloid + queue priority on platforms that respect it). - If none exists, post a new ALO with a freshly generated
cloid. - On WS order-update events, track fills against the resting order's oid. When a fill comes in:
- Reduce remaining chunk size.
- If chunk filled, advance to next chunk.
- Re-tick on book changes or every
aloRepostSeconds(default 5s).
Max wait / order (s) (default 0): after this long unfilled, the resting order steps toward the touch to complete (a more aggressive maker that still never crosses). 0 keeps it at your offset until it fills.
Adaptive offset
With Adaptive offset on, the fixed offset and price cap are replaced by a price range. Set From price (the passive end, where execution starts; it also acts as the cap), To price (the urgent end), Offset at from (%) and Offset at to (%), and the Curve shape. The order rests further from the touch at the passive end and tightens as price moves toward To price. With Taker beyond ‘to’ on (the default), once price passes To price each chunk crosses the spread as a chunk-sized IOC instead of resting; pacing still applies. Not available on outcomes.
Cloid tracking
Each ALO post generates a random 16-byte cloid. The executor maintains a cloidToKey map so order-update WS events can be routed back to the right strategy. Modify-replace flows use expectingOpen to handle the brief race between the canceled-old event and the open-new event.
Persistence
The resting order (oid, cloid, price, size, posted-at) is persisted into the strategy state. On page refresh, the executor adopts the existing resting order instead of cancelling and re-posting — no lost queue priority.
Take Profit
In Limit ALO mode you can attach a per-fill TP. After each chunk fills, a TP order is posted matching the configured mode:
- Percent: TP at
fillPrice × (1 ± percent/100). - Absolute: TP at a fixed price you set.
Inputs
| Input | Required | Modes | Notes |
|---|---|---|---|
Side | Yes | All | Long/Short. |
Total Size | Yes | All | Base asset across the whole schedule. |
Duration | Yes | Market | Presets or a custom value (the unit button cycles m, h, d). 5 minutes to 24 hours when run by Hyperliquid (presets 15m to 24h); up to 30 days when run by Borsa (presets 1h, 4h, 24h, 3d, 7d, 30d). Switching to Hyperliquid caps a longer duration at 24h. |
Frequency | Optional | Market, run by Borsa | Pacing by spacing (every N s or min, default 30s) or Fastest, split by Orders (default 10) or Order size. Picking it switches Run by to Borsa. |
Run by | Yes | Market | Hyperliquid (on-chain) or Borsa (Borsa, this device or Borsa Cloud). |
Max buy price / Min sell price | Optional | Market | Hyperliquid: on-chain terminate price. Borsa: pause-and-resume price bound. |
Trigger price | Optional | All | Starts the TWAP when the price reaches it. Hyperliquid holds it on-chain (mark price); a TWAP run by Borsa waits in the Strategies tab until the mid price reaches it. |
Randomize size and timing | Optional | All | Adds jitter to slice timing/size (on by default). |
Number of orders | Yes | Limit ALO | How many chunks to split total into (default 15). Each chunk must be at least $10. |
Reprice interval (s) | Yes | Limit ALO | Seconds between cancel-and-repost (default 5, max 300). |
Max wait / order (s) | Optional | Limit ALO | Step toward the touch after this long unfilled (0 = never). |
Adaptive offset | Optional | Limit ALO | Price-range offset instead of a fixed one. See above. |
Offset from best bid / ask (%) | Optional | Limit ALO | Place away from best. Positive = more passive. |
Max bid price / Min ask price (optional) | Optional | Limit ALO | Never cross past this price. |
Reduce Only | Optional | All | Applies to every slice / chunk. |
Take Profit | Optional | Limit ALO | Adds a reduce-only TP after each filled chunk (% from fill or Absolute price). |
Fees
- Market, run by Hyperliquid: every slice is a taker IOC; you pay taker fees on each fill.
- Market, run by Borsa: same as native but signed by your agent key (or the Borsa Cloud agent); taker fees apply.
- Limit ALO — every fill is maker; you pay maker fees (lower). TPs are limit or trigger, fee'd per their kind.
When to Use
- You have a size large enough that sending it all at once would meaningfully move the book. Stagger it.
- You want passive participation over time without manual reposting. Limit ALO mode.
- You want a benchmark execution against time-weighted average price. Market.
- You want to work an order over days. Market run by Borsa on Borsa Cloud (up to 30 days, browser closed).
When Not to Use
- You need to be filled now. Use Market or Burst.
- You want price-range distribution rather than time distribution. Use Scale.
Edge Cases & Failures
- Browser closes during a Borsa-run TWAP. Hyperliquid-run TWAPs and Borsa Cloud runs are unaffected. TWAPs running on this device pause until the page is reopened. Progress is persisted; the executor resumes from where it left off. A TWAP longer than 24h set to run in this browser shows a reminder to keep it open, or to set the run location to Cloud.
- A strategy is already running on the market. Starting a Borsa-run TWAP or Chase on a market where another strategy is active, on this device or on Borsa Cloud, first shows Strategy already running on that market with the existing runs listed. Two runs side by side can double your intended size or trade against each other; choose Start anyway only if that is intended.
- Request timed out. If Hyperliquid does not answer when you start a Hyperliquid-run TWAP, Borsa checks whether it started before reporting a failure, so you don't end up with two.
- Limit ALO can't get on the book. If the inside spread is too thin or every price level above best bid is filled by other quoters at submission, the post-only ALO is rejected. The executor logs
maker reprice errorand tries again on the next tick. - Minimum chunk size. $10 per order applies. A 30-minute TWAP needs $300 total; smaller and the slices would each be too small.
- Randomize plus minimum. Randomize jitter (×0.7 to ×1.3) can push a chunk below the minimum. The executor floors at the minimum and adjusts total accordingly.
- Funding swings. If a perp's funding rate flips mid-TWAP, the rest of the schedule is unaffected — funding settles independently of order execution.
Concrete Example: Limit ALO
Buy 10 ETH over 10 chunks with aloRepostSeconds = 5, offset 0%, no cap. Current best bid 2,000.
Chunk 1: post ALO 1 ETH @ 2000. Wait 5s.
Best bid drops to 1999. Modify ALO to 1999.
Wait 5s. Best bid back to 2000. Modify to 2000.
...
Eventually a seller hits your bid at 2000, you fill 1 ETH.
Chunk 2: post ALO 1 ETH @ <current best bid>. Same loop.
...
Chunk 10: fills. Done.
Every fill is maker. The "average fill" is determined by where the book traded against you over the schedule.
Related
- Strategies: Borsa-run TWAPs (Market run by Borsa and Limit ALO) are tracked and stopped from the Strategies tab, on this device or on Borsa Cloud.
- Burst — for immediate execution with adaptive sweeping.
- Scale — for price-range distribution.