Skip to content

Arenas

Arenas are private, ephemeral matching engines you create on demand for AI training, strategy testing, and classroom exercises.


What is an arena?

Feature Live exchange (JTW) Arena
Asset JTW, shared globally Your own synthetic asset
Participants All users You + invited/pre-allocated traders
Settlement Yes — balances transferred No — resets on destroy
Session timing Exchange-controlled You control all transitions
Use case Real trading AI training, classroom, backtesting

Arena lifecycle

create → Suspended → BookOnly → Trade → destroy
arena.transition_to("suspended")   # orders enter, nothing fills
arena.transition_to("book_only")   # book visible, still no fills
arena.transition_to("trade")       # live continuous matching

Lifecycle sequence

Transitions must follow suspended → book_only → trade. Going out-of-order raises a lifecycle error.


Minimal arena — generator only

from fastboxex import Platform, load_config
from fastboxex.price import from_float
import time

cfg   = load_config()
p     = Platform.login(cfg, username, password)

arena = p.create_arena(
    "JTW",
    num_traders         = 0,
    reference_price     = from_float(100.00),
    tick_size           = 100,
    lot_size            = 100,
    generator_cash      = from_float(50_000_000),
    generator_inventory = 50_000,
    max_order_qty       = 50_000,
    circuit_breaker_bps = 2_000,
)

gen = arena.connect_generator()
gen.activate(arena.asset_id)

arena.transition_to("suspended")
arena.transition_to("book_only")
arena.transition_to("trade")

# ... your generator loop runs here ...

p.close_arena(arena.arena_id)

Arena with two pre-allocated trader slots

Pre-allocated slots (num_traders=N) are issued to the arena owner at create time. The owner accesses them via reconnect_arena() → connect_trader(i) without joining.

arena = p.create_arena(
    "JTW",
    num_traders         = 2,
    reference_price     = from_float(100.00),
    tick_size           = 100,
    lot_size            = 100,
    generator_cash      = from_float(50_000_000),
    generator_inventory = 50_000,
    trader_cash         = from_float(1_000_000),
    trader_inventory    = 0,
    max_order_qty       = 50_000,
    circuit_breaker_bps = 2_000,
)

gen     = arena.connect_generator()
trader0 = arena.connect_trader(0)
trader1 = arena.connect_trader(1)

gen.activate(arena.asset_id)
trader0.activate(arena.asset_id)
trader1.activate(arena.asset_id)

Classroom mode — external participants

Issue an invite code and let students join:

print(f"Invite code: {arena.invite_code}")

# Student A (different user) — in their own script:
p_student = Platform.login(cfg, "alice", alice_password)
arena_a   = p_student.join_arena(arena.invite_code, num_traders=1)
conn_a    = arena_a.connect_trader(0)
conn_a.activate(arena_a.asset_id)

Each student who calls join_arena() gets an independent set of joiner_num_traders slots with joiner_cash / joiner_inventory, independent of the generator's and other students'.

Observation visibility follows the same ownership model:

  • the arena owner can monitor all arena sub-users in the arena views
  • each joined participant can monitor only their own arena sub-users

The class game

examples/06_class_game/ is a complete classroom session.

# Teacher
fastboxex run examples/06_class_game/teacher.py --minutes 15 --players 40

# Each student, on their own machine
fastboxex run examples/06_class_game/play.py --code THE-CODE

The teacher sees who has joined and presses ENTER to open trading. A live leaderboard follows, then final standings. Students cannot trade before ENTER, return to their seat if their script crashes, and stop by themselves when the teacher ends the game.

If the teacher's machine dies, the arena stays open with no market maker: students stop within about a minute, and teacher.py --close-old closes the leftover arena.

Student accounts need arena access: max_traders of at least 1 to join, and max_arenas of at least 1 to create their own.


Limits

Arena ids are never reused until the Arena runtime restarts, and the market relay carries a fixed number of them. Past that number a new arena looks normal but has no market data. 04, 07 and the class game then stop at once with No market data reached this machine. Restarting the Arena runtime resets the ids and destroys every open arena.


Cleaning up stale arenas

for info in p.list_server_arenas():
    try:
        p.close_arena(info["arena_id"])
    except Exception:
        pass

Arenas also expire by themselves at the end of their lifetime.


create_arena() parameters

Parameter Default Description
num_traders 0 Pre-allocated same-user slots
reference_price required Mid-price in raw ticks
tick_size 100 Minimum price step
lot_size 100 Minimum quantity
generator_cash required Generator starting cash
generator_inventory required Generator starting inventory
trader_cash 0 Cash per pre-allocated slot
trader_inventory 0 Inventory per pre-allocated slot
joiner_cash 0 Cash per external joiner slot
joiner_inventory 0 Inventory per external joiner slot
joiner_num_traders 1 Trader slots per join call
max_participants 20 Max distinct external joiners
max_order_qty 50_000 Single-order quantity cap
circuit_breaker_bps 2_000 Auto-halt threshold (basis points)