BotsfolioBotsfolio
Methodology

Setup Performance Index (SPI): How We Compute It

Data sources, detection engine, backtest simulation, and every assumption baked into the numbers you see on our pages.

Jay Sharma
Jay Sharma · Founder, Botsfolio
Published August 18, 2026
In short

The Setup Performance Index (SPI) is a rolling record of how every setup our detector finds has resolved historically. For each combination of coin, timeframe, setup type, direction, and management style, we run a walk-forward simulation on real Coinbase candles going back to 2018 where available. Each row reports win rate, expectancy in R, hold time, reversal rate, maximum favorable and adverse excursion, and projected annual gain plus max drawdown at 1, 2, and 5 percent risk per trade. Every reported metric is computed net of a 0.12 percent round-trip fee model, deducted from each simulated trade before aggregation. Rows are only surfaced once the setup grain has at least 20 historical instances. SPI is historical simulation, not a forecast.

What SPI is

The Setup Performance Index is a per-(coin, timeframe, setup type, direction, management mode) record of how instances of that setup have resolved on real historical price action. Every learn article, every setup card, and every backtest table on Botsfolio reads its numbers from the same underlying SPI store. The index is versioned by the exact detection code that produced it, so when we improve a detector, historical instances get re-scored under the new rules.

Data sources

All price data comes from Coinbase Advanced Trade public candles, fetched from the unauthenticated market-data endpoint (api.coinbase.com/api/v3/brokerage/market/products/{id}/candles). This is real settled trade data from a regulated US exchange, not synthetic. We pull hourly candles for the six-month rolling window and daily candles for the multi-year backtest window. Timeframes not natively served by Coinbase (4H, 8H, 12H, 1W) are derived by standard OHLCV resampling from the finer native series, with epoch-aligned bucket boundaries.

Note

No third-party price feeds, no synthetic data, no user-submitted signals. Every SPI row can be independently reconstructed from the raw Coinbase candle series.

Detection engine

Setups are detected by pure functions running on closed candles only. Once a candle closes, the analysis engine runs a dependency-ordered detector suite over the recent series and emits structural objects: order blocks, fair value gaps, liquidity sweeps, breaker blocks, mitigation blocks, break-and-retest, wave signals, and points of interest.

Every object has an immutable formation anchor and a mutable lifecycle status that tracks its reaction as new candles close: active, tested, mitigated, or invalidated. Objects never repaint. If a wick pierces a level intra-candle but the close is on the other side, the level's status only changes based on the closed candle.

For zone-based setups (order blocks, FVGs, POIs), we compute a refined level inside the wider zone by clustering the wick tips of surrounding candles that have already tested the zone. The refined level is typically 5 to 15 percent of the zone width and is the actual trigger price used in the backtest. Sizing off the wide zone would systematically underestimate the trader's position size at their real intended stop.

Backtest simulation

For each detected instance, we run a walk-forward simulation from the moment the setup becomes actionable until one of three exit conditions fires:

  1. The invalidation level is reached (loss).
  2. The first target is reached (partial or full win, depending on management mode).
  3. MAX_BARS = 60 candles have passed without either (time stop, resolved at the running unrealized R).

Two management modes are simulated for every instance:

  • Book early: partial exit at +1R, remainder trailed with structural stop moves.
  • Book at target: hold to the full first target with no partials.

Both modes are reported side by side because they represent different trader profiles and neither is universally better. We publish the numbers for both without steering.

Cost model: COST_PCT = 0.0012 (0.12 percent round-trip fees). This is on the high end of retail perp fee schedules and errs conservative. Real fees on higher tiers or spot-only exchanges are usually lower. Every expectancy R and annual gain figure has fees already deducted.

R:R cap: RR_CAP = 5. Winners exceeding a 5R payout are capped at 5R in the sample. This prevents rare outlier winners from distorting mean expectancy.

What SPI measures

Each SPI row exposes:

  • N: total historical instances at this grain
  • Win rate: percentage of instances that finished with positive R
  • Expectancy R: mean net R per instance after fees, R:R cap applied
  • Avg hold: mean bars held from entry to exit
  • Median MFE R: median maximum favorable excursion in R (best point during the trade)
  • Median MAE R: median maximum adverse excursion in R (worst point during the trade)
  • Reversal rate: percentage of instances that reached +1R at some point and then finished at or below breakeven
  • Annual gain (%) at 1%, 2%, 5% risk: projected annual return if the same strategy were traded continuously at each risk-per-trade level, net of the 0.12 percent round-trip fee applied to every trade
  • Max drawdown (%) at 1%, 2%, 5% risk: worst peak-to-trough equity decline over the sample, net of the same fee

What SPI does NOT measure

  • Future returns. Past performance in backtest does not forecast future performance. Regime shifts, liquidity changes, and market structure evolution all affect forward outcomes.
  • Real fill quality. The simulation assumes the trigger price fills. Real orders may fill worse due to slippage, especially on lower-liquidity coins during high-volatility events.
  • Exchange-specific execution risk. Latency, downtime, and margin call mechanics vary by venue and are not modeled.
  • Weekend and gap risk. Crypto trades 24 by 7 but liquidity is thinner on weekends. Position risk during these windows may exceed the modeled invalidation distance.

Sample thresholds

A row is only surfaced publicly once its sample size crosses MIN_SAMPLE = 20. Below that, we display the row greyed out with a caveat, or fall back to a wider scope (for example, aggregating across long and short when a directional split is thin). This is stricter than most public backtest sites and deliberately so. A 60 percent win rate on 8 instances is directionally interesting but statistically noisy. We label it as such.

How often it updates

SPI is recomputed as new candles close and new setup outcomes resolve. The rolling backtest window advances with every daily maintenance run. The API and the pages that consume it always show the current computed state, timestamped.

Limitations we take seriously

  • Survivorship in the coin list. We backtest coins that currently trade on Coinbase Advanced Trade. Delisted coins are not in the sample. This biases results slightly upward.
  • Regime dependence. The sample window includes multiple market regimes (bull, bear, chop). Aggregate SPI blends across them. Individual future periods may deviate from aggregate.
  • Detector evolution. When we improve a detector (better refined-level clustering, tighter reaction thresholds), we re-score historical instances under the new rules. This means SPI values can shift as our methodology improves. Every material change is logged in the changelog below.

Not investment advice

Botsfolio publishes market structure observations and historical simulation results. We do not provide investment advice, do not issue trade signals, and do not recommend that any specific trade be taken or avoided. Every reader is responsible for their own trading decisions.

Changelog

  • 2026-08-18 — Initial methodology publication.

Related

Educational analysis, not financial advice. Past performance does not predict future results.