""" Iceberg / TWAP detection strategy. Large traders often split big orders into small slices to avoid slippage. This strategy detects those patterns by watching for recurring same-sized trades above average volume, then enters in the same direction. """ from collections import deque from nautilus_trader.trading.strategy import Strategy from nautilus_trader.config import StrategyConfig class IcebergDetectorConfig(StrategyConfig, frozen=True): instrument_id: str lookback_seconds: int = 300 volume_spike_mult: float = 3.0 min_slices: int = 4 trade_size: float = 0.001 class IcebergDetector(Strategy): """ Detects iceberg/TWAP execution patterns. Logic: 1. Track trade sizes in a rolling window 2. When a trade is much larger than average, flag it 3. If same size repeats N times -> confirmed iceberg 4. Trade in the same direction """ def __init__(self, config: IcebergDetectorConfig) -> None: super().__init__(config) self.config = config self.recent_sizes: deque[float] = deque(maxlen=100) self.slice_count = 0 self.last_flagged_size: float | None = None def on_start(self) -> None: self.subscribe_trade_ticks(self.config.instrument_id) self.log.info(f"Iceberg detector started on {self.config.instrument_id}") def on_trade_tick(self, tick) -> None: self.recent_sizes.append(tick.size) avg = sum(self.recent_sizes) / len(self.recent_sizes) if self.recent_sizes else 0 if tick.size > avg * self.config.volume_spike_mult: if tick.size == self.last_flagged_size: self.slice_count += 1 else: self.slice_count = 1 self.last_flagged_size = tick.size else: self.slice_count = 0 if self.slice_count >= self.config.min_slices: self.log.info( f"Iceberg: {self.slice_count} slices of size {self.last_flagged_size}" ) self.submit_order(self.order_factory.market( instrument_id=self.config.instrument_id, order_side="BUY" if tick.is_buyer_maker else "SELL", quantity=self.config.trade_size, )) self.slice_count = 0