BBMR Sampled Report Design
Goal
Add a new real backtest report path for short-horizon Bollinger Band mean reversion.
The feature must:
- fetch one larger pool of recent public OKX candles
- randomly sample multiple non-overlapping time windows from that pool
- run the same Bollinger mean reversion strategy on each sampled window
- output one HTML report file with a segment switcher instead of many separate report pages
Non-Goals
This feature does not:
- replace the existing
10/20 SMA backtest path
- replace the existing
backtest-report command
- add fees or slippage
- add TP/SL trailing logic
- auto-optimize parameters
- support spot symbols
Command
Add one new CLI command:
Required arguments:
--symbol with value BTC-USDT-SWAP or ETH-USDT-SWAP
--bar for candle timeframe
--history-limit for the total candle pool
--leverage in 1..3
--segments for the number of sampled windows
--window-size for bars per sampled window
--output-file for the final single-page HTML report
Optional arguments are not added in v1. Parameters are fixed except where the user explicitly asked for configurability.
Strategy Contract
This v1 strategy is fixed:
- strategy family: Bollinger Band mean reversion
- indicator length:
20
- standard deviation multiplier:
2
- bandwidth filter lookback:
50
- stop loss:
0.5% relative to entry
- initial equity per sampled segment:
10_000 USDT
- position sizing: use
100% of current segment equity as isolated margin for each trade
- leverage: CLI input, limited to integer
1..3
- fees:
0
- slippage:
0
Entry Rules
- if candle close is below lower band, enter
long at next candle open
- if candle close is above upper band, enter
short at next candle open
- entry signals are only evaluated on reported candles that still have a next reported candle inside the same sampled window
- the final reported candle of a sampled window cannot generate a new entry
Filter Rule
- Bollinger bandwidth is defined as
(upper_band - lower_band) / middle_band
- only allow entries when current Bollinger bandwidth is less than or equal to the rolling median of the previous
50 completed bandwidth values
- the current bar is excluded from the median window
Warm-Up Rule
- each sampled report window must have
69 warm-up candles immediately before its first reported candle
- warm-up candles are used only to compute:
- Bollinger bands with
length = 20
- previous
50 completed bandwidth values for the filter
- warm-up candles are never shown in the sampled range labels, trade journal, or per-segment metrics
- sampling must reserve these
69 warm-up candles per segment
- sampled segments must be non-overlapping after including their warm-up context
Exit Rules
- mean-reversion exits are close-based:
- if a
long position is open and candle close is greater than or equal to the middle band, exit at next candle open
- if a
short position is open and candle close is less than or equal to the middle band, exit at next candle open
- mean-reversion exit signals are only evaluated on reported candles that still have a next reported candle inside the same sampled window
- the final reported candle of a sampled window cannot generate a new mean-reversion exit
- stop-loss exits are intrabar:
- if a
long position is open and a later candle low is less than or equal to the stop price, exit on that bar at the stop price
- if a
short position is open and a later candle high is greater than or equal to the stop price, exit on that bar at the stop price
- if both a stop-loss condition and a mean-reversion exit condition would occur on the same bar, stop-loss takes precedence
- same-bar sequencing is fixed:
- first evaluate intrabar stop-loss for an already open position
- if stop-loss exits the position on that bar, the bar is exhausted and no new entry or reversal may be generated from that same bar
- if no stop-loss exit occurs, evaluate close-based mean-reversion exit for an already open position
- if a close-based exit signal is generated on that bar, do not also generate an opposite-side entry from that same bar
- entry signals are only allowed when the strategy is flat at the close of that bar and no exit occurred on that bar
End-Of-Window Rule
- keep current project behavior
- do not force-close an open trade at the final bar
- report realized trades only in the trade journal
- if a position remains open at the end of a sampled window:
- per-segment
trade_count and journal rows remain realized-only
- per-segment
total return and max drawdown use final-bar-close mark-to-market equity
- aggregate return statistics use those per-segment mark-to-market totals
Sampling Contract
Sampling must avoid concentrating on one market regime.
Rules:
- fetch
history-limit candles first
- sample exactly
segments non-overlapping windows
- each sampled window must have exactly
window-size candles
- windows are chosen randomly from the fetched pool
- sampling must fail if
history-limit is too small to fit the requested non-overlapping windows plus 69 warm-up candles per segment
The random process must be reproducible:
- use a deterministic RNG seed
- expose the chosen sampled ranges in the output report
Output Shape
The command outputs one HTML file and supporting plot files.
Main HTML
The main report page is a single journal-first page with:
- summary header
- strategy description
- sampling summary
- segment switcher
- current segment metrics
- current segment trade journal
- current segment interactive plot
Segment Switching
The single HTML file must allow switching between sampled windows without opening separate top-level pages.
Implementation rule for v1:
- generate one plot file per sampled window if needed
- keep one main wrapper HTML
- the wrapper switches the visible segment content client-side
Summary Metrics
Top-level page must include:
- symbol
- timeframe
- history limit
- segment count
- window size
- strategy parameters
- aggregate trade count
- average return across segments
- median return across segments
- best segment return
- worst segment return
Per-Segment Metrics
Each segment view must show:
- sampled range start time
- sampled range end time
- trade count
- total return
- win rate
- max drawdown
Data Model
Add report-side models for:
- sampled segment definition
- start index
- end index
- start timestamp
- end timestamp
- sampled segment result
- summary metrics
- trade journal rows
- plot filename
These models are local to report generation and do not affect existing paper state files.
Error Handling
Allowed failures:
history-limit too small for requested segments * window-size
- invalid sampling result
- public OKX market data failure
- report generation failure
No fallback logic.
Testing
Add tests for:
- CLI parses
backtest-bbmr-report
- report generator rejects insufficient history pool
- sampler returns non-overlapping windows
- sampler is deterministic for the same seed
- report HTML contains aggregate summary and segment switcher
- report HTML contains per-segment trade journal and plot reference
- strategy generates long and short trades on controlled fixtures