How to Build a Hyperliquid TWAP Execution Tool
Build a TWAP execution tool on Hyperliquid: native TWAP orders vs your own slicing, tracking slice fills, and seeing every active TWAP in a market.

TWAP stands for time-weighted average price. Instead of buying $500,000 of BTC at once and pushing the price against yourself, you split it into small pieces spread over hours. Funds, treasuries and anyone moving size use it to get a price close to the market's average over that time.
Why traders split big orders this way:
• To avoid moving the price against themselves. One large market order eats through the book and fills at worse and worse prices.
• To get a fair average price over hours, instead of betting everything on one moment.
• To hide size. Small, steady slices draw less attention than one big order.
• To show a fair execution. Funds and treasuries can point to the average price as their benchmark.
Why should you choose to build a TWAP execution tool on Hyperliquid?
• Plenty of size moves this way. We counted 44 TWAPs running on BTC alone, 33 of them buying.
• The built-in TWAP is fixed once it starts. You choose the size and the time (5 minutes to 7 days, $100 minimum), and after that you can only cancel it.
• A tool adds what it leaves out. Pause when the spread widens, stop at a price limit, report how the fill compared with the market.
• It can show the whole market. Users see what everyone else's TWAPs in a market are doing before they start their own.
• Execution tools pay for themselves. Tread.fi, which runs TWAP and other execution algorithms across several exchanges, is sitting on $2.39M in Hyperliquid builder fees as of Flowscan's 2 October 2026 count (top builders by revenue).
You can build one two ways on Hyperliquid, and the choice decides most of the design. We tried both on 31 October 2026. The one feature where the APIs differ, a live count of everyone's TWAPs in a market, we built and timed on each. Skip the code if it's not your thing.
Option 1: Use Hyperliquid's built-in TWAP
Hyperliquid runs TWAP orders on-chain. You send one twapOrder action with the size and the duration in minutes, and Hyperliquid places the suborders for you. Per its order types docs, suborders go out at regular intervals of at least 30 seconds, and each has a maximum slippage of 3%. A TWAP runs from 5 minutes to 7 days, with a $100 minimum total. If slices fall behind, later ones grow (up to 3 times the normal size) to catch up.
Three settings make it more useful than a plain timer: randomize varies each slice by up to 20% so it's harder to spot, a trigger price starts the TWAP only when the mark price gets there, and a max/min price stops slices filling beyond a limit. As an example from the docs, $10,000 over one hour becomes about 121 slices of $83, one every 30 seconds.
Your tool then reports progress. userTwapSliceFills lists the pieces that filled (2,000 is the most this request returns):
import requests
URL = "https://api.hyperliquid.xyz/info"
USER = "0x0405b6fe11f41ea3f28cbba3fd3015be402bfba9"
fills = requests.post(URL, json={"type": "userTwapSliceFills",
"user": USER}).json()
f = fills[0]["fill"]
print(len(fills), "slice fills; latest:", f["coin"], f["side"], f["sz"],
"@", f["px"], "TWAP id", fills[0]["twapId"])2000 slice fills; latest: BTC B 0.00016 @ 77421.0 TWAP id 2451531That user's BTC TWAP had been running for about 31 hours of a seven-day schedule when we checked, and was about 19% done. The twapStates stream and userTwapHistory give live status and finished TWAPs for one user.
Good for: a simple "buy X over Y hours" button. Less good for: custom logic, such as pausing when the spread widens or speeding up when the price dips, because you can't change a running TWAP, only cancel it. The catch for a business: a twapOrder has no builder field, so a built-in TWAP earns you no builder fee.
Option 2: Slice the order yourself
Your tool places each child order itself: a limit or IOC order every N seconds, sized from what's left. That gives you full control: randomized timing, price limits that follow the book, pausing on wide spreads.
It also means your tool handles what Hyperliquid otherwise does for you: each child order is a normal signed order on /exchange, counts against the account's request budget, and has to meet the $10 minimum order value. The upside: every slice is an order your builder code earns on, so a seven-day TWAP pays out slice by slice.
To pace child orders well, you need to know what a slice of a given size costs. Hydromancer's slippageHistory gives you that cost through the day, not just right now (the funding arbitrage guide runs it), so pick the slice size whose worst hour you can live with.
See every TWAP running in a market
This is the part only market-wide data can do. A big TWAP buying BTC for seven days is information: it tells you there's a steady buyer, and it competes with your own slices. We built a "how many TWAPs are buying or selling BTC right now" counter on both APIs and ran them back to back.
Hyperliquid API
Hyperliquid has no request that lists every user's TWAPs, but you can find them. TWAP slices show up in the public trade feed with an all-zero transaction hash, so step one listens to BTC trades for two minutes and saves the wallets behind those trades to a file, one address per line:
import json, time
from websockets.sync.client import connect
ZERO, wallets, end = "0x" + "0" * 64, set(), time.time() + 120
with connect("wss://api.hyperliquid.xyz/ws") as ws:
ws.send(json.dumps({"method": "subscribe", "subscription":
{"type": "trades", "coin": "BTC"}}))
while time.time() < end:
m = json.loads(ws.recv())
for t in m["data"] if m["channel"] == "trades" else []:
if t["hash"] == ZERO: # TWAP slices have no hash
wallets.add(t["users"][t["side"] == "A"]) # the taker
open("twap_wallets.txt", "w").write("\n".join(wallets))
print(len(wallets), "wallets traded a TWAP slice in 2 minutes")18 wallets traded a TWAP slice in 2 minutesStep two asks twapHistory for each of those wallets and keeps the TWAPs still running:
import time, requests
URL, twaps = "https://api.hyperliquid.xyz/info", {}
for u in open("twap_wallets.txt").read().split():
rows = requests.post(URL, json={"type": "twapHistory", "user": u})
for h in rows.json(): # newest first
twaps.setdefault((u, h.get("twapId"), h["state"]["timestamp"]), h)
time.sleep(7) # stay under 1,200 a minute
live = [h for h in twaps.values() if h["status"]["status"] == "activated"
and h["state"]["coin"] == "BTC"]
buys = sum(h["state"]["side"] == "B" for h in live)
print(len(live), "active BTC TWAPs:", buys, "buying,", len(live) - buys,
"selling")19 active BTC TWAPs: 14 buying, 5 sellingAn all-zero hash isn't only TWAPs: in a sample of 410 such fills, half had no TWAP id, so the lookup step is what confirms each one. And this only finds TWAPs that happened to place a slice while you were listening.
Long, slow TWAPs place a slice every few minutes, so a two-minute listen misses many of them. The complete route on Hyperliquid alone is your own node with --write-fills, which also writes every TWAP's status to disk.
Hydromancer API
perpTwapSnapshots returns every active TWAP in the markets you ask for, with address, side, total size, how much has filled and when the next slice is due. The reply is compressed, so this one also needs pip install msgpack zstandard:
import os, msgpack, requests
H = {"Authorization": "Bearer " + os.environ["HYDROMANCER_API_KEY"]}
r = requests.post("https://api.hydromancer.xyz/info", headers=H,
json={"type": "perpTwapSnapshots", "market_names": ["BTC"]})
twaps = msgpack.unpackb(r.content)[2] # every active BTC TWAP
buys = sum(1 for t in twaps if t[3])
print(len(twaps), "active BTC TWAPs:", buys, "buying,", len(twaps) - buys,
"selling")44 active BTC TWAPs: 33 buying, 11 sellingSide by side
| Hyperliquid API | Hydromancer API | |
|---|---|---|
| Active BTC TWAPs found | 19 | 44 |
| Worked | 1 of 1 runs | 1 of 1 runs |
| Time to finish (median) | 251 s (listens live by design) | 0.2 s |
| Requests | 18 | 1 |
| Rate-limit cost | 1,179 weight (limit: 1,200 a minute per IP) | 1 download of the 5 allowed every 10 minutes |
| Data received over REST (uncompressed) | 5.3 MB | under 0.1 MB |
The Hyperliquid route sees fewer than half the TWAPs that are actually running, which is a different market picture, not just a slower one. An execution tool can show users "33 TWAPs are buying BTC right now" next to their own order, or delay its own slices away from a large one. The snapshot is limited to 5 requests every 10 minutes, so poll it, don't stream it; allTwapStatusUpdates streams changes in between.
Picking between the two
| Built-in TWAP | Your own slicing | |
|---|---|---|
| Placing pieces | Hyperliquid does it | Your code does it |
| Custom rules | Fixed once started | Anything you can code |
| Requests from your app | One to start, one to cancel | One per slice |
| Progress | userTwapSliceFills, twapStates | Your own order records |
| Builder fee | Not possible (no builder field) | On every slice |
Either way, Hyperliquid's free API runs the execution. Hydromancer helps you size and time it: slippage history for slice size, and the market-wide TWAP view.
FAQ
Can you place a TWAP on Hyperliquid?
Yes. Hyperliquid runs TWAP orders natively: you send one twapOrder with size and duration, and suborders go out at regular intervals of at least 30 seconds, each with a maximum slippage of 3%.
How do I see other traders' TWAP orders on Hyperliquid?
On the official API, per wallet: find wallets placing TWAP slices in the trade feed (they have an all-zero hash), then read each one's twapHistory. In our test that found 19 of 44 active BTC TWAPs in four minutes. Hydromancer's perpTwapSnapshots returns every active TWAP in a market in one request.
How do TWAP orders work on Hyperliquid?
You choose a size and a running time, from 5 minutes to 7 days, with a $100 minimum. Hyperliquid splits the order into suborders sent at a fixed interval, as often as every 30 seconds, aiming to have filled elapsed time divided by total time of the size at each point. Once it starts, you can cancel it but not change it.
Why use a TWAP instead of a market order?
For large orders, because each small slice moves the price less, so you pay less market impact than one big order eating through the book. For small orders, a single limit order is simpler and cheaper.
Related reading
• How to build a Hyperliquid trading bot
• Hyperliquid fees and revenue
• Hyperliquid rate limits explained
• Hyperliquid tick size and lot size
Sources
- Hyperliquid docs: Order types, Exchange endpoint, Builder codes
- Hydromancer docs: perpTwapSnapshots, slippageHistory
Read next

How to Build a Trading Terminal on Hyperliquid
Build a Hyperliquid trading terminal: charts, order book, trades and order entry, plus 1-second candles and older chart history. Tested on both APIs.

How to Build a Trading Journal for Hyperliquid
Build a Hyperliquid trading journal: turn fills into closed trades with entry, exit, fees, funding and hold time, and keep history past 10,000 fills.

How to Run a Trading Competition on Hyperliquid
Run a Hyperliquid trading competition: register wallets, score PnL over your own start and end time, filter out cheating, and track it live. Tested.