2026-04-17-bbmr-sampled-report.md 15 KB

BBMR Sampled Report Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Add a backtest-bbmr-report command that samples multiple non-overlapping historical windows, runs a fixed Bollinger Band mean-reversion strategy on each window, and outputs one single-page HTML report with client-side segment switching.

Architecture: Extend the current report pipeline instead of replacing it. Add a dedicated BBMR sampler/runner module that fetches one public candle pool, derives deterministic sampled windows with warm-up context, runs one backtest per sampled window, and feeds a single wrapper HTML that switches per-segment journals and plots client-side.

Tech Stack: Python 3.11+, backtesting.py, pandas, existing OKX public candle client, existing CLI test harness, plain HTML/CSS/JS


File Structure

  • Modify: /home/lxy/okx-codex-trader/okx_codex_trader/cli.py
    • add backtest-bbmr-report CLI command and dispatch
  • Create: /home/lxy/okx-codex-trader/okx_codex_trader/bbmr_report.py
    • deterministic non-overlapping sampler
    • local dataclasses for sampled segment definitions/results
    • BBMR strategy runner
    • aggregate and per-segment result shaping
  • Modify: /home/lxy/okx-codex-trader/okx_codex_trader/report.py
    • add single-page sampled report HTML renderer
  • Modify: /home/lxy/okx-codex-trader/tests/test_cli.py
    • CLI contract for new command
  • Create: /home/lxy/okx-codex-trader/tests/test_bbmr_report.py
    • sampler, strategy, and single-page HTML tests
  • Modify: /home/lxy/okx-codex-trader/README.md
    • add new command example after implementation is stable

Task 1: CLI Contract For backtest-bbmr-report

Files:

  • Modify: /home/lxy/okx-codex-trader/tests/test_cli.py
  • Modify: /home/lxy/okx-codex-trader/okx_codex_trader/cli.py

  • [ ] Step 1: Write the failing CLI test

def test_backtest_bbmr_report_generates_single_page_report(capsys, tmp_path):
    main, client, bbmr_calls = build_main_with_stubs()
    output_file = tmp_path / "bbmr.html"

    exit_code = main(
        [
            "backtest-bbmr-report",
            "--symbol",
            "BTC-USDT-SWAP",
            "--bar",
            "3m",
            "--history-limit",
            "5000",
            "--leverage",
            "2",
            "--segments",
            "8",
            "--window-size",
            "300",
            "--output-file",
            str(output_file),
        ]
    )

    assert exit_code == 0
    assert client.get_candles_called_with == ("BTC-USDT-SWAP", "3m", 5000)
    assert bbmr_calls[0]["segments"] == 8
    assert bbmr_calls[0]["window_size"] == 300
  • Step 2: Run test to verify it fails

Run: cd /home/lxy/okx-codex-trader && .venv/bin/python -m pytest tests/test_cli.py -k bbmr -q Expected: FAIL because backtest-bbmr-report is not implemented

  • Step 3: Write minimal CLI implementation
bbmr_report = subparsers.add_parser("backtest-bbmr-report")
bbmr_report.add_argument("--symbol", choices=SUPPORTED_SYMBOLS, required=True)
bbmr_report.add_argument("--bar", required=True)
bbmr_report.add_argument("--history-limit", type=int, required=True)
bbmr_report.add_argument("--leverage", type=int, choices=(1, 2, 3), required=True)
bbmr_report.add_argument("--segments", type=int, required=True)
bbmr_report.add_argument("--window-size", type=int, required=True)
bbmr_report.add_argument("--output-file", required=True)
if args.command == "backtest-bbmr-report":
    candles = client.get_candles(args.symbol, args.bar, args.history_limit)
    report = bbmr_report_fn(
        candles=candles,
        leverage=args.leverage,
        output_file=Path(args.output_file),
        symbol=args.symbol,
        bar=args.bar,
        segments=args.segments,
        window_size=args.window_size,
    )
    print(_dump_json(report))
    return 0
def main_factory(
    *,
    ...,
    report_fn: Callable = generate_backtest_report,
    bbmr_report_fn: Callable = generate_bbmr_sampled_report,
):
    ...
def build_main_with_stubs(...):
    ...
    def fake_bbmr_report(...):
        ...
    main = main_factory(..., bbmr_report_fn=fake_bbmr_report)
  • Step 4: Run test to verify it passes

Run: cd /home/lxy/okx-codex-trader && .venv/bin/python -m pytest tests/test_cli.py -k bbmr -q Expected: PASS

  • Step 5: Commit
git -C /home/lxy/okx-codex-trader add okx_codex_trader/cli.py tests/test_cli.py
git -C /home/lxy/okx-codex-trader commit -m "feat: add bbmr report cli contract"

Task 2: Deterministic Sampler Contract

Files:

  • Create: /home/lxy/okx-codex-trader/tests/test_bbmr_report.py
  • Create: /home/lxy/okx-codex-trader/okx_codex_trader/bbmr_report.py

  • [ ] Step 1: Write the failing sampler tests

def test_sample_segments_rejects_history_pool_too_small():
    candles = build_candles(count=1000)

    with pytest.raises(ValueError, match="history pool is too small"):
        sample_segments(candles=candles, segments=8, window_size=300, warmup_bars=69, seed=7)


def test_sample_segments_returns_non_overlapping_ranges():
    candles = build_candles(count=5000)

    sampled = sample_segments(candles=candles, segments=4, window_size=300, warmup_bars=69, seed=7)

    ranges = [(segment.context_start, segment.report_end) for segment in sampled]
    assert len(ranges) == len(set(ranges))
    for left, right in zip(ranges, ranges[1:]):
        assert left[1] < right[0] or right[1] < left[0]


def test_sample_segments_is_deterministic_for_same_seed():
    candles = build_candles(count=5000)

    a = sample_segments(candles=candles, segments=4, window_size=300, warmup_bars=69, seed=7)
    b = sample_segments(candles=candles, segments=4, window_size=300, warmup_bars=69, seed=7)

    assert a == b


def test_generate_bbmr_sampled_report_rejects_insufficient_history_pool(tmp_path):
    candles = build_candles(count=1000)

    with pytest.raises(ValueError, match="history pool is too small"):
        generate_bbmr_sampled_report(
            candles=candles,
            leverage=2,
            output_file=tmp_path / "bbmr.html",
            symbol="BTC-USDT-SWAP",
            bar="3m",
            segments=8,
            window_size=300,
        )
  • Step 2: Run tests to verify they fail

Run: cd /home/lxy/okx-codex-trader && .venv/bin/python -m pytest tests/test_bbmr_report.py -k sample_segments -q Expected: FAIL because sampler functions do not exist

  • Step 3: Write minimal deterministic sampler
WARMUP_BARS = 69
SAMPLER_SEED = 7
def sample_segments(...):
    required = segments * (window_size + warmup_bars)
    if len(candles) < required:
        raise ValueError("history pool is too small")
    ...
  • Step 4: Run tests to verify they pass

Run: cd /home/lxy/okx-codex-trader && .venv/bin/python -m pytest tests/test_bbmr_report.py -k sample_segments -q Expected: PASS

  • Step 5: Commit
git -C /home/lxy/okx-codex-trader add okx_codex_trader/bbmr_report.py tests/test_bbmr_report.py
git -C /home/lxy/okx-codex-trader commit -m "feat: add deterministic bbmr segment sampler"

Task 3: BBMR Strategy Rules

Files:

  • Modify: /home/lxy/okx-codex-trader/tests/test_bbmr_report.py
  • Modify: /home/lxy/okx-codex-trader/okx_codex_trader/bbmr_report.py

  • [ ] Step 1: Write the failing strategy tests

def test_run_bbmr_segment_produces_long_trade_on_lower_band_reversion():
    candles = build_lower_band_reversion_fixture()

    result = run_bbmr_segment(candles=candles, leverage=2)

    assert result.trade_count == 1
    assert result.trades[0]["side"] == "Long"


def test_run_bbmr_segment_produces_short_trade_on_upper_band_reversion():
    candles = build_upper_band_reversion_fixture()

    result = run_bbmr_segment(candles=candles, leverage=2)

    assert result.trade_count == 1
    assert result.trades[0]["side"] == "Short"


def test_run_bbmr_segment_marks_open_position_to_market_but_keeps_journal_realized_only():
    candles = build_open_tail_fixture()

    result = run_bbmr_segment(candles=candles, leverage=2)

    assert result.trade_count == 0
    assert result.trades == []
    assert result.total_return != 0
  • Step 2: Run tests to verify they fail

Run: cd /home/lxy/okx-codex-trader && .venv/bin/python -m pytest tests/test_bbmr_report.py -k run_bbmr_segment -q Expected: FAIL because BBMR runner does not exist

  • Step 3: Write minimal BBMR segment runner

Implement fixed rules from the spec and lock them with explicit tests:

  • Bollinger 20/2
  • bandwidth (upper-lower)/middle
  • filter against previous 50 completed bandwidth values
  • stop-loss intrabar at stop price
  • same-bar sequencing: stop first, then close-based exit, then entry only if flat and no exit occurred
  • final reported candle cannot generate next-open entry or mean-reversion exit
  • ending return and drawdown use final-close mark-to-market if trade remains open

Add failing tests for:

def test_run_bbmr_segment_excludes_warmup_from_reported_trade_times():
    ...


def test_run_bbmr_segment_does_not_generate_entry_from_final_reported_candle():
    ...


def test_run_bbmr_segment_stop_loss_takes_precedence_over_close_exit():
    ...


def test_run_bbmr_segment_does_not_reverse_on_exit_bar():
    ...
  • Step 4: Run tests to verify they pass

Run: cd /home/lxy/okx-codex-trader && .venv/bin/python -m pytest tests/test_bbmr_report.py -k run_bbmr_segment -q Expected: PASS

  • Step 5: Commit
git -C /home/lxy/okx-codex-trader add okx_codex_trader/bbmr_report.py tests/test_bbmr_report.py
git -C /home/lxy/okx-codex-trader commit -m "feat: add bbmr segment backtest rules"

Task 4: Single-Page HTML Wrapper

Files:

  • Modify: /home/lxy/okx-codex-trader/tests/test_bbmr_report.py
  • Modify: /home/lxy/okx-codex-trader/okx_codex_trader/report.py
  • Modify: /home/lxy/okx-codex-trader/okx_codex_trader/bbmr_report.py

  • [ ] Step 1: Write the failing HTML wrapper tests

def test_render_bbmr_sampled_report_contains_summary_and_segment_switcher():
    html = render_bbmr_sampled_report(...)
    assert "history limit" in html.lower()
    assert "segment count" in html.lower()
    assert "window size" in html.lower()
    assert "average return across segments" in html.lower()
    assert "median return across segments" in html.lower()
    assert "best segment return" in html.lower()
    assert "worst segment return" in html.lower()
    assert "segment-selector" in html
    assert "data-segment-index=\"0\"" in html


def test_render_bbmr_sampled_report_contains_trade_journal_and_plot_reference():
    html = render_bbmr_sampled_report(...)
    assert "Trade Journal" in html
    assert "/files/segment-0.plot.html" in html
    assert "sampled range start time" in html.lower()
    assert "sampled range end time" in html.lower()
    assert "trade count" in html.lower()
    assert "total return" in html.lower()
    assert "win rate" in html.lower()
    assert "max drawdown" in html.lower()
  • Step 2: Run tests to verify they fail

Run: cd /home/lxy/okx-codex-trader && .venv/bin/python -m pytest tests/test_bbmr_report.py -k render_bbmr -q Expected: FAIL because sampled report wrapper does not exist

  • Step 3: Write minimal single-page wrapper

Render:

  • top-level aggregate metrics
  • strategy description
  • sampled ranges table/list
  • segment buttons/select element
  • one active segment panel at a time
  • client-side JS to switch visible panel and iframe

  • [ ] Step 4: Run tests to verify they pass

Run: cd /home/lxy/okx-codex-trader && .venv/bin/python -m pytest tests/test_bbmr_report.py -k render_bbmr -q Expected: PASS

  • Step 5: Commit
git -C /home/lxy/okx-codex-trader add okx_codex_trader/report.py okx_codex_trader/bbmr_report.py tests/test_bbmr_report.py
git -C /home/lxy/okx-codex-trader commit -m "feat: add bbmr sampled single-page html report"

Task 5: End-To-End Report Generation

Files:

  • Modify: /home/lxy/okx-codex-trader/tests/test_cli.py
  • Modify: /home/lxy/okx-codex-trader/tests/test_bbmr_report.py
  • Modify: /home/lxy/okx-codex-trader/okx_codex_trader/bbmr_report.py
  • Modify: /home/lxy/okx-codex-trader/README.md

  • [ ] Step 1: Write the failing end-to-end generator test

def test_generate_bbmr_sampled_report_writes_wrapper_and_plot_files(tmp_path):
    candles = build_candles(count=5000)

    result = generate_bbmr_sampled_report(
        candles=candles,
        leverage=2,
        output_file=tmp_path / "bbmr.html",
        symbol="BTC-USDT-SWAP",
        bar="3m",
        segments=3,
        window_size=300,
    )

    assert Path(result["report_file"]).exists()
    assert result["segment_count"] == 3
    assert (tmp_path / "bbmr.segment-0.plot.html").exists()
  • Step 2: Run tests to verify they fail

Run: cd /home/lxy/okx-codex-trader && .venv/bin/python -m pytest tests/test_bbmr_report.py -k generate_bbmr -q Expected: FAIL because the assembled generator does not exist

  • Step 3: Write minimal generator and docs

Implement:

  • one wrapper HTML file
  • one plot file per segment
  • aggregate summary JSON return to CLI
  • README command example

  • [ ] Step 4: Run focused tests to verify they pass

Run: cd /home/lxy/okx-codex-trader && .venv/bin/python -m pytest tests/test_cli.py tests/test_bbmr_report.py -q Expected: PASS

  • Step 5: Commit
git -C /home/lxy/okx-codex-trader add README.md okx_codex_trader/bbmr_report.py okx_codex_trader/report.py tests/test_bbmr_report.py tests/test_cli.py
git -C /home/lxy/okx-codex-trader commit -m "feat: add sampled bbmr backtest report"

Task 6: Full Verification And Real Report

Files:

  • Verify only: /home/lxy/okx-codex-trader

  • [ ] Step 1: Run full automated tests

Run: cd /home/lxy/okx-codex-trader && .venv/bin/python -m pytest -q Expected: PASS

  • Step 2: Generate a real sampled report

Run:

cd /home/lxy/okx-codex-trader
.venv/bin/python -m okx_codex_trader.cli backtest-bbmr-report \
  --symbol BTC-USDT-SWAP \
  --bar 3m \
  --history-limit 5000 \
  --leverage 2 \
  --segments 8 \
  --window-size 300 \
  --output-file bbmr-sampled-report.html

Expected: one wrapper HTML plus segment plot files written next to it

  • Step 3: Commit
git -C /home/lxy/okx-codex-trader add README.md okx_codex_trader/cli.py okx_codex_trader/bbmr_report.py okx_codex_trader/report.py tests/test_bbmr_report.py tests/test_cli.py
git -C /home/lxy/okx-codex-trader commit -m "feat: ship sampled bbmr report flow"