Classification: Independent research workflow built on Microsoft Qlib. This repository does not claim authorship of Qlib and does not redistribute its source code.
This study adapts Qlib's Alpha158 and LightGBM workflow to a US-equity universe, adds explicit transaction costs, generates expanding-window walk-forward folds, exports MLflow evidence, and applies a fail-closed research gate before any paper-trading consideration.
| Question | Answer |
|---|---|
| What is the original foundation? | Microsoft's open-source Qlib, specifically its Alpha158/LightGBM benchmark configuration, data handlers, model wrapper, strategy simulator, and MLflow recorders. |
| What did I build or change? | A separate US-equity data pipeline, tuned configuration, deterministic expanding-window folds, explicit trading costs, portable run wrappers, MLflow evidence export, a cross-fold research gate, and a review-only candidate bridge. No Qlib source code is redistributed here. |
| Why did I change it? | To test whether an Alpha158/LightGBM signal remains directionally consistent across distinct US market periods, and to prevent attractive simulated returns from being promoted when ranking evidence is unstable. |
The principal model-configuration changes are explicit rather than presented as a new model:
| Parameter | Qlib reference example | This study | Research intent |
|---|---|---|---|
learning_rate |
0.20 | 0.05 | Slower boosting updates |
num_leaves |
210 | 64 | Reduce tree complexity |
max_depth |
8 | 6 | Add a tighter depth constraint |
lambda_l1 |
205.6999 | 10 | Rebalance sparsity regularization for this experiment |
lambda_l2 |
580.9768 | 50 | Rebalance weight regularization for this experiment |
- built an adjusted daily US-equity dataset pipeline from public market data;
- adapted the Alpha158/LightGBM configuration from the Qlib example to US equities and SPY;
- changed the LightGBM profile to
learning_rate=0.05,num_leaves=64,max_depth=6,lambda_l1=10, andlambda_l2=50; - added 2 bps opening and 2 bps closing costs to the portfolio simulation;
- generated three expanding-window folds with disjoint chronological test periods;
- exported signal and portfolio metrics from Qlib's MLflow artifacts;
- added a research-only gate that rejects the study when cross-fold rank evidence is inconsistent;
- kept the optional candidate bridge review-only: it emits research candidates, never orders.
| Fold | Train | Validation | Test |
|---|---|---|---|
| 1 | 2015–2018 | 2019 | 2020–2021 |
| 2 | 2015–2020 | 2021 | 2022–2023 |
| 3 | 2015–2022 | 2023 | 2024–2026-08-20 |
The portfolio configuration uses TopkDropoutStrategy (topk=30, n_drop=5), SPY as the benchmark, close-price execution, and explicit round-trip costs. Results below are excess returns reported by Qlib, not live trading returns.
| Fold | IC | Rank IC | Excess return with cost, annualized | Information ratio | Max drawdown |
|---|---|---|---|---|---|
| 1 | 0.0093 | -0.0083 | 76.23% | 1.77 | -33.93% |
| 2 | 0.0019 | -0.0109 | 35.63% | 0.83 | -34.25% |
| 3 | 0.0096 | 0.0031 | 80.39% | 1.99 | -32.52% |
The automated gate returns RESEARCH_ONLY. Mean fold IC is positive (0.0069), but mean fold Rank IC is negative (-0.0053) and Rank IC is not positive in every fold. The large simulated portfolio returns therefore are not treated as sufficient evidence of a robust ranking signal.
Raw aggregate evidence is committed under results/; model binaries, MLflow pickles, raw prices, and current candidate lists are intentionally excluded.
public daily prices
-> adjusted Qlib CSVs
-> Qlib binary dataset
-> Alpha158 features
-> LightGBM chronological training
-> cost-aware TopkDropout backtest
-> MLflow metric extraction
-> walk-forward research gate
-> optional review-only shortlist
Create an environment and install Qlib plus the small runtime dependencies:
python -m venv .venv
# Windows: .venv\Scripts\activate
# macOS/Linux: source .venv/bin/activate
pip install -r requirements.txtBuild adjusted CSV inputs. The default list is intentionally small; provide your own point-in-time universe for serious research.
python scripts/build_us_data.py --start 2015-01-01 --output-root data/us_fullConvert the CSV directory with Qlib's dump_bin.py, then point QLIB_DATA_DIR at the resulting provider directory. Generate the fold configs and run one through the portable wrapper:
python scripts/generate_walk_forward_configs.py
set QLIB_DATA_DIR=C:\path\to\qlib_data\us_full_1d
python scripts/run_config.py configs/walk_forward/fold_1.example.yamlOn macOS or Linux, use export QLIB_DATA_DIR=/path/to/qlib_data/us_full_1d.
Summarize completed MLflow recorders:
python scripts/summarize_qlib_recorders.py \
fold_1=<recorder-id> fold_2=<recorder-id> fold_3=<recorder-id> \
--mlruns /path/to/mlruns/<experiment-id> \
--output-root results/latest| Path | Purpose |
|---|---|
configs/us_full.example.yaml |
Tuned US-equity Qlib workflow template |
scripts/build_us_data.py |
Public daily-price ingestion and adjustment |
scripts/generate_walk_forward_configs.py |
Deterministic chronological fold generation |
scripts/run_config.py |
Portable QLIB_DATA_DIR injection and qrun execution |
scripts/export_qlib_signals.py |
MLflow signal and portfolio artifact export |
scripts/summarize_qlib_recorders.py |
Cross-fold metric table and research gate |
scripts/build_bridge_shortlist.py |
Optional review-only candidate merge |
results/ |
Sanitized aggregate evidence and gate decision |
- The recorded universe was selected from a current liquid-stock screen rather than point-in-time constituents, creating survivorship bias.
- Rank IC is inconsistent and negative on average across the three folds.
- Execution uses daily close prices and simplified fixed costs; spread, slippage, borrow availability, taxes, and market impact are not modeled.
- Hyperparameters were selected through iterative research and need a separately frozen final holdout.
- Public data can be revised, delisted symbols can disappear, and reruns may not reproduce the exact historical universe.
This repository is an engineering and research artifact, not investment advice or an executable trading system.