Files
ftdt-quant-lab/strategies/iceberg_detection.py
T
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

67 lines
2.2 KiB
Python

"""
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