""" Funding Rate Arbitrage strategy. Hyperliquid pays funding every 8 hours. When the rate is positive, longs pay shorts. This strategy: 1. Goes LONG spot (no funding payments) 2. Goes SHORT perp (collects funding) 3. Maintains delta neutrality The profit comes from funding, not price direction. """ from nautilus_trader.trading.strategy import Strategy from nautilus_trader.config import StrategyConfig class FundingRateArbConfig(StrategyConfig, frozen=True): spot_instrument: str perp_instrument: str min_funding_rate: float = 0.0001 rebalance_threshold: float = 0.05 position_size: float = 0.01 class FundingRateArb(Strategy): """ Delta-neutral funding rate carry trade. Key idea: funding rate IS the edge. Stay neutral, collect the payments. """ def __init__(self, config: FundingRateArbConfig) -> None: super().__init__(config) self.config = config self.position_open = False def on_start(self) -> None: bar_type = f"{self.config.perp_instrument}-1-MINUTE-LAST-INTERNAL" self.subscribe_bars(bar_type) self.log.info( f"Funding arb: {self.config.spot_instrument} / {self.config.perp_instrument}" ) def on_bar(self, bar) -> None: funding_rate = self._get_funding_rate() if funding_rate is None: return spot_pos = self.portfolio.net_position(self.config.spot_instrument) if funding_rate > self.config.min_funding_rate and spot_pos == 0: self._open() self.position_open = True elif funding_rate < self.config.min_funding_rate / 2 and self.position_open: self._close() self.position_open = False def _get_funding_rate(self) -> float | None: # TODO: fetch from Hyperliquid API return 0.0001 def _open(self) -> None: self.submit_order(self.order_factory.market( instrument_id=self.config.spot_instrument, order_side="BUY", quantity=self.config.position_size, )) self.submit_order(self.order_factory.market( instrument_id=self.config.perp_instrument, order_side="SELL", quantity=self.config.position_size, )) def _close(self) -> None: self.close_all_positions(self.config.spot_instrument) self.close_all_positions(self.config.perp_instrument)