Odys
Optimize energy portfolios under uncertainty.
Features
- Optimization under uncertainty: Stochastic optimization is the default, not an afterthought. Multi-asset, multi-market from day one with built-in CVaR risk management.
- Multi-solver support: Swap between HiGHS (default), Gurobi, CPLEX, or SCIP with a single configuration change.
- Simple API: Define your assets, describe the uncertainty through scenarios, and call
.optimize(). No boilerplate, no configuration files. - Transparent math: Every constraint and objective term is documented with equations. You know exactly what the solver sees.
Why Odys?
In energy systems, deterministic optimization is no longer enough. You need to account for multiple possible futures simultaneously, maximizing expected profit while managing risk.
Odys makes stochastic optimization for energy portfolios as straightforward as possible. Define your assets, describe the uncertainty through scenarios, and let the solver find the optimal dispatch across all possible outcomes.
Whether you're a student learning energy optimization, a researcher prototyping new models, or building decision support tools for industry, Odys lets you focus on the problem instead of the math.
Installation
pip:
pip install odys
uv:
uv add odys
Odys requires a recent and currently supported version of Python. If you use a commercial solver, install the matching extra as well. See Solvers for details.
Quick example
Suppose you have a generator and a fixed demand over 4 hours. How much should the generator produce at each timestep?
First, create a generator with a variable cost and a load representing the demand:
from datetime import timedelta
from odys import AssetPortfolio, EnergySystem, Generator, Load, Scenario
generator = Generator(name="gen", nominal_power=100.0, variable_cost=50.0)
load = Load(name="demand")
Wire them into a portfolio and tell the EnergySystem what demand looks like over time:
portfolio = AssetPortfolio([generator, load])
energy_system = EnergySystem(
portfolio=portfolio,
scenarios=Scenario(load_profiles={"demand": [60, 90, 40, 70]}),
timestep=timedelta(hours=1),
number_of_steps=4,
)
Call .optimize() and look at the results:
result = energy_system.optimize()
print(result.generators.power)
The generator meets demand at every timestep:
time generator
0 gen 60.0
1 gen 90.0
2 gen 40.0
3 gen 70.0
Name: generator_power, dtype: float64
Add a second generator with a different cost, and the solver will use the cheaper one first and only call on the expensive one when necessary.
See the documentation for the full workflow, or check the examples for complete worked scenarios.
Dependencies
- Pydantic — Data validation and settings management
- linopy — Linear optimization modeling
- HiGHS — High-performance optimization solver
- pandas — Data analysis and manipulation
- xarray — Multi-dimensional arrays
All dependencies are installed automatically when you install odys.
Contributing
For guidance on setting up a development environment and how to make a contribution to odys, see Contributing to odys.
License
Odys is licensed under the MIT License.
Metadata
Release files for odys 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| odys-0.2.0.tar.gz | 28.8 kB | Without provenance | Details for odys-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| odys-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for odys-0.2.0-py3-none-any.whl |
Total release size: 75.7 kB
Release files / odys-0.2.0.tar.gz
| Download URL | odys-0.2.0.tar.gz |
|---|---|
| Size | 28.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bcb6e2396bc3e4f74ca122eb8737677af715bacf9e5175a393c37084c489caac
|
|
BLAKE2b-256 checksum How to use checksums |
b9547f294a38030c7831394cb4b6802398c2e1018bd8b8a9fecbf8cec2eab852
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / odys-0.2.0-py3-none-any.whl
| Download URL | odys-0.2.0-py3-none-any.whl |
|---|---|
| Size | 46.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
035d75f4ab86c8aaa53d146382728eb97d61119ae84cdea8facce3c8bf52ed34
|
|
BLAKE2b-256 checksum How to use checksums |
526640ec1fe18ccbd1bc509357c9704c23dfc8add2f7baca415fa7f7391bc53c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for odys 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.