Feature Request
Summary
Hyperliquid provides a public WebSocket channel allMids that returns a snapshot of the mid-price for every tradable coin in a single message. The underlying WebSocket infrastructure in the Hyperliquid adapter already supports this channel (HyperliquidWsChannel::AllMids, SubscriptionRequest::AllMids, and handler parsing are all in place), but the LiveDataClient does not expose a subscription interface. Strategies therefore cannot consume this unique full-market data source through the standard Nautilus framework.
Current State
HyperliquidWsChannel::AllMids is fully defined in crates/adapters/hyperliquid/src/websocket/enums.rs.
SubscriptionRequest::AllMids { dex } and its topic formatting exist in websocket/handler.rs.
- The WebSocket codec already deserializes
allMids messages into AllMidsData { mids: AHashMap<String, String> }.
- However,
HyperliquidDataClient has no subscribe_all_mids() method, so there is no path for a strategy or actor to request this stream.
- Because
allMids is an instrument-agnostic, full-market snapshot (not a per-instrument stream), it does not fit the standard SubscribeQuotes / SubscribeMarkPrices pattern and needs a dedicated SubscribeCustomData path.
Proposed Change
Expose the existing allMids stream as a CustomData source, keeping all changes inside the Hyperliquid adapter crate.
-
Adapter data type
Define a new struct implementing CustomDataTrait:
pub struct HyperliquidAllMids {
pub mids: HashMap<InstrumentId, Price>, // coin → mid price
pub ts_event: UnixNanos,
pub ts_init: UnixNanos,
}
The handler should use the existing instruments_cache to map raw coin symbols (e.g. "BTC") to InstrumentIds so that Python strategies receive familiar identifiers.
-
WebSocket handler
In the handler’s AllMids branch (currently the parsed data is likely unused or returned raw), convert AllMidsData into HyperliquidAllMids and emit it as NautilusWsMessage::Data(vec![Data::Custom(...)]).
-
Data client
Add subscribe_all_mids(&mut self) to HyperliquidDataClient, issuing a SubscribeCustomData command with DataType::new("HyperliquidAllMids", None, None). The unsubscribe path should send the corresponding UnsubscribeCustomData.
-
Python bindings
Expose HyperliquidAllMids through PyO3 so it can be imported and down-casted in on_data.
Why This Matters
allMids is a unique exchange feature: very few venues offer a single message containing every tradable mid-price. It is extremely bandwidth-efficient for market-scanning logic.
- Cross-coin analytics: strategies can compute real-time correlation matrices, market-breadth indicators, or identify relative-value deviations without maintaining hundreds of individual quote subscriptions.
- Scanner / stat-arb strategies: a single
allMids message every second can drive a universe-selection model that then subscribes to L2 books for only the most promising pairs.
- Since the WebSocket plumbing is already complete, the remaining work is primarily surfacing the data into the Nautilus event framework via
CustomData.
Example Usage (Python)
from nautilus_trader.adapters.hyperliquid.data import HyperliquidAllMids
class MarketScanner(Actor):
def on_data(self, data):
if isinstance(data, HyperliquidAllMids):
# Compute market median deviation in a single shot
for inst_id, mid in data.mids.items():
self.log.debug(f"{inst_id}: {mid}")
References
- Hyperliquid WebSocket docs:
allMids subscription
https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket
- Existing
AllMids enum, request, and data structures:
crates/adapters/hyperliquid/src/websocket/enums.rs:45
crates/adapters/hyperliquid/src/websocket/messages.rs:378
crates/adapters/hyperliquid/src/websocket/handler.rs:805
- Nautilus
CustomData / CustomDataTrait extension mechanism:
crates/model/src/data/custom.rs
Feature Request
Summary
Hyperliquid provides a public WebSocket channel
allMidsthat returns a snapshot of the mid-price for every tradable coin in a single message. The underlying WebSocket infrastructure in the Hyperliquid adapter already supports this channel (HyperliquidWsChannel::AllMids,SubscriptionRequest::AllMids, and handler parsing are all in place), but theLiveDataClientdoes not expose a subscription interface. Strategies therefore cannot consume this unique full-market data source through the standard Nautilus framework.Current State
HyperliquidWsChannel::AllMidsis fully defined incrates/adapters/hyperliquid/src/websocket/enums.rs.SubscriptionRequest::AllMids { dex }and its topic formatting exist inwebsocket/handler.rs.allMidsmessages intoAllMidsData { mids: AHashMap<String, String> }.HyperliquidDataClienthas nosubscribe_all_mids()method, so there is no path for a strategy or actor to request this stream.allMidsis an instrument-agnostic, full-market snapshot (not a per-instrument stream), it does not fit the standardSubscribeQuotes/SubscribeMarkPricespattern and needs a dedicatedSubscribeCustomDatapath.Proposed Change
Expose the existing
allMidsstream as a CustomData source, keeping all changes inside the Hyperliquid adapter crate.Adapter data type
Define a new struct implementing
CustomDataTrait:The handler should use the existing
instruments_cacheto map raw coin symbols (e.g."BTC") toInstrumentIds so that Python strategies receive familiar identifiers.WebSocket handler
In the handler’s
AllMidsbranch (currently the parsed data is likely unused or returned raw), convertAllMidsDataintoHyperliquidAllMidsand emit it asNautilusWsMessage::Data(vec![Data::Custom(...)]).Data client
Add
subscribe_all_mids(&mut self)toHyperliquidDataClient, issuing aSubscribeCustomDatacommand withDataType::new("HyperliquidAllMids", None, None). The unsubscribe path should send the correspondingUnsubscribeCustomData.Python bindings
Expose
HyperliquidAllMidsthrough PyO3 so it can be imported and down-casted inon_data.Why This Matters
allMidsis a unique exchange feature: very few venues offer a single message containing every tradable mid-price. It is extremely bandwidth-efficient for market-scanning logic.allMidsmessage every second can drive a universe-selection model that then subscribes to L2 books for only the most promising pairs.CustomData.Example Usage (Python)
References
allMidssubscriptionhttps://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket
AllMidsenum, request, and data structures:crates/adapters/hyperliquid/src/websocket/enums.rs:45crates/adapters/hyperliquid/src/websocket/messages.rs:378crates/adapters/hyperliquid/src/websocket/handler.rs:805CustomData/CustomDataTraitextension mechanism:crates/model/src/data/custom.rs