Skip to content

fastboxex.connection

Connection is the trading channel for one sub-user. Obtained from p.connection(), arena.connect_generator(), or arena.connect_trader(i).


Activation

conn.activate(asset_id)

Must be called once per asset before any fills are routed to this connection. Required for both live trading and arena connections.


Order submission

submit_limit(asset_id, side, price, qty, *, client_tag=0) → None

Post a passive limit order at the given price.

conn.submit_limit(asset_id, side=0, price=999_900, qty=100, client_tag=42)
Parameter Type Description
side int 0 = BUY, 1 = SELL
price int Raw ticks
qty int Quantity (multiple of lot_size)
client_tag int Optional identifier echoed in acks/fills

submit_market(asset_id, side, qty) → None

Sweep the book at any price. Rejected if the opposite side is empty.

conn.submit_market(asset_id, side=0, qty=100)

submit_delta(asset_id, side, delta_ticks, qty, *, client_tag=0) → None

Price-relative order. Effective price = BBO ± delta_ticks × tick_size. Rests if only partially filled.

conn.submit_delta(asset_id, side=0, delta_ticks=2, qty=100)  # 2 ticks inside BBO
conn.submit_delta(asset_id, side=0, delta_ticks=0, qty=100)  # touch (at best bid)

submit_ioc(asset_id, side, delta_ticks, qty, *, client_tag=0) → None

Same as submit_delta but cancels any unfilled remainder immediately.


Cancellation

conn.cancel_all(asset_id)                                   # both sides
conn.cancel_all(asset_id, side=0)                           # bids only
conn.cancel_by_tag(client_tag, asset_id, side=0)            # by tag
conn.cancel_worse_than(asset_id, side=0, ref_price=999_000) # clear inferior quotes

Draining events

Both methods are non-blocking and return all pending events since the last call.

drain_fills() → list[dict]

Returns fill events. Key fields:

Key Type Description
ts int Nanosecond timestamp
price int Fill price (raw ticks)
volume int Filled quantity
side int 0=BUY fill, 1=SELL fill
is_maker bool True if this order was passive
client_tag int Tag from the original submission
asset_id int Asset

drain_acks() → list[dict]

Returns order acknowledgements. Key fields:

Key Type Description
status int 1=New/OK, 6=PendingNew, other=rejected
client_tag int Tag from submission
reject_reason int \| None Non-zero if rejected

Properties

Property Type Description
conn.user_id int Sub-user ID
conn.label str Human-readable label
conn.role str "Generator", "Trader", or "Joiner"

Polars export

fills_df = conn.fills_to_polars(asset_id)    # → Polars DataFrame or None
acks_df  = conn.acks_to_polars(asset_id)

Columns: ts, price, volume, side, is_maker, client_tag, asset_id.

Zero-copy tensor path

import numpy as np

mv  = conn.fills_as_tensor()               # PyMemoryView — zero-copy
arr = np.frombuffer(mv, dtype=np.uint8)    # no allocation

LOB access (live exchange only)

Arena context

conn.lob() is only populated in live exchange connections, not in arena connections. In arena scripts, use p.arena_market().get_latest(asset_id) instead.

# Live exchange:
lob = conn.lob(asset_id=1)
print(lob.best_bid, lob.best_ask, lob.spread)

# Arena:
md  = arena_market.get_latest(arena.asset_id)
mid = (md["bid"] + md["ask"]) // 2

UserLOB

Returned by conn.lob() and conn.rebuild_lob().

Property Type Description
lob.best_bid int \| None Best bid price (raw ticks)
lob.best_ask int \| None Best ask price (raw ticks)
lob.spread int \| None best_ask - best_bid
lob.is_crossed bool True if bid ≥ ask
lob.is_empty bool True if both sides are empty