Skip to main content

EOIL compute optimisation SDK

Project description

EOIL Python SDK

Python client for the EOIL optimisation API.

Version: 0.5.0 — beta. API is stable.

Installation

pip install eoil

Requires Python ≥ 3.10. NumPy is optional but recommended — the SDK passes np.ndarray to your objective function when it's installed, otherwise list[float].

Authentication

Get an API key from app.eoil.ltdAPI Keys.

import eoil

client = eoil.Client(api_key="eoil_sk_...")

# Or set the environment variable EOIL_API_KEY and omit api_key=

1. Custom objective functions (stream_optimize)

Run your own Python function against the EOIL optimizer. Your code never leaves your machine — only candidate coordinate vectors and scalar values cross the network.

def rosenbrock(x):
    # x is np.ndarray (if numpy installed) or list[float]
    f = (1 - x[0])**2 + 100*(x[1] - x[0]**2)**2
    grad = [
        -2*(1 - x[0]) - 400*x[0]*(x[1] - x[0]**2),
        200*(x[1] - x[0]**2),
    ]
    return f, grad   # return (f, grad) to supply gradient directly

result = client.stream_optimize(
    rosenbrock,
    dimension=2,
    budget_steps=500,
    bounds=(-5.0, 5.0),
)

print(result.x_best)       # [1.0, 1.0]        best solution found
print(result.f_best)       # ~0.0              best objective value
print(result.converged)    # True / False
print(result.steps)        # int               evaluations consumed
print(result.eoil_charged) # "5.0"             compute units charged

Gradient options

gradient= Behaviour
"auto" (default) Inspect return type on first call — tuple → use grad; scalar → finite differences
True Function must return (f, grad). Raises StreamError if it returns a scalar.
False Always use finite differences, even if function returns a tuple.

When finite differences are used, the SDK prints a one-time warning and costs 2 × dimension extra function calls per step. Supply an analytic gradient to avoid this.

Live progress

def on_step(step, x, f_best):
    if f_best is not None:
        print(f"step {step:4d} | f_best={f_best:.6f}")

result = client.stream_optimize(
    my_fn,
    dimension=10,
    budget_steps=1000,
    on_step=on_step,
)

All parameters

Parameter Default Description
fn required Objective function. Returns float or (float, list[float]).
dimension required Problem dimensionality (1–1000).
budget_steps 1000 Approximate number of function evaluations (100–100 000).
bounds (-5.0, 5.0) Box bounds (lower, upper) applied uniformly.
x0 None Initial point. Server picks randomly if omitted.
gradient "auto" Gradient supply mode — see table above.
fd_step 1e-5 Finite-difference step size.
on_step None Callback on_step(step, x, f_best) called after each evaluation.
timeout_s 3600.0 Total session wall-clock timeout in seconds.
eval_timeout_s 80.0 Per-evaluation timeout. Raises if function exceeds this.
verify_ssl True Set False for staging or self-signed certs.

2. Catalogue (client.catalogue)

Run built-in optimisation problems — no objective function needed.

Benchmark functions

result = client.catalogue.rastrigin(dimension=20, budget_steps=1000)
result = client.catalogue.sphere(dimension=10, budget_steps=500)
result = client.catalogue.rosenbrock(dimension=15, budget_steps=2000)
result = client.catalogue.ackley(dimension=10, budget_steps=1000)
result = client.catalogue.levy(dimension=10, budget_steps=1000)
result = client.catalogue.griewank(dimension=10, budget_steps=1000)
result = client.catalogue.quadratic(dimension=10, budget_steps=1000)

Portfolio optimisation

import numpy as np

# Maximise Sharpe ratio — pass a (T × N) returns matrix
returns = np.random.randn(252, 5) * 0.01  # 252 trading days, 5 assets
result = client.catalogue.portfolio_sharpe(
    returns=returns,
    dimension=5,
    budget_steps=2000,
)
weights = result.x_best  # portfolio weights, sum to 1

# Minimise portfolio variance — pass an (N × N) covariance matrix
cov = np.cov(returns.T)
result = client.catalogue.portfolio_minvol(
    cov=cov,
    dimension=5,
    budget_steps=2000,
)

Plain Python nested lists are accepted wherever NumPy arrays are shown.

Available catalogue methods

Method Description
catalogue.sphere() Convex, global min at origin
catalogue.rastrigin() Highly multimodal
catalogue.rosenbrock() Narrow curved valley
catalogue.quadratic() Coupled quadratic (ill-conditioned)
catalogue.ackley() Many local minima
catalogue.levy() Global min at x=(1,…,1)
catalogue.griewank() Regularly spaced local minima
catalogue.portfolio_sharpe() Maximise Sharpe ratio
catalogue.portfolio_minvol() Minimise portfolio variance

3. Optimizer presets

Presets are heuristics_override dicts tuned for common scenarios.

from eoil import PRESETS, get_preset

result = client.catalogue.rastrigin(
    dimension=50,
    budget_steps=5000,
    heuristics_override=PRESETS["thorough"],
)

# get_preset() returns a copy — safe to modify
opts = get_preset("portfolio")
opts["escape_strength"] = 0.8
result = client.catalogue.portfolio_sharpe(
    returns=returns,
    dimension=5,
    budget_steps=3000,
    heuristics_override=opts,
)
Preset Best for
fast CI checks and quick feasibility runs
balanced General-purpose (default)
thorough Production-quality results
portfolio Sharpe ratio and minimum-variance problems
ml_hyperparam Machine learning hyperparameter search
high_dimensional Problems with dimension ≥ 100

4. Async job submission

# Submit and get a job ID immediately
job_id = client.submit_job(objective_type="ackley", dimension=20)

# Retrieve the result later (polling)
result = client.get_job(job_id)

5. Result object

Both stream_optimize() and catalogue methods return a result object with these fields:

Field Alias Description
x_best .x Best solution vector found
f_best .f Best objective value
converged Whether the optimizer declared convergence
total_steps .steps Evaluations consumed
eoil_charged Compute units charged (stream_optimize only)

6. Error handling

from eoil import (
    AuthError,
    InsufficientBalanceError,
    RateLimitError,
    StreamError,
    SessionExpiredError,
    EoilError,
)

try:
    result = client.stream_optimize(my_fn, dimension=10, budget_steps=500)
except AuthError:
    print("Invalid or missing API key — check app.eoil.ltd → API Keys")
except InsufficientBalanceError:
    print("Insufficient compute balance")
except RateLimitError:
    print("Rate limit hit — retry shortly")
except SessionExpiredError:
    print("Session expired — try again")
except StreamError as e:
    print(f"Stream error [{e.code}]: {e}")
except EoilError as e:
    print(f"API error: {e}")

What's New in 0.5.0

  • eoil.adapters.scipy — drop-in replacement for scipy.optimize.minimize
  • eoil.adapters.sklearnEOILSearchCV replaces GridSearchCV / RandomizedSearchCV
  • eoil.adapters.pytorchEOILOptimizer for nn.Module training loops
  • eoil.adapters.pandasEOILPortfolioOptimizer for portfolio optimisation on pd.DataFrame
  • Promoted to Beta — all adapters tested against production API

Development

# Install in editable mode with dev dependencies
pip install -e ".[dev]"

# Run tests (no API key needed — HTTP and WebSocket are mocked)
pytest tests/ -v

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

eoil-0.5.1.tar.gz (47.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

eoil-0.5.1-py3-none-any.whl (35.6 kB view details)

Uploaded Python 3

File details

Details for the file eoil-0.5.1.tar.gz.

File metadata

  • Download URL: eoil-0.5.1.tar.gz
  • Upload date:
  • Size: 47.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for eoil-0.5.1.tar.gz
Algorithm Hash digest
SHA256 b07b67674a65d1bc1ad25bbc409958d1cfa48c3d553e2428acfd25a68587612b
MD5 430882ab89c3e9f859db4747348681c1
BLAKE2b-256 d0a85a44adbb2196bbb85cf52787bebc1d735f38a04f6acb9a90123ec0f2b0b5

See more details on using hashes here.

Provenance

The following attestation bundles were made for eoil-0.5.1.tar.gz:

Publisher: publish.yml on EOIL-TEAM/EOIL-PYTHON

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file eoil-0.5.1-py3-none-any.whl.

File metadata

  • Download URL: eoil-0.5.1-py3-none-any.whl
  • Upload date:
  • Size: 35.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for eoil-0.5.1-py3-none-any.whl
Algorithm Hash digest
SHA256 136509bbfd0ded273bdbd3e780b900747f07c998aee456e42e85ed5eb1b78fc6
MD5 3773737a524d4117cb5a2d5baf4d7167
BLAKE2b-256 00937f84f8bcb9ce80b0e1d740e9cdb4aa6eae90d65094a26fcf670c88f316f3

See more details on using hashes here.

Provenance

The following attestation bundles were made for eoil-0.5.1-py3-none-any.whl:

Publisher: publish.yml on EOIL-TEAM/EOIL-PYTHON

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page