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.
On this page
Quickstart
From project to report#
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.
| Parameter | Default | Description |
|---|---|---|
| start / end | — | UTC 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. |
| frequency | 1h | Bar and decision frequency. OPR aggregates supported data to this interval; the strategy runs only at timestamps available on that grid. |
| universe | — | Choose 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_coin | USD | Frozen denomination: USD/BTC/ETH/SOL/XRP. |
| accounts | 1 account | One to 16 isolated accounts with their own initial_assets. |
| instrument_account_map | single account: optional | Exact candidate routes; mandatory for multiple accounts. |
| leverage_max | 3x | Maximum 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_bps | 2 bps | Backtest 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_fee | 1 bps | Fee 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_fee | 4 bps | Fee 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.
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.
passOne-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.