Skip to content

Decorated strategies and runtime

View Markdown

Use @backtest plus runtime.run when a strategy file should carry its default execution settings. For a script or notebook that constructs the run itself, Backtest is the shorter path.

backtest · discover · describe · run · RunLogs · CommissionType · QuantityType · SlippageType · ExecutionTiming · EndPolicy · optimize · resume_optimization

Define and run a decorated strategy

from openbacktesting import (
    Strategy, backtest, runtime, DataContext, Timeframe, EndPolicy,
)
from openbacktesting.broker import InstrumentSpec
from openbacktesting.test import GOOG

@backtest(cash=10_000, commission_value=0.2,
          end_policy=EndPolicy.CLOSE_AT_LAST_CLOSE)
class HoldOne(Strategy):
    def init(self):
        pass

    def next(self):
        if self.bar_index == 0:
            self.buy(qty=1)

data = GOOG.copy()
data.index = data.index.tz_localize("UTC")
description = runtime.describe(globals())
result = runtime.run(
    globals(), data=data, context=DataContext(Timeframe.days(1), "UTC"),
    instrument=InstrumentSpec(symbol="GOOG"),
)
print(result["Return [%]"])

Here commission_value=0.2 means 0.2%, whereas the direct Backtest argument is commission=0.002. A declaration stores settings without running the strategy. runtime.run adopts them; plain Backtest does not.

Decorator settings

Setting Values and units
cash, spread, margin, risk_free_rate Initial balance, fractional execution spread, margin fraction, and annualized statistics rate. See Backtest.
commission_type, commission_value CommissionType.PERCENT uses percentage points; CASH_PER_ORDER uses fee per fill; CASH_PER_CONTRACT uses fee per asset unit.
default_qty_type, default_qty_value QuantityType.FIXED uses asset units; PERCENT_OF_EQUITY uses (0, 100], e.g. 20 for 20%. None requires explicit order sizing.
slippage_type, slippage_value SlippageType.BPS uses basis points; FIXED uses price distance.
execution_timing ExecutionTiming.NEXT_OPEN or SAME_CLOSE.
end_policy EndPolicy.MARK_TO_MARKET or CLOSE_AT_LAST_CLOSE.
allow_short, max_gross_exposure, hedging, exclusive_orders Trading controls described on Backtest.

Use the enums imported from openbacktesting in decorators. Strategy parameters belong in inputs, not decorator settings. Instrument rules and timeframe come from the data supplied for each run.

Runtime arguments and discovery

namespace is the loaded module mapping (globals() in the example, or vars(module)). It must contain exactly one concrete strategy directly decorated in that module. runtime.discover(namespace) returns the class; runtime.describe(namespace) returns its input schema and settings without running it.

runtime.run argument What to pass
request Optional title-based input request from inputs.request_for; omit to use defaults.
data, context, instrument Required chart data, timezone/timeframe, and asset rules. Data must have an aware DatetimeIndex.
settings Sparse dictionary overriding declaration settings, e.g. {"cash": 20000}. Changing a quantity/cost type requires its value too.
options Optional indicator_cache_bytes, plotting, and plotting_limits controls.
logs Optional RunLogs() to retain logs when execution raises.

The result is the same statistics Series as Backtest.run, with effective settings in result.attrs["backtest_snapshot"]. runtime runs an already loaded module; loading arbitrary Python executes code and should be limited to scripts you trust.

For a separate strategy file, load it as an importable Python module, then pass vars(module). The file runner example demonstrates this from a source checkout.

backtest

backtest(
    *,
    cash=10000,
    spread=0.0,
    commission_type=CommissionType.PERCENT,
    commission_value=0.0,
    risk_free_rate=0.0,
    default_qty_type=QuantityType.FIXED,
    default_qty_value=None,
    margin=1.0,
    execution_timing=ExecutionTiming.NEXT_OPEN,
    slippage_type=SlippageType.BPS,
    slippage_value=0.0,
    allow_short=True,
    max_gross_exposure=None,
    hedging=False,
    exclusive_orders=False,
    end_policy=EndPolicy.MARK_TO_MARKET,
)

Attach default backtest settings to a concrete strategy class; the host supplies actual market data and execution.

discover

runtime.discover(namespace)

Discover the single concrete strategy directly decorated in this module; deduplicate aliases and exclude imported and inherited entry points.

describe

runtime.describe(namespace)

Export inputs and complete default backtest settings without market data or executing the strategy lifecycle.

run

runtime.run(
    namespace,
    request=None,
    *,
    data,
    context,
    instrument,
    settings=None,
    options=None,
    logs=None,
)

Run a new session for this chart and return existing results plus backtest_snapshot.

RunLogs

RunLogs()

Host-owned single-run log session, injected through runtime.run(..., logs=session).

RunLogs.get_logs

RunLogs.get_logs()

Return an independent copy of all logs from this run; an empty list before the first run.

Create logs = RunLogs(), pass it to runtime.run(..., logs=logs), and read logs.get_logs() after success or in an exception handler. Reusing it for another run clears the previous records.

Setting enums

CommissionType

Author-facing commission type; PERCENT uses percentage points, and other members use account amounts.

Member Value
CommissionType.PERCENT percent
CommissionType.CASH_PER_ORDER cash_per_order
CommissionType.CASH_PER_CONTRACT cash_per_contract

QuantityType

Default order size: Fixed asset quantity or a percentage of equity at request time.

Member Value
QuantityType.FIXED fixed
QuantityType.PERCENT_OF_EQUITY percent_of_equity

SlippageType

Slippage distance: Fixed price units or basis points of price.

Member Value
SlippageType.FIXED fixed
SlippageType.BPS bps

ExecutionTiming

Execution timing: Process no earlier than the next bar, or process new unconditional market orders at this bar's close.

Member Value
ExecutionTiming.NEXT_OPEN next_open
ExecutionTiming.SAME_CLOSE same_close

EndPolicy

End policy: Retain marked positions or liquidate actual positions at the final close.

Member Value
EndPolicy.MARK_TO_MARKET mark_to_market
EndPolicy.CLOSE_AT_LAST_CLOSE close_at_last_close

Parameter experiments

runtime.optimize saves every candidate's Portfolio; runtime.resume_optimization continues an existing experiment with matching inputs, source identity, and market data. See saved experiments for a complete example and argument meanings.

optimize

runtime.optimize(
    namespace,
    search,
    *,
    path,
    identity,
    data,
    context,
    instrument,
    request=None,
    settings=None,
    constraint=None,
    constraint_id=None,
    cancel=None,
    on_progress=None,
)

Exhaustively search selected inputs sequentially, committing each complete Portfolio to a new local result database.

resume_optimization

runtime.resume_optimization(
    namespace,
    *,
    path,
    experiment_id,
    identity,
    data,
    context,
    instrument,
    request=None,
    settings=None,
    constraint=None,
    constraint_id=None,
    cancel=None,
    on_progress=None,
)

Resume unfinished trials after checking current declarations, inputs, and execution identity; failed trials are not automatically retried.

Data and instruments · Strategy parameters · User manual