mlquantx 0.2.5__tar.gz → 0.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mlquantx-0.2.5/src/mlquantx.egg-info → mlquantx-0.3.1}/PKG-INFO +24 -3
- {mlquantx-0.2.5 → mlquantx-0.3.1}/PYPI_README.md +21 -2
- mlquantx-0.3.1/README.md +208 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/pyproject.toml +4 -1
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/__init__.py +1 -1
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/cli/main.py +74 -2
- mlquantx-0.3.1/src/mlquant/systemone.py +355 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1/src/mlquantx.egg-info}/PKG-INFO +24 -3
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquantx.egg-info/SOURCES.txt +3 -0
- mlquantx-0.3.1/tests/test_benchmark_tensor_factors.py +61 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_cli.py +15 -5
- {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_public_data_validation.py +7 -0
- mlquantx-0.3.1/tests/test_systemone.py +201 -0
- mlquantx-0.3.1/tests/test_technical_pipeline_audit.py +34 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_tensor_factors.py +64 -1
- mlquantx-0.2.5/README.md +0 -517
- mlquantx-0.2.5/tests/test_benchmark_tensor_factors.py +0 -15
- {mlquantx-0.2.5 → mlquantx-0.3.1}/LICENSE +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/NOTICE.md +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/setup.cfg +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/backtest/__init__.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/backtest/engine.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/backtest/metrics.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/cli/__init__.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/configs/__init__.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/configs/small.yaml +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/data/__init__.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/data/akshare_loader.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/data/baostock_loader.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/data/loaders.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/data/panel.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/data/synthetic.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/data/yfinance_loader.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/__init__.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/_factors_add.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/_factors_alpha101.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/_factors_best.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/_factors_better.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/_factors_change.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/_factors_extra.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/_factors_market.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/_factors_old.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/_factors_original.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/_factors_stock.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/alpha101.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/bias.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/legacy_factors.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/market_breadth.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/neutralize.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/target.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/tensor_factors.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/models/__init__.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/models/losses.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/models/nets.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/portfolio/__init__.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/portfolio/frontier.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/portfolio/markowitz.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/training/__init__.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/training/augment.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/training/dataset.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/training/trainer.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/utils/__init__.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/utils/config.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/utils/seed.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquantx.egg-info/dependency_links.txt +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquantx.egg-info/entry_points.txt +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquantx.egg-info/requires.txt +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquantx.egg-info/top_level.txt +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_aggregate_validation_reports.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_akshare.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_akshare_csi300_full_pipeline.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_alpha101.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_audit_validation_report.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_augment.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_baostock.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_bias.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_cost_drag_units.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_export_huggingface_artifacts.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_losses.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_markowitz.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_metrics.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_neutralize.py +0 -0
- {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_synthetic.py +0 -0
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mlquantx
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Reference implementation of ‘ML-Enhanced Multi-Factor Quantitative Trading’ (arXiv:2507.07107).
|
|
5
5
|
Author: Yimin Du
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/initial-d/ml-quant-trading
|
|
8
|
+
Project-URL: Source, https://github.com/initial-d/ml-quant-trading
|
|
8
9
|
Project-URL: Documentation, https://initial-d.github.io/ml-quant-trading/
|
|
9
10
|
Project-URL: Paper, https://arxiv.org/abs/2507.07107
|
|
10
11
|
Project-URL: Issues, https://github.com/initial-d/ml-quant-trading/issues
|
|
12
|
+
Project-URL: Discussions, https://github.com/initial-d/ml-quant-trading/discussions
|
|
11
13
|
Project-URL: Changelog, https://github.com/initial-d/ml-quant-trading/blob/main/CHANGELOG.md
|
|
12
14
|
Keywords: quant,alpha,factor,portfolio,pytorch,markowitz
|
|
13
15
|
Classifier: Development Status :: 4 - Beta
|
|
@@ -54,8 +56,8 @@ Dynamic: license-file
|
|
|
54
56
|
# mlquant
|
|
55
57
|
|
|
56
58
|
**A reproducible PyTorch research stack for machine-learning multi-factor
|
|
57
|
-
trading: 213 factors, bias correction, portfolio optimization,
|
|
58
|
-
backtesting.**
|
|
59
|
+
trading: 213 factors, bias correction, portfolio optimization, vectorized
|
|
60
|
+
backtesting, and System-One-style portfolio decisions.**
|
|
59
61
|
|
|
60
62
|
[](https://github.com/initial-d/ml-quant-trading/actions/workflows/ci.yml)
|
|
61
63
|
[](https://arxiv.org/abs/2507.07107)
|
|
@@ -74,6 +76,22 @@ training, portfolio construction, cost-aware backtesting, and Markdown/JSON
|
|
|
74
76
|
report generation. The default config ships inside the wheel, so the command
|
|
75
77
|
works outside a repository checkout.
|
|
76
78
|
|
|
79
|
+
## Customize or contribute
|
|
80
|
+
|
|
81
|
+
The wheel is the fastest way to try the project. Clone the repository when you
|
|
82
|
+
want to change factors, models, portfolio constraints, data sources, or
|
|
83
|
+
backtest assumptions:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
git clone https://github.com/initial-d/ml-quant-trading.git
|
|
87
|
+
cd ml-quant-trading
|
|
88
|
+
python -m pip install -e '.[dev]'
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
If the demo saves you setup time, consider
|
|
92
|
+
[starring the repository](https://github.com/initial-d/ml-quant-trading) or
|
|
93
|
+
[sharing a reproducible run](https://github.com/initial-d/ml-quant-trading/issues/new?template=reproduction_report.yml).
|
|
94
|
+
|
|
77
95
|
## What is included
|
|
78
96
|
|
|
79
97
|
- 204 hand-crafted factors plus 9 curated Alpha101-style factors
|
|
@@ -84,12 +102,15 @@ works outside a repository checkout.
|
|
|
84
102
|
- vectorized backtesting with turnover and transaction costs
|
|
85
103
|
- AkShare, Baostock, yfinance, and deterministic synthetic data paths
|
|
86
104
|
- auditable public-data validation reports, including negative results
|
|
105
|
+
- `mlquant systemone decide` for typed portfolio-intent decisions from
|
|
106
|
+
structured research state
|
|
87
107
|
|
|
88
108
|
## Start here
|
|
89
109
|
|
|
90
110
|
- [Source and full documentation](https://github.com/initial-d/ml-quant-trading)
|
|
91
111
|
- [Google Colab quick start](https://colab.research.google.com/github/initial-d/ml-quant-trading/blob/main/notebooks/quickstart_colab.ipynb)
|
|
92
112
|
- [Public validation dashboard](https://github.com/initial-d/ml-quant-trading/blob/main/docs/validation_dashboard.md)
|
|
113
|
+
- [System-One-compatible portfolio decisions](https://github.com/initial-d/ml-quant-trading/blob/main/docs/systemone_adapter.md)
|
|
93
114
|
- [Research card and limitations](https://github.com/initial-d/ml-quant-trading/blob/main/docs/research_card.md)
|
|
94
115
|
- [100,000-row synthetic dataset](https://huggingface.co/datasets/dddyym/ml-quant-trading-synthetic)
|
|
95
116
|
- [213-input MLP checkpoint](https://huggingface.co/dddyym/ml-quant-trading-synthetic-mlp)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# mlquant
|
|
2
2
|
|
|
3
3
|
**A reproducible PyTorch research stack for machine-learning multi-factor
|
|
4
|
-
trading: 213 factors, bias correction, portfolio optimization,
|
|
5
|
-
backtesting.**
|
|
4
|
+
trading: 213 factors, bias correction, portfolio optimization, vectorized
|
|
5
|
+
backtesting, and System-One-style portfolio decisions.**
|
|
6
6
|
|
|
7
7
|
[](https://github.com/initial-d/ml-quant-trading/actions/workflows/ci.yml)
|
|
8
8
|
[](https://arxiv.org/abs/2507.07107)
|
|
@@ -21,6 +21,22 @@ training, portfolio construction, cost-aware backtesting, and Markdown/JSON
|
|
|
21
21
|
report generation. The default config ships inside the wheel, so the command
|
|
22
22
|
works outside a repository checkout.
|
|
23
23
|
|
|
24
|
+
## Customize or contribute
|
|
25
|
+
|
|
26
|
+
The wheel is the fastest way to try the project. Clone the repository when you
|
|
27
|
+
want to change factors, models, portfolio constraints, data sources, or
|
|
28
|
+
backtest assumptions:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
git clone https://github.com/initial-d/ml-quant-trading.git
|
|
32
|
+
cd ml-quant-trading
|
|
33
|
+
python -m pip install -e '.[dev]'
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
If the demo saves you setup time, consider
|
|
37
|
+
[starring the repository](https://github.com/initial-d/ml-quant-trading) or
|
|
38
|
+
[sharing a reproducible run](https://github.com/initial-d/ml-quant-trading/issues/new?template=reproduction_report.yml).
|
|
39
|
+
|
|
24
40
|
## What is included
|
|
25
41
|
|
|
26
42
|
- 204 hand-crafted factors plus 9 curated Alpha101-style factors
|
|
@@ -31,12 +47,15 @@ works outside a repository checkout.
|
|
|
31
47
|
- vectorized backtesting with turnover and transaction costs
|
|
32
48
|
- AkShare, Baostock, yfinance, and deterministic synthetic data paths
|
|
33
49
|
- auditable public-data validation reports, including negative results
|
|
50
|
+
- `mlquant systemone decide` for typed portfolio-intent decisions from
|
|
51
|
+
structured research state
|
|
34
52
|
|
|
35
53
|
## Start here
|
|
36
54
|
|
|
37
55
|
- [Source and full documentation](https://github.com/initial-d/ml-quant-trading)
|
|
38
56
|
- [Google Colab quick start](https://colab.research.google.com/github/initial-d/ml-quant-trading/blob/main/notebooks/quickstart_colab.ipynb)
|
|
39
57
|
- [Public validation dashboard](https://github.com/initial-d/ml-quant-trading/blob/main/docs/validation_dashboard.md)
|
|
58
|
+
- [System-One-compatible portfolio decisions](https://github.com/initial-d/ml-quant-trading/blob/main/docs/systemone_adapter.md)
|
|
40
59
|
- [Research card and limitations](https://github.com/initial-d/ml-quant-trading/blob/main/docs/research_card.md)
|
|
41
60
|
- [100,000-row synthetic dataset](https://huggingface.co/datasets/dddyym/ml-quant-trading-synthetic)
|
|
42
61
|
- [213-input MLP checkpoint](https://huggingface.co/dddyym/ml-quant-trading-synthetic-mlp)
|
mlquantx-0.3.1/README.md
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# ml-quant-trading
|
|
2
|
+
|
|
3
|
+
**A reproducible PyTorch research stack for cross-sectional factor research:
|
|
4
|
+
213 mask-aware factors, public-data validation, cost-aware backtests, and
|
|
5
|
+
System-One-style portfolio decisions.**
|
|
6
|
+
|
|
7
|
+
[](https://github.com/initial-d/ml-quant-trading/actions/workflows/ci.yml)
|
|
8
|
+
[](https://github.com/initial-d/ml-quant-trading/stargazers)
|
|
9
|
+
[](https://github.com/initial-d/ml-quant-trading/releases)
|
|
10
|
+
[](https://pypi.org/project/mlquantx/)
|
|
11
|
+
[](https://arxiv.org/abs/2507.07107)
|
|
12
|
+
[](https://www.python.org/downloads/)
|
|
13
|
+
[](LICENSE)
|
|
14
|
+
|
|
15
|
+
Languages: [English](README.md) | [简体中文](README.zh-CN.md) | [繁體中文](README.zh-TW.md)
|
|
16
|
+
|
|
17
|
+
[Run in Colab](https://colab.research.google.com/github/initial-d/ml-quant-trading/blob/main/notebooks/quickstart_colab.ipynb)
|
|
18
|
+
| [System-One Portfolio Decisions](docs/systemone_adapter.md)
|
|
19
|
+
| [Validation Dashboard](docs/validation_dashboard.md)
|
|
20
|
+
| [Project Facts](docs/answer_index.md)
|
|
21
|
+
| [Citation Guide](docs/citation_conversion.md)
|
|
22
|
+
| [Research Card](docs/research_card.md)
|
|
23
|
+
|
|
24
|
+
## What This Is
|
|
25
|
+
|
|
26
|
+
`ml-quant-trading` is a research baseline, not a live trading system. It gives
|
|
27
|
+
students, researchers, engineers, and agent harnesses a concrete way to run and
|
|
28
|
+
inspect a full factor-to-backtest workflow:
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
data -> masks -> 213 factors -> model scores -> portfolio weights -> cost-aware backtest
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The paper-specific contribution is the mask-first factor-computation protocol:
|
|
35
|
+
non-tradable limit-move prices should be masked before rolling-window factors,
|
|
36
|
+
not only filtered later at the portfolio layer.
|
|
37
|
+
|
|
38
|
+
New in the current direction is a System-One-compatible portfolio decision
|
|
39
|
+
adapter. It wraps pipeline state as typed asset decisions in a Jev-style shape:
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
portfolio state + typed questions -> typed portfolio-intent answers
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
It answers research questions such as `asset_action`, `target_weight`,
|
|
46
|
+
`trade_allowed`, `risk_bucket`, and `max_participation_rate`. It does not create
|
|
47
|
+
broker orders, connect to accounts, or run live execution.
|
|
48
|
+
|
|
49
|
+
## Quick Start
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
python -m pip install mlquantx
|
|
53
|
+
mlquant demo
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The demo needs no market-data account or API key. It runs a deterministic
|
|
57
|
+
synthetic pipeline and writes shareable Markdown and JSON reports under
|
|
58
|
+
`artifacts/small/`.
|
|
59
|
+
|
|
60
|
+
For development:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
git clone https://github.com/initial-d/ml-quant-trading.git
|
|
64
|
+
cd ml-quant-trading
|
|
65
|
+
python -m pip install -e '.[dev]'
|
|
66
|
+
python -m pytest
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## System-One Portfolio Decisions
|
|
70
|
+
|
|
71
|
+
The decision adapter is the project's first step toward a quant-specific
|
|
72
|
+
System One model surface. The analogy to Jev is the interface style: a structured
|
|
73
|
+
state plus typed questions returns typed answers. This repository does not claim
|
|
74
|
+
official Jev certification or calibrated probabilities.
|
|
75
|
+
|
|
76
|
+
Example state:
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"as_of": "2024-12-31",
|
|
81
|
+
"universe": ["600519", "000001"],
|
|
82
|
+
"predictions": {
|
|
83
|
+
"score": {"600519": 0.018, "000001": -0.006},
|
|
84
|
+
"rank": {"600519": 0.91, "000001": 0.23}
|
|
85
|
+
},
|
|
86
|
+
"tradability": {
|
|
87
|
+
"600519": {"tradable": true, "halted": false, "limit_up": false, "limit_down": false}
|
|
88
|
+
},
|
|
89
|
+
"liquidity": {
|
|
90
|
+
"600519": {"amount": 1523000000, "adv20": 1340000000}
|
|
91
|
+
},
|
|
92
|
+
"portfolio": {
|
|
93
|
+
"current_weight": {"600519": 0.02},
|
|
94
|
+
"target_weight_baseline": {"600519": 0.04}
|
|
95
|
+
},
|
|
96
|
+
"risk": {
|
|
97
|
+
"asset_volatility_20d": {"600519": 0.021},
|
|
98
|
+
"max_position_weight": 0.05
|
|
99
|
+
},
|
|
100
|
+
"cost_model": {
|
|
101
|
+
"effective_cost_bps": 7,
|
|
102
|
+
"max_participation_rate": 0.1
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Run typed decisions:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
mlquant systemone decide \
|
|
111
|
+
--state artifacts/systemone/decision_state.json \
|
|
112
|
+
--output artifacts/systemone/portfolio_decision.json
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Default questions expand over every asset in `universe`. A custom question file
|
|
116
|
+
can ask only for selected assets or fields. See
|
|
117
|
+
[docs/systemone_adapter.md](docs/systemone_adapter.md).
|
|
118
|
+
|
|
119
|
+
## Why It Matters
|
|
120
|
+
|
|
121
|
+
| Capability | Why it matters |
|
|
122
|
+
|---|---|
|
|
123
|
+
| 213 factor dimensions | A broad mask-aware factor surface for cross-sectional research |
|
|
124
|
+
| Mask-first pipeline | Avoids upstream contamination from non-tradable limit-move observations |
|
|
125
|
+
| Public and synthetic data paths | Start without private data, then test AkShare, Baostock, or yfinance |
|
|
126
|
+
| Cost-aware validation | Keeps turnover, costs, drawdown, baselines, and caveats close to results |
|
|
127
|
+
| Typed decision adapter | Exposes portfolio intent as a callable System-One/Jev-style interface |
|
|
128
|
+
| Auditable reports | Preserves commands, environment, data source, assumptions, and failures |
|
|
129
|
+
|
|
130
|
+
## Public Validation Snapshot
|
|
131
|
+
|
|
132
|
+
Latest maintained public-data snapshot:
|
|
133
|
+
[AkShare CSI 300 Daily 213-Factor Validation](docs/validation_dashboard.md).
|
|
134
|
+
|
|
135
|
+
| Strategy | Annual return | Sharpe | Turnover | Final equity | Note |
|
|
136
|
+
|---|---:|---:|---:|---:|---|
|
|
137
|
+
| `equal_weight_daily` | 17.75% | 0.882 | 0.0010 | 1.8744 | Public-data baseline |
|
|
138
|
+
| `factor_mean_daily` | 15.80% | 0.701 | 0.3627 | 1.7579 | Gross edge, high turnover |
|
|
139
|
+
| `factor_mean_buffered_daily` | 22.20% | 0.919 | 0.1397 | 2.1616 | Buffered daily factor rule |
|
|
140
|
+
|
|
141
|
+
This is a public-data approximation using current CSI 300 constituents, not an
|
|
142
|
+
exact paper reproduction or investment claim. The useful point is framework
|
|
143
|
+
level: factor scores need tradability, turnover, and cost-aware portfolio
|
|
144
|
+
construction before backtests are interpreted.
|
|
145
|
+
|
|
146
|
+
## Core Modules
|
|
147
|
+
|
|
148
|
+
| Module | Role |
|
|
149
|
+
|---|---|
|
|
150
|
+
| `mlquant.data` | Synthetic, yfinance, Baostock, and AkShare panel loaders |
|
|
151
|
+
| `mlquant.features` | Mask-aware tensor primitives, Alpha101 subset, and 204 legacy factors |
|
|
152
|
+
| `mlquant.training` | Factor dataset, augmentation, and trainer |
|
|
153
|
+
| `mlquant.models` | MLP, Transformer, AdjMSE, IC, and RankIC losses |
|
|
154
|
+
| `mlquant.portfolio` | Long-only Markowitz-style portfolio construction |
|
|
155
|
+
| `mlquant.backtest` | Vectorized backtest and metrics |
|
|
156
|
+
| `mlquant.systemone` | Typed portfolio-intent decisions from structured state |
|
|
157
|
+
|
|
158
|
+
## Common Paths
|
|
159
|
+
|
|
160
|
+
| Goal | Start here |
|
|
161
|
+
|---|---|
|
|
162
|
+
| Run the zero-account demo | `mlquant demo` |
|
|
163
|
+
| Try public data | [Public-Data Validation](docs/public_data_validation.md) |
|
|
164
|
+
| Inspect maintained results | [Validation Dashboard](docs/validation_dashboard.md) |
|
|
165
|
+
| Use typed portfolio decisions | [System-One Adapter](docs/systemone_adapter.md) |
|
|
166
|
+
| Cite the project | [Citation Conversion Guide](docs/citation_conversion.md) |
|
|
167
|
+
| Understand boundaries | [Research Card](docs/research_card.md) and [Reality Check](docs/reality_check.md) |
|
|
168
|
+
| Benchmark tensor factors | [Benchmarking Guide](docs/benchmarking.md) |
|
|
169
|
+
| Evaluate an agent | [Agent Quant Benchmark Challenge](docs/agent_quant_benchmark_challenge.md) |
|
|
170
|
+
|
|
171
|
+
## Data Sources
|
|
172
|
+
|
|
173
|
+
| Source | Market | Access | Notes |
|
|
174
|
+
|---|---|---|---|
|
|
175
|
+
| Synthetic | N/A | Zero-config | Deterministic smoke tests and CI |
|
|
176
|
+
| AkShare | A-shares | Public, no API key | Useful public A-share path, endpoints may change |
|
|
177
|
+
| Baostock | A-shares | Free registration | Account-backed public data route |
|
|
178
|
+
| yfinance | US equities / ETFs | Public, rate-limited | Convenient validation and notebook examples |
|
|
179
|
+
|
|
180
|
+
The repository does not redistribute market data.
|
|
181
|
+
|
|
182
|
+
## Citation
|
|
183
|
+
|
|
184
|
+
If you write about A-share factor pipelines, cite the mask-first treatment of
|
|
185
|
+
non-tradable limit-move observations and rolling-window contamination:
|
|
186
|
+
|
|
187
|
+
```bibtex
|
|
188
|
+
@article{du2025mlquant,
|
|
189
|
+
title = {Machine Learning Enhanced Multi-Factor Quantitative Trading:
|
|
190
|
+
A Cross-Sectional Portfolio Optimization Approach with Bias Correction},
|
|
191
|
+
author = {Du, Yimin},
|
|
192
|
+
journal= {arXiv preprint arXiv:2507.07107},
|
|
193
|
+
year = {2025},
|
|
194
|
+
doi = {10.48550/arXiv.2507.07107},
|
|
195
|
+
url = {https://arxiv.org/abs/2507.07107}
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Boundary
|
|
200
|
+
|
|
201
|
+
This project is for research and engineering experimentation. It is not
|
|
202
|
+
financial advice, not investment advice, not a broker-connected system, and not
|
|
203
|
+
a claim of live deployable alpha. Synthetic demos, public-data validations, and
|
|
204
|
+
typed portfolio decisions are research artifacts.
|
|
205
|
+
|
|
206
|
+
## License
|
|
207
|
+
|
|
208
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "mlquantx"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.1"
|
|
8
8
|
description = "Reference implementation of ‘ML-Enhanced Multi-Factor Quantitative Trading’ (arXiv:2507.07107)."
|
|
9
9
|
readme = "PYPI_README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -57,9 +57,11 @@ mlquant = "mlquant.cli.main:main"
|
|
|
57
57
|
|
|
58
58
|
[project.urls]
|
|
59
59
|
Homepage = "https://github.com/initial-d/ml-quant-trading"
|
|
60
|
+
Source = "https://github.com/initial-d/ml-quant-trading"
|
|
60
61
|
Documentation = "https://initial-d.github.io/ml-quant-trading/"
|
|
61
62
|
Paper = "https://arxiv.org/abs/2507.07107"
|
|
62
63
|
Issues = "https://github.com/initial-d/ml-quant-trading/issues"
|
|
64
|
+
Discussions = "https://github.com/initial-d/ml-quant-trading/discussions"
|
|
63
65
|
Changelog = "https://github.com/initial-d/ml-quant-trading/blob/main/CHANGELOG.md"
|
|
64
66
|
|
|
65
67
|
[tool.setuptools.packages.find]
|
|
@@ -70,6 +72,7 @@ where = ["src"]
|
|
|
70
72
|
|
|
71
73
|
[tool.pytest.ini_options]
|
|
72
74
|
testpaths = ["tests"]
|
|
75
|
+
pythonpath = ["src"]
|
|
73
76
|
addopts = "-ra -q --strict-markers"
|
|
74
77
|
filterwarnings = [
|
|
75
78
|
"ignore::DeprecationWarning",
|
|
@@ -24,12 +24,21 @@ from ..features.bias import limit_move_mask
|
|
|
24
24
|
from ..models.losses import AdjMSELoss
|
|
25
25
|
from ..models.nets import MLPRegressor
|
|
26
26
|
from ..portfolio.markowitz import MarkowitzConfig, MarkowitzOptimizer
|
|
27
|
+
from ..systemone import decide as systemone_decide
|
|
28
|
+
from ..systemone import load_questions as load_systemone_questions
|
|
29
|
+
from ..systemone import load_state as load_systemone_state
|
|
27
30
|
from ..training.dataset import FactorDataset
|
|
28
31
|
from ..training.trainer import TrainConfig, Trainer
|
|
29
32
|
from ..utils.config import load_config
|
|
30
33
|
from ..utils.seed import seed_everything
|
|
31
34
|
|
|
32
35
|
|
|
36
|
+
PROJECT_URL = "https://github.com/initial-d/ml-quant-trading"
|
|
37
|
+
REPRODUCTION_REPORT_URL = (
|
|
38
|
+
f"{PROJECT_URL}/issues/new?template=reproduction_report.yml"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
33
42
|
def _artifacts_dir(cfg) -> Path:
|
|
34
43
|
p = Path(cfg.get("artifacts_dir", "artifacts"))
|
|
35
44
|
p.mkdir(parents=True, exist_ok=True)
|
|
@@ -50,6 +59,8 @@ def _write_backtest_summary(
|
|
|
50
59
|
}
|
|
51
60
|
payload = {
|
|
52
61
|
"project": "ml-quant-trading",
|
|
62
|
+
"repository": PROJECT_URL,
|
|
63
|
+
"reproduction_report": REPRODUCTION_REPORT_URL,
|
|
53
64
|
"workflow": "synthetic factor-to-backtest demo",
|
|
54
65
|
"config": config_path,
|
|
55
66
|
"costs_bps": float(costs_bps),
|
|
@@ -59,7 +70,10 @@ def _write_backtest_summary(
|
|
|
59
70
|
),
|
|
60
71
|
}
|
|
61
72
|
json_path = output_dir / "summary.json"
|
|
62
|
-
json_path.write_text(
|
|
73
|
+
json_path.write_text(
|
|
74
|
+
json.dumps(payload, indent=2, sort_keys=True) + "\n",
|
|
75
|
+
encoding="utf-8",
|
|
76
|
+
)
|
|
63
77
|
|
|
64
78
|
rows = []
|
|
65
79
|
for key, value in clean_metrics.items():
|
|
@@ -78,6 +92,11 @@ def _write_backtest_summary(
|
|
|
78
92
|
f"- Config: `{config_path}`",
|
|
79
93
|
f"- Transaction cost assumption: `{costs_bps:g} bps`",
|
|
80
94
|
"- Workflow: synthetic data → 213 factors → MLP → Markowitz → backtest",
|
|
95
|
+
f"- Source: [{PROJECT_URL}]({PROJECT_URL})",
|
|
96
|
+
(
|
|
97
|
+
"- Share a reproducible run: "
|
|
98
|
+
f"[open the report form]({REPRODUCTION_REPORT_URL})"
|
|
99
|
+
),
|
|
81
100
|
"",
|
|
82
101
|
"| Metric | Value |",
|
|
83
102
|
"|---|---:|",
|
|
@@ -89,7 +108,7 @@ def _write_backtest_summary(
|
|
|
89
108
|
]
|
|
90
109
|
)
|
|
91
110
|
markdown_path = output_dir / "summary.md"
|
|
92
|
-
markdown_path.write_text(markdown)
|
|
111
|
+
markdown_path.write_text(markdown, encoding="utf-8")
|
|
93
112
|
return markdown_path, json_path
|
|
94
113
|
|
|
95
114
|
|
|
@@ -137,6 +156,10 @@ def _run_demo(ctx: click.Context, config_path: str) -> None:
|
|
|
137
156
|
ctx.invoke(command, config_path=config_path)
|
|
138
157
|
click.echo()
|
|
139
158
|
click.echo("Demo complete. Inspect the backtest summary above and artifacts/ for outputs.")
|
|
159
|
+
click.echo("\nNext steps")
|
|
160
|
+
click.echo(f" Customize or inspect the source: {PROJECT_URL}")
|
|
161
|
+
click.echo(f" Share a reproducible run: {REPRODUCTION_REPORT_URL}")
|
|
162
|
+
click.echo(" If this saved you setup time, consider starring the repository.")
|
|
140
163
|
|
|
141
164
|
|
|
142
165
|
@cli.command("gen-data")
|
|
@@ -284,6 +307,55 @@ def cmd_backtest(config_path: str) -> None:
|
|
|
284
307
|
click.echo(f"\nShareable reports: {markdown_path} {json_path}")
|
|
285
308
|
|
|
286
309
|
|
|
310
|
+
@cli.group("systemone")
|
|
311
|
+
def cmd_systemone() -> None:
|
|
312
|
+
"""Typed decision adapter for research evidence artifacts."""
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
@cmd_systemone.command("decide")
|
|
316
|
+
@click.option(
|
|
317
|
+
"--state",
|
|
318
|
+
"state_path",
|
|
319
|
+
required=True,
|
|
320
|
+
type=click.Path(exists=True, path_type=Path),
|
|
321
|
+
help="Path to a validation summary.json or compatible state JSON.",
|
|
322
|
+
)
|
|
323
|
+
@click.option(
|
|
324
|
+
"--questions",
|
|
325
|
+
"questions_path",
|
|
326
|
+
default=None,
|
|
327
|
+
type=click.Path(exists=True, path_type=Path),
|
|
328
|
+
help="Optional JSON/YAML file with typed question definitions.",
|
|
329
|
+
)
|
|
330
|
+
@click.option(
|
|
331
|
+
"--output",
|
|
332
|
+
"output_path",
|
|
333
|
+
default=None,
|
|
334
|
+
type=click.Path(path_type=Path),
|
|
335
|
+
help="Optional path for the typed decision JSON.",
|
|
336
|
+
)
|
|
337
|
+
def cmd_systemone_decide(
|
|
338
|
+
state_path: Path,
|
|
339
|
+
questions_path: Path | None,
|
|
340
|
+
output_path: Path | None,
|
|
341
|
+
) -> None:
|
|
342
|
+
"""Convert a research report into System-One-style typed decisions."""
|
|
343
|
+
state = load_systemone_state(state_path)
|
|
344
|
+
questions = (
|
|
345
|
+
load_systemone_questions(questions_path)
|
|
346
|
+
if questions_path is not None
|
|
347
|
+
else None
|
|
348
|
+
)
|
|
349
|
+
payload = systemone_decide(state, questions=questions, source_path=state_path)
|
|
350
|
+
text = json.dumps(payload, indent=2, sort_keys=True) + "\n"
|
|
351
|
+
if output_path is not None:
|
|
352
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
353
|
+
output_path.write_text(text, encoding="utf-8")
|
|
354
|
+
click.echo(f"wrote {output_path}")
|
|
355
|
+
else:
|
|
356
|
+
click.echo(text, nl=False)
|
|
357
|
+
|
|
358
|
+
|
|
287
359
|
def main() -> None:
|
|
288
360
|
cli()
|
|
289
361
|
|