Comprehensive fix: live node resilience + CSS contrast + win_rate + equity curves

- Mainnet API fallback when testnet unavailable (prices, orderbook, instruments)
- Bypassed broken SDK instrument loading, uses raw mainnet meta API
- Dynamic BTC/ETH perp ID lookup (handles "-USD-PERP" suffix changes)
- Strategy-level equity tracking for per-strategy detail charts
- Win rate fixed: checks pnl_net/pnl_gross not just pnl field
- CSS contrast improved: --tx #6b6b7b→#9e9eae, borders/highlights brightened
- Equity curve recalculated on fee tier change (chart adjusts visually)
- Added Open Positions & Orders panel placeholder
This commit is contained in:
ramseshk
2026-08-05 02:53:31 +00:00
parent f45417c105
commit 4457cdffc5
5 changed files with 706 additions and 251 deletions
+18 -10
View File
@@ -175,7 +175,7 @@ async def get_paper_metrics_rest():
# Backtest endpoints
# ═══════════════════════════════════════════════════════════
@app.get("/api/backtests")
@app.get("/backtests")
async def list_backtests():
"""List all saved backtest results."""
results = []
@@ -195,7 +195,7 @@ async def list_backtests():
"sortino": data.get("sortino", 0),
"pnl_pct": data.get("pnl_pct", 0),
"max_dd": data.get("max_dd", 0),
"win_rate": data.get("win_rate", 0),
"win_rate": data.get("win_rate", 0) or recalc_win_rate(data.get("trades", [])) or 0,
"total_trades": data.get("total_trades", 0),
})
except (json.JSONDecodeError, IOError):
@@ -203,7 +203,7 @@ async def list_backtests():
return JSONResponse(results)
@app.get("/api/backtest/{name}")
@app.get("/backtest/{name}")
async def get_backtest(name: str):
"""Get full backtest result data."""
fpath = os.path.join(BACKTEST_DIR, f"{name}.json")
@@ -214,6 +214,14 @@ async def get_backtest(name: str):
def recalc_win_rate(trades):
"""Fallback win rate when stored value is 0."""
if not trades:
return 0.0
wins = sum(1 for t in trades if (t.get("pnl_net") or t.get("pnl_gross") or t.get("pnl", 0)) > 0)
return round(wins / len(trades), 4) if trades else 0.0
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:
@@ -241,7 +249,7 @@ def recalc_equity_curve(equity_curve, trades, new_fee_rate, fee_model):
new_curve.append({"t": pt_time, "v": round(pt.get("v", 0) + cum, 6)})
return new_curve
@app.get("/api/backtest/{name}/recalc")
@app.get("/backtest/{name}/recalc")
async def recalc_backtest(name: str, fee_tier: int = 0, staking_tier: str = "none"):
"""Recalculate backtest PnL with different fee tier."""
fpath = os.path.join(BACKTEST_DIR, f"{name}.json")
@@ -302,12 +310,12 @@ async def recalc_backtest(name: str, fee_tier: int = 0, staking_tier: str = "non
"sharpe": data.get("sharpe", 0),
"sortino": data.get("sortino", 0),
"max_dd": data.get("max_dd", 0),
"win_rate": data.get("win_rate", 0),
"win_rate": data.get("win_rate", 0) or recalc_win_rate(data.get("trades", [])) or 0,
"num_periods": data.get("num_periods", 720),
})
@app.get("/api/backtests/historical")
@app.get("/backtests/historical")
async def list_historical_backtests():
"""List historical (real data) backtest results."""
results = []
@@ -329,7 +337,7 @@ async def list_historical_backtests():
"sortino": data.get("sortino", 0),
"pnl_pct": data.get("pnl_pct", 0),
"max_dd": data.get("max_dd", 0),
"win_rate": data.get("win_rate", 0),
"win_rate": data.get("win_rate", 0) or recalc_win_rate(data.get("trades", [])) or 0,
"total_trades": data.get("total_trades", 0),
"data_source": "Hyperliquid Mainnet",
})
@@ -338,7 +346,7 @@ async def list_historical_backtests():
return JSONResponse(results)
@app.get("/api/backtest/historical/{name}")
@app.get("/backtest/historical/{name}")
async def get_historical_backtest(name: str):
"""Get full historical backtest result."""
fpath = os.path.join(HISTORICAL_DIR, f"{name}.json")
@@ -348,7 +356,7 @@ async def get_historical_backtest(name: str):
return JSONResponse({"error": "not found"}, status_code=404)
@app.get("/api/backtest/{name}/csv")
@app.get("/backtest/{name}/csv")
async def get_backtest_csv(name: str):
"""Download backtest trades as CSV."""
from fastapi.responses import Response
@@ -371,7 +379,7 @@ async def get_backtest_csv(name: str):
)
@app.get("/api/risk")
@app.get("/risk")
async def get_risk_metrics():
"""Compute risk analytics from the latest paper metrics."""
paper = read_paper_metrics()