QuantJourney Backtester

QuantJourney Backtester

Share product feedback

✓

Thank you.

Your note is now in the QuantJourney inbox.

WF05 · example_wf_05_optuna_tpe_optimization.py

WF05 Optuna TPE Optimization + Walk-Forward

Use Optuna's Tree-structured Parzen Estimator (TPE) to search SMA fast/slow windows over continuous integer ranges, then validate the winning parameters with a rolling walk-forward.

What this example shows

This example shows how to build a workflow-level walk-forward validation research example with fold construction, parameter selection, diagnostics, logging and evidence capture.

The goal is educational: to demonstrate the full workflow for validation setup, search space definition, fold diagnostics, objective tracking and reproducible run logging.

Optimization workflow. Parameter-search workflow over 30 trials; the best observed setting was fast=23, slow=206 · observed in-sample Sharpe 0.6659. This is optimization output, not an investable or independently validated result. The subsequent walk-forward view used slice-diagnostics mode rather than per-fold refitting.

Run setup

The ordinary configuration used by the published run—kept visible here and in the Python source.

UniverseXLB · XLE · XLF · XLI · XLK · XLP · XLU · XLV · XLY
Configured period2000-01-03 → 2026-01-01
BenchmarkSPY · SPDR S&P 500 ETF Trust
Initial capitalSee source
Data sourceyfinance
Engine / snapshotPublic engine
Walk-forward / OptimizationMode
workflowGranularity
9Instruments
0Published plots
passedRun status

Dashboard

Compact evidence view built from the same run packet: metrics, plots and run metadata.

30 trials Evaluated
fast=23, slow=206 Best parameters
0.6659 Observed Sharpe

Metrics

This workflow emits diagnostics rather than a standard performance table.

Optimization workflow. Parameter-search workflow over 30 trials; the best observed setting was fast=23, slow=206 · observed in-sample Sharpe 0.6659. This is optimization output, not an investable or independently validated result. The subsequent walk-forward view used slice-diagnostics mode rather than per-fold refitting.

Artifacts

Stable links that can be referenced from GitHub README files or external docs.

Run log

Tail of the execution log for this packet.

  18 │ 2009-01 → 2010-12       │      1.25 │ 2011-01 → 2011-07       │       1.30
  19 │ 2009-07 → 2011-07       │      1.44 │ 2011-07 → 2011-12       │      -0.25
  20 │ 2010-01 → 2011-12       │      0.59 │ 2012-01 → 2012-07       │       1.01
  21 │ 2010-07 → 2012-07       │      1.18 │ 2012-07 → 2013-01       │       1.39
  22 │ 2011-01 → 2013-01       │      0.61 │ 2013-01 → 2013-07       │       1.92
  23 │ 2011-07 → 2013-07       │      0.89 │ 2013-07 → 2014-01       │       2.72
  24 │ 2012-01 → 2014-01       │      1.62 │ 2014-01 → 2014-07       │       1.73
  25 │ 2012-07 → 2014-07       │      1.90 │ 2014-07 → 2015-01       │       1.05
  26 │ 2013-01 → 2015-01       │      1.76 │ 2015-01 → 2015-07       │       0.25
  27 │ 2013-07 → 2015-07       │      1.50 │ 2015-07 → 2015-12       │      -0.80
  28 │ 2014-01 → 2015-12       │      0.44 │ 2016-01 → 2016-07       │       0.25
  29 │ 2014-07 → 2016-07       │      0.03 │ 2016-07 → 2016-12       │       1.49
  30 │ 2015-01 → 2016-12       │      0.19 │ 2017-01 → 2017-06       │       2.10
  31 │ 2015-07 → 2017-06       │      0.43 │ 2017-07 → 2018-01       │       3.50
  32 │ 2016-01 → 2018-01       │      1.40 │ 2018-01 → 2018-07       │       0.12
  33 │ 2016-07 → 2018-07       │      1.38 │ 2018-07 → 2019-01       │      -0.56
  34 │ 2017-01 → 2019-01       │      0.81 │ 2019-01 → 2019-07       │       2.67
  35 │ 2017-07 → 2019-07       │      0.79 │ 2019-07 → 2020-01       │       1.66
  36 │ 2018-01 → 2020-01       │      0.70 │ 2020-01 → 2020-07       │      -0.81
  37 │ 2018-07 → 2020-07       │      0.00 │ 2020-07 → 2020-12       │       2.53
  38 │ 2019-01 → 2020-12       │      0.54 │ 2021-01 → 2021-07       │       2.56
  39 │ 2019-07 → 2021-07       │      0.57 │ 2021-07 → 2021-12       │       1.66
  40 │ 2020-01 → 2021-12       │      0.63 │ 2022-01 → 2022-07       │      -0.19
  41 │ 2020-07 → 2022-07       │      1.46 │ 2022-07 → 2022-12       │       0.00
  42 │ 2021-01 → 2022-12       │      0.87 │ 2023-01 → 2023-06       │       0.93
  43 │ 2021-07 → 2023-06       │      0.48 │ 2023-07 → 2024-01       │       0.53
  44 │ 2022-01 → 2024-01       │      0.25 │ 2024-01 → 2024-07       │       2.10
  45 │ 2022-07 → 2024-07       │      0.79 │ 2024-07 → 2025-01       │       0.96
  46 │ 2023-01 → 2025-01       │      1.24 │ 2025-01 → 2025-07       │       0.26
  47 │ 2023-07 → 2025-07       │      0.64 │ 2025-07 → 2025-12       │       1.44
────────────────────────────────────────────────────────────────────────────────
AGGREGATE (IN-SAMPLE SLICES — not OOS)
  Composite Sharpe (IS slice): 0.75 [5%: 0.47, 95%: 1.06]
  CAGR (IS slice):         9.5%    Overfit Ratio: 0.72
  Max DD (IS slice):     -33.0%    Efficiency:    1.24
  Sharpe Decay:         +0.007/fold
  Deflated Sharpe:      n/a (in-sample; DSR not meaningful without independent trials)
  PBO:                       n/a
    (PBO unavailable: requires per-trial OOS evaluation; set WalkForwardConfig.pbo_trials=K (>=2) with an optimizer to evaluate top-K trials OOS per fold)

WARNINGS
  ⚠ PBO unavailable: requires per-trial OOS evaluation; set WalkForwardConfig.pbo_trials=K (>=2) with an optimizer to evaluate top-K trials OOS per fold
  ⚠ Walk-forward mode=slice_diagnostics: metrics are computed from a full-period NAV; pass backtester_factory for per-fold refit.
  ⚠ Fold 0: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 0: OOS Sharpe -0.88 is negative
  ⚠ Fold 1: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 1: OOS Sharpe -0.50 is negative
  ⚠ Fold 2: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 3: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 4: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 5: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 6: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 6: overfit ratio 5.7 > 2.5
  ⚠ Fold 7: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 8: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 9: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 10: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 11: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 11: overfit ratio 3.1 > 2.5
  ⚠ Fold 12: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 12: OOS Sharpe -0.57 is negative
  ⚠ Fold 12: overfit ratio inf > 2.5
  ⚠ Fold 13: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 13: OOS Sharpe -1.79 is negative
  ⚠ Fold 13: overfit ratio inf > 2.5
  ⚠ Fold 14: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 14: OOS Sharpe -0.62 is negative
  ⚠ Fold 15: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 16: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 16: OOS Sharpe -0.65 is negative
  ⚠ Fold 16: overfit ratio inf > 2.5
  ⚠ Fold 17: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 18: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 19: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 19: OOS Sharpe -0.25 is negative
  ⚠ Fold 19: overfit ratio inf > 2.5
  ⚠ Fold 20: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 21: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 22: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 23: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 24: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 25: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 26: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 26: overfit ratio 7.0 > 2.5
  ⚠ Fold 27: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 27: OOS Sharpe -0.80 is negative
  ⚠ Fold 27: overfit ratio inf > 2.5
  ⚠ Fold 28: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 29: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 30: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 31: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 32: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 32: overfit ratio 11.6 > 2.5
  ⚠ Fold 33: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 33: OOS Sharpe -0.56 is negative
  ⚠ Fold 33: overfit ratio inf > 2.5
  ⚠ Fold 34: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 35: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 36: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 36: OOS Sharpe -0.81 is negative
  ⚠ Fold 36: overfit ratio inf > 2.5
  ⚠ Fold 37: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 38: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 39: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 40: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 40: OOS Sharpe -0.19 is negative
  ⚠ Fold 40: overfit ratio inf > 2.5
  ⚠ Fold 41: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 41: overfit ratio 502.1 > 2.5
  ⚠ Fold 42: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 43: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 44: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 45: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 46: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ Fold 46: overfit ratio 4.8 > 2.5
  ⚠ Fold 47: slice diagnostics mode — metrics are sliced from the full-period NAV (no per-fold refit)
  ⚠ 11/48 folds have OOS Sharpe below 0.0
  MetricVerdict(name='overfit_ratio', value=0.7218739859395392, signal='green', description='< 1.5 — robust')
  MetricVerdict(name='efficiency', value=1.24109635507224, signal='green', description='> 0.7 — robust transfer')
  MetricVerdict(name='sharpe_decay', value=0.00706822603829495, signal='green', description='> -0.01/fold — stable')