Skip to content
DOCUMENTATION / Quickstart

OnePort Research documentation

Research starts in a versioned project. A project may contain one Python file or a complete source tree with pinned Factor versions. Backtests execute that immutable project version through the opbt SDK; each run records its own dates, universe, parameters and cost assumptions.

01Versioned projects
02Point-in-time data
03Reproducible reports
On this page
01

Quickstart

From project to report#

01
Create a projectStart blank or copy a maintained example. Keep one entrypoint and add modules or folders when the strategy grows.
02
Build the researchEdit the source tree, pin reusable factor versions, then freeze the draft you want to run.
03
Configure and runChoose instruments, dates, frequency, base coin, versioned simulated accounts, exact routes, leverage, fees and slippage. Submit one backtest or a batch study from Run.
04
Review the reportThe report keeps the results together with the frozen source, parameters, data range, logs and engine version.

Run configuration reference#

These values become part of the run configuration. The table shows the current Run-panel defaults; REST and MCP clients should still send every research assumption explicitly.

ParameterDefaultDescription
start / endUTC half-open interval [start, end): start is included and end is excluded. End cannot be in the future. Resource admission governs long runs; if admission is disabled, the fallback maximum span is 1,095 days.
frequency1hBar and decision frequency. OPR aggregates supported data to this interval; the strategy runs only at timestamps available on that grid.
universeChoose an exchange, product type and official symbol. Backtest and Paper currently support SPOT and linear UPERP when K-line data is available for the selected period. Order, fill and position quantities are always coin amounts. CPERP is not available for execution yet; older runs remain available for review but cannot be restarted.
base_coinUSDFrozen denomination: USD/BTC/ETH/SOL/XRP.
accounts1 accountOne to 16 isolated accounts with their own initial_assets.
instrument_account_mapsingle account: optionalExact candidate routes; mandatory for multiple accounts.
leverage_max3xMaximum estimated gross exposure after an order, divided by equity in the reporting currency. The range is above 0 and up to 10x; the default is 3x. Orders that would increase exposure above the limit are rejected, while reducing orders remain allowed. Simulations do not model liquidation.
slippage_bps2 bpsBacktest applies this adverse price adjustment at the next decision bar's open. Paper instead reads the current OnePort best bid and ask when an order is submitted; it does not use a K-line price as the quote. Unit: bps (1 bp = 0.01%); range 0–1,000.
maker_fee1 bpsFee charged on passive limit-fill notional. Unit: bps; range 0–1,000. Enter the research assumption explicitly rather than relying on a venue default.
taker_fee4 bpsFee charged on market-fill notional. Unit: bps; range 0–1,000. It is recorded separately from modelled slippage.
params{}A JSON object exposed to strategy code as ctx.params. Keys and meanings are defined by the project; values must be finite JSON and the encoded object must not exceed 64 KiB. Fixed and searched parameter names cannot overlap.

Instrument format#

Instruments use venue:TYPE:SYMBOL, for example binance:UPERP:BTCUSDT. Symbols keep each venue's native naming. The Run panel reads the executable venue, product and symbol combinations from the data catalog.

Dynamic universe#

A dynamic run selects venue and product-type boundaries instead of a hand-written symbol list. Preflight shows the catalog instruments that can execute and cover the requested window. If that result changes before submission, refresh the preview and confirm the universe again. The confirmed candidate set stays fixed during the run.

strategy.py
from opbt import Strategy

class DailySelectionStrategy(Strategy):
    def initialize(self, ctx):
        # Full immutable candidate set resolved at submission.
        ctx.log.info("candidates=%s", len(ctx.candidate_universe))

    def select_universe(self, ctx, candidates):
        # Called on each frozen DAILY or EVERY_N_BARS decision. candidates contains
        # only frozen instruments with a bar at that decision timestamp.
        history = ctx.history_many(candidates, fields="quote_volume", window=24)
        ranked = sorted(
            candidates,
            key=lambda instrument: float(history[instrument]["quote_volume"].sum()),
            reverse=True,
        )
        return ranked[:10]

    def handle_bar(self, ctx, bars):
        # bars and ctx.universe contain only the active selection for this day.
        pass

One-shot notebooks#

An .ipynb file runs as a bounded Notebook Job: all Python cells execute once in order, outputs are stored in an immutable executed-notebook snapshot, and the process exits. There is no persistent kernel, terminal, shell magic or network access. Notebook Jobs can import saved project modules and locked packages. Stored output is capped at 256 KiB per cell and 2 MiB per display job; runtime errors remain visible when earlier output is truncated. Use backtests and Factor Evaluation whenever the research needs OPR point-in-time market data.

ONEPORT RESEARCH · DOCUMENTATION