Metadata-Version: 2.4
Name: brillq-opex-benchmark
Version: 2.1.0
Summary: brillQ OPEX Benchmark: Bayesian cost-frontier benchmarking of operating costs with credible intervals, an evidence gate, explainable drivers and client reports (HTML, Excel) in English and Polish. Commercial software by brillQ.
Author-email: "brillQ sp. z o.o." <hello@brillq.today>
Maintainer-email: Ava Brill <hello@brillq.today>
License-Expression: LicenseRef-brillQ-Commercial
Project-URL: Homepage, https://brillq.today
Keywords: opex,stochastic-frontier-analysis,bayesian,mcmc,gibbs-sampler,cost-efficiency,benchmarking,explainable-ai,shap,anomaly-detection,forecasting,energy,dso,utilities,hospitals,opex-benchmark,reporting
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Intended Audience :: Science/Research
Classifier: Natural Language :: English
Classifier: Natural Language :: Polish
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE.txt
Requires-Dist: numpy>=1.24
Requires-Dist: scipy>=1.10
Requires-Dist: pandas>=2.0
Requires-Dist: scikit-learn>=1.3
Requires-Dist: pydantic>=2.0
Requires-Dist: cryptography>=41.0
Requires-Dist: tabulate>=0.9
Provides-Extra: ml
Requires-Dist: xgboost>=2.0; extra == "ml"
Requires-Dist: shap>=0.44; extra == "ml"
Provides-Extra: bayes
Requires-Dist: pymc>=5.10; extra == "bayes"
Requires-Dist: arviz>=0.17; extra == "bayes"
Provides-Extra: forecast
Requires-Dist: statsmodels>=0.14; extra == "forecast"
Provides-Extra: excel
Requires-Dist: openpyxl>=3.1; extra == "excel"
Provides-Extra: all
Requires-Dist: brillq-opex-benchmark[bayes,excel,forecast,ml]; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-cov>=4.1; extra == "dev"
Requires-Dist: build>=1.0; extra == "dev"
Requires-Dist: ruff>=0.4; extra == "dev"
Dynamic: license-file

# brillQ OPEX Benchmark

**Bayesian cost-frontier benchmarking of operational expenditure (OPEX).**
A commercial Python library by [brillQ](https://brillq.today), Warsaw, Poland,
published on PyPI as `brillq-opex-benchmark`. It installs the Python package
`brillq_opex` and the command-line tool `brillq-opex`.

> **Licence.** brillQ OPEX Benchmark is commercial software of brillQ sp. z o.o.
> Without a licence key it runs in evaluation mode: all features, at most 30 units
> per analysis of your own data; the built-in demonstration panels run in full. Use
> beyond evaluation requires a licence key; contact **hello@brillq.today**. The
> licence agreement (`LICENSE.txt`) is included in the package.

The library answers six questions about a set of comparable units (network
areas, plants, branches, subsidiaries, hospitals, stores, departments):

1. **Do the data show inefficiency at all?** Before anything that counts units
   or money is reported, three safeguards run: a residual screening rule without
   a quota, a curvature check and an evidence gate. When the cross-section does not
   establish inefficiency, the report says so and withholds efficiencies, savings
   and efficiency-gap recommendations.
2. **How efficient is each unit, and how sure are we?** A Bayesian stochastic cost
   frontier gives every unit a posterior distribution of cost efficiency, credible
   intervals and a rank distribution instead of a single point.
3. **Where does the money go?** Observed cost is decomposed into frontier cost, a
   stochastic component and excess cost; savings at a target efficiency come with
   credible intervals, next to the assumptions they rest on and their sensitivity
   to those assumptions.
4. **What is associated with excess cost?** A second-stage model with Shapley
   attributions ranks operational metrics (failure rates, asset age, length of stay,
   staff turnover) and says when they carry no reliable signal. Its findings are
   reported as associations, not causes.
5. **Which records should be checked first?** Units whose cost is far from what
   their frontier variables imply are set aside, scored against the frontier of
   the others and listed as data-quality items, with a checklist and a scenario of
   the saving if the records prove real.
6. **Which savings can be defended, and at what cost to quality and capital?** The
   savings become a portfolio: an expected saving weighted by the probability that
   each unit is below the target, the amount reached with 95 % probability, and
   baskets (secure, large but uncertain, conditional on quality, other, to verify).
   Savings of units whose quality (for example SAIDI and SAIFI) is among the worst
   are not counted. With a capital cost in the data the same frontier is fitted to
   total cost (TOTEX), which shows capitalisation and deferred renewals; every
   saving comes with the investment it pays back, and cost components separate the
   controllable part of the excess.

The result is a traceable, quantified list of recommendations, a **client report**
(one HTML file with charts, findings and an action plan, printable to PDF), an
**analyst workbook** (Excel), JSON and Markdown, in English or Polish. Forecasting of
OPEX series (exponential smoothing with back-test selection) is included.

The methodology and its validation are described in *A. B. Brill, "Explainable
Bayesian Cost-Frontier Analytics for Operational Expenditure Benchmarking: Method,
Monte Carlo Validation and Empirical Applications", brillQ & LastHuman R&D Lab
technical paper (preprint), 2026* (ResearchGate). Version 2.0 implements the
safeguards and the sampler that the paper recommends.

A Polish README (`README.pl.md`), a Polish user guide (`docs/guide.pl.md`) and the
full documentation (`docs/`) are included in the source distribution.

---

## Installation

```bash
# core (numpy, scipy, pandas, scikit-learn, pydantic, cryptography, tabulate)
pip install brillq-opex-benchmark

# recommended: XGBoost + SHAP explanations and Excel export
pip install "brillq-opex-benchmark[ml,excel]"

# everything (adds the PyMC/ArviZ NUTS backend and statsmodels forecasting)
pip install "brillq-opex-benchmark[all]"
```

Python 3.10 or newer. No compiled extensions; the wheel is platform-independent.
Earlier releases were distributed as `brillq-opex-analytics` (2.0) and `brillq-opex`
(1.x). All of them install the same package `brillq_opex`, so uninstall the old one
first (`pip uninstall brillq-opex-analytics brillq-opex`), then install
`brillq-opex-benchmark` and replace the name in requirement files. Code, the command
and licence keys stay as they are; for the changes of 2.0 see `docs/migration-2.0.md`
in the source distribution.

### Try it first

```bash
brillq-opex demo                                     # 100 network areas of a utility, full report
brillq-opex demo --sector hospitals --language pl    # also: branches, plants, subsidiaries
brillq-opex demo --report demo.html                  # the client report: open it in a browser
```

The demonstration panels are synthetic, with known inefficiency, two gross cost
errors and two true drivers among the operational metrics. The output ends with
this known truth, so the estimates can be checked against it. The panels run in full
in evaluation mode; in Python they are `generate_demo_panel("hospitals").panel`.

### Licence activation

Without a key the library runs in **evaluation mode** (all features, at most 30
units per analysis of your own data, evaluation notice; the built-in demonstration
panels run in full). Keys are verified offline; keys issued for 1.x remain valid.

```bash
brillq-opex license "BQOPEX-..." --save     # stores the key in ~/.brillq/opex.lic
# or
export BRILLQ_OPEX_LICENSE_KEY="BQOPEX-..."
```

```python
import brillq_opex
brillq_opex.activate("BQOPEX-...")          # per process
print(brillq_opex.license_status().describe())
```

Commercial licences: **hello@brillq.today**. The terms are in `LICENSE.txt`, included in the package.

---

## Quick start

```python
import pandas as pd
from brillq_opex import CostPanel, OpexAnalyzer

df = pd.read_csv("units.csv")                  # one row per unit
panel = CostPanel.from_dataframe(
    df,
    cost_col="annual_opex",
    driver_cols=["customers", "network_km", "stations"],      # outputs and scale variables
    condition_cols=["service_area_km2"],                      # conditions the units cannot choose
    indicator_cols=["urban"],                                 # 0/1 conditions
    price_cols=[],                                            # input-price indices, if any
    metric_cols=["failure_rate", "asset_age", "utilisation", "overtime_share"],
    id_col="unit_id", group_col="region",
)

report = OpexAnalyzer(target_efficiency=0.90, currency="PLN", language="en",
                      sector="dso", seed=42).run(panel)
print(report.summary())                         # status, evidence gate, results, reliability notes

report.status                  # "established" | "not_established" | "gate_off"
report.safeguards.table()      # screening, curvature check, evidence gate
report.screening               # residual, robust z-score and decision for every unit
if not report.withheld:
    report.efficiency          # posterior mean, equal-tailed and highest-density intervals, ranks
    report.decomposition.table # efficient vs excess cost with intervals
    report.savings             # savings at the target efficiency
    report.sensitivity         # the same figures under other priors and the other law
report.recommendations         # data-quality items first, then quantified items per unit
report.to_html("opex_report.html")    # client report (see Reports below)
report.to_excel("opex_report.xlsx")   # analyst workbook
```

When the evidence gate is closed, `report.withheld` is true, `report.ols` holds the
OLS cost function and `report.portfolio_summary` the statement that the
cross-section does not establish inefficiency.

Command line:

```bash
brillq-opex demo --sector hospitals --excel demo.xlsx     # Excel export needs the [excel] extra
brillq-opex sectors dso --language pl
brillq-opex analyze units.csv --cost-col annual_opex \
    --drivers customers network_km stations --conditions service_area_km2 --indicators urban \
    --metrics failure_rate asset_age utilisation --id-col unit_id --language pl --excel report.xlsx
brillq-opex analyze units.csv --cost-col opex --drivers customers network_km \
    --conditions service_area_km2 forest_share --capex-col capex --quality SAIDI SAIFI \
    --quality-limit SAIDI 150 --components own_labour contracted_services shared_services \
    --noncontrollable shared_services --group-col group --group-note "quartiles of customer density" \
    --report report.html
```

### Reports

`report.to_html("report.html")` writes the **client report**: one self-contained HTML
file for management (no external resources; it works offline and can be sent by
e-mail). It opens with the key figures, the findings and where to start, then shows
the whole analysis in charts: the evidence of inefficiency, the efficiency of every
unit with its interval, where the money goes, the savings by unit, robustness, what
goes with higher cost, peer groups, profiles of the units with the largest potential
and an action plan by unit, followed by data quality, the method and a sortable table
of all units. With the decision layer it adds the savings portfolio (baskets, the
defensible amount, the quality condition and the scenario of the records to verify),
investment and total cost (TOTEX ranks, flags and the break-even investment), cost
components, benchmark profiles of the peer groups and the limits of the method.
Every chart has a table view and tooltips; the browser's *Print* gives an A4 PDF.

```python
report.to_html("opex_report.html", client="Client name", logo="client_logo.png")
report.to_excel("opex_report.xlsx")       # analyst workbook
report.to_markdown("opex_report.md")      # the client report as text
```

The **analyst workbook** follows the report language: a summary with the key figures,
findings and native charts, then the portfolio (baskets, scenario and a decision
table of every unit), every unit, the action plan, TOTEX, cost components, drivers
and their per-unit contributions, peer groups and benchmark profiles, sensitivity,
data quality, the model and the input data. Numbers stay numbers, headers are frozen and filterable.
`to_excel(path, layout="data")` writes the raw tables, one per sheet, as in 2.0.

```bash
brillq-opex demo --language pl --report demo.html
brillq-opex analyze units.csv ... --report report.html --client "Client name" --logo logo.png
```

### Data requirements

| Column type | Role | Meaning | Requirements |
|---|---|---|---|
| cost | | operating cost of the unit for one period | > 0, same currency, period and cost scope for all units |
| outputs and scale variables | `scale` | what the unit has to serve: customers, cases, transactions, network length | > 0 (they enter in logarithms) |
| conditions | `condition` | what the unit cannot choose: service area, case mix, product mix, location type | > 0; 0/1 conditions via `indicator_cols` |
| input-price indices | `price` | regional wage index, energy prices, where units buy at different prices | > 0 |
| metrics (optional) | | controllable indicators used to *explain* inefficiency | finite |
| group (optional) | | peer group (region, segment) for benchmark items | any label; state how the groups were formed with `notes={"groups": ...}` |
| capital cost (optional) | `capex_col` | annual capital cost (depreciation and return), for the TOTEX view | >= 0 for every unit |
| quality (optional) | `quality_cols` | quality indicators such as SAIDI and SAIFI; lower is better unless `quality_better` says `"higher"` | finite; > 0 to enter the frontier |
| cost components (optional) | `component_cols` | parts of the cost (own labour, contracted services, ...); `noncontrollable_cols` marks those outside the unit's control | >= 0, adding up to the cost |

Only scale variables enter the cost elasticity of scale, the size index of the
curvature check and the cost intensities of the anomaly screen. A variable that the
management of a unit cannot influence and that legitimately changes cost belongs in
the frontier; left out, or moved to the metrics, it is read as inefficiency.
`brillq-opex sectors` prints typical specifications for five kinds of organisations.

Rule of thumb: at least 30 units and 8 to 10 units per frontier variable. With fewer
than about 60 units the priors carry considerable weight and the evidence gate has
little power; the report says so.

---

## What the analysis does

Log cost is modelled as a stochastic cost frontier

```
ln C_i = b0 + b' z_i + v_i + u_i,      v_i ~ N(0, s_v^2),   u_i >= 0  (half-normal or exponential)
```

with `z_i` the standardised logarithms of the frontier variables. Cost efficiency
is `exp(-u_i)`. The pipeline runs:

1. **Residual screening** (no quota): units whose OLS residual has a robust z-score
   above 3.5 in absolute value are set aside, on either side.
2. **Curvature check**: a squared size index is added to the frontier and kept if the
   95 % interval of its coefficient excludes zero.
3. **Evidence gate**: the skewness test of the OLS residuals under the final
   specification must reject the absence of inefficiency at the 5 % level.
4. **Bayesian frontier** on the units that remain, by adaptive random-walk Metropolis
   on the posterior with the inefficiencies integrated out; units set aside are
   scored against it.
5. **Decomposition, efficiency, savings**, with equal-tailed intervals by default.
6. **Second stage** (drivers of inefficiency) behind its reliability gate.
7. **Recommendations**: data-quality items first; efficiency-gap, driver and peer
   items only when the evidence gate is open.
8. **Sensitivity and reliability notes**: refits under a prior median efficiency of
   0.70 and 0.95 and under the other inefficiency law; notes on weak signals, small
   panels, a narrowly open gate, size-dependent residual spread and convergence.
9. **Decision layer**: the posterior draws of the savings become a portfolio
   (expected and 5 % quantile, baskets, scenario of the records set aside,
   break-even investment over `capex_horizon` years at `discount_rate`), with the
   quality condition (`quality_tail`, `quality_limits` or `quality_in_frontier`),
   cost components and, when every unit has a capital cost, the same frontier on
   TOTEX with flags for capitalisation, deferred renewal and an OPEX gap offset by
   low capital cost. Recommendation priorities follow the baskets.

Priors are proper and weakly informative; the hyper-parameter a user normally sets
is the *prior median efficiency* `r*` (default 0.85). Baselines (`mle_fit`,
`cols_fit`) implement maximum likelihood with JLMS / Battese-Coelli efficiencies and
Horrace-Schmidt intervals, and corrected OLS. `backend="gibbs"` runs the
data-augmentation sampler of 1.x and `backend="nuts"` the same model in PyMC.

Details, assumptions and references: `docs/methodology.md`; API: `docs/api.md`;
Polish user guide: `docs/guide.pl.md` (all in the source distribution).

---

## Package layout

```
brillq_opex/
  data.py            CostPanel / UnitRecord (validated inputs, roles, size index, design matrix)
  synthetic.py       generators with known ground truth (panels of the paper, demonstration panels)
  safeguards.py      screening, curvature check, evidence gate, OLS cost function, evidence statistics
  frontier/
    model.py         BayesianCostFrontier (backends marginal | gibbs | nuts)
    marginal.py      adaptive random-walk Metropolis on the marginal posterior (default)
    gibbs.py         data-augmentation Gibbs sampler with partially collapsed refresh
    pymc_backend.py  optional NUTS backend
    priors.py        PriorConfig (half-Cauchy priors elicited by medians)
    likelihood.py    composed-error density, exact draws of u
    mle.py           ML (JLMS, Battese-Coelli, Horrace-Schmidt), COLS
    diagnostics.py   split R-hat, ESS (also vectorised), Geweke, MCSE, HDI
    results.py       FrontierResult (summaries, intervals, decomposition, scoring new units)
  decomposition.py   CostDecomposition (efficient / excess cost, savings at target)
  sensitivity.py     prior_sensitivity (refits under alternative assumptions)
  efficiency_ml.py   EfficiencyDriverModel (ridge or boosting + SHAP, reliability gate)
  anomaly.py         AnomalyDetector (residual, robust-z, Isolation Forest, ensemble; no quota)
  recommend.py       RecommendationEngine (EN/PL, whole-word action templates)
  sectors.py         sector templates (DSO, branches, plants, subsidiaries, hospitals)
  forecasting.py     OpexForecaster (Holt-Winters family, back-test, bootstrap intervals)
  pipeline.py        OpexAnalyzer / AnalysisConfig / AnalysisReport
  report.py          Excel / JSON / Markdown export
  licensing.py       offline Ed25519 licence keys, evaluation mode
  cli.py             brillq-opex command
```

## Support

E-mail: hello@brillq.today. Web: https://brillq.today
© 2026 brillQ sp. z o.o. All rights reserved. This software is licensed, not sold; see `LICENSE.txt`.
