055da97a79
Perps tiers 4-6 had wrong volume thresholds, taker rates, and incorrect negative maker rebates (HL only has rebates via staking). Changes (matching https://hyperliquid.gitbook.io/.../trading/fees): Tier 4: $250M→$500M vol, taker 0.025%→0.028% Tier 5: $750M→$2B vol, taker 0.020%→0.026%, maker -0.002%→0.000% Tier 6: $2.5B→$7B vol, taker 0.015%→0.024%, maker -0.004%→0.000% UI dropdown labels updated to match. Chart refresh enhanced with resize+fitContent after recalc for smooth transitions.
92 lines
3.8 KiB
Python
92 lines
3.8 KiB
Python
"""
|
||
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": 500_000_000, "taker": 0.00028, "maker": 0.00000},
|
||
5: {"name": "VIP 5", "volume": 2_000_000_000, "taker": 0.00026, "maker": 0.00000},
|
||
6: {"name": "VIP 6", "volume": 7_000_000_000, "taker": 0.00024, "maker": 0.00000},
|
||
}
|
||
|
||
# ── 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",
|
||
}
|