Rank the top-50 most-traded Bybit perps by 30-day volatility-normalised return; each period go long the top 5 (signal-proportional sizing, 100-day MA trend filter) and short the bottom 5 (equal weight, VNR ≤ −0.5). Biweekly rebalance, 15% stop per position.
The optimised XSMOM configuration shows PF 3.99, Sharpe 0.236 weekly (≈1.70 annualized), +$2,514 total P&L over 21 biweekly periods, with a 32.5% win rate but an 8.27:1 win/loss ratio — the momentum profile: few large winners, many small losses, 15% stops.
Two honest caveats: fees are not modelled (taker 0.055%/side would reduce returns by ~2%), and the sample is only ~10.5 months. The parameter sweep identified the optimal config (30d signal, 100d MA filter, biweekly, 15% stop, short VNR floor −0.5) — but the short window means the configuration is not yet regime-tested.
Top 50 most-traded Bybit USDT perps by volume.
30-day volatility-normalised return (VNR); longs sized proportionally to signal strength, shorts equal weight.
Long side: only coins above 100-day MA with positive 30-day raw return (prevents low-vol rank-chasers). Short side: only VNR ≤ −0.5, no trend filter.
Biweekly (14 days); 15% stop-loss per position; portfolio 5 long / 5 short.
| Metric | Value | Note |
|---|---|---|
| Total P&L | +$2,514 | 21 biweekly periods (~10.5 months) |
| Sharpe | 0.236 weekly | ≈1.70 annualized |
| Profit factor | 3.99 | — |
| Win rate | 32.5% | Low hit rate, high payoff — classic momentum |
| Max drawdown | −$284.42 | 11.3% of equity |
| Avg win / avg loss | $124.28 / $15.03 | 8.27:1 ratio |
Daily OHLCV from Bybit V5 API, cached locally per symbol; the sweep and backtest reuse the cache to avoid repeated API calls.
sweep.py explores signal window, MA filter period, rebalance frequency, stop, short VNR floor, sizing — the config above is the sweep's optimum.
report.py (extended diagnostics) + charts.py (equity curve, long/short decomposition, drawdown profile); robustness.py (robustness analysis) + montecarlo.py in repo.
~10.5 months of data; fees not modelled; no walk-forward OOS documented in the README — treat the optimum as in-sample.
cd .. && python -m MOMSXperp.run # backtest with cached data
python -m MOMSXperp.sweep # parameter sweep optimisation
python -m MOMSXperp.report && python -m MOMSXperp.charts
# skill: xsmom-parameter-sweep