Skip to main content
COSMICBYTEZLABS
NewsSecurityHOWTOsToolsStudyTraining
ProjectsNewsletterHire MeAbout
Subscribe

Press Enter to search or Esc to close

News
Security
HOWTOs
Tools
Study
Training
Projects
Newsletter
Hire Me
About
RSS Feed
Reading List
Subscribe

Stay in the Loop

Get the latest security alerts, tutorials, and tech insights delivered to your inbox.

Subscribe NowFree forever. No spam.
COSMICBYTEZLABS

Your trusted source for IT intelligence, cybersecurity insights, and hands-on technical guides.

1184+ Articles
136+ Guides

CONTENT

  • Latest News
  • Security Alerts
  • HOWTOs
  • Checklists
  • Projects
  • Exam Prep

RESOURCES

  • Search
  • Browse Tags
  • Newsletter Archive
  • Reading List
  • RSS Feed

COMPANY

  • About Us
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CosmicBytez Labs. All rights reserved.

System Status: Operational
  1. Home
  2. Projects
  3. Building a Multi-Asset Trading Bot in Python with Async Event Bus
Building a Multi-Asset Trading Bot in Python with Async Event Bus
PROJECTAdvanced

Building a Multi-Asset Trading Bot in Python with Async Event Bus

Event-driven trading bot for Canadian markets — 8 strategies, 4 broker integrations (Alpaca, Questrade, CCXT, paper), kill switch, FINTRAC reporting, and async pub/sub end-to-end on SQLAlchemy 2.

Dylan H.

Projects

May 5, 2026
4 min read
10-15 hours

Tools & Technologies

Python 3.10+asyncioSQLAlchemy 2.0FastAPIDockeralpaca-pyccxt

Overview

Most trading-bot tutorials stop at "loop through symbols and call the broker." Real bots need an event bus, multiple broker abstractions, paper-trading parity, a kill switch you can hit fast, and a database schema that survives your first compliance audit. This bot covers all of that — Canadian-market focused (Questrade), with US stocks via Alpaca and crypto via CCXT, all running through one async event loop.

Stack

  • Language: Python 3.10+ (tested on 3.10, 3.11, 3.12)
  • Async: asyncio, aiohttp, httpx
  • Data: pandas, numpy
  • Database: SQLAlchemy 2.0 async — SQLite/aiosqlite (dev), PostgreSQL (prod)
  • Config: Pydantic Settings (BaseSettings from .env)
  • CLI: Click + Rich
  • Brokers: alpaca-py, ccxt (crypto)
  • Dashboard: FastAPI + uvicorn (optional)
  • Testing: pytest, pytest-asyncio, pytest-cov
  • Linting: ruff, black, mypy
  • Deployment: Docker

Event-Driven Architecture

Components communicate exclusively through an event bus (core/events.py):

  • QUOTE_UPDATE — market data updates from a broker
  • SIGNAL_GENERATED — a strategy fires
  • ORDER_SUBMITTED / ORDER_FILLED — order lifecycle
  • POSITION_CHANGED — portfolio update
  • KILL_SWITCH_TRIGGERED — emergency stop

Strategies don't know about brokers and brokers don't know about strategies. Everything routes through events.

Broker Abstraction

Every broker implements BaseBroker:

async def connect(self) -> None: ...
async def disconnect(self) -> None: ...
async def get_quote(self, symbol: str) -> Quote: ...
async def submit_order(self, order: Order) -> str: ...
async def cancel_order(self, order_id: str) -> bool: ...
async def get_positions(self) -> list[Position]: ...
async def get_account_balance(self) -> Decimal: ...

Switching from paper to live is one config change.

Strategy Interface

Strategies implement BaseStrategy with initialize(), generate_signals(), and validate_parameters(). The bot auto-discovers strategies via STRATEGY_NAME and STRATEGY_CLASS exports — adding a new one is a single file.

Active Strategies

StrategyTypeSignal Logic
sma_crossoverTrendFast/slow SMA crossover
rsi_mean_reversionMean reversionOversold (<30) buy, overbought (>70) sell
grid_tradingRangeBuy/sell at grid intervals
vwapVolumeBuy below VWAP, sell above
bollinger_breakoutVolatilityBuy on upper-BB breakout with volume confirm
macd_crossoverMomentumMACD/signal-line cross with trend filter
stochastic_oscillatorFast oscillator%K/%D cross in oversold/overbought
crypto_momentumMomentumCrypto-specific momentum with volume confirmation

Database Models

AuditLog, Order, Trade, Position, MarketData, StrategyState, FintracReport. Schema is created directly via init_db() — no migrations layer; the schema is the code.

Risk & Compliance

  • Kill switch: any subscriber can publish KILL_SWITCH_TRIGGERED. Brokers cancel open orders and halt new submissions immediately.
  • FINTRAC reporting: any single transaction at or above CA$10,000 is auto-flagged into a FintracReport row.
  • Position limits: MAX_POSITION_SIZE_PCT (default 5%), MAX_DAILY_LOSS (default $1,000).

Key CLI Commands

trading-bot run --mode paper --strategies sma_crossover
trading-bot backtest -s sma_crossover --start 2024-01-01 --end 2024-12-31 -sym AAPL
trading-bot verify-broker
trading-bot status

Lessons Learned

  • float(None) crashes: optional price fields must be guarded — broker APIs return null on illiquid symbols and a single float(quote.bid) deep in a loop will down the bot.
  • Questrade 401 retry guard: a naive retry-on-401 will infinite-loop when the refresh token is genuinely dead. Cap retries and surface the error.
  • Admin keys belong in request bodies, not query strings: query strings end up in access logs.
  • Dashboard auth is critical: a FastAPI dashboard with no auth is a remote shell to your broker. Don't ship without it.

Testing

206 tests (pytest), 43% coverage. CI matrix runs Python 3.10, 3.11, and 3.12 through ruff → black → mypy → pytest with coverage.

#Python#Trading#asyncio#SQLAlchemy#FastAPI#Algorithmic Trading#DevOps

Related Articles

Build a Production Monitoring Stack with Prometheus and Grafana

Deploy a full observability stack — Prometheus metrics collection, Grafana dashboards, AlertManager notifications, and three exporters — all containerized...

8 min read

A Real-Time Trading Dashboard with Next.js 15 and lightweight-charts

Frontend for an algorithmic trading bot — TradingView-style candlestick charts, WebSocket auto-reconnect, dark theme, and zero SSR because the bot's API lives on a separate server.

3 min read

Claude Code for IT Operations: Building a Multi-Project

Transform Claude Code from a chatbot into a DevOps co-pilot. Set up CLAUDE.md templates, custom hooks, reusable agents, deployment skills, and MCP server...

12 min read
Back to all Projects