macrostress 0.1.0__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.
- macrostress-0.1.0/LICENSE +21 -0
- macrostress-0.1.0/PKG-INFO +154 -0
- macrostress-0.1.0/README.md +117 -0
- macrostress-0.1.0/pyproject.toml +87 -0
- macrostress-0.1.0/pyproject.toml.orig +85 -0
- macrostress-0.1.0/src/mst/README.md +32 -0
- macrostress-0.1.0/src/mst/__init__.py +5 -0
- macrostress-0.1.0/src/mst/contracts.py +48 -0
- macrostress-0.1.0/src/mst/corpus/README.md +35 -0
- macrostress-0.1.0/src/mst/corpus/__init__.py +1 -0
- macrostress-0.1.0/src/mst/corpus/__main__.py +7 -0
- macrostress-0.1.0/src/mst/corpus/cli.py +314 -0
- macrostress-0.1.0/src/mst/corpus/convert.py +357 -0
- macrostress-0.1.0/src/mst/corpus/embed.py +59 -0
- macrostress-0.1.0/src/mst/corpus/episodes.py +287 -0
- macrostress-0.1.0/src/mst/corpus/fetch.py +191 -0
- macrostress-0.1.0/src/mst/corpus/index.py +474 -0
- macrostress-0.1.0/src/mst/corpus/manifest.py +194 -0
- macrostress-0.1.0/src/mst/corpus/series.py +234 -0
- macrostress-0.1.0/src/mst/corpus/tool.py +124 -0
- macrostress-0.1.0/src/mst/data/README.md +39 -0
- macrostress-0.1.0/src/mst/data/__init__.py +1 -0
- macrostress-0.1.0/src/mst/data/__main__.py +7 -0
- macrostress-0.1.0/src/mst/data/cbr.py +176 -0
- macrostress-0.1.0/src/mst/data/cbr_stats.py +193 -0
- macrostress-0.1.0/src/mst/data/cli.py +70 -0
- macrostress-0.1.0/src/mst/data/daily.py +51 -0
- macrostress-0.1.0/src/mst/data/fred.py +45 -0
- macrostress-0.1.0/src/mst/data/mintsifry-roots.pem +113 -0
- macrostress-0.1.0/src/mst/data/moex.py +186 -0
- macrostress-0.1.0/src/mst/data/release.py +12 -0
- macrostress-0.1.0/src/mst/data/rosstat.py +282 -0
- macrostress-0.1.0/src/mst/data/sources.py +115 -0
- macrostress-0.1.0/src/mst/data/sources.toml +228 -0
- macrostress-0.1.0/src/mst/data/store.py +118 -0
- macrostress-0.1.0/src/mst/data/update.py +40 -0
- macrostress-0.1.0/src/mst/drivers/README.md +38 -0
- macrostress-0.1.0/src/mst/drivers/__init__.py +1 -0
- macrostress-0.1.0/src/mst/drivers/__main__.py +11 -0
- macrostress-0.1.0/src/mst/drivers/catalogs/README.md +19 -0
- macrostress-0.1.0/src/mst/drivers/catalogs/__init__.py +17 -0
- macrostress-0.1.0/src/mst/drivers/catalogs/base.py +57 -0
- macrostress-0.1.0/src/mst/drivers/catalogs/cbr.py +62 -0
- macrostress-0.1.0/src/mst/drivers/catalogs/moex.py +240 -0
- macrostress-0.1.0/src/mst/drivers/catalogs/rosstat.py +62 -0
- macrostress-0.1.0/src/mst/drivers/check.py +98 -0
- macrostress-0.1.0/src/mst/drivers/cli.py +109 -0
- macrostress-0.1.0/src/mst/drivers/estimate.py +411 -0
- macrostress-0.1.0/src/mst/drivers/objects.py +39 -0
- macrostress-0.1.0/src/mst/drivers/registry.py +216 -0
- macrostress-0.1.0/src/mst/drivers/registry.toml +138 -0
- macrostress-0.1.0/src/mst/drivers/simulate.py +152 -0
- macrostress-0.1.0/src/mst/drivers/spec.py +33 -0
- macrostress-0.1.0/src/mst/drivers/spec.toml +24 -0
- macrostress-0.1.0/src/mst/drivers/update.py +82 -0
- macrostress-0.1.0/src/mst/drivers/version.py +215 -0
- macrostress-0.1.0/src/mst/engine/README.md +21 -0
- macrostress-0.1.0/src/mst/engine/__init__.py +11 -0
- macrostress-0.1.0/src/mst/engine/dispatch.py +269 -0
- macrostress-0.1.0/src/mst/engine/model_catalog.py +57 -0
- macrostress-0.1.0/src/mst/engine/run.py +102 -0
- macrostress-0.1.0/src/mst/engine/status.py +21 -0
- macrostress-0.1.0/src/mst/importer.py +25 -0
- macrostress-0.1.0/src/mst/jobs.py +246 -0
- macrostress-0.1.0/src/mst/macro/README.md +36 -0
- macrostress-0.1.0/src/mst/macro/__init__.py +1 -0
- macrostress-0.1.0/src/mst/macro/__main__.py +7 -0
- macrostress-0.1.0/src/mst/macro/backtest.py +269 -0
- macrostress-0.1.0/src/mst/macro/backtest.toml +157 -0
- macrostress-0.1.0/src/mst/macro/cli.py +192 -0
- macrostress-0.1.0/src/mst/macro/estimate.py +377 -0
- macrostress-0.1.0/src/mst/macro/forecast.py +307 -0
- macrostress-0.1.0/src/mst/macro/identify.py +120 -0
- macrostress-0.1.0/src/mst/macro/panel.py +94 -0
- macrostress-0.1.0/src/mst/macro/registry.py +120 -0
- macrostress-0.1.0/src/mst/macro/registry.toml +194 -0
- macrostress-0.1.0/src/mst/macro/spec.py +62 -0
- macrostress-0.1.0/src/mst/macro/spec.toml +55 -0
- macrostress-0.1.0/src/mst/macro/sv.py +75 -0
- macrostress-0.1.0/src/mst/macro/var.py +59 -0
- macrostress-0.1.0/src/mst/macro/version.py +87 -0
- macrostress-0.1.0/src/mst/mcp.py +398 -0
- macrostress-0.1.0/src/mst/plugin.py +288 -0
- macrostress-0.1.0/src/mst/plugin_sdk/README.md +25 -0
- macrostress-0.1.0/src/mst/plugin_sdk/__init__.py +62 -0
- macrostress-0.1.0/src/mst/plugin_sdk/fx.py +64 -0
- macrostress-0.1.0/src/mst/plugin_sdk/model.py +156 -0
- macrostress-0.1.0/src/mst/plugin_sdk/paths.py +114 -0
- macrostress-0.1.0/src/mst/plugin_sdk/plugin.py +45 -0
- macrostress-0.1.0/src/mst/plugin_sdk/results.py +139 -0
- macrostress-0.1.0/src/mst/plugin_sdk/testing.py +120 -0
- macrostress-0.1.0/src/mst/plugin_sdk/version.py +45 -0
- macrostress-0.1.0/src/mst/plugins/README.md +25 -0
- macrostress-0.1.0/src/mst/plugins/__init__.py +345 -0
- macrostress-0.1.0/src/mst/plugins/bond/__init__.py +6 -0
- macrostress-0.1.0/src/mst/plugins/bond/model.py +88 -0
- macrostress-0.1.0/src/mst/plugins/bond/plugin.py +37 -0
- macrostress-0.1.0/src/mst/plugins/credit/__init__.py +6 -0
- macrostress-0.1.0/src/mst/plugins/credit/model.py +88 -0
- macrostress-0.1.0/src/mst/plugins/credit/plugin.py +37 -0
- macrostress-0.1.0/src/mst/plugins/equity/__init__.py +6 -0
- macrostress-0.1.0/src/mst/plugins/equity/model.py +87 -0
- macrostress-0.1.0/src/mst/plugins/equity/plugin.py +36 -0
- macrostress-0.1.0/src/mst/plugins/housing/__init__.py +6 -0
- macrostress-0.1.0/src/mst/plugins/housing/model.py +93 -0
- macrostress-0.1.0/src/mst/plugins/housing/plugin.py +41 -0
- macrostress-0.1.0/src/mst/portfolio/README.md +29 -0
- macrostress-0.1.0/src/mst/portfolio/__init__.py +5 -0
- macrostress-0.1.0/src/mst/portfolio/report.py +121 -0
- macrostress-0.1.0/src/mst/portfolio/spec.py +29 -0
- macrostress-0.1.0/src/mst/portfolio/tool.py +220 -0
- macrostress-0.1.0/src/mst/runs.py +309 -0
- macrostress-0.1.0/src/mst/scenario/README.md +32 -0
- macrostress-0.1.0/src/mst/scenario/__init__.py +1 -0
- macrostress-0.1.0/src/mst/scenario/build.py +165 -0
- macrostress-0.1.0/src/mst/scenario/contracts.py +89 -0
- macrostress-0.1.0/src/mst/scenario/spec.py +17 -0
- macrostress-0.1.0/src/mst/scenario/tool.py +83 -0
- macrostress-0.1.0/src/mst/store.py +140 -0
- macrostress-0.1.0/src/mst/templates/plugin/README.md.tmpl +33 -0
- macrostress-0.1.0/src/mst/templates/plugin/__init__.py.tmpl +6 -0
- macrostress-0.1.0/src/mst/templates/plugin/model.py.tmpl +83 -0
- macrostress-0.1.0/src/mst/templates/plugin/plugin.py.tmpl +41 -0
- macrostress-0.1.0/src/mst/templates/plugin/tests/__init__.py.tmpl +1 -0
- macrostress-0.1.0/src/mst/templates/plugin/tests/test_plugin.py.tmpl +9 -0
- macrostress-0.1.0/src/mst/versions.py +83 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 LeoLourson
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: macrostress
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Portfolio stress testing over macroeconomic scenarios, as an MCP server
|
|
5
|
+
Keywords: stress-testing,scenario-analysis,macroeconomic,bvar,portfolio-risk,mcp
|
|
6
|
+
Author: LeoLourson
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
18
|
+
Requires-Dist: numpy==2.4.4
|
|
19
|
+
Requires-Dist: scipy==1.17.1
|
|
20
|
+
Requires-Dist: pydantic==2.12.5
|
|
21
|
+
Requires-Dist: httpx==0.28.1
|
|
22
|
+
Requires-Dist: fastmcp==2.14.7
|
|
23
|
+
Requires-Dist: openpyxl==3.1.5
|
|
24
|
+
Requires-Dist: pypdf==6.21.4
|
|
25
|
+
Requires-Dist: pyyaml==6.0.3
|
|
26
|
+
Requires-Dist: snowballstemmer==3.1.1
|
|
27
|
+
Requires-Dist: onnxruntime==1.31.1
|
|
28
|
+
Requires-Dist: tokenizers==0.23.2
|
|
29
|
+
Requires-Dist: huggingface-hub==1.33.0
|
|
30
|
+
Requires-Python: >=3.12
|
|
31
|
+
Project-URL: Homepage, https://github.com/LeoLourson/MacroStress-DSH
|
|
32
|
+
Project-URL: Documentation, https://github.com/LeoLourson/MacroStress-DSH/blob/main/docs/README.md
|
|
33
|
+
Project-URL: Repository, https://github.com/LeoLourson/MacroStress-DSH
|
|
34
|
+
Project-URL: Issues, https://github.com/LeoLourson/MacroStress-DSH/issues
|
|
35
|
+
Project-URL: Changelog, https://github.com/LeoLourson/MacroStress-DSH/blob/main/CHANGELOG.md
|
|
36
|
+
Description-Content-Type: text/markdown
|
|
37
|
+
|
|
38
|
+
# MacroStress
|
|
39
|
+
|
|
40
|
+
[English](README.md) | [Русский](README.ru.md) | [中文](README.zh.md)
|
|
41
|
+
|
|
42
|
+
[](https://github.com/LeoLourson/MacroStress-DSH/actions/workflows/ci.yml)
|
|
43
|
+
[](LICENSE)
|
|
44
|
+
[](pyproject.toml)
|
|
45
|
+
|
|
46
|
+
MacroStress answers one question: how much does a portfolio lose under a given macroeconomic
|
|
47
|
+
scenario? An analyst or an agent names paths for a few macro variables (say, the policy rate at
|
|
48
|
+
21 % for the next year) and the shocks behind them. A BVAR estimated on history completes
|
|
49
|
+
consistent paths for the other variables, satellite models turn those paths into drivers (equity
|
|
50
|
+
prices, bond spreads, industry overdue shares, housing prices), and every position is repriced
|
|
51
|
+
along the same draws. The output is a loss distribution with $P_5$, $P_{50}$, $P_{95}$, ES95 and
|
|
52
|
+
the scenario severity $\delta$. The method is described in
|
|
53
|
+
[docs/scenario-formalization.md](docs/scenario-formalization.md) (Russian).
|
|
54
|
+
|
|
55
|
+
The server speaks MCP, so any client can drive it: Claude Desktop, Cursor, Claude Code. A
|
|
56
|
+
DeepSeek Harness plugin in `dsh/` adds three skills and a workspace snapshot for the agent
|
|
57
|
+
prompt. All state lives in one `workspace/` directory; there is no web app, no database, and no
|
|
58
|
+
scheduler.
|
|
59
|
+
|
|
60
|
+
## What it does
|
|
61
|
+
|
|
62
|
+
| Part | What it does |
|
|
63
|
+
|---|---|
|
|
64
|
+
| Series | Monthly series from MOEX, the Bank of Russia, Rosstat, and FRED, with the release date of every value |
|
|
65
|
+
| Macro model | BVAR with stochastic volatility, sign restrictions, conditional forecasts, scenario severity, and checks on historical episodes |
|
|
66
|
+
| Drivers | Object catalogs, hierarchical satellite models, out-of-sample checks, driver paths on the macro draws |
|
|
67
|
+
| Scenario | A $(N, C, D, O)$ file with validation and paths: conditional forecast and drivers on the same draws |
|
|
68
|
+
| Positions | Equity, bond, credit or deposit, housing |
|
|
69
|
+
| Run and report | Positions along scenario paths, with $P_5$, $P_{50}$, $P_{95}$, ES95, and $\delta$ |
|
|
70
|
+
| Extensions | A new asset type is a plugin: `python -m mst.plugin new`, contract checks, a demo run |
|
|
71
|
+
| DSH plugin | Scenario from the corpus, report, drivers; the prompt section built from `workspace.json` |
|
|
72
|
+
|
|
73
|
+
MCP tools: `jobs`, `series`, `corpus`, `scenario`, `run`, `portfolio`, `model`. The reference is
|
|
74
|
+
in [docs/tools.md](docs/tools.md) (Russian).
|
|
75
|
+
|
|
76
|
+
## Install
|
|
77
|
+
|
|
78
|
+
Python 3.12 or newer and [uv](https://docs.astral.sh/uv/) are enough.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
git clone https://github.com/LeoLourson/MacroStress-DSH
|
|
82
|
+
cd MacroStress-DSH
|
|
83
|
+
uv sync
|
|
84
|
+
uv run macrostress --workspace C:/data/macrostress
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
The server speaks over stdio and prints only errors; it waits for a client. Configuration for
|
|
88
|
+
Claude Desktop, Cursor, and any other MCP client is in [docs/mcp.md](docs/mcp.md). The DeepSeek
|
|
89
|
+
Harness plugin is covered in [docs/install.md](docs/install.md).
|
|
90
|
+
|
|
91
|
+
## First session
|
|
92
|
+
|
|
93
|
+
Once a client is connected, it sees seven tools. Long operations start jobs: a tool returns a
|
|
94
|
+
`job` at once, and `jobs` shows the progress.
|
|
95
|
+
|
|
96
|
+
1. `jobs(action="state")` — what is in the workspace: model versions, corpus index, jobs.
|
|
97
|
+
2. `series(action="update")` — download the macro series. FRED needs a key in `FRED_API_KEY`.
|
|
98
|
+
3. `jobs(action="status", id=...)` and `jobs(action="log", id=...)` — wait for the job.
|
|
99
|
+
4. `model(kind="macro", action="estimate", as_of="2026-10-29")` — estimate the macro model on the
|
|
100
|
+
data known at that date. The version is a hash.
|
|
101
|
+
5. `series(action="update", quantity="share_price")` — find the objects of a quantity and
|
|
102
|
+
download their series; the same for `bond_spread`, `overdue_share`, `housing_price_primary`,
|
|
103
|
+
`housing_price_secondary`.
|
|
104
|
+
6. `model(kind="satellites", action="estimate", version=<macro hash>)` — estimate the satellites
|
|
105
|
+
on that macro version.
|
|
106
|
+
7. `model(kind="satellites", action="describe", version=<hash>)` — which drivers passed the
|
|
107
|
+
out-of-sample check and why the rest were rejected.
|
|
108
|
+
8. `corpus(action="search", query=..., as_of=...)` — fragments known at the date;
|
|
109
|
+
`corpus(action="index")` rebuilds the index as a job.
|
|
110
|
+
9. `scenario(action="save", id=..., spec={...})` — save a scenario;
|
|
111
|
+
`scenario(action="validate", id=...)` — list everything that blocks the calculation.
|
|
112
|
+
10. `portfolio(action="save", id=..., spec={...})` — save a portfolio;
|
|
113
|
+
`portfolio(action="check", id=..., scenario=...)` — check it against the scenario.
|
|
114
|
+
11. `run(action="start", scenario=..., portfolio=..., draws=..., seed=...)` — start a run;
|
|
115
|
+
`run(action="result", id=...)` — read $P_5$/$P_{50}$/$P_{95}$, $\delta$, and coverage.
|
|
116
|
+
|
|
117
|
+
## Documentation
|
|
118
|
+
|
|
119
|
+
The documentation is in Russian, except [docs/mcp.md](docs/mcp.md), which is in English.
|
|
120
|
+
|
|
121
|
+
- [docs/mcp.md](docs/mcp.md) — any MCP client, the first session, troubleshooting;
|
|
122
|
+
- [docs/install.md](docs/install.md) — the Python package and the DeepSeek Harness plugin;
|
|
123
|
+
- [docs/architecture.md](docs/architecture.md) — packages, workspace, versions, jobs;
|
|
124
|
+
- [docs/tools.md](docs/tools.md) — MCP tools and `python -m mst.*` commands;
|
|
125
|
+
- [docs/plugins.md](docs/plugins.md) — a new asset type as a plugin;
|
|
126
|
+
- [docs/platform.md](docs/platform.md) — the contracts: position, paths, model, registry;
|
|
127
|
+
- [docs/scenario-formalization.md](docs/scenario-formalization.md) — the method and what the code
|
|
128
|
+
implements.
|
|
129
|
+
|
|
130
|
+
Every package folder has its own README that names its files.
|
|
131
|
+
|
|
132
|
+
## Development
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
uv sync
|
|
136
|
+
uv run pytest -q -m "not slow"
|
|
137
|
+
uv run ruff check .
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
The `slow` tests estimate the BVAR and take minutes; the night workflow runs the full suite.
|
|
141
|
+
CI runs the fast suite on Linux and Windows with Python 3.12 and 3.13.
|
|
142
|
+
|
|
143
|
+
## Status
|
|
144
|
+
|
|
145
|
+
0.1.0, beta. Interfaces may change before 1.0. The data sources are the Russian market (MOEX,
|
|
146
|
+
the Bank of Russia, Rosstat) plus FRED for global series.
|
|
147
|
+
|
|
148
|
+
## Contributing and license
|
|
149
|
+
|
|
150
|
+
Contributing rules and the release process are in [CONTRIBUTING.md](CONTRIBUTING.md);
|
|
151
|
+
vulnerabilities go through [SECURITY.md](SECURITY.md). The code is MIT-licensed, see
|
|
152
|
+
[LICENSE](LICENSE). Series from MOEX, the Bank of Russia, Rosstat, FRED, and BIS are not part of
|
|
153
|
+
this repository: you load them under the terms of each source, and the license does not cover
|
|
154
|
+
that data. Citations are described in [CITATION.cff](CITATION.cff).
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# MacroStress
|
|
2
|
+
|
|
3
|
+
[English](README.md) | [Русский](README.ru.md) | [中文](README.zh.md)
|
|
4
|
+
|
|
5
|
+
[](https://github.com/LeoLourson/MacroStress-DSH/actions/workflows/ci.yml)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](pyproject.toml)
|
|
8
|
+
|
|
9
|
+
MacroStress answers one question: how much does a portfolio lose under a given macroeconomic
|
|
10
|
+
scenario? An analyst or an agent names paths for a few macro variables (say, the policy rate at
|
|
11
|
+
21 % for the next year) and the shocks behind them. A BVAR estimated on history completes
|
|
12
|
+
consistent paths for the other variables, satellite models turn those paths into drivers (equity
|
|
13
|
+
prices, bond spreads, industry overdue shares, housing prices), and every position is repriced
|
|
14
|
+
along the same draws. The output is a loss distribution with $P_5$, $P_{50}$, $P_{95}$, ES95 and
|
|
15
|
+
the scenario severity $\delta$. The method is described in
|
|
16
|
+
[docs/scenario-formalization.md](docs/scenario-formalization.md) (Russian).
|
|
17
|
+
|
|
18
|
+
The server speaks MCP, so any client can drive it: Claude Desktop, Cursor, Claude Code. A
|
|
19
|
+
DeepSeek Harness plugin in `dsh/` adds three skills and a workspace snapshot for the agent
|
|
20
|
+
prompt. All state lives in one `workspace/` directory; there is no web app, no database, and no
|
|
21
|
+
scheduler.
|
|
22
|
+
|
|
23
|
+
## What it does
|
|
24
|
+
|
|
25
|
+
| Part | What it does |
|
|
26
|
+
|---|---|
|
|
27
|
+
| Series | Monthly series from MOEX, the Bank of Russia, Rosstat, and FRED, with the release date of every value |
|
|
28
|
+
| Macro model | BVAR with stochastic volatility, sign restrictions, conditional forecasts, scenario severity, and checks on historical episodes |
|
|
29
|
+
| Drivers | Object catalogs, hierarchical satellite models, out-of-sample checks, driver paths on the macro draws |
|
|
30
|
+
| Scenario | A $(N, C, D, O)$ file with validation and paths: conditional forecast and drivers on the same draws |
|
|
31
|
+
| Positions | Equity, bond, credit or deposit, housing |
|
|
32
|
+
| Run and report | Positions along scenario paths, with $P_5$, $P_{50}$, $P_{95}$, ES95, and $\delta$ |
|
|
33
|
+
| Extensions | A new asset type is a plugin: `python -m mst.plugin new`, contract checks, a demo run |
|
|
34
|
+
| DSH plugin | Scenario from the corpus, report, drivers; the prompt section built from `workspace.json` |
|
|
35
|
+
|
|
36
|
+
MCP tools: `jobs`, `series`, `corpus`, `scenario`, `run`, `portfolio`, `model`. The reference is
|
|
37
|
+
in [docs/tools.md](docs/tools.md) (Russian).
|
|
38
|
+
|
|
39
|
+
## Install
|
|
40
|
+
|
|
41
|
+
Python 3.12 or newer and [uv](https://docs.astral.sh/uv/) are enough.
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
git clone https://github.com/LeoLourson/MacroStress-DSH
|
|
45
|
+
cd MacroStress-DSH
|
|
46
|
+
uv sync
|
|
47
|
+
uv run macrostress --workspace C:/data/macrostress
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The server speaks over stdio and prints only errors; it waits for a client. Configuration for
|
|
51
|
+
Claude Desktop, Cursor, and any other MCP client is in [docs/mcp.md](docs/mcp.md). The DeepSeek
|
|
52
|
+
Harness plugin is covered in [docs/install.md](docs/install.md).
|
|
53
|
+
|
|
54
|
+
## First session
|
|
55
|
+
|
|
56
|
+
Once a client is connected, it sees seven tools. Long operations start jobs: a tool returns a
|
|
57
|
+
`job` at once, and `jobs` shows the progress.
|
|
58
|
+
|
|
59
|
+
1. `jobs(action="state")` — what is in the workspace: model versions, corpus index, jobs.
|
|
60
|
+
2. `series(action="update")` — download the macro series. FRED needs a key in `FRED_API_KEY`.
|
|
61
|
+
3. `jobs(action="status", id=...)` and `jobs(action="log", id=...)` — wait for the job.
|
|
62
|
+
4. `model(kind="macro", action="estimate", as_of="2026-10-29")` — estimate the macro model on the
|
|
63
|
+
data known at that date. The version is a hash.
|
|
64
|
+
5. `series(action="update", quantity="share_price")` — find the objects of a quantity and
|
|
65
|
+
download their series; the same for `bond_spread`, `overdue_share`, `housing_price_primary`,
|
|
66
|
+
`housing_price_secondary`.
|
|
67
|
+
6. `model(kind="satellites", action="estimate", version=<macro hash>)` — estimate the satellites
|
|
68
|
+
on that macro version.
|
|
69
|
+
7. `model(kind="satellites", action="describe", version=<hash>)` — which drivers passed the
|
|
70
|
+
out-of-sample check and why the rest were rejected.
|
|
71
|
+
8. `corpus(action="search", query=..., as_of=...)` — fragments known at the date;
|
|
72
|
+
`corpus(action="index")` rebuilds the index as a job.
|
|
73
|
+
9. `scenario(action="save", id=..., spec={...})` — save a scenario;
|
|
74
|
+
`scenario(action="validate", id=...)` — list everything that blocks the calculation.
|
|
75
|
+
10. `portfolio(action="save", id=..., spec={...})` — save a portfolio;
|
|
76
|
+
`portfolio(action="check", id=..., scenario=...)` — check it against the scenario.
|
|
77
|
+
11. `run(action="start", scenario=..., portfolio=..., draws=..., seed=...)` — start a run;
|
|
78
|
+
`run(action="result", id=...)` — read $P_5$/$P_{50}$/$P_{95}$, $\delta$, and coverage.
|
|
79
|
+
|
|
80
|
+
## Documentation
|
|
81
|
+
|
|
82
|
+
The documentation is in Russian, except [docs/mcp.md](docs/mcp.md), which is in English.
|
|
83
|
+
|
|
84
|
+
- [docs/mcp.md](docs/mcp.md) — any MCP client, the first session, troubleshooting;
|
|
85
|
+
- [docs/install.md](docs/install.md) — the Python package and the DeepSeek Harness plugin;
|
|
86
|
+
- [docs/architecture.md](docs/architecture.md) — packages, workspace, versions, jobs;
|
|
87
|
+
- [docs/tools.md](docs/tools.md) — MCP tools and `python -m mst.*` commands;
|
|
88
|
+
- [docs/plugins.md](docs/plugins.md) — a new asset type as a plugin;
|
|
89
|
+
- [docs/platform.md](docs/platform.md) — the contracts: position, paths, model, registry;
|
|
90
|
+
- [docs/scenario-formalization.md](docs/scenario-formalization.md) — the method and what the code
|
|
91
|
+
implements.
|
|
92
|
+
|
|
93
|
+
Every package folder has its own README that names its files.
|
|
94
|
+
|
|
95
|
+
## Development
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
uv sync
|
|
99
|
+
uv run pytest -q -m "not slow"
|
|
100
|
+
uv run ruff check .
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The `slow` tests estimate the BVAR and take minutes; the night workflow runs the full suite.
|
|
104
|
+
CI runs the fast suite on Linux and Windows with Python 3.12 and 3.13.
|
|
105
|
+
|
|
106
|
+
## Status
|
|
107
|
+
|
|
108
|
+
0.1.0, beta. Interfaces may change before 1.0. The data sources are the Russian market (MOEX,
|
|
109
|
+
the Bank of Russia, Rosstat) plus FRED for global series.
|
|
110
|
+
|
|
111
|
+
## Contributing and license
|
|
112
|
+
|
|
113
|
+
Contributing rules and the release process are in [CONTRIBUTING.md](CONTRIBUTING.md);
|
|
114
|
+
vulnerabilities go through [SECURITY.md](SECURITY.md). The code is MIT-licensed, see
|
|
115
|
+
[LICENSE](LICENSE). Series from MOEX, the Bank of Russia, Rosstat, FRED, and BIS are not part of
|
|
116
|
+
this repository: you load them under the terms of each source, and the license does not cover
|
|
117
|
+
that data. Citations are described in [CITATION.cff](CITATION.cff).
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "macrostress"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Portfolio stress testing over macroeconomic scenarios, as an MCP server"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
requires-python = ">=3.12"
|
|
9
|
+
keywords = [
|
|
10
|
+
"stress-testing",
|
|
11
|
+
"scenario-analysis",
|
|
12
|
+
"macroeconomic",
|
|
13
|
+
"bvar",
|
|
14
|
+
"portfolio-risk",
|
|
15
|
+
"mcp",
|
|
16
|
+
]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 4 - Beta",
|
|
19
|
+
"Intended Audience :: Financial and Insurance Industry",
|
|
20
|
+
"Intended Audience :: Science/Research",
|
|
21
|
+
"Operating System :: OS Independent",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
"Topic :: Office/Business :: Financial :: Investment",
|
|
26
|
+
"Topic :: Scientific/Engineering :: Mathematics",
|
|
27
|
+
]
|
|
28
|
+
dependencies = [
|
|
29
|
+
"numpy==2.4.4",
|
|
30
|
+
"scipy==1.17.1",
|
|
31
|
+
"pydantic==2.12.5",
|
|
32
|
+
"httpx==0.28.1",
|
|
33
|
+
"fastmcp==2.14.7",
|
|
34
|
+
"openpyxl==3.1.5",
|
|
35
|
+
"pypdf==6.21.4",
|
|
36
|
+
"pyyaml==6.0.3",
|
|
37
|
+
"snowballstemmer==3.1.1",
|
|
38
|
+
"onnxruntime==1.31.1",
|
|
39
|
+
"tokenizers==0.23.2",
|
|
40
|
+
"huggingface-hub==1.33.0",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[[project.authors]]
|
|
44
|
+
name = "LeoLourson"
|
|
45
|
+
|
|
46
|
+
[project.urls]
|
|
47
|
+
Homepage = "https://github.com/LeoLourson/MacroStress-DSH"
|
|
48
|
+
Documentation = "https://github.com/LeoLourson/MacroStress-DSH/blob/main/docs/README.md"
|
|
49
|
+
Repository = "https://github.com/LeoLourson/MacroStress-DSH"
|
|
50
|
+
Issues = "https://github.com/LeoLourson/MacroStress-DSH/issues"
|
|
51
|
+
Changelog = "https://github.com/LeoLourson/MacroStress-DSH/blob/main/CHANGELOG.md"
|
|
52
|
+
|
|
53
|
+
[project.scripts]
|
|
54
|
+
macrostress = "mst.mcp:main"
|
|
55
|
+
|
|
56
|
+
[dependency-groups]
|
|
57
|
+
dev = [
|
|
58
|
+
"pytest==8.4.2",
|
|
59
|
+
"pytest-timeout==2.4.0",
|
|
60
|
+
"ruff==0.12.12",
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
[build-system]
|
|
64
|
+
requires = ["uv_build>=0.12.13,<0.13.0"]
|
|
65
|
+
build-backend = "uv_build"
|
|
66
|
+
|
|
67
|
+
[tool.uv.build-backend]
|
|
68
|
+
module-name = "mst"
|
|
69
|
+
|
|
70
|
+
[tool.pytest.ini_options]
|
|
71
|
+
testpaths = ["tests"]
|
|
72
|
+
pythonpath = ["."]
|
|
73
|
+
addopts = "-ra"
|
|
74
|
+
markers = ["slow: estimates the BVAR and takes minutes"]
|
|
75
|
+
|
|
76
|
+
[tool.ruff]
|
|
77
|
+
target-version = "py312"
|
|
78
|
+
line-length = 100
|
|
79
|
+
|
|
80
|
+
[tool.ruff.lint]
|
|
81
|
+
select = [
|
|
82
|
+
"E",
|
|
83
|
+
"F",
|
|
84
|
+
"I",
|
|
85
|
+
"UP",
|
|
86
|
+
"B",
|
|
87
|
+
]
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "macrostress"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Portfolio stress testing over macroeconomic scenarios, as an MCP server"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
requires-python = ">=3.12"
|
|
9
|
+
authors = [{ name = "LeoLourson" }]
|
|
10
|
+
keywords = [
|
|
11
|
+
"stress-testing",
|
|
12
|
+
"scenario-analysis",
|
|
13
|
+
"macroeconomic",
|
|
14
|
+
"bvar",
|
|
15
|
+
"portfolio-risk",
|
|
16
|
+
"mcp",
|
|
17
|
+
]
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Development Status :: 4 - Beta",
|
|
20
|
+
"Intended Audience :: Financial and Insurance Industry",
|
|
21
|
+
"Intended Audience :: Science/Research",
|
|
22
|
+
"Operating System :: OS Independent",
|
|
23
|
+
"Programming Language :: Python :: 3",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Programming Language :: Python :: 3.13",
|
|
26
|
+
"Topic :: Office/Business :: Financial :: Investment",
|
|
27
|
+
"Topic :: Scientific/Engineering :: Mathematics",
|
|
28
|
+
]
|
|
29
|
+
dependencies = [
|
|
30
|
+
"numpy==2.4.4",
|
|
31
|
+
"scipy==1.17.1",
|
|
32
|
+
"pydantic==2.12.5",
|
|
33
|
+
"httpx==0.28.1",
|
|
34
|
+
"fastmcp==2.14.7",
|
|
35
|
+
# Excel tables of the Bank of Russia and Rosstat archives.
|
|
36
|
+
"openpyxl==3.1.5",
|
|
37
|
+
# Corpus: PDF text extraction, the YAML header of a document, BM25 stems.
|
|
38
|
+
"pypdf==6.21.4",
|
|
39
|
+
"pyyaml==6.0.3",
|
|
40
|
+
"snowballstemmer==3.1.1",
|
|
41
|
+
# Corpus search vectors: multilingual-e5-small on the CPU through ONNX Runtime.
|
|
42
|
+
"onnxruntime==1.31.1",
|
|
43
|
+
"tokenizers==0.23.2",
|
|
44
|
+
"huggingface-hub==1.33.0",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
[project.urls]
|
|
48
|
+
Homepage = "https://github.com/LeoLourson/MacroStress-DSH"
|
|
49
|
+
Documentation = "https://github.com/LeoLourson/MacroStress-DSH/blob/main/docs/README.md"
|
|
50
|
+
Repository = "https://github.com/LeoLourson/MacroStress-DSH"
|
|
51
|
+
Issues = "https://github.com/LeoLourson/MacroStress-DSH/issues"
|
|
52
|
+
Changelog = "https://github.com/LeoLourson/MacroStress-DSH/blob/main/CHANGELOG.md"
|
|
53
|
+
|
|
54
|
+
[project.scripts]
|
|
55
|
+
macrostress = "mst.mcp:main"
|
|
56
|
+
|
|
57
|
+
[dependency-groups]
|
|
58
|
+
dev = [
|
|
59
|
+
"pytest==8.4.2",
|
|
60
|
+
"pytest-timeout==2.4.0",
|
|
61
|
+
"ruff==0.12.12",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
[build-system]
|
|
65
|
+
requires = ["uv_build>=0.12.13,<0.13.0"]
|
|
66
|
+
build-backend = "uv_build"
|
|
67
|
+
|
|
68
|
+
# The import package is mst; the distribution is macrostress.
|
|
69
|
+
[tool.uv.build-backend]
|
|
70
|
+
module-name = "mst"
|
|
71
|
+
|
|
72
|
+
[tool.pytest.ini_options]
|
|
73
|
+
testpaths = ["tests"]
|
|
74
|
+
pythonpath = ["."]
|
|
75
|
+
addopts = "-ra"
|
|
76
|
+
markers = [
|
|
77
|
+
"slow: estimates the BVAR and takes minutes",
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
[tool.ruff]
|
|
81
|
+
target-version = "py312"
|
|
82
|
+
line-length = 100
|
|
83
|
+
|
|
84
|
+
[tool.ruff.lint]
|
|
85
|
+
select = ["E", "F", "I", "UP", "B"]
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# mst
|
|
2
|
+
|
|
3
|
+
Ядро MacroStress: MCP-сервер, задачи, workspace и пакеты расчёта. Единственное состояние —
|
|
4
|
+
файлы workspace; каждый инструмент MCP разбирает аргументы и вызывает одну функцию
|
|
5
|
+
пакета или запускает задачу. Устройство целиком — в
|
|
6
|
+
[../../docs/architecture.md](../../docs/architecture.md).
|
|
7
|
+
|
|
8
|
+
| Модуль или пакет | Что делает |
|
|
9
|
+
|---|---|
|
|
10
|
+
| `mcp.py` | Сервер FastMCP с инструментами `jobs`, `series`, `corpus`, `scenario`, `run`, `portfolio`, `model` ([../../docs/tools.md](../../docs/tools.md)); `python -m mst.mcp --workspace DIR` |
|
|
11
|
+
| `plugin.py` | `python -m mst.plugin new|check|demo-run`: пакет типа актива, его контракт и демо-расчёт ([../../docs/plugins.md](../../docs/plugins.md)) |
|
|
12
|
+
| `jobs.py` | Задачи: дочерний процесс `python <argv>` под обёрткой `python -m mst.jobs`, которая пишет код выхода, с логом в `jobs/<id>/`, блокировка ресурса (`series`, `models`, `corpus`, `code`, `runs`), отмена дерева процессов |
|
|
13
|
+
| `runs.py` | Прогон на путях сценария: запрос, мета, пути, вклады позиций и отчёт в `runs/<id>/`; `python -m mst.runs <id> --workspace DIR` |
|
|
14
|
+
| `store.py` | Каталоги workspace (`Workspace`), атомарная запись JSON, канонический хеш `sha256_of`, снимок `workspace.json` |
|
|
15
|
+
| `versions.py` | Версии моделей на диске: хеш по метаданным и массивам, запись через черновик, чтение с проверкой хеша и имени, список без черновиков |
|
|
16
|
+
| `contracts.py` | Базовый класс контрактов pydantic (`extra="forbid"`, без NaN и бесконечностей) и общие типы: идентификатор, хеш, горизонт, сид, валюта, код объекта, статус результата |
|
|
17
|
+
| `importer.py` | Копирование рядов из каталога CSV (`<source>/data/series/*.csv`) в workspace |
|
|
18
|
+
| [data/](data/README.md) | Загрузка и хранение месячных рядов |
|
|
19
|
+
| [macro/](macro/README.md) | Макромодель: оценка, идентификация, условный прогноз, жёсткость, бэктест |
|
|
20
|
+
| [drivers/](drivers/README.md) | Драйверы: каталоги, сателлиты, их проверка и пути |
|
|
21
|
+
| [corpus/](corpus/README.md) | Корпус источников: манифест, загрузка, Markdown, эпизоды, индекс и поиск |
|
|
22
|
+
| [scenario/](scenario/README.md) | Сценарий: контракт, проверка и сборка путей |
|
|
23
|
+
| [plugin_sdk/](plugin_sdk/README.md) | Что модель позиции объявляет, читает и возвращает: `Paths`, требования, результат; `testing.py` — конформанс-проверка |
|
|
24
|
+
| [engine/](engine/README.md) | Каталог моделей, подготовка входов и расчёт позиций без ветвления по типу актива |
|
|
25
|
+
| [plugins/](plugins/README.md) | Пакеты типов активов: обнаружение, реестр объявлений и модели позиций |
|
|
26
|
+
| [portfolio/](portfolio/README.md) | Портфель, его проверка, стоимость позиций и отчёт прогона |
|
|
27
|
+
|
|
28
|
+
Зависимости между пакетами идут в одну сторону: `data` → `macro` → `drivers`; `scenario`
|
|
29
|
+
нужен `macro` и `drivers`, `corpus` — бэктесту `macro`; `engine` и `runs` — `plugin_sdk`,
|
|
30
|
+
`plugins`, `scenario` и обеим версиям моделей; `portfolio` — `engine` и `scenario`.
|
|
31
|
+
`plugin.py` читает реестр `plugins` и `plugin_sdk.testing`; сам `engine` конкретных плагинов
|
|
32
|
+
не импортирует.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Wire conventions: money in millions of its currency, rates as fractions, time in months/days."""
|
|
2
|
+
|
|
3
|
+
from typing import Annotated, Literal
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
6
|
+
|
|
7
|
+
Identifier = Annotated[str, Field(min_length=1, pattern=r"\S")]
|
|
8
|
+
Sha256 = Annotated[str, Field(pattern=r"^[0-9a-f]{64}$")]
|
|
9
|
+
Number = Annotated[float, Field(strict=True, allow_inf_nan=False)]
|
|
10
|
+
Probability = Annotated[Number, Field(ge=0, le=1)]
|
|
11
|
+
NonNegative = Annotated[Number, Field(ge=0)]
|
|
12
|
+
Positive = Annotated[Number, Field(gt=0)]
|
|
13
|
+
Horizon = Annotated[int, Field(strict=True, ge=1, le=360)]
|
|
14
|
+
Seed = Annotated[int, Field(strict=True, ge=0, le=2**32 - 1)]
|
|
15
|
+
#: An ISO 4217 code: the currency of a position, a portfolio's base currency.
|
|
16
|
+
Currency = Annotated[str, Field(pattern=r"^[A-Z]{3}$")]
|
|
17
|
+
#: A kind of code a position carries and an object may cover (``Registry.match``).
|
|
18
|
+
CodeKind = Literal["secid", "isin", "inn", "okved", "okato"]
|
|
19
|
+
Status = Literal["ok", "needs_review"]
|
|
20
|
+
#: The status of a calculated position: ``invalid`` never enters portfolio arithmetic.
|
|
21
|
+
ResultStatus = Literal["ok", "needs_review", "invalid"]
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
"CodeKind",
|
|
25
|
+
"Contract",
|
|
26
|
+
"Currency",
|
|
27
|
+
"Horizon",
|
|
28
|
+
"Identifier",
|
|
29
|
+
"NonNegative",
|
|
30
|
+
"Number",
|
|
31
|
+
"Positive",
|
|
32
|
+
"Probability",
|
|
33
|
+
"ResultStatus",
|
|
34
|
+
"Seed",
|
|
35
|
+
"Sha256",
|
|
36
|
+
"Status",
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class Contract(BaseModel):
|
|
41
|
+
model_config = ConfigDict(
|
|
42
|
+
extra="forbid",
|
|
43
|
+
allow_inf_nan=False,
|
|
44
|
+
validate_default=True,
|
|
45
|
+
validate_assignment=True,
|
|
46
|
+
revalidate_instances="always",
|
|
47
|
+
)
|
|
48
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# mst.corpus
|
|
2
|
+
|
|
3
|
+
Корпус источников сценария ([corpus/README.md](../../../corpus/README.md)): манифест с
|
|
4
|
+
адресами оригиналов, загрузка, перевод PDF и веб-страниц в Markdown, карточки эпизодов с
|
|
5
|
+
таблицами движений, индекс фрагментов и поиск по нему.
|
|
6
|
+
|
|
7
|
+
```powershell
|
|
8
|
+
python -m mst.corpus check --corpus DIR
|
|
9
|
+
python -m mst.corpus fetch [ID ...] --corpus DIR [--force]
|
|
10
|
+
python -m mst.corpus add KEY FILE [--url URL] --corpus DIR
|
|
11
|
+
python -m mst.corpus convert [ID ...] --corpus DIR
|
|
12
|
+
python -m mst.corpus series [SERIES ...] --corpus DIR --store DIR
|
|
13
|
+
python -m mst.corpus episodes [ID ...] --corpus DIR --store DIR
|
|
14
|
+
python -m mst.corpus index --corpus DIR
|
|
15
|
+
python -m mst.corpus search QUERY --as-of DAY --corpus DIR
|
|
16
|
+
python -m mst.corpus eval --corpus DIR
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`--corpus` — корень корпуса в workspace (`workspace/corpus`). В git лежат только манифест,
|
|
20
|
+
`series.toml`, проверочные вопросы и шаблоны (`corpus/` в корне репозитория); скачанные
|
|
21
|
+
оригиналы, тексты и индекс — данные workspace.
|
|
22
|
+
|
|
23
|
+
| Файл | Что делает |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `manifest.py` | Контракты манифеста: источники и их издания, адреса оригиналов (`url` или `page` + `match`), карточки эпизодов, ряды; `Document` — один файл источника |
|
|
26
|
+
| `fetch.py` | Загрузка оригиналов в `raw/`, запись в `downloads.json` с хешем и датой; файл с тем же хешем повторно не скачивается |
|
|
27
|
+
| `convert.py` | PDF и веб-страница в Markdown: текстовый слой pypdf, заголовки из оглавления, колонтитулы и номера страниц выброшены, шапка с датой публикации |
|
|
28
|
+
| `series.py` | Дневные ряды D1–D5 для таблиц движений: загрузчик из `mst.data` или BIS, кеш в `series/`, месячный ряд из хранилища как запасной вариант |
|
|
29
|
+
| `episodes.py` | Карточка эпизода: окно, база, экстремум, изменение, дни до экстремума и восстановления; написанные руками разделы сохраняются |
|
|
30
|
+
| `index.py` | Нарезка Markdown на фрагменты, `chunks.jsonl`, векторы e5, BM25 + косинус с фильтром `as_of`, recall@5 по `eval/questions.md` |
|
|
31
|
+
| `embed.py` | Векторы multilingual-e5-small на CPU через ONNX Runtime |
|
|
32
|
+
| `tool.py` | Операции инструмента `corpus`: `search`, `get`, `list`, `add` |
|
|
33
|
+
| `cli.py`, `__main__.py` | Команда `python -m mst.corpus` |
|
|
34
|
+
|
|
35
|
+
Тесты — [../../../tests/corpus](../../../tests/corpus/).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""The scenario corpus (corpus/README.md): manifest, downloads, texts, episode cards, search."""
|