diff --git a/config/fee_tiers.py b/config/fee_tiers.py index 3716df1..c348f30 100644 --- a/config/fee_tiers.py +++ b/config/fee_tiers.py @@ -12,24 +12,24 @@ 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}, + 0: {"name": "Tier 0", "volume": 0, "taker": 0.00045, "maker": 0.00015}, + 1: {"name": "Tier 1", "volume": 5_000_000, "taker": 0.00040, "maker": 0.00012}, + 2: {"name": "Tier 2", "volume": 25_000_000, "taker": 0.00035, "maker": 0.00008}, + 3: {"name": "Tier 3", "volume": 100_000_000,"taker": 0.00030, "maker": 0.00004}, + 4: {"name": "Tier 4", "volume": 500_000_000, "taker": 0.00028, "maker": 0.00000}, + 5: {"name": "Tier 5", "volume": 2_000_000_000, "taker": 0.00026, "maker": 0.00000}, + 6: {"name": "Tier 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}, + 0: {"name": "Tier 0", "volume": 0, "taker": 0.00070, "maker": 0.00040}, + 1: {"name": "Tier 1", "volume": 100_000, "taker": 0.00060, "maker": 0.00030}, + 2: {"name": "Tier 2", "volume": 1_000_000, "taker": 0.00050, "maker": 0.00020}, + 3: {"name": "Tier 3", "volume": 10_000_000, "taker": 0.00040, "maker": 0.00010}, + 4: {"name": "Tier 4", "volume": 50_000_000, "taker": 0.00030, "maker": 0.00005}, + 5: {"name": "Tier 5", "volume": 200_000_000, "taker": 0.00020, "maker": 0.00000}, + 6: {"name": "Tier 6", "volume": 1_000_000_000,"taker":0.00010,"maker": -0.00005}, } # ── Staking discount multipliers ── diff --git a/dashboard/server.py b/dashboard/server.py index d0325c6..79f6ead 100644 --- a/dashboard/server.py +++ b/dashboard/server.py @@ -200,6 +200,34 @@ async def get_backtest(name: str): return JSONResponse({"error": "not found"}, status_code=404) + +def recalc_equity_curve(equity_curve, trades, new_fee_rate, fee_model): + """Rebuild equity curve with new fee rates, preserving gross PnL.""" + if not equity_curve or not trades: + return equity_curve + fee_deltas = {} + cum_delta = 0.0 + for t in trades: + sz = t.get("size", 0) + px = t.get("price", 0) + old_fee = t.get("fee", 0) + new_fee = sz * px * new_fee_rate * 2 + delta = old_fee - new_fee + cum_delta += delta + fee_deltas[t.get("time", "")] = cum_delta + + new_curve = [] + delta_idx = 0 + trade_times = list(fee_deltas.keys()) + cum = 0.0 + for pt in equity_curve: + pt_time = pt.get("t", "") + while delta_idx < len(trade_times) and trade_times[delta_idx] <= pt_time: + cum = fee_deltas[trade_times[delta_idx]] + delta_idx += 1 + new_curve.append({"t": pt_time, "v": round(pt.get("v", 0) + cum, 6)}) + return new_curve + @app.get("/api/backtest/{name}/recalc") async def recalc_backtest(name: str, fee_tier: int = 0, staking_tier: str = "none"): """Recalculate backtest PnL with different fee tier.""" @@ -251,7 +279,12 @@ async def recalc_backtest(name: str, fee_tier: int = 0, staking_tier: str = "non "pnl_net_pct": round(new_pnl_pct, 4), "fees_total": round(new_fees, 4), "total_trades": len(new_trades), - "equity_curve": data.get("equity_curve", []), + "equity_curve": recalc_equity_curve( + data.get("equity_curve", []), + data.get("trades", []), + new_fee_rate, + fee_model + ), "trades": new_trades[-100:], "sharpe": data.get("sharpe", 0), "sortino": data.get("sortino", 0), diff --git a/dashboard/static/index.html b/dashboard/static/index.html index b1f7842..9476c0c 100644 --- a/dashboard/static/index.html +++ b/dashboard/static/index.html @@ -162,13 +162,13 @@ footer a{color:#3f3f4a;text-decoration:none}footer a:hover{color:var(--tx)} Inc. fees