Canada Stock API Integration:Real-Time TSX/TSXV Market Data & Quantitative Practices

  1. iTick
  2. Tutorial
Canada Stock API Integration:Real-Time TSX/TSXV Market Data & Quantitative Practices - iTick
Canada Stock API Integration:Real-Time TSX/TSXV Market Data & Quantitative Practices

Introduction: Why Canada? Why Now?

Within the global quantitative trading landscape, the Toronto Stock Exchange (TSX) and its venture tier (TSXV) occupy a distinctive niche: rich in resource names, characterized by stable dividend profiles, and exhibiting unique volatility patterns — yet access to high-quality, timely market data has historically been far more challenging than for U.S. or Hong Kong equities.

Bloomberg Terminal access is prohibitively expensive, free data sources are frequently rate-limited or blocked, and most mainstream API providers either deliver Canadian coverage with significant latency or restrict it to end-of-day bars. For quant developers focused on cross-market arbitrage, energy sector rotation, high-dividend strategies, or Canada-specific factor models, real-time TSX data has long been a major bottleneck.

The 2026 release of the iTick API now provides comprehensive coverage of the entire Canadian equity universe. This article demonstrates — with production-ready Python code — how to access real-time quotes, historical bars, and ultra-low-latency streaming data for key TSX-listed names using iTick’s REST and WebSocket endpoints.


I. iTick Canadian Market Coverage Overview

Per the latest iTick documentation and platform update notes, the API now supports 40+ global exchanges, including full coverage of Canada (TSX and TSXV).
The region code for Canadian securities is “CA”, and symbols follow the native exchange ticker format.

Supported data types:

  • Real-time quotes (last price, change, volume, etc.)
  • Real-time trade-by-trade ticks
  • Real-time order book (Level 1 / best bid & offer)
  • Historical bars (1-min to monthly, up to 15 years of history)
  • WebSocket streaming (millisecond-level updates)

Typical use cases:

  • Real-time monitoring and alerting for Canadian resource equities (energy & mining)
  • Automated execution of high-dividend yield strategies on TSX constituents
  • Data infrastructure for multi-region relative value and statistical arbitrage systems

II. Quick Start: Obtaining an API Token

Before writing any code:

  1. Register an account at https://itick.org
  2. Retrieve your API Key from the developer console (free tier available — sufficient for most individual quant developers)

The free tier currently provides unlimited basic quote calls, making it highly attractive for Canadian market backtesting and live monitoring.

III. Example 1: REST API – Fetching Real-Time TSX Quotes

Example uses Royal Bank of Canada (RY) — the largest financial name by market cap on the TSX.

      import requests

API_TOKEN = 'your_itick_token_here'     # ← replace with your actual token
BASE_URL  = 'https://api.itick.org'

def get_tsx_quote(symbol: str):
    """
    Retrieve real-time quote for a TSX-listed security.
    
    Args:
        symbol: TSX ticker (e.g. 'RY', 'ENB', 'BNS')
    """
    headers = {
        'accept': 'application/json',
        'token': API_TOKEN
    }
    
    # Region is fixed to 'CA' for all Canadian securities
    url = f'{BASE_URL}/stock/quote?region=CA&code={symbol}'
    
    try:
        resp = requests.get(url, headers=headers, timeout=10)
        if resp.status_code == 200:
            payload = resp.json()
            return payload.get('data', {})
        else:
            print(f"Request failed | HTTP {resp.status_code}")
            print(f"Error: {resp.text}")
            return None
    except Exception as e:
        print(f"Network error: {e}")
        return None


if __name__ == '__main__':
    quote = get_tsx_quote('RY')
    
    if quote:
        print("═" * 60)
        print("Toronto Stock Exchange (TSX) — Real-Time Quote")
        print("═" * 60)
        print(f"Ticker     : {quote.get('s', 'N/A')}")
        print(f"Last       : {quote.get('ld', 'N/A')} CAD")
        print(f"Change     : {quote.get('ch', 'N/A')}")
        print(f"Change %   : {quote.get('chp', 'N/A')}%")
        print(f"Volume     : {quote.get('v', 'N/A'):,}")
        print(f"Open       : {quote.get('o', 'N/A')}")
        print(f"High       : {quote.get('h', 'N/A')}")
        print(f"Low        : {quote.get('l', 'N/A')}")
        print(f"Timestamp  : {quote.get('t', 'N/A')}")
    else:
        print("No data returned. Check token, network, or symbol.")

    

Key response fields (TSX-specific mapping):

FieldDescriptionExample
sTickerRY
ldLast traded price168.32
chChange (absolute)0.05
chpChange (percentage)0.45
oOpen price168.05
hSession high168.32
lSession low167.95
vCumulative volume1000
tUNIX timestamp (ms)1631234567000

Note: TSXV (venture) tickers follow the same pattern (region=CA); iTick automatically routes to the correct venue.

IV. Example 2: WebSocket – Low-Latency Real-Time Streaming

For millisecond-level monitoring of Canadian energy names or building execution signals, WebSocket streaming is essential.

      import websocket
import json
import threading
import time

WS_URL    = "wss://api.itick.org/stock"
API_TOKEN = 'your_itick_token_here'

class TSXRealTimeMonitor:
    def on_message(self, ws, message):
        try:
            msg = json.loads(message)
            if 'data' in msg:
                d = msg['data']
                symbol = d.get('s')
                typ    = d.get('type')
                
                if typ == 'quote':
                    print(f"[QUOTE] {symbol:6}  Last: {d.get('ld')}  Vol: {d.get('v'):,}")
                elif typ == 'tick':
                    print(f"[TRADE] {symbol:6}  Price: {d.get('ld')}  Size: {d.get('v'):,}")
        except Exception as e:
            print(f"Parse error: {e}")

    def on_open(self, ws):
        print("WebSocket connected. Subscribing to TSX symbols...")
        sub = {
            "ac": "subscribe",
            "params": "RY$CA,ENB$CA,ABX$CA",
            "types": "quote,tick"
        }
        ws.send(json.dumps(sub))

    def on_error(self, ws, error):
        print(f"Error: {error}")

    def on_close(self, ws, code, msg):
        print("Connection closed")

    def run(self):
        headers = {"token": API_TOKEN}
        self.ws = websocket.WebSocketApp(
            WS_URL,
            header=headers,
            on_open=self.on_open,
            on_message=self.on_message,
            on_error=self.on_error,
            on_close=self.on_close
        )

        # Heartbeat thread (required to prevent idle disconnect)
        def heartbeat():
            while True:
                time.sleep(30)
                if self.ws.sock and self.ws.sock.connected:
                    ping = {"ac": "ping", "params": str(int(time.time()*1000))}
                    self.ws.send(json.dumps(ping))

        threading.Thread(target=heartbeat, daemon=True).start()
        self.ws.run_forever()

if __name__ == '__main__':
    monitor = TSXRealTimeMonitor()
    monitor.run()

    

Important notes:

  • Symbol format: RY$CA (consistent with US format AAPL$US)
  • Subscription types: quote, tick, depth (can be combined)
  • Maximum recommended symbols per connection: ~50

V. Example 3: Historical Bars – Essential for Backtesting

iTick provides up to 15 years of daily history and granular intraday bars for Canadian equities.

      import requests
import pandas as pd

def fetch_tsx_bars(symbol: str, ktype: int = 8, limit: int = 20):
    """
    Fetch historical OHLCV bars for a TSX-listed security.
    
    Args:
        symbol: Ticker (e.g. 'ENB')
        ktype : Bar resolution
                1=1min, 2=5min, 3=15min, 4=30min, 5=1H, 6=2H, 7=4H,
                8=Daily, 9=Weekly, 10=Monthly
        limit : Number of bars to return
    """
    headers = {'accept': 'application/json', 'token': 'your_itick_token_here'}
    
    url = f"https://api.itick.org/stock/kline?region=CA&code={symbol}&kType={ktype}&limit={limit}"
    
    resp = requests.get(url, headers=headers)
    if resp.status_code != 200:
        print(f"Failed: HTTP {resp.status_code}")
        return None
    
    bars = resp.json().get('data', [])
    if not bars:
        return None
    
    df = pd.DataFrame(bars)
    df.rename(columns={'t':'timestamp','o':'open','h':'high','l':'low','c':'close','v':'volume'}, inplace=True)
    df['datetime'] = pd.to_datetime(df['timestamp'], unit='ms')
    
    return df[['datetime','open','high','low','close','volume']]


if __name__ == '__main__':
    df = fetch_tsx_bars('ENB', ktype=8, limit=10)
    if df is not None:
        print(df.to_string(index=False))

    

These bars can be directly fed into common strategies (dual moving average, RSI timing, volatility breakout, etc.).


Appendix: Selected High-Liquidity TSX / TSXV Tickers for Testing

CompanyTickerSector
Royal Bank of CanadaRYFinancials
Toronto-Dominion BankTDFinancials
Suncor EnergySUEnergy
Canadian Natural ResourcesCNQEnergy
Barrick GoldABXMaterials
Wheaton Precious MetalsWPMMaterials
Canadian National RailwayCNRIndustrials

TSXV example: NGEX (exploration & mining)

Conclusion: Canadian Equities Are No Longer a Data Island

For many years the TSX has been underserved in the retail and mid-tier quant API ecosystem. With full real-time and historical coverage now available through iTick, individual developers and smaller funds can finally build robust, latency-sensitive Canadian equity strategies without relying on expensive terminal solutions.

Official Documentation: https://docs.itick.org
GitHub Organization: https://github.com/itick-org