""" Hyperliquid fee tiers — perps and spot, base rates + staking discounts. Source: https://hyperliquid.gitbook.io/hyperliquid-docs/trading/fees Fee = base_rate × staking_multiplier Staking tiers are based on staked HYPE tokens. """ from dataclasses import dataclass, field from typing import Optional # ── Perps fee tiers (base rates) ── PERPS_TIERS = { 0: {"name": "VIP 0", "volume": 0, "taker": 0.00045, "maker": 0.00015}, 1: {"name": "VIP 1", "volume": 5_000_000, "taker": 0.00040, "maker": 0.00012}, 2: {"name": "VIP 2", "volume": 25_000_000, "taker": 0.00035, "maker": 0.00008}, 3: {"name": "VIP 3", "volume": 100_000_000,"taker": 0.00030, "maker": 0.00004}, 4: {"name": "VIP 4", "volume": 250_000_000,"taker": 0.00025, "maker": 0.00000}, 5: {"name": "VIP 5", "volume": 750_000_000,"taker": 0.00020, "maker": -0.00002}, 6: {"name": "VIP 6", "volume": 2_500_000_000,"taker":0.00015,"maker": -0.00004}, } # ── Spot fee tiers (base rates) ── SPOT_TIERS = { 0: {"name": "VIP 0", "volume": 0, "taker": 0.00070, "maker": 0.00040}, 1: {"name": "VIP 1", "volume": 100_000, "taker": 0.00060, "maker": 0.00030}, 2: {"name": "VIP 2", "volume": 1_000_000, "taker": 0.00050, "maker": 0.00020}, 3: {"name": "VIP 3", "volume": 10_000_000, "taker": 0.00040, "maker": 0.00010}, 4: {"name": "VIP 4", "volume": 50_000_000, "taker": 0.00030, "maker": 0.00005}, 5: {"name": "VIP 5", "volume": 200_000_000, "taker": 0.00020, "maker": 0.00000}, 6: {"name": "VIP 6", "volume": 1_000_000_000,"taker":0.00010,"maker": -0.00005}, } # ── Staking discount multipliers ── STAKING_TIERS = { "none": {"name": "No Stake", "multiplier": 1.00}, "wood": {"name": "Wood", "multiplier": 0.95}, "bronze": {"name": "Bronze", "multiplier": 0.90}, "silver": {"name": "Silver", "multiplier": 0.85}, "gold": {"name": "Gold", "multiplier": 0.80}, "platinum": {"name": "Platinum", "multiplier": 0.70}, "diamond": {"name": "Diamond", "multiplier": 0.60}, } def effective_rate(base_rate: float, staking_tier: str = "none") -> float: """Calculate effective fee rate after staking discount.""" mult = STAKING_TIERS.get(staking_tier, STAKING_TIERS["none"])["multiplier"] return base_rate * mult def get_perp_fees(vip_tier: int, staking_tier: str = "none", fee_model: str = "taker") -> float: """Get effective perp fee for a given VIP tier and staking tier.""" tier = PERPS_TIERS.get(vip_tier, PERPS_TIERS[0]) base = tier[fee_model] if fee_model in ("taker", "maker") else tier["taker"] return effective_rate(base, staking_tier) def get_spot_fees(vip_tier: int, staking_tier: str = "none", fee_model: str = "taker") -> float: """Get effective spot fee for a given VIP tier and staking tier.""" tier = SPOT_TIERS.get(vip_tier, SPOT_TIERS[0]) base = tier[fee_model] if fee_model in ("taker", "maker") else tier["taker"] return effective_rate(base, staking_tier) def fee_tier_from_volume(volume_14d: float, market: str = "perps") -> int: """Determine fee tier from 14-day rolling volume.""" tiers = PERPS_TIERS if market == "perps" else SPOT_TIERS current = 0 for t in sorted(tiers.keys()): if volume_14d >= tiers[t]["volume"]: current = t return current # ── Strategy-specific defaults (matching existing classification) ── STRATEGY_FEE_MODELS = { "Order Book Imbalance": "taker", "Iceberg Detection": "taker", "Funding Rate Arb": "taker", "Pairs Trading": "taker", "Avellaneda-Stoikov": "maker", "Momentum Breakout": "taker", "Mean Reversion": "taker", "Hawkes OFI": "taker", "Deep LOB": "maker", "Cartea-Jaimungal": "maker", "Queue Imbalance": "taker", "Guéant Market Making": "maker", }