Files
ramseshk b59dcc3629 Initial project scaffold: five quant strategies for Hyperliquid Testnet
Set up the directory structure and wrote placeholder logic for:

- Order Book Imbalance: trades on L2 bid/ask skew
- Iceberg/TWAP detection: follows whale accumulation patterns
- Funding rate arbitrage: delta-neutral carry on perp funding
- Pairs trading: BTC/ETH spread mean reversion
- Avellaneda-Stoikov market making: optimal bid/ask quoting

Also added shared risk manager, portfolio tracker, and a plain-language strategy walkthrough in docs/.
2026-08-03 11:12:20 +00:00

77 lines
2.5 KiB
Python

"""
Order Book Imbalance strategy.
Enters positions when bid/ask volume at the top of the order book
shows a significant directional skew. The idea: when one side of
the book is much heavier, price tends to move toward the thinner
side as the heavy side absorbs market orders.
"""
from nautilus_trader.trading.strategy import Strategy
from nautilus_trader.config import StrategyConfig
class OrderBookImbalanceConfig(StrategyConfig, frozen=True):
instrument_id: str
depth: int = 10
imbalance_threshold: float = 0.6
trade_size: float = 0.001
max_position: float = 0.003
cooldown_bars: int = 5
class OrderBookImbalance(Strategy):
"""
Trades on L2 order book imbalance.
- imbalance > threshold -> bid side heavy -> buy
- imbalance < 1-threshold -> ask side heavy -> sell
"""
def __init__(self, config: OrderBookImbalanceConfig) -> None:
super().__init__(config)
self.config = config
self.bars_since_last_trade = 0
def on_start(self) -> None:
self.subscribe_order_book_deltas(
self.config.instrument_id,
depth=self.config.depth,
)
self.log.info(
f"OFI started on {self.config.instrument_id} "
f"(depth={self.config.depth})"
)
def on_order_book_deltas(self, deltas) -> None:
self.bars_since_last_trade += 1
if self.bars_since_last_trade < self.config.cooldown_bars:
return
book = self.cache.order_book(self.config.instrument_id)
if not book or len(book.bids) == 0 or len(book.asks) == 0:
return
depth = min(self.config.depth, len(book.bids), len(book.asks))
bid_vol = sum(book.bids[i].size for i in range(depth))
ask_vol = sum(book.asks[i].size for i in range(depth))
total = bid_vol + ask_vol
if total == 0:
return
imbalance = bid_vol / total
pos = self.portfolio.net_position(self.config.instrument_id)
if imbalance > self.config.imbalance_threshold and pos <= 0:
self._enter("BUY")
self.bars_since_last_trade = 0
elif imbalance < (1 - self.config.imbalance_threshold) and pos >= 0:
self._enter("SELL")
self.bars_since_last_trade = 0
def _enter(self, side: str) -> None:
self.submit_order(self.order_factory.market(
instrument_id=self.config.instrument_id,
order_side=side,
quantity=self.config.trade_size,
))