Metadata-Version: 2.5
Name: openbb-tmx
Version: 2.0.0
Summary: Unofficial TMX data provider extension for the OpenBB Platform - Public Canadian markets data for Python and Fast API.
Project-URL: Homepage, https://openbb.co
Project-URL: Repository, https://github.com/OpenBB-finance/OpenBB
Author-email: OpenBB Team <hello@openbb.co>
License: Apache-2.0
Requires-Python: <4,>=3.10
Requires-Dist: aiohttp-client-cache>=0.11
Requires-Dist: aiosqlite>=0.20
Requires-Dist: curl-cffi>=0.7
Requires-Dist: diskcache>=5.6
Requires-Dist: exchange-calendars>=4.13.2
Requires-Dist: lxml>=5.0
Requires-Dist: openbb-core[pandas]>=2.0.0
Requires-Dist: pdfplumber>=0.11
Requires-Dist: pyarrow>=16.0
Requires-Dist: python-dateutil>=2.8
Requires-Dist: random-user-agent>=1.0.1
Requires-Dist: tzdata>=2024.1
Provides-Extra: all
Requires-Dist: openbb-charting>=4.0.0; extra == 'all'
Requires-Dist: pywry>=2.0.6; extra == 'all'
Provides-Extra: builder
Requires-Dist: pywry>=2.0.6; extra == 'builder'
Provides-Extra: charting
Requires-Dist: openbb-charting>=4.0.0; extra == 'charting'
Description-Content-Type: text/markdown

# OpenBB TMX Provider

This extension integrates [TMX Group](https://www.tmx.com) data into the OpenBB Platform.

Every dataset is read from public endpoints. **No API key or account is required.**

> This extension is unofficial. It is not affiliated with, endorsed by, or authorized by TMX Group Limited.

## Installation

Install from PyPI:

```bash
pip install openbb-tmx
```

Or from the source tree:

```bash
uv pip install -e openbb_platform/providers/tmx
```

Then rebuild the Python interface:

```python
import openbb

openbb.build()
```

### Optional extras

Two surfaces need a package no dataset requires, so each is declared as an
extra:

| Extra | Pulls in | Needed by | Without it |
| ----- | -------- | --------- | ---------- |
| `charting` | `openbb-charting` | `derivatives.options.smile` · `surface` · `stats` · `term_structure` | The four chart routes are not registered. |
| `builder` | `pywry` | `equity.screener_builder` and its `/screener_builder/view` iframe | The iframe raises `ImportError`, so the Workspace app's Screener tab cannot render, and the native window cannot open. |

```bash
pip install 'openbb-tmx[all]'
```

## Coverage

TMX publishes far more than Canadian equities. This extension covers the TMX
Money quote feed, the Montreal Exchange derivatives universe, and the CIRO debt
trade reporting facility.

| Command | Description |
| ------- | ----------- |
| `equity.search` | Search the instrument symbology across every market and asset class. |
| `equity.screener` | Screen by venue, type, and size, joined to vendor fundamentals. Indices are quoted over the directory, and futures are read from the Montreal Exchange session summary and settlement prices. |
| `equity.screener_builder` | The screen built interactively, in a native window or as a Workspace iframe. |
| `equity.symbol_reference` | Resolve symbols to their canonical form, validity, and listing venue. |
| `equity.quote` · `profile` · `historical` | Quotes, company reference data, and price history. |
| `equity.filings` | SEDAR filings, with links to the filed PDFs, and a viewer that serves the documents themselves. |
| `equity.gainers` | Curated stock lists, including the CIBC CDR list. |
| `equity.fundamental.income` · `balance` · `cash` | Statements, annual or quarterly, one record per period, with a view that lays the periods out as columns. |
| `equity.fundamental.dividends` · `splits` | Declared distributions and share splits. |
| `equity.calendar.earnings` | Earnings calendar with estimated and actual EPS. |
| `equity.ownership.insider_trading` · `insider_transactions` | Activity summary, and every SEDI filing. |
| `equity.estimates.consensus` | Analyst consensus, ratings, and price targets. |
| `equity.rankings` | The TSX 30 and TSX Venture 50 annual rankings. |
| `etf.search` · `info` · `holdings` · `sectors` · `countries` · `historical` | The TMX-listed fund universe. |
| `index.available` · `info` · `historical` · `constituents` · `sectors` · `snapshots` | The S&P/TSX index family, with profiles, levels, and key data. |
| `index.documents` | Factsheet and methodology PDFs, served through a file viewer. |
| `derivatives.options.chains` | Full option chains with greeks, Canadian and US. |
| `derivatives.options.covered_calls` | Listed calls screened by annualized premium return. |
| `derivatives.options.straddle` · `strangle` · `spreads` | Strategy pricing over the loaded chain. |
| `derivatives.options.smile` · `surface` · `stats` · `term_structure` | Plotly views of the chain. Registered only when `openbb-charting` is installed. |
| `derivatives.futures.instruments` · `futures.historical` | The Montreal Exchange universe and its history. |
| `currency.historical` | Currency pair history. |
| `fixedincome.prices` · `treasury_prices` · `trades` | The CIRO bond master and reported trades. |
| `markets.movers` · `trades` · `short_interest` | Market breadth, time and sales, and short interest. |
| `news.company` | Company news, press releases, and upcoming events. |
| `news.feed` · `market` · `blog` · `search` | Per-symbol, cross-symbol, editorial, and full-text news, each with the article body. |

## Symbology

A bare symbol is a Canadian listing; `.TO` and `.TSX` suffixes are accepted and
stripped. A prefix or exchange suffix selects something else:

| Form | Meaning | Example |
| ---- | ------- | ------- |
| `^` | Index | `^TSX` |
| `/` | Future | `/CGB`, `/CL:NMX` |
| `$` | Currency pair | `$USDCAD` |
| `~` | Cryptocurrency pair | `~BTCUSD:US`, `~ETHUSD:US` |
| `@` | Option contract | `@AC    260918P00011000:CA` |
| `:XX` | Exchange suffix | `IBM:US`, `AIR:PA`, `ASML:AS` |

Thirty-six exchange suffixes are addressable, spanning Europe, Asia, Latin
America, and the Middle East. Price history reaches back to each listing's
start - `IBM:US` to 1990, `$USDCAD` to 1996, the European venues to 2006.

Cryptocurrency pairs carry the `:US` suffix and quote against the US dollar.
An option contract is addressed by the padded symbol the chain publishes as
`contract_symbol`, so a contract is quoted and charted like any other listing.

## Notes on the data

**Options cover both sides of the border.** A bare symbol resolves to the
Montreal Exchange listing; suffix `:US` for the OPRA-listed contracts. Both
carry implied volatility and the full greeks on every expiry. Historical
end-of-day chains are available from the Montreal Exchange back to 2009.

**The instrument directory is swept, not listed.** The symbology has no
enumeration endpoint, so the directory is built by sweeping symbol prefixes and
de-duplicating on the vendor's symbol id. A prefix that saturates the row cap is
re-swept one character deeper, so a dense letter cannot silently truncate the
result. The Canadian sweep yields roughly 120,000 instruments, most of them
mutual funds.

**Fixed income comes from CIRO, behind Cloudflare.** The bond master is about
195,000 securities and 70MB, so it is fetched through a browser-impersonating
session and held on disk as parquet for the day rather than in the HTTP cache.
The edge refuses individual requests at random rather than blocking the session
— a warmup that is itself refused is routinely followed by a request that
succeeds — so every call rides out a refusal by retrying, backing off between
attempts. Trade history is capped at ninety days per query, so a longer range
is bracketed into consecutive windows; an unbounded request starts at the
bond's original issue date. A window still refused after every attempt is
reported rather than read as a window with no trades, so a partial answer is
never returned as a whole one. Trades carry the CIRO record id and the
submission date, which is later than the execution date when a trade is
reported late or amended.

**The file viewers serve the documents, not links to them.** A browser cannot
fetch either publisher's PDFs from a Workspace page, so a selected document is
downloaded and handed over whole. QuoteMedia serves the SEDAR filings to any
client; S&P refuses every server-side request for its index factsheets and
methodologies, so those are still passed through as URLs for the browser to
load.

**Most futures do not trade every session.** The exchange's intra-session
summary reports a last price only for contracts that have traded, which on a
given day is a handful of the roughly three hundred it lists. Every screened
contract therefore also carries the settlement price the exchange publishes for
it, read from that product's quotes page - a request per product root, held for
an hour, and made only for the products in the rows being returned. A contract
reported at the root level, as share and ETF futures are, carries its front
month's settlement.

**Insider trading does not use the standard model shape.** The values returned
are aggregate shares traded over the previous three, six, and twelve months.

**Price history intervals.** Daily, weekly, monthly, and intraday at any number
of minutes. Weekly and monthly bars are for the period beginning. Intraday
history is a rolling window of roughly one year, whatever start date is asked
for. Split-adjusted, split-and-dividend-adjusted, and unadjusted prices are
available for daily intervals only; other intervals are split-adjusted. The feed
leaves the high and low empty on a handful of historical foreign bars, so both
are optional.

**Responses are cached on disk.** A SQLite-backed HTTP cache holds responses
with a TTL per endpoint family - sixty seconds for quotes and movers, up to a
day for statements and reference data - and GraphQL operations carry their own
TTL table. Any request can bypass it with `use_cache=False`.

## TradingView charting

The extension serves TradingView's Universal Data Feed at `/tmx/udf`, so the
historical price widgets are declared as `advanced_charting` and render as
interactive charts over the same universe the provider addresses. The feed
implements `config`, `search`, `symbols`, `history`, and `time`, at every
resolution from one minute to monthly.

## Standalone usage

The extension registers its own router, so installing `openbb-tmx` alone still
exposes every dataset under `/tmx`. Each namespace registers its model-backed
commands only when the OpenBB extension that normally owns those standard models
is absent; when `openbb-equity` is installed, for example, the equity models are
served through it instead and the TMX routes step aside.

The fetchers can also be used directly, independent of the Python and API
interfaces:

```python
from openbb_tmx import tmx_provider

tmx_provider.fetcher_dict
```

## OpenBB Workspace

A bundled dashboard is served at `/api/v1/tmx/apps.json`. Start the API and add
it as a Workspace backend:

```bash
openbb-api
```

The app carries tabs for the market overview, the screener, company detail,
financials, options, futures and FX, fixed income, ETFs, indices, and news.
Clicking a row in a search, mover, or directory table drives the linked widgets
in that tab.

## Development

```bash
uv pip install -e '.[all]'
uv pip install --group dev
pytest tests --cov=openbb_tmx --cov-report=term-missing --cov-fail-under=100
```

The suite exercises both extras, so the unit run needs `.[all]` installed.

The unit suite runs entirely offline - no cassettes and no network - and is held
at one hundred percent coverage. Integration tests hit the live endpoints and
are excluded by default. The API half calls `http://0.0.0.0:8000`, so start the
API first:

```bash
openbb-api &
pytest integration -m integration
```

## OpenBB Documentation

OpenBB Platform documentation is available [here](https://docs.openbb.co/platform).

OpenBB Workspace documentation is available [here](https://docs.openbb.co/workspace).
