Machine Learning Enhanced Multi-Factor Quantitative Trading — A Cross-Sectional Portfolio Optimization Approach with Bias Correction
arXiv:2507.07107 | Hugging Face Papers | Yimin Du, 2025
Languages: English | 简体中文 | 繁體中文
A clean, fork-friendly, end-to-end A-share quantitative trading system:
In one clone, you get: a tensor factor engine, 213 factor dimensions, bias correction, ML baselines, Markowitz portfolio optimization, vectorized backtesting, synthetic/public-data demos, CI, tests, and benchmark tooling.
| If you want to... | Start here | What you get |
|---|---|---|
| See the project run | make paper CONFIG=configs/small.yaml |
A 30-90 second synthetic end-to-end smoke test |
| Understand the claims | Research Card | Intended use, non-goals, validation status, and data caveats |
| Try public data | Public-Data Mini Reproduction | A small yfinance factor-IC check with documented outputs |
| Run a larger validation | Public-Data Validation | Walk-forward baselines, costs, turnover, bootstrap CIs, and report artifacts |
| Contribute results | Benchmark discussion | A place to share benchmark and reproduction reports |
This repository is validation-first: simple baselines, transaction costs, public-data failure modes, and negative results are documented alongside the research pipeline.
Current calls for contributors
- Try the
v0.2.0release. - Read the Research Card for intended use, current evidence, and non-goals.
- Read the public-data mini reproduction.
- Share benchmark or public-data results in Discussions #13.
- Pick up a newcomer task: more benchmark reports or a paired public-data validation or benchmark contribution.
- Read the Reality Check and Validation Status before interpreting any backtest as evidence of deployable alpha.
Research and educational use only. This project is not investment advice and is not production-ready. Backtest results do not represent live trading performance; they depend on data quality, transaction costs, slippage, and modeling assumptions that differ from real markets. Treat all results as research validation, not verified out-of-sample performance claims. See Reality Check for known limitations.
中文说明
仅用于研究和教学。 本项目不构成投资建议,也不是可直接用于实盘交易的 生产系统。回测结果会受到数据质量、交易成本、滑点和建模假设影响,不代表 真实交易表现。请先阅读 Reality Check 中的限制说明。
| Module | What it does |
|---|---|
features.tensor_factors |
GPU-vectorised masked primitives (rank, corr, ewma, ts_*) |
features.legacy_factors |
204 hand-crafted alpha factors (English handbook · 中文) |
features.alpha101 |
Alpha101-style formulaic factors |
features.neutralize |
Cross-sectional & industry neutralisation |
features.bias |
Limit-up / limit-down / halt bias correction |
training.augment |
GBM data augmentation |
models.nets |
MLP / Transformer |
models.losses |
AdjMSE, IC, RankIC losses |
portfolio.markowitz |
Cross-sectional Markowitz (shrunk cov, no-short) |
backtest.engine |
Vectorised backtest → Sharpe / IC / IR / DD |
- You want a runnable reference implementation for ML-enhanced multi-factor research.
- You need a factor pipeline that handles masks, limit-up / limit-down events, halts, and cross-sectional operations.
- You want to reproduce or extend the accompanying paper without rebuilding data, factor, model, portfolio, and backtest modules from scratch.
- You are looking for a practical template for testing quantitative finance research code.
If you build on this work, please consider citing the paper and opening issues or pull requests for reproducibility notes, new examples, or benchmark results.
| Source | Market | Access | Notes |
|---|---|---|---|
| Baostock | A-shares | Free registration | Supported A-share loader; requires account |
| yfinance | US equities / ETFs | Public, rate-limited | Used for public-data validation and cross-market examples |
| Synthetic | N/A | Zero-config | Deterministic GBM panel for smoke testing the pipeline |
The repository does not redistribute market data. Baostock and yfinance data are downloaded on-demand by the loader scripts. Synthetic data is generated deterministically from a fixed seed.
git clone https://github.com/initial-d/ml-quant-trading.git
cd ml-quant-trading
pip install -e .[dev] # add ,gpu for CUDA; add ,mosek for MOSEK solver
# 30-second smoke test (synthetic 200 stocks × 500 days)
make paper CONFIG=configs/small.yamlYou can run an end-to-end demo of this project instantly in Google Colab without installing anything locally:
For a lightweight public-data walkthrough, open notebooks/public_factor_ic.ipynb. It downloads a small yfinance universe, computes a factor subset, and plots one-day forward rank IC. If public data download fails, the notebook falls back to the synthetic panel so the workflow remains runnable.
For a larger public-data validation run with walk-forward baselines, costs, slippage, cost-sensitivity reports, optional bootstrap confidence intervals, turnover, drawdown, and equal-weight / momentum / Alpha101 / MLP / Transformer comparisons:
python scripts/public_data_validation.py \
--source yfinance \
--preset us-large-100 \
--max-tickers 100See docs/public_data_validation.md. Treat
these runs as validation diagnostics, not trading recommendations. The script
writes summary.md, summary.csv, summary.json, metadata.json, and a
copy-ready submission.md for community reports. Add --cost-grid-bps 0,7,15,30
to generate cost_sensitivity.* files, and add --bootstrap-samples 500 to
include return and Sharpe uncertainty intervals. Maintainers can aggregate
multiple summary.json files with scripts/aggregate_validation_reports.py and
audit individual reports with scripts/audit_validation_report.py.
To benchmark core tensor primitives and a small factor subset on CPU/GPU, run:
make benchmarkSee docs/benchmarking.md for larger-panel commands and reporting guidance.
Benchmark reports from different machines are welcome through the
Benchmark result issue template.
For a Docker-based CPU environment:
docker build -t ml-quant-trading .
docker run --rm ml-quant-trading make testSee docs/docker.md for Docker benchmark, synthetic pipeline,
and public-data validation commands.
For VS Code or GitHub Codespaces, use the included Dev Container:
.devcontainer/devcontainer.json
It installs Python 3.11 and the project with pip install -e .[dev].
CHANGELOG.mdsummarizes the public baseline release.docs/launch_playbook.mdcontains the launch checklist, recommended repository topics, and social preview guidance.docs/start_here.mdgives new users a fast path through the project.docs/research_card.mdsummarizes intended use, validation status, data assumptions, and known risks.docs/architecture.mdshows the factor → model → portfolio → backtest pipeline.docs/reality_check.mdexplains what is real, what is still a smoke test, and what is not claimed.docs/faq.mdanswers common setup, data, and reproducibility questions.docs/docker.mddocuments the Docker and Dev Container setup.docs/benchmark_board.mdtracks community benchmark reports.docs/public_data_mini_reproduction.mdrecords a small yfinance factor IC reproduction.docs/public_data_validation.mddocuments larger public-data walk-forward validation runs.docs/validation_digest_20260720.mdsummarizes the public validation surface forv0.2.0.docs/community.mdexplains contribution lanes and maintainer response rules.docs/release_draft_v0.1.0.mdis a copy-ready first release draft.docs/release_draft_v0.2.0.mdis the public validation and contributor-workflow release draft.docs/promotion_kit.mdcontains copy-ready social and community posts.docs/community_outreach.mdlists target communities and copy-ready outreach posts.docs/content_calendar.mdturns real updates into a four-week launch rhythm.docs/visibility_status.mdtracks live launch links, contributor calls, and next outreach steps.v0.1.0is the first public research baseline release.v0.2.0is the public validation and contributor-workflow release.- Benchmark and reproduction discussion is open for community reports.
The full feature set comprises 9 curated Alpha101 formulas (features.alpha101) plus 204 hand-crafted legacy factors (features.legacy_factors) for a total of 213 dimensions. All factors are mask-aware PyTorch tensors with signature Panel → (values[T,N], mask[T,N]).
📖 Factor Handbook: English · 中文 — design notes and implementation rationale for each factor.
| Family | Count | Description |
|---|---|---|
better_001 – better_028 |
28 | VWAP deviation + volume-weighted momentum |
best_001 – best_021 |
21 | Close-location momentum variants |
old_027 – old_076 |
50 | Classic alpha signals (corr/rank composites) |
stock_001 – stock_022 |
22 | Per-stock derived series (volume, range, price) |
extra_001 – extra_014 |
14 | Turnover + amount features |
add_001 – add_030 |
30 | Additional composite factors |
change_001 – change_005 |
5 | Short-window change-of-velocity |
original_001 – original_028 |
28 | Close/volume direct statistics |
cs_rank_* |
6 | Market breadth (cross-sectional rank signals) |
Full factor list (click to expand)
add_001 add_002 add_003 add_004 add_005 add_006
add_007 add_008 add_009 add_010 add_011 add_012
add_013 add_014 add_015 add_016 add_017 add_018
add_019 add_020 add_021 add_022 add_023 add_024
add_025 add_026 add_027 add_028 add_029 add_030
best_001 best_002 best_003 best_004 best_005 best_006
best_007 best_008 best_009 best_010 best_011 best_012
best_013 best_014 best_015 best_016 best_017 best_018
best_019 best_020 best_021
change_001 change_002 change_003 change_004 change_005
extra_001 extra_002 extra_003 extra_004 extra_005 extra_006
extra_007 extra_008 extra_009 extra_010 extra_011 extra_012
extra_013 extra_014
old_027 old_028 old_029 old_030 old_031 old_032
old_033 old_034 old_035 old_036 old_037 old_038
old_039 old_040 old_041 old_042 old_043 old_044
old_045 old_046 old_047 old_048 old_049 old_050
old_051 old_052 old_053 old_054 old_055 old_056
old_057 old_058 old_059 old_060 old_061 old_062
old_063 old_064 old_065 old_066 old_067 old_068
old_069 old_070 old_071 old_072 old_073 old_074
old_075 old_076
original_001 original_002 original_003 original_004 original_005
original_006 original_007 original_008 original_009 original_010
original_011 original_012 original_013 original_014 original_015
original_016 original_017 original_018 original_019 original_020
original_021 original_022 original_023 original_024 original_025
original_026 original_027 original_028
stock_001 stock_002 stock_003 stock_004 stock_005 stock_006
stock_007 stock_008 stock_009 stock_010 stock_011 stock_012
stock_013 stock_014 stock_015 stock_016 stock_017 stock_018
stock_019 stock_020 stock_021 stock_022
You can directly fetch stock data from Yahoo Finance or Baostock (for A-shares).
yfinance:
from mlquant.data import make_panel
panel = make_panel(
source="yfinance",
tickers=["000001.SZ", "600000.SS"],
start="2020-01-01",
end="2023-12-31"
)baostock:
from mlquant.data import make_panel
panel = make_panel(
source="baostock",
tickers=["sh.600000", "sz.000001"],
start="2020-01-01",
end="2023-12-31"
)from mlquant.features import compute_legacy_set, LEGACY_REGISTRY
# Compute all 213 factors (204 legacy + 9 Alpha101)
factors, mask, names = compute_legacy_set(panel) # → [T, N, 213]
# Or a subset
factors, mask, names = compute_legacy_set(panel, names=("best_001", "add_015", "old_042"))flowchart LR
subgraph Data["1. Data"]
A[Raw OHLCV] --> B[loaders<br/>synthetic / yfinance / baostock]
end
subgraph Features["2. Features"]
B --> C[tensor_factors<br/>GPU masked primitives]
C --> D[bias<br/>limit-up/down/halt correction]
D --> E[compute_legacy_set<br/>213-factor tensor<br/>204 legacy + 9 Alpha101]
end
subgraph Training["3. Training"]
E --> F[FactorDataset<br/>forward returns + masks]
F --> G[MLP Regressor]
F -.->|optional| GBM[GBM augment]
G -.->|alternative| T[Transformer]
G --> H[losses<br/>AdjMSE / IC / RankIC]
end
subgraph Portfolio["4. Portfolio"]
H --> I[Markowitz<br/>Ledoit-Wolf shrunk cov<br/>no-short constraint]
end
subgraph Backtest["5. Backtest"]
I --> J[engine<br/>vectorized backtest]
J --> K[Sharpe / IC / IR / DD]
end
Solid = required in default pipeline. Dashed = optional / alternative module (not called by CLI).
ml-quant-trading/
├── src/mlquant/
│ ├── data/ # Panel dataclass, loaders, synthetic generator
│ ├── features/ # Factor engine + 204 legacy + Alpha101
│ ├── training/ # Dataset, augmentation, trainer
│ ├── models/ # MLP, Transformer, losses
│ ├── portfolio/ # Markowitz, frontier sweep
│ ├── backtest/ # Engine, metrics
│ └── cli/ # Command-line interface
├── configs/ # small.yaml (smoke) / paper.yaml (full)
├── tests/ # pytest suite
├── scripts/ # IC eval, frontier plot
├── legacy/ # Original research scripts (archival, unsupported)
└── docs/ # Architecture, factor docs, paper reproduction
See docs/reproducing_paper.md for table-by-table mapping.
| Paper section | Code module | Tests |
|---|---|---|
| §3.1 Tensor factor engine | features.tensor_factors |
test_tensor_factors |
| §3.2 Alpha + microstructure factors | features.alpha101, features.legacy_factors |
test_alpha101 |
| §3.3 Neutralisation | features.neutralize |
— |
| §3.4 Bias correction | features.bias |
test_bias |
| §4.1 GBM augmentation | training.augment |
test_augment |
| §4.2 ML models | models.nets, models.losses |
test_losses |
| §5 Portfolio optimisation | portfolio.markowitz |
test_markowitz |
| §6 Backtest | backtest.engine, backtest.metrics |
test_metrics |
See docs/roadmap.md for contributor-friendly tasks, research extensions,
engineering extensions, and community milestones.
For announcements, release posts, and benchmark calls, see the
Promotion Kit. For the maintainer growth loop, see
docs/growth_plan.md.
Contributions are welcome, especially docs, reproducibility notes, tests, data adapters, and small examples. See CONTRIBUTING.md for setup and pull request guidance.
This repository is for research and engineering experimentation. It is not financial advice, investment advice, or a trading recommendation. Historical backtests and factor results do not guarantee future performance.
@article{du2025mlquant,
title = {Machine Learning Enhanced Multi-Factor Quantitative Trading:
A Cross-Sectional Portfolio Optimization Approach with Bias Correction},
author = {Du, Yimin},
journal= {arXiv preprint arXiv:2507.07107},
year = {2025},
url = {https://arxiv.org/abs/2507.07107}
}MIT — see LICENSE.
