ML Model Training Pipeline
A comprehensive technical reference for BitPredict's 18-step machine learning model training pipeline. Each step is documented with its mathematical foundations, practical rationale, and configuration guidance: covering everything from model selection and feature engineering through triple-barrier labeling, combinatorial purged cross-validation, overfitting diagnostics, and ensemble construction.
Pipeline Overview
The ML training pipeline transforms raw market data into validated, deployable prediction models through a sequence of 18 rigorously designed stages. Unlike the strategy optimization pipeline, which searches for optimal parameters of hand-crafted rules, the ML pipeline learns predictive patterns directly from data. This makes it both more powerful and more susceptible to overfitting, requiring a substantially more elaborate validation framework.
The pipeline operates in five conceptual stages:
- Setup (Steps 1–4): Model selection, data sourcing, train/walk-forward/holdout splitting, and feature selection.
- Feature Engineering (Steps 5–7): Fractional differentiation, winsorization, IC-based filtering, triple-barrier labeling, and sample weighting.
- Training & Optimization (Steps 8–10): Combinatorial purged cross-validation, TPE hyperparameter search, model calibration, and feature importance analysis.
- Backtesting & Validation (Steps 11–16): Signal generation, backtest execution, walk-forward analysis, Monte Carlo simulation, overfitting diagnostics, and holdout evaluation.
- Selection & Deployment (Steps 17–18): Multi-gate model selection and ensemble construction.
The pipeline supports both classification (predicting discrete market states: long, short, or neutral) and regression (predicting continuous returns). With 45 classifiers and 58 regressors available, including GPU-accelerated CatBoost, LightGBM, and XGBoost, the model space is vast, making rigorous validation essential.
Model Selection & Hyperparameter Configuration
The first step selects the model architecture and configures its hyperparameters. The system exposes 45 scikit-learn-compatible classifiers and 58 regressors through a unified interface built on ml_registry.json.
Classifier vs. Regressor
Classifiers predict discrete labels: typically long (+1), short (−1), or neutral (0). They are the natural choice when the labeling method (Step 6) produces categorical outputs, such as triple-barrier labels. The predicted class probabilities can be thresholded to control signal frequency and confidence.
Regressors predict continuous values: expected return, volatility, or any numeric target. They are appropriate when using regression-based labeling (Step 6) and produce signals proportional to the predicted magnitude, naturally scaling position sizes to conviction.
GPU-Accelerated Models
CatBoost, LightGBM, and XGBoost, available in both classifier and regressor variants, support GPU acceleration when use_gpu is enabled (Step 9). For datasets exceeding 10,000 bars, GPU training can reduce wall-clock time by 5–20× depending on model complexity and feature count. GPU models use histogram-based tree construction, which parallelises efficiently across CUDA cores.
Hyperparameter Optimization
When optimize_params is enabled, the system searches the model's hyperparameter space using the same TPE sampler described in the Strategy Optimization pipeline (Step 2 of that document). Each model in ml_registry.json defines its own parameter ranges with three optimization presets:
- Low (Narrow): 75–125% of default: fast, conservative search near defaults.
- Medium (Balanced): 50–150% of default: recommended for most use cases.
- High (Wide): 0–200% of default: broad exploration at higher overfitting risk.
Each parameter's min, max, and step can be individually overridden for fine-grained control. The total combination count, the product of all enabled parameter ranges, determines the minimum n_trials needed for adequate coverage.
Model selection is not merely a preference; different model families have fundamentally different inductive biases. Tree-based models (Random Forest, XGBoost, LightGBM) handle non-linear feature interactions and outliers well but can extrapolate poorly. Linear models (Logistic Regression, Ridge) extrapolate reliably but miss non-linear patterns. Neural networks (MLP) can learn arbitrary functions but require more data and careful regularisation. Choosing the right family for your data characteristics, and then optimising its hyperparameters, is the single most consequential decision in the pipeline.
| Parameter | Type | Default | Description |
|---|---|---|---|
| model_type | classifiers | regressors | classifiers | Classification predicts discrete labels (long/short/neutral); regression predicts continuous values (returns). |
| model_name | string | adaboostclassifier | Model identifier from ml_registry.json. 45 classifiers and 58 regressors available. |
| optimize_params | boolean | false | Enable TPE hyperparameter search with preset-controlled search ranges. |
Data Source & Structural Break Detection
The data source configuration specifies the trading pair, bar type, timeframe, and historical date range. Data is sourced from Binance. These choices fundamentally determine what patterns the model can learn and whether those patterns generalise.
Bar Type & Timeframe Selection
The choice of bar type (time, dollar, volume, hybrid, renko, range) and timeframe (1m through 1w) determines the information density and statistical properties of the input data. Time bars at 12h (the default) provide a balance of statistical sample size and signal-to-noise ratio for most strategies. Dollar and volume bars produce more stationary return distributions, important for ML models that assume IID data. For a detailed treatment of bar types, see the Data Quality documentation.
Structural Break Detection
Financial time series are non-stationary: the data-generating process changes at unpredictable points due to regulatory shifts, market structure evolution, or macroeconomic regime changes. When enabled, structural break detection uses the Chow test to identify points where the statistical properties of the series change significantly:
where RSS is residual sum of squares from regressions on each segment and the pooled data. The threshold parameter controls the F-statistic significance level. Breaks above the threshold are flagged; the model can then be trained only on data since the most recent break, avoiding contamination from structurally different historical regimes.
Training on data spanning a structural break (e.g., pre- and post-ETF approval for Bitcoin) contaminates the model with relationships that no longer hold. A model trained on pre-break data and tested post-break will fail regardless of its architectural quality. Structural break detection provides an objective criterion for truncating the training window.
| Parameter | Type | Default | Description |
|---|---|---|---|
| symbol | string | btc | Trading pair symbol (e.g., btc, eth, sol). |
| bar_type | time | dollar | volume | hybrid | renko | range | time | Bar construction method. Non-time bars produce more stationary returns for ML training. |
| time_horizon | string | 12h | Bar timeframe from 1m to 1w. 12h provides a good signal-to-noise balance. |
| start_date | date | 2020-01-01 | Training period start. Earlier dates capture more regimes but risk structural breaks. |
| end_date | date | 2025-01-01 | Training period end. Must leave sufficient holdout period after this date. |
| structural_break_detection.enabled | boolean | false | Enable Chow test break detection to avoid training across regime changes. |
Data Splits & Purge Gap
The dataset is partitioned into three temporal segments: train (70%), walk-forward (20%), and holdout (10%). As with the strategy optimization pipeline, splits are strictly temporal, no random shuffling, to prevent look-ahead bias.
Percentage vs. Date-Based Splits
Percentage mode allocates fixed fractions of the total date range. Simple and reproducible. Date-based mode allows explicit cut points: useful when you know specific dates where market regimes changed and want the walk-forward period to cover a particular event.
Purge Gap Multiplier
The purge gap is an embargo period inserted between the train and test sets within each cross-validation fold. It prevents data leakage from overlapping labels: a trade whose holding period spans the train/test boundary would leak future information into the training set. The gap is calculated as:
where horizon is the labeling horizon from Step 6. With horizon=15 and multiplier=1, a 15-bar gap is inserted between each train and test fold. Higher multipliers provide conservative protection against leakage at the cost of reducing effective training data.
Purge gaps are the single most overlooked source of data leakage in financial ML. Without them, a model can achieve impressive backtest results by learning to predict the label overlap at fold boundaries: a pattern that cannot exist in live trading. López de Prado (2018) demonstrates that purging alone can reduce reported Sharpe ratios by 30–50% in strategies with long holding periods.
| Parameter | Type | Default | Description |
|---|---|---|---|
| mode | percentage | datetime | percentage | Percentage: fixed fractions. Datetime: explicit date cut points for regime-aware splitting. |
| train_pct | integer (10–90) | 70 | Fraction of data for training. Balance against walk-forward and holdout needs. |
| walkforward_pct | integer (5–80) | 20 | Fraction for walk-forward OOS validation windows. |
| holdout_pct | integer (5–50) | 10 | Fraction reserved for final untouched evaluation. |
| purge_gap_multiplier | integer (1–10) | 1 | Multiplier on labeling horizon for embargo gap between folds. Higher = more conservative. |
Feature Selection
BitPredict provides 29 pre-computed financial features spanning multiple domains: momentum and trend (returns, EMA, supertrend, risk-adjusted momentum), volatility and dispersion (skewness, volume ROC, entropy collapse rate), market regime metadata (transition pressure, regime scores, trend acceleration Z-scores), information theory (transfer entropy between timeframes, information geometry distance), and structural features (VWAP, overnight gap, PV divergence, recovery slope).
Feature Categories
- Momentum/trend (8): returns_4hr, returns_arith, returns_abs, ema_20, supertrend, risk_adj_momentum_50, score_accelerating, mr_trend_acceleration_z
- Volatility/dispersion (5): skewness_60, volume_roc, entropy_collapse_rate, mr_volatility_skew_chg, log_return_50
- Regime metadata (7): transition_pressure, mr_transition_pressure_chg, score_bear, mr_score_bear_chg, mr_score_transition_z, mr_score_accelerating_z, recovery_slope
- Information theory (2): transfer_entropy_5m_15m, information_geometry_dist
- Structural (7): vwap, overnight_gap, pv_divergence, return_autocorr_5, time_sine, ...
The default selection, "all", passes all 29 features to the feature pipeline (Step 5), which then performs automated filtering. A custom subset can be specified to restrict the model to domain-specific features or to test hypotheses about which feature families drive performance.
Feature selection is the complement to feature engineering: before transforming features, you must decide which raw signals enter the pipeline. The 29 features span fundamentally different information sources: regime metadata captures market structure, transfer entropy captures cross-timeframe information flow, and momentum features capture trend persistence. A model limited to one family will miss cross-domain interactions; a model using all features without filtering risks the curse of dimensionality.
Feature Pipeline: Preprocessing, Filtering & Dimensionality Reduction
The feature pipeline is the most mathematically sophisticated preprocessing step. It transforms raw features into stationary, decorrelated, high-signal inputs through a sequence of operations: outlier treatment, fractional differentiation, feature selection via Information Coefficient (IC), adversarial validation, cluster-based redundancy removal, and predictive decay analysis.
Winsorization
Extreme outliers, common in financial data due to flash crashes, exchange errors, or data feed anomalies, can dominate model training. Winsorization clips feature values at specified percentiles:
The default clips at the 1st and 99th percentiles, preserving the central 98% of the distribution unchanged. This is a one-sided operation on each feature independently.
Fractional Differentiation (FFD)
Financial time series are typically I(1): integrated of order 1, meaning they contain a unit root and are non-stationary. Standard ML models assume I(0) stationarity. Integer differentiation (first differences) achieves stationarity but destroys all memory: the differenced series retains no information about past levels.
Fractional differentiation provides a continuum between levels (d = 0, maximum memory, non-stationary) and first differences (d = 1, minimum memory, stationary). The optimal order d* is found by grid search over [d_min, d_max] at step granularity, testing each candidate with the Augmented Dickey-Fuller (ADF) test:
where the weights for fractional differentiation are computed via the binomial expansion:
The result is a stationary series that preserves as much memory as possible, critical for financial ML where persistent trends carry predictive signal.
Information Coefficient (IC) Filtering
The IC measures the cross-sectional correlation between a feature's values and forward returns. For each feature f:
where Spearman (rank) correlation is used for robustness to outliers. Features with |IC| < ic_threshold (default 0.02) are dropped: they carry negligible predictive signal. The ICIR (Information Coefficient Information Ratio) adds a consistency dimension:
Features with ICIR < icir_threshold (default 0.5) are dropped: their predictive power is inconsistent over time, making them unreliable for training.
Adversarial Validation
A subtle form of overfitting occurs when features differ systematically between train and test periods, not in their predictive relationship with the target, but in their marginal distributions. The model learns to exploit these distributional differences rather than genuine predictive patterns. Adversarial validation detects this by training a classifier to distinguish train from test samples using the features. Features with AUC > adversarial_auc_threshold (default 0.55) are flagged as “too predictive of time” and removed.
Cluster-Based Decorrelation
Redundant features inflate dimensionality without adding information, increasing overfitting risk. Features are clustered by their pairwise correlation distance; within each cluster closer than cluster_distance_threshold (default 0.5), only the feature with the highest IC is retained. This reduces the effective feature count while preserving the information content of each independent signal family.
Predictive Decay Analysis
A feature that predicts well at horizon 1 but degrades at horizon 20 may be useful for short-term models but harmful for longer-horizon strategies. Decay analysis measures IC at multiple horizons [1, 2, 5, 10, 20] and computes the decay ratio:
Features with decay_ratio < decay_min_ic_ratio (default 0.75) are flagged for potential removal: their signal fades too quickly for the chosen labeling horizon.
Pipeline Modes
Four aggressiveness modes control how aggressively features are filtered:
- Auto (default): Balances feature retention against signal quality using adaptive thresholds.
- Balanced: Moderately aggressive, suitable for most use cases.
- Strict: Aggressively removes features with marginal IC, high correlation, or temporal instability. Fewer features survive but those that do are high-confidence. Risk of underfitting.
- Lenient: Retains most features. Useful for initial exploration or when the feature count is already small. Higher overfitting risk.
The feature pipeline is where raw data becomes ML-ready input. Each step, FFD for stationarity, IC for signal identification, adversarial validation for temporal robustness, clustering for dimensionality reduction, addresses a specific failure mode in financial ML. Skipping any of these steps produces models that work in backtests and fail in production for reasons that are difficult to diagnose post-hoc. The pipeline makes these failure modes explicit and testable.
Setting ffd_adf_threshold too high (e.g., 0.10) may leave features non-stationary, violating the IID assumption of most ML models. Conversely, setting ic_threshold too low retains features with negligible predictive power, increasing dimensionality and overfitting risk with no benefit.
| Parameter | Type | Default | Description |
|---|---|---|---|
| enabled | boolean | true | Enable the feature preprocessing pipeline. Disable only for debugging raw feature behaviour. |
| mode | auto | balanced | strict | lenient | auto | Aggressiveness of feature filtering. Auto adapts thresholds; strict removes more features. |
| winsorize_lower_pct | float (0–10) | 1.0 | Lower percentile for outlier clipping. Values below this are capped. |
| ffd_d_min / ffd_d_max | float (0–1) | 0.0 / 1.0 | Search range for optimal fractional differentiation order via ADF test. |
| ffd_adf_threshold | 0.01 | 0.05 | 0.1 | 0.05 | p-value threshold for ADF stationarity test. 0.05 is standard; 0.01 is conservative. |
| ic_threshold | float (0–1) | 0.02 | Minimum absolute IC to retain a feature. Features with weaker predictive power are dropped. |
| adversarial_auc_threshold | float (0.5–1) | 0.55 | AUC above which a feature is considered temporally unstable and removed. |
| cluster_distance_threshold | float (0–1) | 0.5 | Maximum correlation distance for clustering redundant features. Lower = more aggressive deduplication. |
| decay_min_ic_ratio | float (0–1) | 0.75 | Minimum IC decay ratio across horizons. Features whose signal fades faster are flagged. |
Labeling: Triple Barrier, Fixed Percentage & Regression
Labeling transforms raw price data into supervised learning targets. This is arguably the most consequential modeling decision: the label definition determines what the model learns to predict, and errors in labeling propagate through every downstream step.
Triple Barrier Method (López de Prado)
The triple barrier method defines three boundaries for each observation at time t:
- Profit-Taking (PT) barrier: upper threshold at price × (1 + pt_mult × σ). If hit first, label = +1 (long) or −1 (short) depending on direction.
- Stop-Loss (SL) barrier: lower threshold at price × (1 − sl_mult × σ). If hit first, label = opposite sign.
- Vertical (time) barrier: horizon bars after entry. If neither PT nor SL is hit, label = 0 or the sign of the return at the vertical barrier.
The volatility σ is either the Average True Range (ATR, default) or a fixed percentage (pct_base). ATR adapts barrier distances to current volatility, producing more consistent hit rates across different market conditions:
Fixed Percentage
Simpler alternative: label = +1 if the return over the horizon exceeds threshold, −1 if it falls below −threshold, 0 otherwise. Suitable when volatility is stable or when you want uniform thresholds across all observations.
Regression
Produces continuous labels: log returns, simple returns, or raw prices. Used with regressor models (Step 1). The risk_adjusted option normalises returns by realised volatility, making labels comparable across volatility regimes.
Label Quality Filter
Labels are tested for statistical significance: for each label class, a t-test compares the mean forward return conditional on that label against zero. Labels with |t| < min_tvalue (default 1.0) are considered uninformative and can be dropped or down-weighted.
Meta-Labeling
Meta-labeling trains a secondary binary classifier to predict whether the primary model's prediction will be correct. This “model of the model” filters out low-confidence predictions, improving precision at the cost of recall. Particularly effective when the primary model has high recall but low precision: the meta-model suppresses false positives.
The triple barrier method is the gold standard for financial ML labeling because it respects the path-dependent nature of trading outcomes. A fixed-horizon label (“was the return positive after 15 bars?”) ignores what happened during those 15 bars: a position might have been stopped out at bar 3 with a 5% loss, yet the fixed-horizon label at bar 15 shows a 2% gain. The triple barrier correctly captures the actual trading outcome: the stop-loss was hit first.
Setting pt_mult = sl_mult (e.g., both at 2.0) produces symmetric barriers but ignores the empirical fact that financial returns are negatively skewed: losses tend to be larger and faster than gains. The default 3.0/1.5 ratio reflects this asymmetry.
| Parameter | Type | Default | Description |
|---|---|---|---|
| method | triple_barrier | fixed_pct | regression | triple_barrier | Labeling methodology. Triple barrier captures path-dependent outcomes. |
| horizon | integer (1–500) | 15 | Maximum holding period in bars. Longer horizons = fewer labels but less noise. |
| pt_mult | float (0.5–10) | 3.0 | Profit-taking multiplier on ATR/%. Higher = wider profit targets, fewer PT hits. |
| sl_mult | float (0.5–10) | 1.5 | Stop-loss multiplier on ATR/%. Lower = tighter stops, more SL hits. |
| barrier_type | atr | pct | atr | ATR adapts barriers to volatility; pct uses fixed percentage of price. |
| label_quality_filter.enabled | boolean | true | Filter labels by t-test significance against zero-mean null hypothesis. |
Sample Weights: Uniqueness, Time Decay & Sequential Bootstrap
Financial labels are not IID: labels generated from overlapping time windows share information, violating the independence assumption of standard ML loss functions. Sample weights correct for this by assigning lower weight to samples with higher overlap.
Uniqueness Weights
Each observation's weight is proportional to the fraction of its return that is not overlapped by other observations' labels. An observation whose entire return window is covered by other labels receives zero weight; it contributes no independent information:
where Ti is the length of label i's return window and the inner sum counts how many labels cover each time point.
Time Decay Weights
Older observations receive exponentially lower weight, reflecting the intuition that recent market behaviour is more relevant for predicting near-future returns:
With decay_factor = 0.95 and 100 bars, the oldest observation receives 0.95100 ≈ 0.006, effectively zero weight. Recent observations dominate.
Sequential Bootstrap
Standard bootstrap resampling assumes IID data and produces unrealistic resampled datasets for financial time series. The sequential bootstrap modifies the sampling probability to favour observations with lower average uniqueness, those that are less overlapped with already-sampled observations. This produces bootstrap samples that better preserve the dependency structure of the original data.
Without sample weights, models treat every labeled observation as equally informative. With overlapping labels, this double-counts information and produces overconfident predictions. Sample weights are not optional for financial ML; they are a prerequisite for valid statistical inference. López de Prado (2018) shows that unweighted models overstate significance by 2–5× on typical financial datasets.
| Parameter | Type | Default | Description |
|---|---|---|---|
| enabled | boolean | true | Apply sample weighting. Disable only for debugging; weights are essential for valid inference. |
| uniqueness.enabled | boolean | true | Down-weight samples with high label overlap to prevent double-counting information. |
| time_decay.decay_factor | float (0.5–1) | 0.95 | Exponential decay rate. 0.95 = older samples lose ~5% weight per bar. |
| sequential_bootstrap.enabled | boolean | true | Use overlap-aware sequential bootstrap instead of standard IID bootstrap. |
Cross-Validation: CPCV & Purged K-Fold
Standard k-fold cross-validation, the workhorse of general ML, is invalid for financial data because it randomly shuffles observations across folds, leaking future information into training. Financial cross-validation must respect temporal ordering and purge overlapping labels.
Purged K-Fold
Splits data into n_splits sequential folds. Each fold's training set consists of all data before the test fold, with a purge gap (Step 3) inserted before the test boundary. This eliminates look-ahead bias but provides only one train/test path; the performance estimate can be sensitive to the particular split boundaries.
Combinatorial Purged Cross-Validation (CPCV)
CPCV generates multiple train/test paths by combinatorially selecting groups of folds for testing while using the remaining folds for training. With n_splits = 5 and oos_groups = 2:
Each path provides an independent performance estimate. The distribution of these estimates, not just the mean, reveals how sensitive the model is to the particular historical period used for testing. A model with Sharpe ranging from 0.8 to 2.4 across paths is far less trustworthy than one with Sharpe consistently at 1.5 ± 0.2, even though both have the same mean.
CPCV also enables the Probability of Backtest Overfitting (PBO) calculation in Step 15: by comparing the rank of the selected model across all paths, PBO estimates the probability that a different model would have been selected under different market conditions.
CPCV is the most important methodological advance in financial ML validation. A single train/test split produces a point estimate of performance; it cannot reveal whether that estimate is representative or an outlier. CPCV produces a distribution, enabling statistical tests of performance stability. Any model intended for live deployment should be validated with CPCV.
| Parameter | Type | Default | Description |
|---|---|---|---|
| method | purged_kfold | cpcv | cpcv | CPCV generates multiple train/test paths for distributional performance estimates. |
| n_splits | integer (3–20) | 5 | Number of folds. More folds = more paths in CPCV but less data per fold. |
| oos_groups | integer (1–5) | 2 | Number of folds held out per path. C(n_splits, oos_groups) paths generated. |
Hyperparameter Optimization: TPE Search & Composite Scoring
When optimize_params is enabled (Step 1), this step controls the search study configuration. Unlike the strategy optimization pipeline which always runs the search, ML training can run with fixed hyperparameters, useful for rapid iteration when you already know good parameter ranges.
Composite Score
The default objective function is a weighted composite of four metrics, each clipped to prevent individual extremes from dominating:
where PF = Profit Factor, DD = Max Drawdown (normalised). Sortino Ratio receives the highest weight (0.4) because it penalises only downside volatility, the kind that matters for trading. A custom formula string can override these weights entirely.
Median Pruner
The MedianPruner terminates unpromising trials early. After n_startup_trials (default 10) complete, each subsequent trial's intermediate fold scores are compared to the median of completed trials at the same step. If a trial consistently underperforms the median, it is pruned - saving compute for more promising configurations.
The composite score balances return (Sortino, Calmar), consistency (Profit Factor), and risk (Max Drawdown) in a single objective. Optimising Sharpe alone often produces models with unacceptable drawdowns; optimising return alone ignores risk entirely. The weighted composite ensures the optimizer finds models that are good across multiple dimensions.
| Parameter | Type | Default | Description |
|---|---|---|---|
| n_trials | integer (1–1000) | 15 | Number of search trials. Higher = more thorough search. Rule of thumb: 10× number of optimised params. |
| top_k | integer (1–20) | 5 | Number of best trials carried forward to validation phases. |
| min_trades_per_fold | integer (1–100) | 5 | Trials with fewer trades per fold are discarded as statistically unreliable. |
| composite_score.w_sortino | float (0–1) | 0.4 | Weight for Sortino Ratio in composite objective. |
| pruner.n_startup_trials | integer (1–100) | 10 | Trials before pruning begins. First N trials always complete. |
| use_gpu | boolean | false | Enable GPU training for CatBoost/LightGBM/XGBoost. 5–20× speedup on large datasets. |
Training: Calibration & Feature Importance
After hyperparameter optimization, the top_k models are trained on the full training set with two optional post-training analyses.
Probability Calibration
Many classifiers produce biased probability estimates: a predicted probability of 0.8 may correspond to an empirical frequency of only 0.6. Calibration adjusts predicted probabilities to match empirical frequencies using cross-validated isotonic regression or Platt scaling:
where f is the calibration function learned on held-out folds. With cv = 3, the model is trained on 2/3 of the data, calibrated on the remaining 1/3, and the process is repeated 3 times. Well-calibrated probabilities are essential for position sizing; if the model says “80% confident” but is actually only 60% correct, your position sizes will be systematically too large.
Feature Importance (SHAP)
When enabled, feature importance is computed either natively (model built-in) or via SHAP (SHapley Additive exPlanations). SHAP values decompose each prediction into additive feature contributions using cooperative game theory:
where φj is the Shapley value for feature j, F is the set of all features, and the sum is over all possible feature subsets. SHAP values satisfy three desirable properties, local accuracy, missingness, and consistency, making them the most theoretically grounded feature importance method.
The stability_threshold measures the consistency of feature importance rankings across cross-validation folds. Features whose importance rank fluctuates significantly across folds (stability < 0.5) are flagged as unreliable.
Calibration is the difference between a model that predicts well and a model you can safely size positions on. An uncalibrated model claiming 95% confidence in every prediction is worse than useless; it inspires false confidence. Calibration transforms raw model outputs into actionable probabilities.
| Parameter | Type | Default | Description |
|---|---|---|---|
| calibration.enabled | boolean | true | Calibrate predicted probabilities to match empirical frequencies. |
| calibration.cv | integer (2–10) | 3 | Cross-validation folds for calibration. Higher = less data per fold but more robust calibration. |
| feature_importance.method | native | shap | native | SHAP provides game-theoretic importance values; native is faster but model-specific. |
| feature_importance.stability_threshold | float (0–1) | 0.5 | Features with importance stability below this across folds are flagged. |
Signal Generation
Raw model predictions, class probabilities or regression values, must be converted into actionable trading signals. This step defines the thresholds and filters that control signal frequency, confidence, and expected return.
Probability Threshold
proba_threshold (default 0.0) sets the minimum predicted probability to generate any signal. At 0.0, all predictions generate signals. At 0.7, only high-confidence predictions generate signals, reducing trade frequency but increasing the win rate.
Confidence Margin
For multi-class classifiers, the confidence margin is the minimum difference between the highest and second-highest class probabilities to take a position:
A margin of 0.05 means the model must be at least 5% more confident in “long” than “short” to generate a long signal. This suppresses ambiguous predictions where the model is uncertain between classes.
Minimum Return Threshold
min_return_threshold (default 0.01 = 1%) suppresses signals whose predicted return is below this value. This avoids generating signals for tiny expected moves that would be consumed by transaction costs.
Signal generation is where prediction meets execution. A model with 60% accuracy that generates 10 signals per day will likely be profitable. A model with 60% accuracy that generates 500 signals per day may lose money to transaction costs, even though both models have identical predictive performance. Threshold tuning controls this trade-off.
| Parameter | Type | Default | Description |
|---|---|---|---|
| proba_threshold | float (0–1) | 0.0 | Minimum probability to generate a signal. Higher = fewer, higher-confidence signals. |
| confidence_margin | float (0–1) | 0.05 | Minimum gap between top two class probabilities to take a position. |
| min_return_threshold | float (0–1) | 0.01 | Minimum predicted return (1% = 0.01) to generate a signal. Filters micro-moves. |
Backtest Execution & Risk Management
The backtest step simulates trading the model's signals through historical data with realistic execution assumptions: starting balance, position sizing, leverage, transaction fees, slippage, and a full risk management stack.
Risk Management Stack
Four independent risk controls, each configurable:
- Stop Loss (SL): Static (fixed %), ATR-based (dynamic volatility-adjusted), or none. Default: static at 1%.
- Take Profit (TP): Static (2%), ATR-based, risk-reward ratio (RR), or none. RR mode sets TP = SL × ratio (default 2.0), ensuring asymmetric risk-reward.
- Trailing Stop Loss (TSL): Trailing (locks in gains at trail_pct from peak, default 0.5%), Chandelier (ATR-based), or none. Activation threshold (default 1.0%) prevents trailing from triggering on noise.
- Time Stop: Closes positions after max_duration (default 12h) regardless of P&L. Prevents capital from being locked in stagnant positions.
Cost Sensitivity
When enabled, the backtest is repeated at multiple fee tiers (default: 0.0% and 0.2%) to assess the model's sensitivity to trading costs. A model that is profitable at 0.0% but loses money at 0.2% fees is fragile; small increases in exchange fees or spread widenings will erase its edge. Models are filtered at min_fee_tier (default 0.1%).
The backtest is where theory meets reality. A model with a Sharpe of 2.0 before costs can become unprofitable after accounting for 0.1% fees, 0.05% slippage, and the bid-ask spread. Cost sensitivity analysis quantifies exactly how much headroom the model has before costs consume its edge, essential for knowing whether the model is deployable on exchanges with different fee structures.
| Parameter | Type | Default | Description |
|---|---|---|---|
| starting_balance | float | 10000 | Initial account balance. Affects absolute P&L but not percentage-based metrics. |
| position_size | float (0.01–1) | 1.0 | Fraction of balance per trade. 1.0 = 100% per position. |
| leverage | float (1–100) | 1.0 | Leverage multiplier. Amplifies both gains and losses proportionally. |
| transaction_fee | float (0–5%) | 0.05 | Fee per trade as percentage. 0.05% ≈ typical Binance spot fee. |
| sl.type | none | static | atr | static | Stop loss method. ATR adapts to volatility; static uses fixed %. SL at 1%. |
| tp.type | none | static | atr | rr | static | Take profit method. RR mode ensures asymmetric risk-reward with TP = SL × ratio. TP at 2%. |
| tsl.type | none | trailing | chandelier | trailing | Trailing stop. Locks in gains; chandelier uses ATR for dynamic trailing distance. |
| cost_sensitivity.enabled | boolean | false | Test model robustness across multiple fee tiers to quantify cost headroom. |
Walk-Forward Analysis
Walk-forward analysis extends out-of-sample testing across multiple sequential time windows, simulating how the model would perform if periodically retrained. This is the closest backtesting approximation to live model deployment.
Rolling Window Design
The walk-forward period is divided into n_windows (default 5) sequential windows. For each window:
- The model is trained on all data before the window start (if
retrain=true). - Signals are generated for the window period.
- Performance metrics are computed for the window.
- The window advances and the process repeats.
Two aggregate metrics gate this phase:
- Profitable Ratio: fraction of windows with positive return. Must exceed
min_profitable_ratio(default 0.6). - Consistency Score: measures the stability of window-level Sharpe ratios. Must exceed
min_consistency_score(default 0.5).
A model that earns a 150% return in one window and loses 40% in four others has a profitable ratio of 0.2; it will fail the walk-forward gate despite a strong aggregate return. Walk-forward analysis surfaces time-period dependency that aggregate metrics conceal. In live trading, you experience each window sequentially; consistency across windows is more important than aggregate return.
| Parameter | Type | Default | Description |
|---|---|---|---|
| enabled | boolean | true | Enable walk-forward OOS validation. Essential for any model intended for deployment. |
| n_windows | integer (3–50) | 5 | Number of rolling OOS windows. More windows = finer temporal resolution. |
| retrain | boolean | true | Retrain on expanding window before each OOS period. Simulates live model maintenance. |
| min_profitable_ratio | float (0–1) | 0.6 | Minimum fraction of windows that must be profitable. |
| min_consistency_score | float (0–1) | 0.5 | Minimum consistency of Sharpe ratios across windows. |
Monte Carlo Simulation
Monte Carlo simulation reshuffles the sequence of trade returns to estimate the distribution of possible strategy outcomes. This is the same methodology as the strategy optimization pipeline's Step 10, applied to ML model trades.
ML-Specific Considerations
ML models introduce additional Monte Carlo considerations beyond those for rule-based strategies. Model predictions are conditional on feature values: reshuffling trade returns implicitly assumes that trade outcomes are exchangeable, which may not hold if the model's edge varies systematically with market conditions.
The stationary method (Politis-Romano, default) is recommended for ML models because it preserves short-range dependencies in trade outcomes while randomising long-range structure. With n_simulations = 500 and worst_case_percentile = 5, the bottom 5th percentile of simulated outcomes must pass the profitability and worst-case thresholds.
| Parameter | Type | Default | Description |
|---|---|---|---|
| n_simulations | integer (100–10000) | 500 | Number of trade-sequence reshuffles. 500+ recommended for stable percentile estimates. |
| method | shuffle | bootstrap | hybrid | moving_block | stationary | parametric | stationary | Stationary bootstrap recommended for ML trade sequences. |
| profitable_ratio_threshold | float (0–1) | 0.6 | Minimum fraction of simulated runs that must be profitable. |
| worst_case_threshold | float (−100–0%) | -10 | Maximum acceptable loss at the worst_case_percentile. |
| worst_case_percentile | integer (1–20) | 5 | Worst case defined at this percentile. 5 = bottom 5th percentile. |
Overfitting Diagnostics: PBO, DSR & Multiple Testing
Three complementary overfitting tests form the core model validation framework. A model must pass all enabled tests to proceed to holdout evaluation and deployment.
Probability of Backtest Overfitting (PBO)
PBO uses the CPCV path structure (Step 8) to estimate the probability that the model selected as “best” is overfit. For each CPCV path p, the model with the highest in-sample performance is identified. If this “best” model consistently underperforms out-of-sample, relative to other models that ranked lower in-sample, the selection process is overfit:
A PBO of 0.5 means the “best” model performs no better than the median model out-of-sample; the selection process adds no value. A PBO of 0.05 means the selected model is genuinely superior. The default rejection threshold is max_pbo = 0.2.
Deflated Sharpe Ratio (DSR)
As in the strategy optimization pipeline (Step 3), DSR adjusts the observed Sharpe ratio for the expected maximum Sharpe from N trials under the null of no predictive power. For ML models, N is the product of search trials (Step 9) and the number of CPCV paths, typically 15 × 10 = 150. The resulting deflation is substantial:
With N = 150 trials, the expected maximum Sharpe under the null is approximately 2.5 - meaning a reported Sharpe of 2.0 may not be statistically significant. DSR must exceed min_dsr (default 1.0).
Multiple Testing Correction
When enabled, applies Bonferroni-style correction across all tested models. The effective number of tests accounts for both the number of search trials and the CPCV path count.
PBO is the single most important overfitting diagnostic in the pipeline. It directly answers the question: “If I had run this optimization on different historical data, would I have selected a different model?” If the answer is yes (high PBO), the model selection process is fragile and the selected model's performance is unlikely to repeat. PBO below 0.2 is the minimum bar for deployment consideration.
| Parameter | Type | Default | Description |
|---|---|---|---|
| pbo.max_pbo | float (0–1) | 0.2 | Maximum acceptable PBO. Models with PBO > 0.2 are rejected as overfit. |
| dsr.min_dsr | float (0–10) | 1.0 | Minimum Deflated Sharpe Ratio. DSR < 1.0 means the Sharpe is not statistically significant. |
| multiple_testing.enabled | boolean | true | Apply Bonferroni-style correction across all trials and CPCV paths. |
Holdout Evaluation
The holdout set, reserved since Step 3 and never seen by the optimizer, the feature pipeline, or any intermediate processing, provides the final, unbiased performance estimate. This is the closest approximation to future unseen data.
Primary Metric
The default evaluation metric is Sharpe Ratio, but any of six metrics can serve as the primary gate: Sharpe, Sortino, Calmar, Win Rate, Profit Factor, or Max Drawdown %. The choice should align with the optimization objective (Step 9); evaluating on a different metric than you optimised for creates an inconsistency.
The holdout result is the most honest number in the entire pipeline. Every preceding step, feature selection, hyperparameter optimization, even the choice of which overfitting tests to enable, can be iteratively refined based on validation set performance. The holdout cannot. A model that passes all preceding gates but fails the holdout test has been overfit to the validation process itself.
Never adjust parameters, thresholds, or model selection criteria based on holdout results. Doing so converts the holdout into a validation set, and its results become optimistically biased. The only correct response to a failed holdout is to start over with a fresh hypothesis and, critically, a fresh holdout period.
| Parameter | Type | Default | Description |
|---|---|---|---|
| enabled | boolean | true | Enable final holdout evaluation. Should always be enabled for deployment-bound models. |
| metric | sharpe_ratio | sortino_ratio | calmar_ratio | win_rate | profit_factor | max_drawdown_pct | sharpe_ratio | Primary evaluation metric for the holdout gate. |
Model Selection: Multi-Gate Filtering
Model selection applies a configurable set of mandatory and soft gates to filter the pool of trained models. Only models that pass all mandatory gates are eligible for deployment; soft gate failures produce warnings but do not block.
Mandatory Gates (all must pass)
| Gate | Source Step | Condition |
|---|---|---|
| PBO | 15 | PBO ≤ max_pbo (0.2) |
| DSR | 15 | DSR ≥ min_dsr (1.0) |
| Degradation | 12/13 | Holdout performance not significantly worse than walk-forward |
| Monte Carlo Profitable Ratio | 14 | Profitable ratio ≥ threshold (0.6) |
Optional Mandatory Gates
Walk-forward profitable ratio, walk-forward consistency, and cost sensitivity can be promoted from optional to mandatory via the multi-select configuration.
Soft Gates (warnings)
Feature importance stability: flags models whose important features vary significantly across folds, suggesting the model relies on features that are not consistently predictive.
Multi-gate selection prevents cherry-picking. A model with excellent Sharpe but PBO = 0.8 is overfit; it just happens to look good on this particular historical path. Requiring all mandatory gates to pass ensures the selected model is robust across multiple independent validation dimensions. No single metric can capture all failure modes.
Ensemble Construction
Ensemble methods combine multiple models to reduce variance, improve robustness, and capture complementary predictive signals. When enabled, models that individually pass the selection gates (Step 17) are combined into a single predictor.
Weighted Vote
Each model's prediction is weighted by its validation performance (e.g., Sharpe ratio). The ensemble prediction is the weighted average of individual model probabilities. Weights are normalised to sum to 1.
Meta-Model
A secondary “meta-model” is trained to combine individual model predictions, learning which models to trust under which market conditions. More powerful than weighted voting but requires additional training data and is itself susceptible to overfitting.
Signal Correlation Constraint
Models with pairwise signal correlation above max_signal_correlation (default 0.5) are not combined: they provide redundant information. This constraint ensures ensemble diversity: the benefit of ensembling comes from combining models that make different mistakes, not from averaging identical predictions.
Ensemble methods are one of the few techniques in ML that almost universally improve out-of-sample performance, provided the constituent models are genuinely diverse. The signal correlation constraint is critical: an ensemble of 5 nearly identical XGBoost models provides no benefit over a single model. An ensemble of an XGBoost classifier, a LightGBM regressor, and a Random Forest, each trained on different feature subsets, can capture complementary signals and substantially reduce variance.
| Parameter | Type | Default | Description |
|---|---|---|---|
| enabled | boolean | false | Enable ensemble construction. Adds compute cost but can improve robustness. |
| method | weighted_vote | meta_model | weighted_vote | Weighted vote averages model predictions; meta-model learns to combine them. |
| max_signal_correlation | float (0–1) | 0.5 | Models with signal correlation above this are not combined; ensures diversity. |
| min_models | integer (2–10) | 2 | Minimum number of models in the ensemble. Fewer than this and ensembling is skipped. |
Pipeline Execution Summary
| # | Step | Category | Default | Key Concept |
|---|---|---|---|---|
| 1 | Model Selection | Setup | Always | 45 classifiers / 58 regressors, TPE hyperparameter search |
| 2 | Data Source | Setup | Always | Exchange, bar type, timeframe, structural break detection |
| 3 | Data Splits | Setup | Always | 70/20/10 temporal split with purge gap multiplier |
| 4 | Feature Selection | Setup | Always | 29 pre-computed features across 5 domains |
| 5 | Feature Pipeline | Engineering | Enabled | FFD, winsorization, IC/ICIR filtering, adversarial validation, clustering |
| 6 | Labeling | Engineering | Always | Triple barrier / fixed % / regression; label quality filter |
| 7 | Sample Weights | Engineering | Enabled | Uniqueness, time decay, sequential bootstrap |
| 8 | Cross-Validation | Training | Always | CPCV: C(n_splits, oos_groups) purged train/test paths |
| 9 | Optimization | Training | Always* | TPE search, composite score, median pruner, GPU support |
| 10 | Training | Training | Always | Probability calibration (CV), SHAP feature importance |
| 11 | Signals | Backtesting | Always | Probability threshold, confidence margin, min return |
| 12 | Backtest | Backtesting | Always | SL/TP/TSL/Time stops, cost sensitivity analysis |
| 13 | Walk-Forward | Validation | Enabled | N rolling OOS windows, retrain, profitable ratio & consistency gates |
| 14 | Monte Carlo | Validation | Enabled | 500 trade-sequence simulations, worst-case percentile analysis |
| 15 | Overfitting Tests | Validation | Enabled | PBO ≤ 0.2, DSR ≥ 1.0, multiple testing correction |
| 16 | Holdout | Validation | Enabled | Untouched unseen data, final unbiased performance estimate |
| 17 | Model Selection | Selection | Always | 4 mandatory gates + optional + soft warnings |
| 18 | Ensemble | Deployment | Disabled | Weighted vote / meta-model with signal correlation constraint |
* Step 9 (Optimization) runs TPE hyperparameter search when optimize_params=true in Step 1. When false, the model trains with fixed parameters and the validation phases still run.
References & Further Reading
- López de Prado, M. (2018). Advances in Financial Machine Learning. Wiley. The foundational text. Chapters 2–5 (labeling, sample weights, fractionally differentiated features), 7–9 (cross-validation), 11–13 (backtesting), and 14–16 (ensemble methods).
- Bailey, D. H. & López de Prado, M. (2014). “The Deflated Sharpe Ratio: Correcting for Selection Bias, Backtest Overfitting, and Non-Normality.” Journal of Portfolio Management, 40(5), 94–107.
- Bailey, D. H., Borwein, J. M., López de Prado, M., & Zhu, Q. J. (2017). “The Probability of Backtest Overfitting.” Journal of Computational Finance, 20(4), 39–69. The PBO framework used in Steps 8 and 15.
- Lundberg, S. M. & Lee, S.-I. (2017). “A Unified Approach to Interpreting Model Predictions.” NeurIPS. SHAP values for feature importance (Step 10).
- Politis, D. N. & Romano, J. P. (1994). “The Stationary Bootstrap.” Journal of the American Statistical Association, 89(428), 1303–1313.
- Akiba, T., Sano, S., Yanase, T., Ohta, T., & Koyama, M. (2019). “Optuna: A Next-generation Hyperparameter Optimization Framework.” KDD.
- Bergstra, J., Bardenet, R., Bengio, Y., & Kégl, B. (2011). “Algorithms for Hyper-Parameter Optimization.” NeurIPS. TPE sampler.
- Benjamini, Y. & Hochberg, Y. (1995). “Controlling the False Discovery Rate.” Journal of the Royal Statistical Society: Series B, 57(1), 289–300.
- Chen, T. & Guestrin, C. (2016). “XGBoost: A Scalable Tree Boosting System.” KDD.
- Ke, G., Meng, Q., Finley, T., Wang, T., Chen, W., Ma, W., Ye, Q., & Liu, T.-Y. (2017). “LightGBM: A Highly Efficient Gradient Boosting Decision Tree.” NeurIPS.
- Prokhorenkova, L., Gusev, G., Vorobev, A., Dorogush, A. V., & Gulin, A. (2018). “CatBoost: Unbiased Boosting with Categorical Features.” NeurIPS.