Quantitative Research · Bybit Perpetuals

XSMOM — Cross-Sectional Momentum

A vol-normalised momentum strategy that each week ranks the 50 most-traded Bybit perpetuals by 30-day risk-adjusted return, goes long the top-5 winners and short the bottom-5 losers. Optimised via an 8-dimensional parameter sweep.

+$2,514
Total P&L (21 biweekly periods)
3.99
Profit factor
0.236
Weekly Sharpe (≈1.20 ann.)
-284
Max drawdown ($)
50
Universe (top Bybit perps)
14d
Rebalance cycle

01Overview

XSMOM applies a classic cross-sectional momentum framework to crypto perpetuals, with two deliberate asymmetries: a trend-confirmation filter on the long side, and no filter on the short side.

Core idea

In crypto, relative momentum persists over multi-week horizons: coins that have outperformed on a risk-adjusted basis tend to keep outperforming, and the weakest tend to keep underperforming. Ranking by vol-normalised return (return ÷ volatility) rather than raw return avoids buying high-volatility noise — a coin that rose 30% on 60% daily vol is a weaker signal than one that rose 20% on 15% vol.

Why the long filter exists

The vol-normalised metric can rank a coin highly because its volatility collapsed, not because it's trending up. The long side therefore requires the coin to be above its 50-day (now 100-day) moving average and have a positive raw 30-day return. The short side needs no filter: in a structurally risk-off altcoin regime, the weakest losers keep losing — shorting them has been the more reliable leg.

TL;DR: Buy the strongest risk-adjusted momentum that is confirmed by trend; short the weakest regardless. Rebalance biweekly; size longs by signal strength, size shorts equally; cut any position that loses 15%.

02How it works

The full pipeline, from raw Bybit data to a ranked long/short book.

① Fetch top-50 USDT perps by 24h volume
② Pull 400 daily OHLCV candles per symbol
③ Rank by 30-day vol-normalised return
④ Apply long trend filter / short VNR floor
⑤ Size & simulate the biweekly book

Signal — vol-normalised return (VNR)

For each symbol, over the trailing 30 days ending at the rebalance date:

raw_return   = (close[t] - close[t-30]) / close[t-30]
atr_pct      = ATR(14) / close[t]            # daily vol, as % of price
VNR          = raw_return / (atr_pct × √30)  # risk-adjusted momentum

VNR measures how far price moved per unit of volatility over the window — the standard "vol-normalised" momentum used in academic cross-sectional momentum studies.

Selection rules

  • Longs (top 5 by VNR) — must pass trend filter: close > MA(100) and raw_return > 0. Only coins with genuine upward momentum qualify.
  • Shorts (bottom 5 by VNR) — require VNR ≤ -0.5 (optimised floor). In the current sample no coin met this threshold, so the optimised run is effectively long-only.
  • Sizing — long weights are linear in VNR (strongest signal → biggest position); shorts are equally weighted.
  • Exit — positions close at the next rebalance, or earlier at a 15% stop-loss.

Optimised parameters (after sweep)

Universe: top 50 perps VNR window: 30 days Trend MA: 100 (was 50) Rebalance: biweekly (was weekly) Stop-loss: 15% (was none) Short VNR floor: -0.5 (was none) Longs: 5 · signal-proportional Shorts: 5 · equal weight Filter: MA(100) + raw return>0 Notional per leg: $100 (unit)

03Results

Backtest of the optimised configuration over 21 biweekly periods (10 Nov 2025 → 17 Aug 2026). Data: real Bybit daily OHLCV for the top-50 volume perps; universe expands as newer perps accumulate enough history (33 → 47 symbols).

XSMOM equity curve
Cumulative P&L across 21 biweekly rebalances. Note the single dominant week of 2026-08-17 (+$2,280) — see Caveats.
Long vs short decomposition
Side decomposition — with the optimised short floor, the short book is flat for this sample.
Drawdown profile
Drawdown profile from running P&L peak.

Headline metrics

Total P&L+$2,513.65
Long P&L+$2,513.65
Short P&L$0.00 (flat — floor never triggered)
Periods (biweekly)21
Avg P&L / period+$119.70
Win rate (trades)32.5% (27W / 56L)
Avg win+$124.28
Avg loss-$15.03
Profit factor3.99
Max drawdown-$284.42
Sharpe (weekly, 0% Rf)0.236
Sharpe (annualised ×√26)≈1.20
Total trades83 (all long)

Monthly P&L

MonthPeriodsP&L
2025-112-$171.2
2025-122+$11.5
2026-012+$88.4
2026-022+$93.7
2026-033-$58.1
2026-042+$267.6
2026-052-$110.1
2026-062+$110.5
2026-072-$109.1
2026-082+$2,390.5

August's figure is almost entirely the single +$2,280 week.

Period-by-period equity path

Rebalance dateUniverseLongsShortsPeriod P&LCumulative

04Parameter optimisation sweep

50+ configurations × 24 weeks, one dimension at a time against the baseline (30d VNR · MA=50 · weekly · 5L/5S · no stop · no short floor · ma+rawpos). Rankings by Sharpe. In-sample optimisation — results are likely optimistic; treat as directional, not as expected live performance.

Rebalance frequency biggest lever

ScheduleP&LSharpePF
weekly (baseline)+$4090.1821.23
biweekly+$3,8150.3282.53

Extending the hold from 7→14 days lets winners compound and cuts rebalance whipsaw. Note: this leg of the sweep ran without the short floor, so shorts were still active here.

Stop-loss best Sharpe

StopP&LSharpePFMaxDD
none (baseline)+$4100.1821.23-$180
15%+$8300.3711.60-$126
25%+$5970.2621.37-$170

15% is the single best Sharpe improvement: it caps the catastrophic single-coin blow-ups (e.g. -247% SKRUSDT week in the unfiltered run) while letting winners run.

Trend-filter MA period

MAP&LSharpePF
none (raw-pos only)+$3640.1561.20
20+$3550.1501.19
50 (baseline)+$4110.1831.23
100+$5250.2211.32
200+$2890.1461.21

MA=100 is the sweet spot — a slower regime filter that rejects more false-positive longs in chop.

Short VNR floor

FloorP&LSharpePFTrades
none (baseline)+$4100.1821.23239
-0.3+$4980.1981.38167
-0.5+$5550.1991.49119
-0.75+$5550.1991.49119
-1.0+$5550.1991.49119

Tighter floors cull weak/mean-reverting shorts and lift the profit factor from 1.23 → 1.49. Past -0.5 nothing changes: the weak cohorts simply stop qualifying.

Signal window (VNR days)

WindowP&LSharpeMaxDD
14+$4720.144-$510
21+$480.019-$180
30 (baseline)+$4120.183-$178
45+$1170.040-$329
60-$137-0.058-$272

30 days has the best Sharpe / drawdown balance. 14d has higher raw P&L but 2.9× the drawdown.

Portfolio size & concentration

ConfigP&LSharpe
3L/3S+$2870.194
5L/5S (baseline)+$4100.182
7L/7S+$6670.193
cap 50% / 40% / 30%+$393 / +$393 / +$387≈0.177 / 0.175

Concentration caps hurt: signal-proportional sizing is an alpha source, not a risk bug. 7L/7S maximises raw P&L; 5L/5S is the risk/reward compromise.

Combined configurations

ConfigP&LSharpeWRPF
Baseline (30d/MA50/weekly)+$4100.18245.6%1.23
Best-of-each-dimension (30d/MA100/biweekly/15%SL/floor-0.5)+$2,4880.28541.2%2.43
Applied optimised config (same, with floor active → long-only)+$2,5140.23632.5%3.99

Full 50-row sweep data available at sweep_data.json in this repo.

05Implementation

Pure-Python, stdlib-only backtest (no pandas/numpy). Fetches real data from the Bybit V5 public REST API and caches it locally.

Repository layout

MOMSXperp/
├── config.py      # strategy parameters (optimised)
├── run.py         # backtest entry point
├── analysis.py    # ranking, selection, sizing, P&L engine
├── fetch.py       # Bybit V5 OHLCV fetch + local cache
├── report.py      # extended diagnostics (monthly, streaks, conc.)
├── charts.py      # matplotlib equity/side/drawdown charts
├── sweep.py       # 8-dimension parameter sweep
├── xsmom_results.json       # optimised backtest output
├── xsmom_sweep_results.json # full sweep output
└── README.md

Run it yourself

# backtest (cached data; --force to re-fetch)
python3 -m xsmom.run

# extended diagnostics
python3 -m xsmom.report

# charts (needs matplotlib)
python3 -m xsmom.charts

# full parameter sweep (2-3 min)
python3 -m xsmom.sweep

Data is cached under xsmom/data_cache/ so repeat runs are instant. No API key required for public market data.

Key engineering choices

  • Per-symbol history depth — newer perps have less history, so each rebalance uses only symbols with enough data (universe grows 33 → 47 over the backtest). No look-ahead: signal uses only candles up to the rebalance date.
  • Variable-depth schedule — rebalance dates go back only as far as enough symbols have data, avoiding a survivorship bias on listing dates.
  • Stop-loss semantics — a position's realised return is floored at -15% (a hard stop before the next rebalance), which is what tames the worst blow-up weeks.
  • Sweep mechanics — one dimension at a time against a fixed baseline; each config is a full backtest over the same 24 weeks. sweep.py reloads modules between runs so parameter changes take effect.
  • Fees not modelled — perp taker fees (~0.055%/side) would shave a small % off returns; with only 83 trades in the optimised run, the drag is modest but non-zero.

06Caveats & honest limitations

Read this before acting on anything on this page. These are the results a critical reviewer should weigh.

1 · One week drives the entire result. The 2026-08-17 period returned +$2,280 = 90.7% of total P&L. Excluding that single week, the strategy made only +$233; excluding the top two weeks it is negative (-$64). This is an extreme outlier dependence, typical of a short backtest with a few large momentum winners (here, PUMPFUN +72.8% in one period). Treat the headline P&L as fragile.
2 · The short side is dormant in the optimised run. With the -0.5 VNR floor + biweekly schedule, no coin in the sample ever reached VNR ≤ -0.5, so the optimised backtest placed zero short trades. The "long/short" strategy is effectively long-only in this window. The improvement attributed to the short floor actually comes from removing losing shorts, not from profiting on them. In a proper risk-off regime with genuinely crashing coins, the short leg could reappear — but it is unproven here.
3 · In-sample optimisation = overfitting risk. Every parameter (MA period, rebalance frequency, stop-loss, short floor) was chosen because it looked best on this same 24-week window. With 50+ configs tried, some will look great by chance. The sweep is a research map, not a forward-tested edge. Real validation requires out-of-sample / walk-forward testing on data the sweep never saw.
4 · Short sample, bull-leaning regime. 24 weeks of a generally rising altcoin tape favours a long-only momentum book. The low win rate (32.5%) with a huge payoff ratio (8.3:1) is a lottery-like profile: most periods are small losses, occasionally punctuated by a big winner. That distribution is uncomfortable to trade and depends on big winners actually occurring.
What would strengthen this analysis: (a) walk-forward / out-of-sample validation, (b) much longer history (fetch 400+ more days as they accrue), (c) explicit fee + slippage modelling, (d) a regime overlay (e.g. only run longs when BTC > 200-day MA), (e) re-introducing a short book that actually triggers, e.g. via a looser floor or a dedicated weak-cohort shorting test.

07Repository & data

Everything is open for review. Clone, re-run, and challenge the numbers.

View on GitHub Download sweep data (JSON)

Raw data files

  • xsmom_results.json — full optimised backtest, per-trade detail.
  • xsmom_sweep_results.json — all 50 sweep configurations with weekly P&L series.
  • sweep_data.json — condensed sweep tables used to build this page.
  • config.py — the exact optimised parameter set.