Live (paper) trading
Live mode warms up the strategy with recent history, subscribes to the Alpaca real-time bar stream, and routes signals to the broker as bracket orders.
make live
# or
uv run python main.py live --strategy volume_spike --scanner volume --symbols NVDA,META,TSLA
With PAPER_TRADE = True (the default) this trades the paper account. Set it
to False only when you intend to trade real money.
What happens on start
- The scanner picks the universe from your candidate symbols.
- The engine fetches enough history to make every indicator valid, and seeds the strategy's rolling buffers (warm-up).
- It subscribes to the live bar stream for every monitored symbol. The stream auto-reconnects with backoff if the socket drops.
- Each streamed OHLCV bar updates the strategy, which emits a signal.
- Actionable signals go to the
LiveTrader, which sizes the position and submits a bracket order (entry + stop-loss + take-profit) through the broker. - In parallel, the trade-update stream logs fills/cancels/rejects so you can see what the account is actually doing.
Press Ctrl-C to stop.
Order safety
- Entries are skipped while an order is pending for that symbol, so a repeated signal can't double-submit before the first fills.
- A discretionary close cancels the resting bracket legs first, so you're never left with an orphaned stop/take order.
- Orders are only sent during market hours (the clock is checked, with a short
cache; disable with
respect_market_hours=Falseif you need extended-hours).
Position sizing
By default each entry is sized by the strategy's risk-per-trade / stop-loss
config (RiskBasedSizer). Add --portfolio to instead size positions by
portfolio weights computed with the OR-Tools allocator — capital is shared
across the universe rather than sized per trade:
make live-portfolio
# or
uv run python main.py live --scanner volume --symbols NVDA,META,TSLA \
--portfolio --max-positions 5 --max-weight 0.25
With --portfolio, only the symbols the allocator funds are traded; if OR-Tools
isn't installed or nothing is funded, it falls back to risk-based sizing. See
Portfolio allocation.
Or use --beta-sizing to scale each position inversely by its beta vs a
benchmark (default SPY) — higher-beta names get smaller positions, evening out
risk:
make live-beta
# or
uv run python main.py live --scanner volume --symbols NVDA,META,TSLA --beta-sizing --benchmark SPY
Managing the account
make cancel-orders # cancel all open orders
make close-positions # liquidate all positions (also cancels orders)
The full real-time path is described in The Engine and Broker Abstraction.