opera-eco 0.4.5__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.
- opera_eco-0.4.5/LICENSE +21 -0
- opera_eco-0.4.5/PKG-INFO +140 -0
- opera_eco-0.4.5/README.md +88 -0
- opera_eco-0.4.5/pyproject.toml +103 -0
- opera_eco-0.4.5/setup.cfg +4 -0
- opera_eco-0.4.5/src/opera/__init__.py +8 -0
- opera_eco-0.4.5/src/opera/cli.py +174 -0
- opera_eco-0.4.5/src/opera/sample_realtime_data.py +160 -0
- opera_eco-0.4.5/src/opera/skill_api.py +315 -0
- opera_eco-0.4.5/src/opera/skills/__init__.py +1 -0
- opera_eco-0.4.5/src/opera/skills/bvar.md +251 -0
- opera_eco-0.4.5/src/opera/skills/forecast_combo.md +284 -0
- opera_eco-0.4.5/src/opera/skills/forecast_evaluation.md +574 -0
- opera_eco-0.4.5/src/opera/skills/forecast_realtime.md +420 -0
- opera_eco-0.4.5/src/opera/skills/news_decomp.md +185 -0
- opera_eco-0.4.5/src/opera/skills/nowcast_midas.md +674 -0
- opera_eco-0.4.5/src/opera/skills/opera.md +374 -0
- opera_eco-0.4.5/src/opera/skills_manager.py +169 -0
- opera_eco-0.4.5/src/opera/tests/__init__.py +0 -0
- opera_eco-0.4.5/src/opera/tests/conftest.py +0 -0
- opera_eco-0.4.5/src/opera/tests/contracts/__init__.py +0 -0
- opera_eco-0.4.5/src/opera/tests/contracts/schema.py +4 -0
- opera_eco-0.4.5/src/opera/tests/contracts/test_forecast_evaluation_contract.py +133 -0
- opera_eco-0.4.5/src/opera/tests/contracts/test_forecast_model_contract.py +49 -0
- opera_eco-0.4.5/src/opera/tests/contracts/test_interoperability_contract.py +76 -0
- opera_eco-0.4.5/src/opera/tests/contracts/test_news_decomposition_contract.py +65 -0
- opera_eco-0.4.5/src/opera/tests/contracts/test_schema.py +20 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/__init__.py +0 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/bvar/__init__.py +0 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/bvar/__snapshots__/test_bvar_snapshot.ambr +415 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/bvar/test_bvar_snapshot.py +144 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/ecosystem/__init__.py +0 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/ecosystem/__snapshots__/test_ecosystem_pipeline.ambr +5242 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/ecosystem/test_ecosystem_pipeline.py +132 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/midas/__init__.py +0 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/midas/__snapshots__/test_midas_snapshot.ambr +1125 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/midas/__snapshots__/test_multimidas_snapshot.ambr +1629 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/midas/__snapshots__/test_scmidas_snapshot.ambr +145 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/midas/sample_data.py +18 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/midas/test_midas_snapshot.py +113 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/midas/test_multimidas_snapshot.py +120 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/midas/test_scmidas_snapshot.py +155 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/mixed_freq/__init__.py +0 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/mixed_freq/__snapshots__/test_mixed_freq_snapshot.ambr +5183 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/mixed_freq/test_mixed_freq_snapshot.py +132 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/news/__init__.py +0 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/news/sample_news.py +933 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/news/test_news.py +594 -0
- opera_eco-0.4.5/src/opera/tests/pipelines/sample_data.py +29 -0
- opera_eco-0.4.5/src/opera/tests/skills_tests/test_skill_api.py +197 -0
- opera_eco-0.4.5/src/opera/tests/skills_tests/test_skill_snippets.py +175 -0
- opera_eco-0.4.5/src/opera/tests/skills_tests/test_skills.py +123 -0
- opera_eco-0.4.5/src/opera_eco.egg-info/PKG-INFO +140 -0
- opera_eco-0.4.5/src/opera_eco.egg-info/SOURCES.txt +56 -0
- opera_eco-0.4.5/src/opera_eco.egg-info/dependency_links.txt +1 -0
- opera_eco-0.4.5/src/opera_eco.egg-info/entry_points.txt +2 -0
- opera_eco-0.4.5/src/opera_eco.egg-info/requires.txt +33 -0
- opera_eco-0.4.5/src/opera_eco.egg-info/top_level.txt +1 -0
opera_eco-0.4.5/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bank of England
|
|
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.
|
opera_eco-0.4.5/PKG-INFO
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: opera-eco
|
|
3
|
+
Version: 0.4.5
|
|
4
|
+
Summary: Dependency and skill manager for the OPERA ecosystem
|
|
5
|
+
Author-email: Paul Labonne <Paul.Labonne@bankofengland.co.uk>, Diego Lopez <Diego.Lopez@bankofengland.co.uk>
|
|
6
|
+
Maintainer-email: Paul Labonne <Paul.Labonne@bankofengland.co.uk>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Documentation, https://bank-of-england.github.io/opera-eco/
|
|
9
|
+
Project-URL: Repository, https://github.com/bank-of-england/opera-eco
|
|
10
|
+
Project-URL: Issues, https://github.com/bank-of-england/opera-eco/issues
|
|
11
|
+
Keywords: time-series,forecasting,evaluation,backtesting,economics
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: numpy
|
|
24
|
+
Requires-Dist: pandas
|
|
25
|
+
Provides-Extra: modules
|
|
26
|
+
Requires-Dist: forecast_evaluation==0.1.13; extra == "modules"
|
|
27
|
+
Requires-Dist: forecast_realtime[models]==0.5.4; extra == "modules"
|
|
28
|
+
Requires-Dist: forecast_combo==0.1.1; extra == "modules"
|
|
29
|
+
Requires-Dist: bvar==0.3.1; extra == "modules"
|
|
30
|
+
Requires-Dist: nowcast-midas==0.0.1; extra == "modules"
|
|
31
|
+
Requires-Dist: news_decomp==0.0.7; extra == "modules"
|
|
32
|
+
Provides-Extra: test
|
|
33
|
+
Requires-Dist: opera-eco[modules]; extra == "test"
|
|
34
|
+
Requires-Dist: pytest; extra == "test"
|
|
35
|
+
Requires-Dist: pytest-xdist; extra == "test"
|
|
36
|
+
Requires-Dist: pytest-timeout; extra == "test"
|
|
37
|
+
Requires-Dist: pandera; extra == "test"
|
|
38
|
+
Requires-Dist: syrupy; extra == "test"
|
|
39
|
+
Provides-Extra: notebooks
|
|
40
|
+
Requires-Dist: marimo==0.24.0; extra == "notebooks"
|
|
41
|
+
Provides-Extra: dev
|
|
42
|
+
Requires-Dist: build; extra == "dev"
|
|
43
|
+
Requires-Dist: packaging; extra == "dev"
|
|
44
|
+
Requires-Dist: pre-commit; extra == "dev"
|
|
45
|
+
Requires-Dist: pydoclint; extra == "dev"
|
|
46
|
+
Requires-Dist: ruff; extra == "dev"
|
|
47
|
+
Requires-Dist: twine; extra == "dev"
|
|
48
|
+
Provides-Extra: docs
|
|
49
|
+
Requires-Dist: mkdocstrings[python]; extra == "docs"
|
|
50
|
+
Requires-Dist: zensical; extra == "docs"
|
|
51
|
+
Dynamic: license-file
|
|
52
|
+
|
|
53
|
+
# OPERA: Open-Source Prediction Evaluation and Real-Time Analysis
|
|
54
|
+
|
|
55
|
+
**[Documentation](https://bank-of-england.github.io/opera-eco/)**
|
|
56
|
+
|
|
57
|
+
OPERA is a modular ecosystem aimed at streamlining forecasting tasks for economists and fostering open collaboration. Model logic - estimation, forecasting, forecast decomposition - is separated from the real-time workflow, making it easier to compare models in replicable environments and leverage open source contributions. The ecosystem is currently composed of seven blocks which cover the full pipeline from raw data to evaluation. Its architecture, interfaces and design principles reflect the specific constraints of macro analysis: data revision, ragged edge, mixed-frequency, conditional projections, uncertainty quantification, narrative accounting and nested models. By making these modules open-source, OPERA provides a platform for central bankers, academics and other forecasters to share infrastructure and collaborate.
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Architecture
|
|
63
|
+
|
|
64
|
+

|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Modules
|
|
69
|
+
|
|
70
|
+
| Module | Package | Role |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| Model Libraries | `bvar`, `nowcast-midas` | Bayesian VARs; mixed-data sampling and SC-MIDAS combinations |
|
|
73
|
+
| Forecast Evaluation | `forecast_evaluation` | Validate data, evaluate accuracy, run statistical tests, visualise |
|
|
74
|
+
| Real-time Forecasting | `forecast_realtime` | Fit and forecast wrappers, backtesting, simulation, stress-testing, R/MATLAB/Julia adapters |
|
|
75
|
+
| Forecast Combination | `forecast_combo` | Inverse-error, regression and hierarchical combination |
|
|
76
|
+
| News Decomposition | `news_decomp` | Nowcast decomposition into level and revision; news/reestimation/interaction |
|
|
77
|
+
|
|
78
|
+
Install all ecosystem packages with `pip install "opera-eco[modules]"`.
|
|
79
|
+
|
|
80
|
+
## Authors
|
|
81
|
+
|
|
82
|
+
The package authors listed in each repository's `pyproject.toml` are:
|
|
83
|
+
|
|
84
|
+
| Package | Authors |
|
|
85
|
+
|---|---|
|
|
86
|
+
| `opera-eco` | Paul Labonne; Diego Lopez |
|
|
87
|
+
| `forecast_evaluation` | James Hurley; Paul Labonne; Harry Li |
|
|
88
|
+
| `forecast_realtime` | Paul Labonne; Sumer Singh; Harry Li; Nades Raviraj |
|
|
89
|
+
| `bvar` | Paul Labonne; Andrea Renzetti; Joseph Oyegoke |
|
|
90
|
+
| `nowcast-midas` | James Kensett; Paul Labonne; Andre Moreira |
|
|
91
|
+
| `forecast_combo` | Filippo Busetto; Paul Labonne; James McConachie; Roshni Tara |
|
|
92
|
+
| `news_decomp` | Guido Bonatti; Kensley Blaise; Paul Labonne; Nades Raviraj |
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Quick Start
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
pip install opera-eco # Install the CLI and skills only.
|
|
100
|
+
pip install "opera-eco[modules]" # Install the CLI and all ecosystem packages.
|
|
101
|
+
pip install "opera-eco[notebooks]" # Install Marimo notebook tooling.
|
|
102
|
+
opera install skills # Install AI skills in .claude/skills/.
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Then ask Copilot or Claude to use an installed skill:
|
|
106
|
+
|
|
107
|
+
```text
|
|
108
|
+
Tell me about @opera and how I can use it with my model.
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## OPERA Skills for Claude and Copilot
|
|
112
|
+
|
|
113
|
+
The package includes seven skills for AI coding assistants:
|
|
114
|
+
|
|
115
|
+
| Skill | Description |
|
|
116
|
+
|---|---|
|
|
117
|
+
| **opera** | Meta-skill covering the full ecosystem: architecture, modules, data flows, conventions, integration patterns |
|
|
118
|
+
| **forecast-evaluation** | Data validation, accuracy metrics, statistical tests, visualisations, dashboards |
|
|
119
|
+
| **forecast-realtime** | Real-time forecasting, backtesting, model wrapping, external language models (R, MATLAB, Julia) |
|
|
120
|
+
| **bvar** | Bayesian VARs, conditional forecasting with hard/soft/skewed constraints, GIRFs |
|
|
121
|
+
| **nowcast-midas** | MIDAS regressions, MultiMIDAS, SC-MIDAS combinations, monthly-to-quarterly nowcasting |
|
|
122
|
+
| **forecast-combo** | Forecast combination methods, hierarchical pooling, weight analysis |
|
|
123
|
+
| **forecast-decomp** | Nowcast decomposition: levels and revisions, news, reestimation, interaction, and New York Fed-style analysis |
|
|
124
|
+
|
|
125
|
+
## Project Layout
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
docs/ # Documentation site.
|
|
129
|
+
examples/illustration.py # Runnable end-to-end example.
|
|
130
|
+
examples/illustration_marimo.py # Native Marimo version of the example.
|
|
131
|
+
src/opera/ # Package source, bundled skills, and tests.
|
|
132
|
+
cli.py # Command-line interface.
|
|
133
|
+
skills_manager.py # Skill discovery and installation.
|
|
134
|
+
skills/ # Bundled Markdown skill files.
|
|
135
|
+
pyproject.toml # Python package configuration.
|
|
136
|
+
zensical.toml # Documentation site configuration.
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Data Classification
|
|
140
|
+
Bank of England Data Classification: OFFICIAL BLUE
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# OPERA: Open-Source Prediction Evaluation and Real-Time Analysis
|
|
2
|
+
|
|
3
|
+
**[Documentation](https://bank-of-england.github.io/opera-eco/)**
|
|
4
|
+
|
|
5
|
+
OPERA is a modular ecosystem aimed at streamlining forecasting tasks for economists and fostering open collaboration. Model logic - estimation, forecasting, forecast decomposition - is separated from the real-time workflow, making it easier to compare models in replicable environments and leverage open source contributions. The ecosystem is currently composed of seven blocks which cover the full pipeline from raw data to evaluation. Its architecture, interfaces and design principles reflect the specific constraints of macro analysis: data revision, ragged edge, mixed-frequency, conditional projections, uncertainty quantification, narrative accounting and nested models. By making these modules open-source, OPERA provides a platform for central bankers, academics and other forecasters to share infrastructure and collaborate.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Architecture
|
|
11
|
+
|
|
12
|
+

|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Modules
|
|
17
|
+
|
|
18
|
+
| Module | Package | Role |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| Model Libraries | `bvar`, `nowcast-midas` | Bayesian VARs; mixed-data sampling and SC-MIDAS combinations |
|
|
21
|
+
| Forecast Evaluation | `forecast_evaluation` | Validate data, evaluate accuracy, run statistical tests, visualise |
|
|
22
|
+
| Real-time Forecasting | `forecast_realtime` | Fit and forecast wrappers, backtesting, simulation, stress-testing, R/MATLAB/Julia adapters |
|
|
23
|
+
| Forecast Combination | `forecast_combo` | Inverse-error, regression and hierarchical combination |
|
|
24
|
+
| News Decomposition | `news_decomp` | Nowcast decomposition into level and revision; news/reestimation/interaction |
|
|
25
|
+
|
|
26
|
+
Install all ecosystem packages with `pip install "opera-eco[modules]"`.
|
|
27
|
+
|
|
28
|
+
## Authors
|
|
29
|
+
|
|
30
|
+
The package authors listed in each repository's `pyproject.toml` are:
|
|
31
|
+
|
|
32
|
+
| Package | Authors |
|
|
33
|
+
|---|---|
|
|
34
|
+
| `opera-eco` | Paul Labonne; Diego Lopez |
|
|
35
|
+
| `forecast_evaluation` | James Hurley; Paul Labonne; Harry Li |
|
|
36
|
+
| `forecast_realtime` | Paul Labonne; Sumer Singh; Harry Li; Nades Raviraj |
|
|
37
|
+
| `bvar` | Paul Labonne; Andrea Renzetti; Joseph Oyegoke |
|
|
38
|
+
| `nowcast-midas` | James Kensett; Paul Labonne; Andre Moreira |
|
|
39
|
+
| `forecast_combo` | Filippo Busetto; Paul Labonne; James McConachie; Roshni Tara |
|
|
40
|
+
| `news_decomp` | Guido Bonatti; Kensley Blaise; Paul Labonne; Nades Raviraj |
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Quick Start
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install opera-eco # Install the CLI and skills only.
|
|
48
|
+
pip install "opera-eco[modules]" # Install the CLI and all ecosystem packages.
|
|
49
|
+
pip install "opera-eco[notebooks]" # Install Marimo notebook tooling.
|
|
50
|
+
opera install skills # Install AI skills in .claude/skills/.
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Then ask Copilot or Claude to use an installed skill:
|
|
54
|
+
|
|
55
|
+
```text
|
|
56
|
+
Tell me about @opera and how I can use it with my model.
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## OPERA Skills for Claude and Copilot
|
|
60
|
+
|
|
61
|
+
The package includes seven skills for AI coding assistants:
|
|
62
|
+
|
|
63
|
+
| Skill | Description |
|
|
64
|
+
|---|---|
|
|
65
|
+
| **opera** | Meta-skill covering the full ecosystem: architecture, modules, data flows, conventions, integration patterns |
|
|
66
|
+
| **forecast-evaluation** | Data validation, accuracy metrics, statistical tests, visualisations, dashboards |
|
|
67
|
+
| **forecast-realtime** | Real-time forecasting, backtesting, model wrapping, external language models (R, MATLAB, Julia) |
|
|
68
|
+
| **bvar** | Bayesian VARs, conditional forecasting with hard/soft/skewed constraints, GIRFs |
|
|
69
|
+
| **nowcast-midas** | MIDAS regressions, MultiMIDAS, SC-MIDAS combinations, monthly-to-quarterly nowcasting |
|
|
70
|
+
| **forecast-combo** | Forecast combination methods, hierarchical pooling, weight analysis |
|
|
71
|
+
| **forecast-decomp** | Nowcast decomposition: levels and revisions, news, reestimation, interaction, and New York Fed-style analysis |
|
|
72
|
+
|
|
73
|
+
## Project Layout
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
docs/ # Documentation site.
|
|
77
|
+
examples/illustration.py # Runnable end-to-end example.
|
|
78
|
+
examples/illustration_marimo.py # Native Marimo version of the example.
|
|
79
|
+
src/opera/ # Package source, bundled skills, and tests.
|
|
80
|
+
cli.py # Command-line interface.
|
|
81
|
+
skills_manager.py # Skill discovery and installation.
|
|
82
|
+
skills/ # Bundled Markdown skill files.
|
|
83
|
+
pyproject.toml # Python package configuration.
|
|
84
|
+
zensical.toml # Documentation site configuration.
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Data Classification
|
|
88
|
+
Bank of England Data Classification: OFFICIAL BLUE
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "opera-eco"
|
|
7
|
+
version = "0.4.5"
|
|
8
|
+
description = "Dependency and skill manager for the OPERA ecosystem"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
authors = [
|
|
12
|
+
{name="Paul Labonne", email="Paul.Labonne@bankofengland.co.uk"},
|
|
13
|
+
{name="Diego Lopez", email="Diego.Lopez@bankofengland.co.uk"},
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
maintainers = [
|
|
17
|
+
{name="Paul Labonne", email="Paul.Labonne@bankofengland.co.uk"},
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
license = "MIT"
|
|
21
|
+
keywords = ["time-series", "forecasting", "evaluation", "backtesting", "economics"]
|
|
22
|
+
classifiers = [
|
|
23
|
+
"Development Status :: 4 - Beta",
|
|
24
|
+
"Operating System :: OS Independent",
|
|
25
|
+
"Programming Language :: Python :: 3",
|
|
26
|
+
"Programming Language :: Python :: 3.11",
|
|
27
|
+
"Programming Language :: Python :: 3.12",
|
|
28
|
+
"Programming Language :: Python :: 3.13",
|
|
29
|
+
"Programming Language :: Python :: 3.14",
|
|
30
|
+
"Topic :: Scientific/Engineering",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
dependencies = [
|
|
34
|
+
"numpy",
|
|
35
|
+
"pandas",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
[project.urls]
|
|
39
|
+
Documentation = "https://bank-of-england.github.io/opera-eco/"
|
|
40
|
+
Repository = "https://github.com/bank-of-england/opera-eco"
|
|
41
|
+
Issues = "https://github.com/bank-of-england/opera-eco/issues"
|
|
42
|
+
|
|
43
|
+
# Integration manifest containing the pinned ecosystem versions.
|
|
44
|
+
# Update these pins only after the contract and pipeline suites pass.
|
|
45
|
+
[project.optional-dependencies]
|
|
46
|
+
modules = [
|
|
47
|
+
"forecast_evaluation == 0.1.13",
|
|
48
|
+
"forecast_realtime[models]==0.5.4",
|
|
49
|
+
"forecast_combo==0.1.1",
|
|
50
|
+
"bvar==0.3.1",
|
|
51
|
+
"nowcast-midas==0.0.1",
|
|
52
|
+
"news_decomp==0.0.7",
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
test = [
|
|
56
|
+
"opera-eco[modules]",
|
|
57
|
+
"pytest",
|
|
58
|
+
"pytest-xdist",
|
|
59
|
+
"pytest-timeout",
|
|
60
|
+
"pandera",
|
|
61
|
+
"syrupy",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
notebooks = [
|
|
65
|
+
"marimo==0.24.0",
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
dev = [
|
|
69
|
+
"build",
|
|
70
|
+
"packaging",
|
|
71
|
+
"pre-commit",
|
|
72
|
+
"pydoclint",
|
|
73
|
+
"ruff",
|
|
74
|
+
"twine",
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
docs = [
|
|
78
|
+
"mkdocstrings[python]",
|
|
79
|
+
"zensical",
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
[project.scripts]
|
|
83
|
+
opera = "opera.cli:main"
|
|
84
|
+
|
|
85
|
+
[tool.setuptools.packages.find]
|
|
86
|
+
where = ["src"]
|
|
87
|
+
|
|
88
|
+
[tool.setuptools.package-data]
|
|
89
|
+
"opera.skills" = ["*.md"]
|
|
90
|
+
"opera.tests" = ["**/*.py", "**/__snapshots__/*.ambr"]
|
|
91
|
+
|
|
92
|
+
[tool.pytest.ini_options]
|
|
93
|
+
testpaths = ["src/opera/tests"]
|
|
94
|
+
markers = [
|
|
95
|
+
"contract: shared-schema and interface contract tests (fast)",
|
|
96
|
+
"skill_snippet: isolated executable skill documentation snippets",
|
|
97
|
+
"pipeline: cross-module end-to-end tests (slow)",
|
|
98
|
+
"bvar: pipeline tests exercising the BVAR model",
|
|
99
|
+
"midas: pipeline tests exercising the MIDAS-family models (MIDAS, MultiMIDAS, SC-MIDAS)",
|
|
100
|
+
"news: pipeline tests exercising the news/decomposition pipeline",
|
|
101
|
+
"mixed_freq: pipeline tests exercising the real-time mixed-frequency pipeline",
|
|
102
|
+
"ecosystem: pipeline tests exercising the full OPERA ecosystem illustration",
|
|
103
|
+
]
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"""Manage OPERA skills from the command line.
|
|
2
|
+
|
|
3
|
+
Usage
|
|
4
|
+
-----
|
|
5
|
+
::
|
|
6
|
+
|
|
7
|
+
opera install skills [--target DIR] [--only name1,name2]
|
|
8
|
+
opera list skills
|
|
9
|
+
opera show skill <name>
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import argparse
|
|
15
|
+
import sys
|
|
16
|
+
import textwrap
|
|
17
|
+
|
|
18
|
+
from opera import __version__
|
|
19
|
+
|
|
20
|
+
# Subcommands
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _cmd_install_skills(args: argparse.Namespace) -> None:
|
|
24
|
+
"""Install the selected bundled skills into the requested directory.
|
|
25
|
+
|
|
26
|
+
The parsed arguments provide the destination and an optional comma-separated
|
|
27
|
+
list of skill names. The command reports each skill after installation.
|
|
28
|
+
"""
|
|
29
|
+
from opera.skills_manager import SKILL_FILES, install_skills
|
|
30
|
+
|
|
31
|
+
skills = None
|
|
32
|
+
if args.only:
|
|
33
|
+
skills = [s.strip() for s in args.only.split(",")]
|
|
34
|
+
|
|
35
|
+
target = install_skills(target=args.target, skills=skills)
|
|
36
|
+
|
|
37
|
+
installed = skills or list(SKILL_FILES)
|
|
38
|
+
print(f"Installed {len(installed)} skill(s) to {target}")
|
|
39
|
+
for name in installed:
|
|
40
|
+
print(f" - {name}")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _cmd_list_skills(_args: argparse.Namespace) -> None:
|
|
44
|
+
"""Print a table of bundled skills, files, and descriptions."""
|
|
45
|
+
from opera.skills_manager import list_skills
|
|
46
|
+
|
|
47
|
+
skills = list_skills()
|
|
48
|
+
header = f"{'Name':<25} {'File':<30} Description"
|
|
49
|
+
sep = f"{'-' * 25} {'-' * 30} {'-' * 50}"
|
|
50
|
+
print(header)
|
|
51
|
+
print(sep)
|
|
52
|
+
for s in skills:
|
|
53
|
+
desc = textwrap.shorten(s["description"], width=50, placeholder="…")
|
|
54
|
+
print(f"{s['name']:<25} {s['filename']:<30} {desc}")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _cmd_show_skill(args: argparse.Namespace) -> None:
|
|
58
|
+
"""Write the named bundled skill to standard output as UTF-8 text.
|
|
59
|
+
|
|
60
|
+
An unknown skill name is reported on standard output and causes the command
|
|
61
|
+
to exit with status 1.
|
|
62
|
+
"""
|
|
63
|
+
from opera.skills_manager import show_skill
|
|
64
|
+
|
|
65
|
+
try:
|
|
66
|
+
text = show_skill(args.name)
|
|
67
|
+
sys.stdout.buffer.write(text.encode("utf-8", errors="replace"))
|
|
68
|
+
sys.stdout.buffer.write(b"\n")
|
|
69
|
+
except KeyError as exc:
|
|
70
|
+
print(str(exc))
|
|
71
|
+
sys.exit(1)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _cmd_sync_api(_args: argparse.Namespace) -> None:
|
|
75
|
+
"""Synchronise generated API sections in the bundled skill files.
|
|
76
|
+
|
|
77
|
+
The command reports changed files, or confirms that the generated sections
|
|
78
|
+
are current. Synchronisation errors are written to standard error and cause
|
|
79
|
+
the command to exit with status 1.
|
|
80
|
+
"""
|
|
81
|
+
from opera.skill_api import sync_api_sections
|
|
82
|
+
|
|
83
|
+
try:
|
|
84
|
+
changed = sync_api_sections()
|
|
85
|
+
except Exception as exc:
|
|
86
|
+
print(f"opera skills sync-api: {exc}", file=sys.stderr)
|
|
87
|
+
raise SystemExit(1) from exc
|
|
88
|
+
for path in changed:
|
|
89
|
+
print(f"Updated {path}")
|
|
90
|
+
if not changed:
|
|
91
|
+
print("Skill API sections are current.")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
# Argument parser
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
98
|
+
"""Build and return the parser for all OPERA CLI commands.
|
|
99
|
+
|
|
100
|
+
The parser registers skill installation, listing, display, and API
|
|
101
|
+
synchronisation commands and attaches each command's handler.
|
|
102
|
+
"""
|
|
103
|
+
parser = argparse.ArgumentParser(
|
|
104
|
+
prog="opera",
|
|
105
|
+
description="OPERA ecosystem CLI — manage skills and dependencies.",
|
|
106
|
+
)
|
|
107
|
+
parser.add_argument(
|
|
108
|
+
"-V", "--version", action="version", version=f"%(prog)s {__version__}"
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
sub = parser.add_subparsers(dest="command", required=True)
|
|
112
|
+
|
|
113
|
+
# Install skills or dependencies.
|
|
114
|
+
install_parser = sub.add_parser("install", help="Install skills or dependencies")
|
|
115
|
+
install_sub = install_parser.add_subparsers(dest="install_target", required=True)
|
|
116
|
+
|
|
117
|
+
# Install skills.
|
|
118
|
+
install_skills_parser = install_sub.add_parser(
|
|
119
|
+
"skills", help="Copy OPERA skill files to a target directory"
|
|
120
|
+
)
|
|
121
|
+
install_skills_parser.add_argument(
|
|
122
|
+
"--target",
|
|
123
|
+
default=None,
|
|
124
|
+
help="Destination directory (default: .claude/skills or .github/skills)",
|
|
125
|
+
)
|
|
126
|
+
install_skills_parser.add_argument(
|
|
127
|
+
"--only",
|
|
128
|
+
default=None,
|
|
129
|
+
help="Comma-separated list of skill names to install (default: all)",
|
|
130
|
+
)
|
|
131
|
+
install_skills_parser.set_defaults(func=_cmd_install_skills)
|
|
132
|
+
|
|
133
|
+
# Synchronise generated API sections in the repository checkout.
|
|
134
|
+
skills_command_parser = sub.add_parser(
|
|
135
|
+
"skills", help="Maintain bundled skill resources"
|
|
136
|
+
)
|
|
137
|
+
skills_sub = skills_command_parser.add_subparsers(
|
|
138
|
+
dest="skills_command", required=True
|
|
139
|
+
)
|
|
140
|
+
sync_api_parser = skills_sub.add_parser(
|
|
141
|
+
"sync-api", help="Update generated skill API sections"
|
|
142
|
+
)
|
|
143
|
+
sync_api_parser.set_defaults(func=_cmd_sync_api)
|
|
144
|
+
|
|
145
|
+
# List available resources.
|
|
146
|
+
list_parser = sub.add_parser("list", help="List available resources")
|
|
147
|
+
list_sub = list_parser.add_subparsers(dest="list_target", required=True)
|
|
148
|
+
|
|
149
|
+
list_skills_parser = list_sub.add_parser("skills", help="List bundled skills")
|
|
150
|
+
list_skills_parser.set_defaults(func=_cmd_list_skills)
|
|
151
|
+
|
|
152
|
+
# Show a resource.
|
|
153
|
+
show_parser = sub.add_parser("show", help="Show a resource")
|
|
154
|
+
show_sub = show_parser.add_subparsers(dest="show_target", required=True)
|
|
155
|
+
|
|
156
|
+
show_skill_parser = show_sub.add_parser("skill", help="Print a skill file")
|
|
157
|
+
show_skill_parser.add_argument("name", help="Skill short-name (e.g. opera, bvar)")
|
|
158
|
+
show_skill_parser.set_defaults(func=_cmd_show_skill)
|
|
159
|
+
|
|
160
|
+
return parser
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def main(argv: list[str] | None = None) -> None:
|
|
164
|
+
"""Parse arguments and dispatch to the selected OPERA CLI command.
|
|
165
|
+
|
|
166
|
+
When ``argv`` is omitted, arguments are read from the process command line.
|
|
167
|
+
"""
|
|
168
|
+
parser = build_parser()
|
|
169
|
+
args = parser.parse_args(argv)
|
|
170
|
+
args.func(args)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
if __name__ == "__main__":
|
|
174
|
+
main()
|