mlquantx 0.2.6__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.6/src/mlquantx.egg-info → mlquantx-0.3.1}/PKG-INFO +6 -3
  2. {mlquantx-0.2.6 → mlquantx-0.3.1}/PYPI_README.md +5 -2
  3. mlquantx-0.3.1/README.md +208 -0
  4. {mlquantx-0.2.6 → mlquantx-0.3.1}/pyproject.toml +2 -1
  5. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/__init__.py +1 -1
  6. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/cli/main.py +57 -2
  7. mlquantx-0.3.1/src/mlquant/systemone.py +355 -0
  8. {mlquantx-0.2.6 → mlquantx-0.3.1/src/mlquantx.egg-info}/PKG-INFO +6 -3
  9. {mlquantx-0.2.6 → 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.6 → mlquantx-0.3.1}/tests/test_cli.py +8 -5
  12. {mlquantx-0.2.6 → 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.6 → mlquantx-0.3.1}/tests/test_tensor_factors.py +64 -1
  16. mlquantx-0.2.6/README.md +0 -526
  17. mlquantx-0.2.6/tests/test_benchmark_tensor_factors.py +0 -15
  18. {mlquantx-0.2.6 → mlquantx-0.3.1}/LICENSE +0 -0
  19. {mlquantx-0.2.6 → mlquantx-0.3.1}/NOTICE.md +0 -0
  20. {mlquantx-0.2.6 → mlquantx-0.3.1}/setup.cfg +0 -0
  21. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/backtest/__init__.py +0 -0
  22. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/backtest/engine.py +0 -0
  23. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/backtest/metrics.py +0 -0
  24. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/cli/__init__.py +0 -0
  25. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/configs/__init__.py +0 -0
  26. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/configs/small.yaml +0 -0
  27. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/data/__init__.py +0 -0
  28. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/data/akshare_loader.py +0 -0
  29. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/data/baostock_loader.py +0 -0
  30. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/data/loaders.py +0 -0
  31. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/data/panel.py +0 -0
  32. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/data/synthetic.py +0 -0
  33. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/data/yfinance_loader.py +0 -0
  34. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/features/__init__.py +0 -0
  35. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/features/_factors_add.py +0 -0
  36. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/features/_factors_alpha101.py +0 -0
  37. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/features/_factors_best.py +0 -0
  38. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/features/_factors_better.py +0 -0
  39. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/features/_factors_change.py +0 -0
  40. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/features/_factors_extra.py +0 -0
  41. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/features/_factors_market.py +0 -0
  42. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/features/_factors_old.py +0 -0
  43. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/features/_factors_original.py +0 -0
  44. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/features/_factors_stock.py +0 -0
  45. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/features/alpha101.py +0 -0
  46. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/features/bias.py +0 -0
  47. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/features/legacy_factors.py +0 -0
  48. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/features/market_breadth.py +0 -0
  49. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/features/neutralize.py +0 -0
  50. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/features/target.py +0 -0
  51. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/features/tensor_factors.py +0 -0
  52. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/features.py +0 -0
  53. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/models/__init__.py +0 -0
  54. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/models/losses.py +0 -0
  55. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/models/nets.py +0 -0
  56. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/portfolio/__init__.py +0 -0
  57. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/portfolio/frontier.py +0 -0
  58. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/portfolio/markowitz.py +0 -0
  59. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/training/__init__.py +0 -0
  60. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/training/augment.py +0 -0
  61. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/training/dataset.py +0 -0
  62. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/training/trainer.py +0 -0
  63. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/utils/__init__.py +0 -0
  64. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/utils/config.py +0 -0
  65. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquant/utils/seed.py +0 -0
  66. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquantx.egg-info/dependency_links.txt +0 -0
  67. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquantx.egg-info/entry_points.txt +0 -0
  68. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquantx.egg-info/requires.txt +0 -0
  69. {mlquantx-0.2.6 → mlquantx-0.3.1}/src/mlquantx.egg-info/top_level.txt +0 -0
  70. {mlquantx-0.2.6 → mlquantx-0.3.1}/tests/test_aggregate_validation_reports.py +0 -0
  71. {mlquantx-0.2.6 → mlquantx-0.3.1}/tests/test_akshare.py +0 -0
  72. {mlquantx-0.2.6 → mlquantx-0.3.1}/tests/test_akshare_csi300_full_pipeline.py +0 -0
  73. {mlquantx-0.2.6 → mlquantx-0.3.1}/tests/test_alpha101.py +0 -0
  74. {mlquantx-0.2.6 → mlquantx-0.3.1}/tests/test_audit_validation_report.py +0 -0
  75. {mlquantx-0.2.6 → mlquantx-0.3.1}/tests/test_augment.py +0 -0
  76. {mlquantx-0.2.6 → mlquantx-0.3.1}/tests/test_baostock.py +0 -0
  77. {mlquantx-0.2.6 → mlquantx-0.3.1}/tests/test_bias.py +0 -0
  78. {mlquantx-0.2.6 → mlquantx-0.3.1}/tests/test_cost_drag_units.py +0 -0
  79. {mlquantx-0.2.6 → mlquantx-0.3.1}/tests/test_export_huggingface_artifacts.py +0 -0
  80. {mlquantx-0.2.6 → mlquantx-0.3.1}/tests/test_losses.py +0 -0
  81. {mlquantx-0.2.6 → mlquantx-0.3.1}/tests/test_markowitz.py +0 -0
  82. {mlquantx-0.2.6 → mlquantx-0.3.1}/tests/test_metrics.py +0 -0
  83. {mlquantx-0.2.6 → mlquantx-0.3.1}/tests/test_neutralize.py +0 -0
  84. {mlquantx-0.2.6 → mlquantx-0.3.1}/tests/test_synthetic.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mlquantx
3
- Version: 0.2.6
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
@@ -56,8 +56,8 @@ Dynamic: license-file
56
56
  # mlquant
57
57
 
58
58
  **A reproducible PyTorch research stack for machine-learning multi-factor
59
- trading: 213 factors, bias correction, portfolio optimization, and vectorized
60
- backtesting.**
59
+ trading: 213 factors, bias correction, portfolio optimization, vectorized
60
+ backtesting, and System-One-style portfolio decisions.**
61
61
 
62
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)
63
63
  [![arXiv](https://img.shields.io/badge/arXiv-2507.07107-b31b1b.svg)](https://arxiv.org/abs/2507.07107)
@@ -102,12 +102,15 @@ If the demo saves you setup time, consider
102
102
  - vectorized backtesting with turnover and transaction costs
103
103
  - AkShare, Baostock, yfinance, and deterministic synthetic data paths
104
104
  - auditable public-data validation reports, including negative results
105
+ - `mlquant systemone decide` for typed portfolio-intent decisions from
106
+ structured research state
105
107
 
106
108
  ## Start here
107
109
 
108
110
  - [Source and full documentation](https://github.com/initial-d/ml-quant-trading)
109
111
  - [Google Colab quick start](https://colab.research.google.com/github/initial-d/ml-quant-trading/blob/main/notebooks/quickstart_colab.ipynb)
110
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)
111
114
  - [Research card and limitations](https://github.com/initial-d/ml-quant-trading/blob/main/docs/research_card.md)
112
115
  - [100,000-row synthetic dataset](https://huggingface.co/datasets/dddyym/ml-quant-trading-synthetic)
113
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)
@@ -47,12 +47,15 @@ If the demo saves you setup time, consider
47
47
  - vectorized backtesting with turnover and transaction costs
48
48
  - AkShare, Baostock, yfinance, and deterministic synthetic data paths
49
49
  - auditable public-data validation reports, including negative results
50
+ - `mlquant systemone decide` for typed portfolio-intent decisions from
51
+ structured research state
50
52
 
51
53
  ## Start here
52
54
 
53
55
  - [Source and full documentation](https://github.com/initial-d/ml-quant-trading)
54
56
  - [Google Colab quick start](https://colab.research.google.com/github/initial-d/ml-quant-trading/blob/main/notebooks/quickstart_colab.ipynb)
55
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)
56
59
  - [Research card and limitations](https://github.com/initial-d/ml-quant-trading/blob/main/docs/research_card.md)
57
60
  - [100,000-row synthetic dataset](https://huggingface.co/datasets/dddyym/ml-quant-trading-synthetic)
58
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.6"
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"
@@ -72,6 +72,7 @@ where = ["src"]
72
72
 
73
73
  [tool.pytest.ini_options]
74
74
  testpaths = ["tests"]
75
+ pythonpath = ["src"]
75
76
  addopts = "-ra -q --strict-markers"
76
77
  filterwarnings = [
77
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.6"
17
+ __version__ = "0.3.1"
18
18
  __all__ = ["__version__"]
@@ -24,6 +24,9 @@ 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
@@ -67,7 +70,10 @@ def _write_backtest_summary(
67
70
  ),
68
71
  }
69
72
  json_path = output_dir / "summary.json"
70
- 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
+ )
71
77
 
72
78
  rows = []
73
79
  for key, value in clean_metrics.items():
@@ -102,7 +108,7 @@ def _write_backtest_summary(
102
108
  ]
103
109
  )
104
110
  markdown_path = output_dir / "summary.md"
105
- markdown_path.write_text(markdown)
111
+ markdown_path.write_text(markdown, encoding="utf-8")
106
112
  return markdown_path, json_path
107
113
 
108
114
 
@@ -301,6 +307,55 @@ def cmd_backtest(config_path: str) -> None:
301
307
  click.echo(f"\nShareable reports: {markdown_path} {json_path}")
302
308
 
303
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
+
304
359
  def main() -> None:
305
360
  cli()
306
361