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.
Files changed (84) hide show
  1. {mlquantx-0.2.5/src/mlquantx.egg-info → mlquantx-0.3.1}/PKG-INFO +24 -3
  2. {mlquantx-0.2.5 → mlquantx-0.3.1}/PYPI_README.md +21 -2
  3. mlquantx-0.3.1/README.md +208 -0
  4. {mlquantx-0.2.5 → mlquantx-0.3.1}/pyproject.toml +4 -1
  5. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/__init__.py +1 -1
  6. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/cli/main.py +74 -2
  7. mlquantx-0.3.1/src/mlquant/systemone.py +355 -0
  8. {mlquantx-0.2.5 → mlquantx-0.3.1/src/mlquantx.egg-info}/PKG-INFO +24 -3
  9. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquantx.egg-info/SOURCES.txt +3 -0
  10. mlquantx-0.3.1/tests/test_benchmark_tensor_factors.py +61 -0
  11. {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_cli.py +15 -5
  12. {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_public_data_validation.py +7 -0
  13. mlquantx-0.3.1/tests/test_systemone.py +201 -0
  14. mlquantx-0.3.1/tests/test_technical_pipeline_audit.py +34 -0
  15. {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_tensor_factors.py +64 -1
  16. mlquantx-0.2.5/README.md +0 -517
  17. mlquantx-0.2.5/tests/test_benchmark_tensor_factors.py +0 -15
  18. {mlquantx-0.2.5 → mlquantx-0.3.1}/LICENSE +0 -0
  19. {mlquantx-0.2.5 → mlquantx-0.3.1}/NOTICE.md +0 -0
  20. {mlquantx-0.2.5 → mlquantx-0.3.1}/setup.cfg +0 -0
  21. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/backtest/__init__.py +0 -0
  22. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/backtest/engine.py +0 -0
  23. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/backtest/metrics.py +0 -0
  24. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/cli/__init__.py +0 -0
  25. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/configs/__init__.py +0 -0
  26. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/configs/small.yaml +0 -0
  27. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/data/__init__.py +0 -0
  28. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/data/akshare_loader.py +0 -0
  29. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/data/baostock_loader.py +0 -0
  30. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/data/loaders.py +0 -0
  31. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/data/panel.py +0 -0
  32. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/data/synthetic.py +0 -0
  33. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/data/yfinance_loader.py +0 -0
  34. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/__init__.py +0 -0
  35. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/_factors_add.py +0 -0
  36. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/_factors_alpha101.py +0 -0
  37. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/_factors_best.py +0 -0
  38. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/_factors_better.py +0 -0
  39. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/_factors_change.py +0 -0
  40. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/_factors_extra.py +0 -0
  41. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/_factors_market.py +0 -0
  42. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/_factors_old.py +0 -0
  43. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/_factors_original.py +0 -0
  44. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/_factors_stock.py +0 -0
  45. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/alpha101.py +0 -0
  46. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/bias.py +0 -0
  47. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/legacy_factors.py +0 -0
  48. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/market_breadth.py +0 -0
  49. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/neutralize.py +0 -0
  50. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/target.py +0 -0
  51. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features/tensor_factors.py +0 -0
  52. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/features.py +0 -0
  53. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/models/__init__.py +0 -0
  54. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/models/losses.py +0 -0
  55. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/models/nets.py +0 -0
  56. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/portfolio/__init__.py +0 -0
  57. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/portfolio/frontier.py +0 -0
  58. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/portfolio/markowitz.py +0 -0
  59. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/training/__init__.py +0 -0
  60. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/training/augment.py +0 -0
  61. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/training/dataset.py +0 -0
  62. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/training/trainer.py +0 -0
  63. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/utils/__init__.py +0 -0
  64. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/utils/config.py +0 -0
  65. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquant/utils/seed.py +0 -0
  66. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquantx.egg-info/dependency_links.txt +0 -0
  67. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquantx.egg-info/entry_points.txt +0 -0
  68. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquantx.egg-info/requires.txt +0 -0
  69. {mlquantx-0.2.5 → mlquantx-0.3.1}/src/mlquantx.egg-info/top_level.txt +0 -0
  70. {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_aggregate_validation_reports.py +0 -0
  71. {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_akshare.py +0 -0
  72. {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_akshare_csi300_full_pipeline.py +0 -0
  73. {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_alpha101.py +0 -0
  74. {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_audit_validation_report.py +0 -0
  75. {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_augment.py +0 -0
  76. {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_baostock.py +0 -0
  77. {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_bias.py +0 -0
  78. {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_cost_drag_units.py +0 -0
  79. {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_export_huggingface_artifacts.py +0 -0
  80. {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_losses.py +0 -0
  81. {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_markowitz.py +0 -0
  82. {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_metrics.py +0 -0
  83. {mlquantx-0.2.5 → mlquantx-0.3.1}/tests/test_neutralize.py +0 -0
  84. {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.2.5
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, and vectorized
58
- backtesting.**
59
+ trading: 213 factors, bias correction, portfolio optimization, vectorized
60
+ backtesting, and System-One-style portfolio decisions.**
59
61
 
60
62
  [![CI](https://github.com/initial-d/ml-quant-trading/actions/workflows/ci.yml/badge.svg)](https://github.com/initial-d/ml-quant-trading/actions/workflows/ci.yml)
61
63
  [![arXiv](https://img.shields.io/badge/arXiv-2507.07107-b31b1b.svg)](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, and vectorized
5
- backtesting.**
4
+ trading: 213 factors, bias correction, portfolio optimization, vectorized
5
+ backtesting, and System-One-style portfolio decisions.**
6
6
 
7
7
  [![CI](https://github.com/initial-d/ml-quant-trading/actions/workflows/ci.yml/badge.svg)](https://github.com/initial-d/ml-quant-trading/actions/workflows/ci.yml)
8
8
  [![arXiv](https://img.shields.io/badge/arXiv-2507.07107-b31b1b.svg)](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)
@@ -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
+ [![CI](https://github.com/initial-d/ml-quant-trading/actions/workflows/ci.yml/badge.svg)](https://github.com/initial-d/ml-quant-trading/actions/workflows/ci.yml)
8
+ [![GitHub stars](https://img.shields.io/github/stars/initial-d/ml-quant-trading?style=flat&logo=github&label=Stars)](https://github.com/initial-d/ml-quant-trading/stargazers)
9
+ [![Release](https://img.shields.io/github/v/release/initial-d/ml-quant-trading?display_name=tag)](https://github.com/initial-d/ml-quant-trading/releases)
10
+ [![PyPI](https://img.shields.io/pypi/v/mlquantx.svg)](https://pypi.org/project/mlquantx/)
11
+ [![arXiv](https://img.shields.io/badge/arXiv-2507.07107-b31b1b.svg)](https://arxiv.org/abs/2507.07107)
12
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue.svg)](https://www.python.org/downloads/)
13
+ [![MIT](https://img.shields.io/badge/license-MIT-green.svg)](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.2.5"
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",
@@ -14,5 +14,5 @@ import torch or cvxpy. Sub-packages are loaded lazily on demand.
14
14
  """
15
15
  from __future__ import annotations
16
16
 
17
- __version__ = "0.2.5"
17
+ __version__ = "0.3.1"
18
18
  __all__ = ["__version__"]
@@ -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(json.dumps(payload, indent=2, sort_keys=True) + "\n")
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