# Saved parameter experiments



Use `runtime.optimize` to save a complete Portfolio for every parameter combination to a local SQLite file. Reopen that file to rank, filter, or inspect reports without rerunning strategies. Use [Backtest.optimize](https://docs.openbacktesting.com/reference/core/index.md#find-a-parameter-combination) if you only need the best run and a score grid.

[Values](https://docs.openbacktesting.com/reference/optimizer/#openbacktesting-optimizer-values) · [Range](https://docs.openbacktesting.com/reference/optimizer/#openbacktesting-optimizer-range) · [ExecutionIdentity](https://docs.openbacktesting.com/reference/optimizer/#openbacktesting-optimizer-executionidentity) · [open_result](https://docs.openbacktesting.com/reference/optimizer/#openbacktesting-optimizer-open-result) · [ExperimentResult](https://docs.openbacktesting.com/reference/optimizer/#openbacktesting-optimizer-experimentresult) · [OptimizationError](https://docs.openbacktesting.com/reference/optimizer/#openbacktesting-optimizer-optimizationerror) · [plan](https://docs.openbacktesting.com/reference/optimizer/#openbacktesting-optimizer-plan) · [Plan](https://docs.openbacktesting.com/reference/optimizer/#openbacktesting-optimizer-plan) · [execute](https://docs.openbacktesting.com/reference/optimizer/#openbacktesting-optimizer-execute)

## Run and query an experiment

Save this complete example as `experiment.py`, then run `python experiment.py`. The temporary directory gives each invocation a new result file; replace it with a new persistent path to retain the experiment.

```python
import hashlib
import tempfile
from pathlib import Path
from openbacktesting import Strategy, backtest, inputs, runtime, DataContext, Timeframe
from openbacktesting.broker import InstrumentSpec
from openbacktesting.optimizer import ExecutionIdentity, Range, open_result
from openbacktesting.test import GOOG

@backtest()
class Experiment(Strategy):
    quantity = inputs.int(1, title="Quantity", minval=1)

    def init(self):
        pass

    def next(self):
        if self.bar_index == 0:
            self.buy(qty=self.quantity)
        elif self.bar_index == 10:
            self.position.close()

if __name__ == "__main__":
    data = GOOG.iloc[:30].copy()
    data.index = data.index.tz_localize("UTC")
    identity = ExecutionIdentity(
        strategy_sha256=hashlib.sha256(Path(__file__).read_bytes()).hexdigest(),
        dependencies_sha256=hashlib.sha256(b"no local dependencies").hexdigest(),
    )
    with tempfile.TemporaryDirectory() as directory:
        path = Path(directory) / "experiment.db"
        saved = runtime.optimize(
            globals(), {"Quantity": Range(1, 3, 1)}, path=path, identity=identity,
            data=data, context=DataContext(Timeframe.days(1), "UTC"),
            instrument=InstrumentSpec(symbol="GOOG"),
        )
        reopened = open_result(path)
        ranking = reopened.query(order_by=["summary.all.totalReturn.value"])
        print(ranking)
        trial = ranking["rows"][0]
        report = reopened.load_portfolio(trial["trial_id"])
        print(report["summary"]["all"]["totalReturn"])
```

## Choose search domains

Search keys are unique **input titles**, not Python attribute names. `Values([10, 20, 40])` supplies explicit choices. `Range(5, 25, 5)` supplies an integer grid, including the stop only if it lies on the grid. Use decimal strings for exact float ranges, e.g. `Range("0.1", "0.3", "0.1")`. Empty domains, duplicates, and invalid candidates are rejected.

Parameters not in `search` use the current `request` (from `inputs.request_for`) or declaration defaults. Every candidate starts a fresh account. This interface retains Portfolios but disables plot/log history; it does not automatically choose or rerun a winner.

## Execution arguments

| Argument | Meaning |
| --- | --- |
| `namespace`, `data`, `context`, `instrument` | Same loaded strategy and chart arguments as [runtime.run](https://docs.openbacktesting.com/reference/runtime/index.md). |
| `path` | New local database path. Use resume for an existing experiment. |
| `identity` | `ExecutionIdentity` with SHA256 digests of the strategy source and its local dependencies. Include all code that affects the strategy. |
| `request`, `settings` | Current input request and sparse backtest setting overrides. |
| `constraint` | Optional predicate receiving complete serialized input values and returning bool. Requires a stable `constraint_id`. False records a skipped candidate. |
| `cancel` | Optional zero-argument callable; returning True stops dispatch after the in-flight candidate completes. |
| `on_progress` | Called after a candidate commits. Its event includes `trial_id`; committed reports are already readable. |

The library checks data/settings/environment identity on resume. Call `runtime.resume_optimization(namespace, path=path, experiment_id=saved.experiment_id, identity=identity, data=data, context=context, instrument=instrument, ...)` with the same current inputs/settings/constraint. Changed material requires a new experiment. Successful, failed, and skipped candidates are not automatically rerun; interrupted or undispatched work can continue.

## Inspect results

| Method | Result and arguments |
| --- | --- |
| `info()` | Experiment metadata and counts. |
| `trials(limit=100, offset=0)` | Visited candidate records with `trial_id`, `state`, and any `error`, including failures. |
| `fields()` | Queryable scalar paths, units, and suggested sort direction. |
| `query(order_by=..., filters=..., fields=..., limit=100, cursor=None)` | A page of ranked/filtered candidates. Limit is 1..1000. |
| `load_portfolio(trial_id)` | One successful candidate's complete report. |
| `backup(destination)` | Safe database copy, including committed work while a run is active. |

For explicit sorting, use `order_by=[("summary.all.totalReturn.value", "desc")]`. Filters are `(path, operator, value)` tuples; operators include `eq`, `ne`, `lt`, `le`, `gt`, `ge`, and `status`. `fields` selects scalars to return. Null values sort last. Use the returned cursor for the next page; restart without it to include newer commits.

<a id="openbacktesting-optimizer-values"></a>



## Values

```python
optimizer.Values(values)
```

Finite candidate values; plan validates against the corresponding input declaration.

| Attribute | Type | Meaning |
| --- | --- | --- |
| <a id="openbacktesting-optimizer-values-values"></a>`values` | `tuple \| list` | Explicit candidate values. |

<a id="openbacktesting-optimizer-range"></a>



## Range

```python
optimizer.Range(start, stop, step)
```

Ascending grid range; int uses integers, float/price uses decimal strings or integers.

| Attribute | Type | Meaning |
| --- | --- | --- |
| <a id="openbacktesting-optimizer-range-start"></a>`start` | `int \| str` | First grid value. |
| <a id="openbacktesting-optimizer-range-stop"></a>`stop` | `int \| str` | Inclusive upper bound when it falls exactly on the grid. |
| <a id="openbacktesting-optimizer-range-step"></a>`step` | `int \| str` | Positive grid increment. |

<a id="openbacktesting-optimizer-executionidentity"></a>



## ExecutionIdentity

```python
optimizer.ExecutionIdentity(strategy_sha256, dependencies_sha256)
```

Host declaration of SHA256 digests for loaded source and local dependencies; no files are loaded or executed.

| Attribute | Type | Meaning |
| --- | --- | --- |
| <a id="openbacktesting-optimizer-executionidentity-strategy-sha256"></a>`strategy_sha256` | `str` | SHA256 digest of the executed strategy source. |
| <a id="openbacktesting-optimizer-executionidentity-dependencies-sha256"></a>`dependencies_sha256` | `str` | SHA256 digest identifying its local code dependencies. |

<a id="openbacktesting-optimizer-open-result"></a>



## open_result

```python
optimizer.open_result(path, experiment_id=None)
```

Open an experiment result database read-only, without strategy or market-data dependencies.

<a id="openbacktesting-optimizer-experimentresult"></a>



## ExperimentResult

Reopenable read-only result handle; each access uses an independent connection without live strategy references.

| Attribute | Type | Meaning |
| --- | --- | --- |
| <a id="openbacktesting-optimizer-experimentresult-path"></a>`path` | `str` | Local experiment database path. |
| <a id="openbacktesting-optimizer-experimentresult-experiment-id"></a>`experiment_id` | `str` | Identifier of the experiment in that database. |

<a id="openbacktesting-optimizer-experimentresult-backup"></a>



### ExperimentResult.backup

```python
ExperimentResult.backup(destination)
```

Create a consistent backup in a new local file; reject overwriting existing files.

<a id="openbacktesting-optimizer-experimentresult-fields"></a>



### ExperimentResult.fields

```python
ExperimentResult.fields()
```

Return scalar paths, types, units, statuses, methods, and suggested sort directions.

<a id="openbacktesting-optimizer-experimentresult-info"></a>



### ExperimentResult.info

```python
ExperimentResult.info()
```

Return experiment status, category counts, and an immutable plan copy.

<a id="openbacktesting-optimizer-experimentresult-load-portfolio"></a>



### ExperimentResult.load_portfolio

```python
ExperimentResult.load_portfolio(trial_id)
```

Validate and load one complete report; explicitly reject failures and corruption.

<a id="openbacktesting-optimizer-experimentresult-query"></a>



### ExperimentResult.query

```python
ExperimentResult.query(*, order_by=(), filters=(), fields=(), limit=100, cursor=None)
```

Query scalar values and parameters for successful trials; cursors freeze the commit range, and new queries refresh it.

<a id="openbacktesting-optimizer-experimentresult-trials"></a>



### ExperimentResult.trials

```python
ExperimentResult.trials(*, limit=100, offset=0)
```

Browse live statuses of all visited trials by page, without complete Portfolios.

<a id="openbacktesting-optimizer-optimizationerror"></a>



## OptimizationError

Experiment infrastructure error preserving result location, identity, and last known committed count.

An `OptimizationError` identifies the path, experiment, and last known committed count. A failed strategy is recorded as a failed candidate; a storage failure stops the experiment. Already committed results remain available for inspection.

## Advanced: supply your own executor

Most users should call `runtime.optimize`. If integrating a separate executor, `plan(strategy_class, search, base_inputs=..., execution=..., constraint_id=...)` validates and freezes the search. `execution` supplies the execution identity mapping; `base_inputs` is the title-based input request. A `Plan` exposes `.total` and `.snapshot()`.

`execute(plan_value, executor, path, ...)` calls your executor for each input request; it must return the complete Portfolio report. Supply `experiment_id` to resume the matching plan. Cancellation, progress, and constraints have the same role as above. See the [complete runtime example](https://docs.openbacktesting.com/repository/examples/advanced/optimizer_results.py/index.md) for the supported default path.

<a id="openbacktesting-optimizer-plan"></a>



## plan

```python
optimizer.plan(strategy_class, search, *, base_inputs=None, execution, constraint_id=None)
```

Freeze complete current configuration and selected dimensions; the host must explicitly supply execution identity.

<a id="openbacktesting-optimizer-plan"></a>



## Plan

Immutable canonical text; snapshot returns an independent copy, and combinations are generated incrementally at runtime.

### Attributes

| Attribute | Meaning |
| --- | --- |
| <a id="openbacktesting-optimizer-plan-total"></a>`total` | Raw Cartesian-product count, without deducting constraints not yet checked. |

<a id="openbacktesting-optimizer-plan-snapshot"></a>



### Plan.snapshot

```python
Plan.snapshot()
```

Return an independent JSON copy of the complete plan.

<a id="openbacktesting-optimizer-execute"></a>



## execute

```python
optimizer.execute(
    plan_value,
    executor,
    path,
    *,
    experiment_id=None,
    constraint=None,
    cancel=None,
    on_progress=None,
)
```

Execute or resume a plan; executor receives title-based requests and returns complete Portfolio dictionaries.

[Portfolio](https://docs.openbacktesting.com/reference/portfolio/index.md) · [Runtime](https://docs.openbacktesting.com/reference/runtime/index.md) · [User manual](https://docs.openbacktesting.com/index.md)
