HiveQ Flow
API Reference
Institutional-grade quantitative trading and backtesting — in a few lines of Python. You author the strategy on your machine; HiveQ runs it on the engine that has executed billions of dollars in live trades — sourcing the data, simulating real market microstructure, and handing back a full performance report.
python -m pip install --upgrade "hiveq-sdk==1.0.2.1"
python -c "import importlib.metadata as m; print(m.version('hiveq-sdk'))"HiveQ Video Setup Guide.
Learn HiveQ without leaving Docs. Move from a clean Python environment and secure sign-in to a reviewed strategy, a completed backtest, and evidence you can explain.
Install and Sign In to HiveQ
Create an isolated Python environment, install the public HiveQ SDK, complete secure browser authentication, and verify the session.
python -m venv .venvpython -m pip install hiveq-sdkhiveq loginNine steps. One evidence trail.
Follow the same supported workflow in text. The core journey ends with a completed, understood backtest; competition is an optional next step.
Install and sign in
Create an isolated Python environment, install the public HiveQ SDK, and complete the secure browser sign-in.
python -m venv .venv
source .venv/bin/activate
python -m pip install hiveq-sdk
hiveq login- Use Python 3.11 or newer.
- Let the CLI complete the secure browser handoff.
- Never copy API keys or token files into strategy code.
Overview
Install hiveq-sdk on your machine and author strategies through its hiveq.flow namespace. The local client captures and submits your strategy; HiveQ then runs its callbacks in the managed engine, sources the declared data, and returns a Run handle for results. Direct local data discovery is a separate hiveq_data workflow—not something to call from a strategy callback.
Why HiveQ
- A simulator built to mirror production. Orders clear against real market microstructure — tick-level data, exchange session windows, primary-exchange auctions, per-asset fee models, slippage, and tick-size rounding.
- Research → live, same code. The strategy you backtest runs unchanged in paper and live trading — promote a validated backtest from the platform in one click.
- Every run tracked & versioned. Strategy code and config are captured per run, so any backtest is reproducible — inspect the exact code behind a result and build from it.
- Production execution algos built in. POV, TWAP, and open/close auctions — the same algorithms used in live trading, not approximations.
- Multi-asset, multi-strategy. Equities, futures (continuous contracts with automatic rollover), and options down to 0DTE — together in one backtest, with TCA and PDF tearsheets out of the box.
The model in one minute
- One class, callback methods. Implement only the events you care about —
on_start,on_bar,on_order, and more. - Subscribe in
on_start. The callback runs once per calendar day; repeated identical subscriptions are deduplicated. Guard any truly one-time setup with instance state. - Fills arrive in
on_order— there is no separate fill callback; checkorder.is_filled. - Time is U.S. Eastern.
ctx.now()and every timestamp are already in market time (ET) — no timezone math.
hiveq-sdk 1.0.2.1 · import root hiveq.flow · Python >=3.11. (Don't install the separate hiveq-flow engine package alongside it — same namespace.) This reference covers backtest authoring, reading results, and remote deploy. Live trading is out of scope here.Choose your HiveQ surface
HiveQ uses related package and namespace names for different jobs. Pick one path before copying an example. For a normal strategy and backtest, stay in the first two columns: install hiveq-sdk, import hiveq.flow, and let the managed runtime execute the callbacks.
hiveq-sdk
The package researchers install. It provides login, dataset discovery, the Flow authoring API, submission, and result handles.
hiveq.flow
The strategy namespace inside hiveq-sdk. Define the class locally; run_backtest packages and submits it to HiveQ.
Managed engine
ctx, event callbacks, entitled market data, fills, and analytics exist here. The full hiveq-flow engine package is platform-only.
hiveq_data
A standalone client for discovery, historical queries, streams, and publishing outside a Flow strategy callback.
hiveq-flow locally. That is the full engine distribution used by the managed executor and it shares the hiveq.flow namespace. A researcher installs only hiveq-sdk, unless an approved direct-data workflow explicitly calls for the separate hiveq_data package.Data Access
Inside a HiveQ Flow strategy, declare data in data_configsand subscribe through ctx; the managed HiveQ engine retrieves it under the authenticated account's entitlements. Outside a strategy, use the dataset CLI for bounded discovery or the standalone hiveq_data client for an explicitly approved direct-data workflow. Never call hiveq_data from a strategy callback.
Declare the dataset.
Use the installed Flow reference and one confirmed dataset/schema in data_configs.
Entitlements decide access.
Available datasets and schemas follow the authenticated HiveQ account—not a public catalog promise.
HiveQ retrieves the data.
The remote engine sources the declared data and preserves one reproducible run contract.
Auction imbalance feeds
Auction imbalances describe the buy/sell pressure around an exchange opening or closing auction. Use them for auction research and execution logic—not as ordinary intraday bars. When the authenticated account is entitled to this data, HiveQ exposes four logical HIVEQ_US_EQ schemas. Each delivers an ImbalanceData event to on_imbalance during the venue's available publication window:
{'type':'hiveq_historical','dataset':'HIVEQ_US_EQ','schema':['early_imbalance']}
{'type':'hiveq_historical','dataset':'HIVEQ_US_EQ','schema':['arca_imbalance']}
{'type':'hiveq_historical','dataset':'HIVEQ_US_EQ','schema':['nasd_imbalance']}
{'type':'hiveq_historical','dataset':'HIVEQ_US_EQ','schema':['nyse_imbalance']}None. If the strategy places MOO, MOC, LOO, or LOC orders, also subscribe to the appropriate tick-by-tick trade schema: aggregated bars_* contain no auction print and cannot fill an auction order.Standalone data client
SDK 1.0.2.1 also ships authoring stubs for the public standalone hiveq_data 0.2.9 surface. Use this only when your workflow explicitly needs direct historical discovery, publishing, or a live/replay stream outside a Flow strategy.
from hiveq_data import Historical, InstrumentReference, Publisher, LiveStream
ref = InstrumentReference()
futures = ref.get_futures(
symbols=['ES.v.0', 'NQ.v.0'],
start_date='2025-06-01', end_date='2025-06-30',
)
publisher = Publisher() # async_mode=True by default
# publisher.publish(...)
publisher.flush() # or publisher.close() before process exit
stream = LiveStream()
# stream.subscribe(..., keys=[...], replay=True, from_ts=..., to_ts=...)
stream.close()Install & Sign-in
python -m pip install --upgrade "hiveq-sdk==1.0.2.1"
python -c "import importlib.metadata as m; print(m.version('hiveq-sdk'))"
hiveq loginhiveq login performs the supported one-time browser sign-in before dataset discovery or direct-data work. You may also skip that command and start a backtest; the first run_backtest opens the same browser flow automatically and waits while you sign in. Every later command reuses the saved access—there is no key to copy into code.
Quickstart
This file contains both sides of the boundary. The class is authored on your machine; its callbacks and ctx execute in the managed HiveQ engine. The guarded main() stays on the client, submits the source through run_backtest, waits for the remote run, and reads the report.
import hiveq.flow as hf
from hiveq.flow import StrategyConfig
from hiveq.flow.config import AssetType
from hiveq.flow.logger import logger as _get_logger
logger = _get_logger() # module-level — REQUIRED in every strategy
class BuyAndHold:
def __init__(self):
self.bought = False
def on_start(self, ctx, event):
ctx.subscribe_bars(ctx.strategy_config.symbols,
asset_type=AssetType.EQUITY, interval='1m')
logger.info(f"[START] subscribed 1m bars for {ctx.strategy_config.symbols}")
def on_bar(self, ctx, event):
bar = event.data() # -> SigmaBar
logger.debug(f"[BAR] {bar.symbol} {bar.time} close={bar.close:.2f} bought={self.bought}")
if not self.bought and ctx.is_flat(bar.symbol):
logger.info(f"[ENTRY] buying 100 {bar.symbol} at {bar.close:.2f}")
ctx.buy_order(bar.symbol, quantity=100)
self.bought = True
def on_order(self, ctx, event): # fills come HERE, not on_order_filled
order = event.data() # -> SigmaOrder
logger.info(f"[ORDER] {order.symbol} status={order.status} filled={order.is_filled}")
if order.is_filled:
fill = order.last_fill # -> SigmaFill
def main():
# run_backtest submits from the client and returns a Run HANDLE.
run = hf.run_backtest(
strategy_configs=[StrategyConfig(name='BuyAndHold', type='BuyAndHold')],
symbols=['AAPL'],
start_date='2025-08-01',
end_date='2025-08-31',
# the managed HiveQ engine retrieves this declared source
data_configs=[{'type': 'hiveq_historical', 'dataset': 'HIVEQ_US_EQ',
'schema': ['bars_1m']}],
)
print(f"run {run.run_id} task {run.task_id}")
run.wait(progress=False) # wait for the remote terminal state
report = run.report() # -> PerformanceReport
print(report.return_stats.to_string())
if __name__ == '__main__':
main()StrategyConfig.type is the class name as a string (must match exactly), and run_backtest(...) returns a Run handle — call run.report() for results. Every strategy must also use the HiveQ logger throughout its callbacks and decision branches. Keep client submission behind the standard if __name__ == '__main__' guard so importing the bundled strategy source cannot submit another run.Strategy Contract
A strategy is a plain Python class with per-event callback methods, each with the signature (self, ctx, event). Define only the handlers you need.
class MyStrategy:
def __init__(self): ... # per-strategy state
def on_start(self, ctx, event): ... # subscribe here
def on_bar(self, ctx, event): ... # event.data() -> SigmaBar
def on_order(self, ctx, event): ... # fills/rejects/cancels -> SigmaOrder
def on_position(self, ctx, event):... # event.data() -> SigmaPosition
def on_timer(self, ctx, event): ... # event.data() -> TimerEventData
def on_rollover(self, ctx, event):... # futures contract rollRecognized callbacks
on_start, on_stop, on_bar, on_trade, on_quote, on_snap, on_order, on_position, on_timer, on_custom_data, on_index_price (alias on_index), on_rollover, on_imbalance, on_executor, on_security_event. Unknown method names are ignored. on_imbalance delivers an ImbalanceData from the auction imbalance feed. Configure early_imbalance, arca_imbalance, nasd_imbalance, or nyse_imbalance in data_configs; on_executor (EXECUTOR_EVENT) and on_security_event (SECURITY_EVENT) carry opaque payloads.
on_order_filled — fills are delivered to on_order. Don't place orders in on_stop; the engine has already stopped and rejects them.Required strategy instrumentation
Every strategy must create the HiveQ logger at module level and instrument every callback and decision branch. Use logger.debug(...) for per-bar state and condition checks; use logger.info(...) for signals, orders, and fills. The default engine level is WARNING, so healthy runs remain quiet even though the diagnostic context is already in the strategy.
from hiveq.flow.logger import logger as _get_logger
logger = _get_logger() # module level — never logging.getLogger(__name__)
# Required coverage:
# on_start -> subscriptions/config (INFO)
# on_bar -> time, price, state, every condition outcome (DEBUG)
# order placement + on_order -> side, quantity, reason, status/fill (INFO)logging.getLogger(__name__) or logging.basicConfig; the executor silences them. Do not leave a hiveq_log_level override in normal or delivered code — enable it only for a diagnostic re-run.Order lifecycle contract (FIX-style: status ≠ events)
order.status is the order's state; events are the history. Terminal statuses (FILLED / CANCELED / REJECTED) are sticky — later request-level events never change them. The canonical race: you cancel a resting order but a fill lands while the cancel is in flight → you receive ORDER_FILLED first (the fill is never lost), then ORDER_CANCEL_REJECTED ("too late to cancel"). order.status reads FILLED on both.
- Act on fills from the
ORDER_FILLEDevent, using the cumulativefilled_qty/leaves_qty(idempotent). - Treat
ORDER_CANCEL_REJECTED/ORDER_MODIFY_REJECTEDas informational no-ops whenorder.is_filled— do not count them toward reject/error limits. ORDER_REJECTEDis reserved for the order itself being rejected (entry rejects); it never fires for cancel/replace request rejections.- An order canceled after a partial fill ends
CANCELEDwithfilled_qty > 0. - Never infer disposition from the last event — use
order.status/filled_qty.
on_order_filled — fills arrive on on_order; check order.is_filled / order.status / order.last_fill.Context API — ctx
Everything you do at runtime goes through ctx (a SigmaContext): subscribe to data, place & manage orders, query positions, read the clock, and run managed executors.
Subscriptions (call in on_start)
ctx.subscribe_bars(symbols, asset_type=AssetType.EQUITY, interval='1m')
ctx.subscribe_trades(symbols) # tick prints (asset_type defaults to EQUITY)
ctx.subscribe_quotes(symbols) # bid/ask (asset_type defaults to EQUITY)
ctx.subscribe_option_snaps('SPY', expiration_type='0dte') # '0dte' | 'YYYY-MM-DD' | datetime
# futures bars: use the canonical symbol + interval API; one call per interval
ctx.subscribe_bars(['ES.v.0', 'NQ.v.0'], asset_type=AssetType.FUTURES, interval='1s')
ctx.subscribe_bars(['ES.v.0', 'NQ.v.0'], asset_type=AssetType.FUTURES, interval='1m')
ctx.subscribe_futures_trades(symbols=['ES.v.0'])
# custom / quant signals — data_id must match the 'id' in data_configs
ctx.subscribe_data(data_id='mysignals') # -> on_custom_datasubscribe_trades and subscribe_quotes share the same symbol-keyed instrument registration. Repeating either—or calling both for the same symbol—is idempotent and does not duplicate events. Use exactly one overlapping tick schema per symbol in data_configs.ctx.subscribe_futures_quotes — futures bars use subscribe_bars(..., asset_type=AssetType.FUTURES), while trades retain their dedicated convenience method. For futures NBBO quotes use ctx.subscribe_quotes(['ES.v.0'], asset_type=AssetType.FUTURES). Continuous symbols use ROOT.roll.rank: .c.0 selects a calendar-based front contract and .v.0 selects a volume-based front contract. Both roll rules are supported for every root; choose the rule that matches the strategy rather than inferring it from the product.Order placement
ctx.buy_order(symbol, quantity, order_type=OrderType.LIMIT, limit_price=px)
ctx.sell_order(symbol, quantity) # exit long
ctx.short_order(symbol, quantity, time_in_force='DAY') # open short
# sizing helpers (off the current net position)
ctx.close_position(symbol) # flatten one symbol (no-op if flat)
ctx.order_to_target(symbol, 100) # signed target: +long / -short / 0
ctx.flatten_all() # close every position in this strategyclose_position / order_to_target / flatten_all) are idempotent — they skip if a working order already exists for the symbol, so they're safe to call every bar. buy_order/sell_order/short_order have no such guard — calling them every bar stacks orders. Round your own limit_price/stop_price to the instrument tick with adjust_tick_size(symbol, px).Order management & queries
ctx.cancel_order(order_id)
ctx.modify_order(order_id, limit_price=..., stop_price=...)
ctx.cancel_all_orders(symbol)
ctx.net_position(symbol) # signed float (+long / -short / 0)
ctx.is_flat(symbol) # bool
ctx.has_open_order(symbol) # bool
ctx.now() # ET datetime (time is ALWAYS U.S. Eastern)
ctx.set_timer('poll', timedelta(minutes=1)) # fires on_timerExecutors — managed order working (POV / TWAP / VWAP / AUCTION)
An executor is a server-side algo that owns a target's full lifecycle — slicing the parent quantity, repricing, replacing/cancelling, and aggregating fills. Reach for one when execution quality matters (large sliced orders, live order-chasing, auction routing); for a simple one-shot market order, a direct buy_order is simpler.
params = ctx.build_executor_params(
symbol='AAPL', quantity=1000, side='BUY',
executor_type='POV', participate_pct=10, # work at 10% of volume
)
handle = ctx.add_executor(params) # start it (None if it failed)
ctx.executor_state(handle) # "PARTIALLY_FILLED" | "FILLED" | ...
# re-target IN PLACE — never add a second executor for the same target:
eid = str(handle.executorID)
ctx.replace_executor_params_by_id(eid, new_params)ctx.subscribe_trades(...) (schema eq_trades/fut_trades). Keep one handle per target.Events & Payloads
Each callback receives an event; call event.data() for the payload. The concrete type depends on event.type:
event.type # EventType (branch on this)
event.data() # payload object (type depends on event.type)
event.time # ET datetime
event.ts_event # int nanosecondsPayload types
SigmaBar—symbol, open, high, low, close, volume, interval, timeSigmaOrder— status/fills plusis_sell_short, is_executor_order, strategy_id, router_idSigmaFill—order_id, leaves_qty, order_qty, exec_type, market_centerplus execution/price/fee fields (viaorder.last_fill)SigmaPosition— P&L pluslast_price, long_notional, short_notional, max_exposure, total_fill_qtySigmaTradeTick— normalizedexchange/market_center/conditionplus raw venue/condition fieldsSigmaQuoteTick— bid/ask plus normalized exchange fields, condition, andis_validSigmaSnapData— options snapshot (strike, option_type, bid_px, ask_px, is_valid)SigmaCustomData— custom/CSV rows; read columns withcolumn_data(name)(values are strings — cast yourself; quant signals arrive as asignal_jsoncolumn)Rollover—continuous_symbol, prev_contract, current_contractImbalanceData— auction imbalance record fromearly_imbalance,arca_imbalance,nasd_imbalance, ornyse_imbalance:symbol, side(normalized venue state),imbalance(signed for NYSE),paired_shares, ref_price?, near_price?, far_price?, clearing_price?(NYSE),cont_book_clearing_price?, closing_only_clearing_price?, market_imbalance?(Arca),cross_type?('O'/'C'/'A', Nasdaq),transaction_type?, exchange?, ts_event, ts_init, time?/time_utc?— venue-specific optional fields areNonewhen not meaningfully published
Results & Reports
run_backtest(...) returns a Run handle — your single accessor for status and results, local or remote.
run.report() # -> PerformanceReport
run.positions() # positions over time (DataFrame)
run.orders() # complete order history (DataFrame)
run.trades() # executed trades (DataFrame)
run.fills() # executed order fills (DataFrame)
run.daily_returns() # daily P&L (DataFrame)
run.tearsheet() # -> '<run>.pdf' in the cwd (PDF, the default)
run.tearsheet(output='report.html') # explicit HTML file (format from the extension)
# silent=True is the DEFAULT — run_backtest deploys and returns the Run immediately:
run = hf.run_backtest(...)
run.wait(progress=False) # block quietly until terminal (no tqdm bar)
report = run.report()
# reattach later from any machine (results outlive your Python process):
report = hf.get_run(run.run_id).wait(progress=False).report()run_backtest(...) always returns a Run handle, never a bare report. silent=True is the default (deploy and return immediately); silent=False blocks with a live progress bar (interactive only). Calling run.wait() without progress=False renders a tqdm bar that pollutes captured/scripted output — always pass progress=False in scripted or agent-driven runs.run.report() is the only output you need. Do not poll status, stream progress, or fetch run.logs() / run.event_logs() routinely. If a run misbehaves, re-run once with config={'hiveq_log_level': 'DEBUG'}, inspect run.logs(), then remove the override before delivering the strategy.PerformanceReport
report = run.report()
print(report.return_stats.to_string()) # Sharpe, Sortino, vol, drawdown, win rate
total_trades = report.stats.get('Total Trades', 0) # one metric by name
stats = report.summary_stats() # dict: Sharpe, CAGR, Max Drawdown, ...
html = report.create_tearsheet() # inline HTML string (Jupyter/Marimo) — to save a file use run.tearsheet()fills, orders, …) can be None/empty — always guard before use. Tearsheets and summary_stats() are powered by quantstats, bundled with the SDK. Reader endpoints default to a 100k-row limit (raise hiveq_data_page_size for very dense schemas like options), so long backtests aren't silently truncated.run.report() backfills positions, orders, and trades from their dedicated endpoints. run.fills() and report.fills are derived from executed orders, so all four report tables match their corresponding run.*() accessors.report.stats.get('Total Trades', 0); if it is zero or implausibly low, diagnose the entry logic and re-run until the strategy trades realistically within the requested window.Function Registry
A versioned store of reusable Python callables that live on the platform. Write a function once, push_function it (with its requirements and a semver version), then fetch and run it from any script or machine by name and version.
import hiveq.flow as hf
def zscore(series, window=20):
"""Rolling z-score."""
import numpy as np
return (series[-1] - np.mean(series[-window:])) / np.std(series[-window:])
# register once with your chosen semantic version...
FUNCTION_VERSION = "MAJOR.MINOR.PATCH"
hf.push_function(zscore, version=FUNCTION_VERSION, requirements=["numpy"])
# ...then load it back and run it on the platform from anywhere:
fn = hf.load_function("zscore", version=FUNCTION_VERSION)
hf.run_function(fn, [1, 2, 3, 4, 5], window=3, requirements=["numpy"]) # -> valuenamespace="default" is the shared/public namespace. Treat cross-namespace permissions as subject to change.Markets & Examples
Equities, futures (incl. continuous contracts with automatic rollover), options, and your own custom data feeds. Each is demonstrated by a complete, runnable example in the SDK's examples/ directory.
# Futures: subscribe to a continuous contract; rollover is automatic.
class Breakout:
def on_start(self, ctx, event):
ctx.subscribe_bars(['ES.v.0'], asset_type=AssetType.FUTURES, interval='1m')
def on_rollover(self, ctx, event):
roll = event.data() # Rollover: prev_contract -> current_contract
run = hf.run_backtest(
strategy_configs=[StrategyConfig(name='Breakout', type='Breakout')],
symbols=['ES.v.0'],
start_date='2024-01-01', end_date='2024-03-01',
data_configs=[{'type': 'hiveq_historical', 'dataset': 'HIVEQ_US_FUT',
'schema': ['bars_1m']}],
backtest_config=BacktestConfig(enable_auto_rollover=True),
)Enums & Config
Imports cheat-sheet
import hiveq.flow as hf
from hiveq.flow import StrategyConfig, BacktestConfig, EngineConfig, AssetType, get_run
from hiveq.flow.config import EventType, EventLogType, OMSType
from hiveq.flow.logger import logger as _get_logger
from hiveq.flow.trading_types import OrderType, OrderSide, OrderStatus, MarketCenter
from hiveq.flow.trading.price_utils import adjust_tick_size, get_min_tickKey enums
AssetType:EQUITY · OPTIONS · FUTURES · CRYPTO · INDEXOrderType:MARKET · LIMIT · STOP · STOP_LIMIT · MOO · MOC · LOO · LOCOrderSide:BUY · SELL·OrderStatus:PENDING · SUBMITTED · ACCEPTED · REJECTED · CANCELED · FILLED · PARTIALLY_FILLED
BacktestConfig (key fields)
BacktestConfig(
initial_capital=1_000_000.0,
commission=0.001,
equity_fee=0.0011, # per share
futures_fee=0.5, # per contract
session_start=None, # asset default: equity 04:00, futures 18:00 ET
session_end=None, # asset default: equity 18:30, futures 17:00 ET
enable_auto_rollover=False,
auto_flatten_at_close=False, # force-close non-option positions at session close
enable_tca=False,
)18:30 ET. Keep the session open beyond 16:00 so resting MOC and closing-cross orders can fill against the official close print.Pitfalls & Patterns
HiveQ Flow is deliberately lean on authoring conveniences — these are the things that are easy to get wrong, and the idioms to handle them.
- No built-in indicators or history buffer — keep your own
collections.dequewindow and compute with numpy/pandas. - Each run has a 2 GB memory limit. Keep per-event state bounded with
deque(maxlen=N), running counters, or last-value maps; never accumulate every bar, order, fill, payload, or a growing DataFrame onself. The engine already records those artifacts for post-run access. - No native brackets/OCO — place protective child orders on fill in
on_orderand cancel siblings yourself. - No percent-of-equity sizing — size in fixed quantity (or off
ctx.portfolio().equityand a price you track). - Timestamps
ts_event/ts_initare nanoseconds — use.time/ctx.now()for datetimes. - Set
symbols/start_date/end_datein one place (top-level args OR BacktestConfig), not both. - On a continuous-futures subscription,
bar.symbolis the resolved outright contract (e.g.ESZ5), never theES.v.0string you subscribed with — soif bar.symbol != 'ES.v.0'silently drops every bar. Key off the root, or place orders onbar.symboldirectly. - End-of-day flatten is opt-in, not automatic — set
BacktestConfig(auto_flatten_at_close=True)to force-close non-option positions at session close (options settle automatically regardless).
Bracket / stop-loss + take-profit
def on_order(self, ctx, event):
o = event.data()
if o.is_filled and o.symbol == self.entry_symbol and not self.protected:
entry = o.avg_px
ctx.sell_order(o.symbol, quantity=o.filled_qty,
order_type=OrderType.STOP, stop_price=entry * 0.98)
ctx.sell_order(o.symbol, quantity=o.filled_qty,
order_type=OrderType.LIMIT, limit_price=entry * 1.04)
self.protected = True
# when one leg fills, cancel_all_orders(symbol) to emulate OCOReady to prove your alpha?
Build, optimize, deploy, and scale — on institutional-grade infrastructure.
Get Early Access