BoC Economics

Canadian macro, from raw API to a live dashboard.

An end-to-end analytics-engineering pipeline built on Canadian macroeconomic data. It pulls four Bank of Canada indicators, the policy interest rate, inflation (CPI), the CAD/USD exchange rate, and the 5-year government bond yield, through one warehouse-agnostic dbt project that runs on both BigQuery and Snowflake, into a tested staging โ†’ intermediate โ†’ mart star schema and a live Looker Studio dashboard. Python ingestion, 8 data-quality tests, GitHub Actions CI, and local Airflow orchestration.

2
Warehouses (BigQuery + Snowflake)
4
Macro indicators
8
dbt tests, green on both
Airflow
daily orchestration

The question it answers

How do the Bank of Canada's policy rate, inflation, exchange rate, and bond yields move together, for example through the 2022โ€“24 tightening cycle? Each of these lives in a different place, at a different frequency. This pipeline lands all four on a single monthly timeline so they can be read on one chart.

๐Ÿฆ
Policy rate

Target for the overnight rate (daily).

๐Ÿ“ˆ
Inflation (CPI)

Total Consumer Price Index (monthly).

๐Ÿ’ฑ
CAD / USD

Daily average exchange rate.

๐Ÿ“Š
5yr bond yield

GoC 5-year benchmark (daily).

The domain is deliberate: clean, credible, financial-services data that stays interesting to talk through, and a realistic testbed for a production-shaped dbt project.

How it's built: API to warehouse to dashboard

A Python script lands raw data in BigQuery; dbt then transforms it in clean layers, each building on the last, into a small star schema that Looker Studio reads directly.

๐Ÿ“ก
Bank of Canada Valet API
Free public REST API, four macro series confirmed against the live catalogue
โ†“
๐Ÿ
Python ingestion (requests)
Idempotent truncate-and-reload into boc_raw, with retry + backoff
โ†“
Transformed in layers with dbt
๐Ÿ”นStaging
One typed, cleaned view per series.
๐Ÿ”ธIntermediate
Union to one monthly grain (daily โ†’ month-end).
โญMart
Fact + dimension seed = a clean star schema.
โ†“
โœ…
GitHub Actions CI
Runs dbt build + tests on every PR, against an isolated CI dataset
โ†“
๐Ÿ“Š
Looker Studio
Interactive dashboard on the fact table: indicator selector, date zoom, KPI scorecards

The layered pattern (staging โ†’ intermediate โ†’ mart) keeps a clean lineage: every number on the dashboard can be traced back through the models to the original API observation.

The details that make it real

๐Ÿ—“๏ธ

Mixed frequencies, one grain

CPI is monthly; the rate, FX, and yield are daily. A window function collapses each daily series to its month-end value, so all four align on a single monthly timeline without distorting a step-function like the policy rate.

๐Ÿงช

A custom data-quality test

Alongside seven built-in tests, a custom no_missing_months test flags gaps in any series. It's partition-aware, so series with different start dates (FX only begins 2017) are each checked over their own history.

๐Ÿ”

CI that can't touch prod

Every pull request runs the full build and test suite via GitHub Actions, writing to a separate CI dataset so it never affects the production data. Auth is a single env-var swap shared by local and CI.

Two warehouses, one codebase

The same dbt project runs on BigQuery and Snowflake, chosen by target, with no forked models, no forked ingestion. The BigQuery-isms are resolved with dbt cross-database macros (date_trunc, datediff, generate_surrogate_key) and a target-aware source, so all 8 tests, including the custom one, pass identically on both. Snowflake auth is key-pair via env vars, mirroring BigQuery's; the ingestion script loads either warehouse with a --warehouse flag.

The dbt star schema materialized in Snowflake
The same models, built in Snowflake: BOC_DB.BOC_ANALYTICS, all 8 tests green.

Orchestrated with Airflow

A local Apache Airflow stack (Docker Compose, LocalExecutor + Postgres) runs the pipeline on a schedule: one DAG, ingest_raw โ†’ dbt_build, @daily with retries and catchup=False. dbt runs from an isolated venv baked into the image so its dependencies never collide with Airflow's, and it targets an isolated CI dataset so scheduled runs never touch the dashboard's data.

A successful boc_pipeline DAG run in Airflow
A successful boc_pipeline run, both tasks green on the daily schedule.

The stack

Warehouse & transform

BigQuery Snowflake dbt Core dbt-bigquery dbt-snowflake SQL

Ingestion

Python requests google-cloud-bigquery snowflake-connector

Orchestration

Airflow Docker Compose Postgres

CI & delivery

GitHub Actions Looker Studio

The Looker Studio dashboard, embedded below. Use the selector to switch indicators and drag across the chart to zoom into any period.