Skip to content

Live Functional Strategy Quickstart

This guide focuses on function-style strategy entry with LiveRunner, covering both paper and broker_live modes.

1. When to use this

  • You prefer on_bar(ctx, bar) style over subclassing Strategy.
  • You want a fast migration path from function-style backtests to live sessions.
  • You need direct submit_order(...) in broker_live.

2. Two runtime modes

2.1 paper (simulated matching)

Start with paper mode to verify callback flow:

2.2 broker_live (real broker order routing)

Switch to broker_live after gateway connectivity is verified:

  • Example: 39_live_broker_submit_order_demo.py
  • Audit example: 42_live_broker_event_audit_demo.py
  • Key points:
  • trading_mode="broker_live"
  • call ctx.submit_order(...) inside on_bar
  • pass explicit client_order_id for idempotency tracking
  • default execution semantics is execution_semantics_mode="strict" (terminal states are driven by broker order callbacks)
  • optional on_broker_event for unified event_type/owner_strategy_id/payload persistence

You can pass execution_semantics_mode via gateway_options:

  • strict (default, recommended for production): terminal states such as Cancelled/Rejected/Filled are confirmed by OnRtnOrder; error callbacks cache rejection reasons and merge them into subsequent order callbacks.
  • compatible (migration mode): allows immediate local terminal-state updates for selected error/cancel paths to preserve legacy behavior.

3. Function-style template

def initialize(ctx):
    ctx.sent = False

def on_bar(ctx, bar):
    if not ctx.sent and hasattr(ctx, "submit_order"):
        ctx.submit_order(
            symbol=bar.symbol,
            side="Buy",
            quantity=1.0,
            client_order_id="demo-1",
            order_type="Market",
        )
        ctx.sent = True

runner = LiveRunner(
    strategy_cls=on_bar,
    initialize=initialize,
    on_order=on_order,
    on_trade=on_trade,
    on_timer=on_timer,
    context={"strategy_name": "demo"},
    instruments=instruments,
    broker="ctp",
    trading_mode="broker_live",
    gateway_options={"execution_semantics_mode": "strict"},
)
runner.run(duration="30s", show_progress=False)

4. Common troubleshooting

  • submit_order not injected yet
  • Cause: trader gateway binding is not ready.
  • Fix: guard with hasattr(ctx, "submit_order") before placing.
  • duplicate active client_order_id
  • Cause: reused active client id.
  • Fix: generate a fresh client_order_id for each new order.
  • Market data arrives but no trades
  • Cause: trader gateway not connected, risk rejection, or invalid lot/tick constraints.
  • Fix: inspect on_order status and rejection reason first.
  • Cancel request sent but status remains Submitted
  • Cause: strict semantics requires OnRtnOrder(Cancelled) to finalize terminal state.
  • Fix: verify trader callback path and broker order-return logs, not only request send success.

5. Suggested rollout

  • Step 1: validate callback flow in paper mode.
  • Step 2: run broker_live with minimum order size.
  • Step 3: add advanced logic after connectivity is stable.