Project 01 · Data Quality · Anomaly Detection
Market Data Health Monitor: flag a bad feed before a model uses it.
Ingests a markets feed, runs data-correctness checks, and flags abnormal behavior with rolling z-score control limits, then reports what a researcher should review.
Premise: trading and research run on clean data, and the most expensive failures begin as a bad feed: a gap, a stale value, or a price that should never have printed.
Runs calendar, duplicate, validity, staleness, and freshness checks, then rolling z-score anomaly detection on returns and volume, and produces a per-feed verdict on whether to hold downstream models. A companion PySpark pipeline validates and models the feed into a star-schema DuckDB and Parquet lakehouse, publishes per-feed data-quality SLAs and source-to-target column lineage, ships a Databricks variant that writes Delta tables to Azure Data Lake, and is orchestrated by an Apache Airflow DAG with a data-quality gate. Built in Python and pandas, on a synthetic feed with issues injected on purpose, or a CSV upload of real data.
Relevant to
Time series · Anomaly detection · Data health
PySpark · Databricks · Azure ADLS · Delta
Airflow · Star schema · Lineage · DuckDB / Parquet
Project 02 · Machine Learning · Credit Risk
Credit Default Risk Model: rank the risk, then set the policy.
An end-to-end machine-learning credit model that predicts default probability and turns it into a lending decision, exposing the trade-off a policy threshold sets.
Premise: a lender approves on a policy. The interesting part of a credit model is the threshold you set and what it costs, more than the AUC.
Trains a gradient-boosting model against a logistic baseline on held-out data (about 0.80 AUC), then a threshold slider turns predicted risk into approve or decline, with the approval rate, the default rate among approved, and the share of bad applicants caught. Calibration and permutation importance show whether to trust it. A responsible-AI panel then audits approval-rate fairness across protected groups with fairlearn (disparate impact, equalized odds) and shows a bias-mitigation trade-off with a model card. Built in Python and scikit-learn on the Statlog German Credit data via OpenML. The point: the model ranks risk, and the threshold turns that ranking into a decision.
Relevant to
Gradient boosting · Calibration · Threshold policy
Responsible AI · fairlearn
Python · scikit-learn
Project 03 · Interactive Dashboard · Credit Risk
Credit Portfolio Risk Dashboard: where 2.26M loans actually default.
A fully interactive, self-hosted analytics dashboard over $34B of consumer lending, with grade risk gradients, vintage and geographic heatmaps, a risk-return frontier, and two US maps.
Premise: a credit book's real risk sits in the cross-tabs. The job is to show, fast, which grade, vintage, geography, and borrower profile carry the loss, and whether the portfolio is paid for taking it.
Rolls up the full 1.2GB Lending Club universe (2.26M loans, 2007 to 2018) locally in Python and pandas into a compact JSON of aggregates and cross-tabs, then renders it client-side with Apache ECharts: a dual-axis default-and-rate-by-grade chart, a 35-point sub-grade risk curve, a size-weighted risk-return scatter, a grade-to-sub-grade treemap, a zoomable origination-and-default vintage series, a state choropleth and a volume-and-risk bubble map, grade-by-purpose and grade-by-year heatmaps, and borrower-factor cuts. Same loan universe as the Credit Default Risk Model. Built to a strict content-security policy with no third-party calls.
Relevant to
Dashboards · BI · Data visualization
Choropleth and geo maps · Heatmaps · Vintage analysis
Python · pandas · Apache ECharts
Project 04 · Quantitative Finance · Factor Research
Has the value premium decayed? A retrospective on HML.
A research note on the Fama-French value factor, asking how strong the premium has been across history and across regimes, and how much of it should carry into forward expectations.
Premise: treating an in-sample factor mean as a forecast is a common error, and this note is built to show that gap.
Using monthly Fama-French factors from the Ken French Data Library, it estimates the full-sample premium with Newey-West standard errors and tracks how stable that premium stays across subperiods and a 10-year rolling window. It measures the value-winter drawdown directly, then closes on an honest forward read instead of a point forecast. Built in Python and statsmodels.
Relevant to
Factor research · Newey-West · Regime analysis
Python · statsmodels
Project 05 · Applied AI · Financial NLP
Cadence: structured intelligence from earnings calls.
A local-first AI tool that turns an unstructured earnings-call transcript into a structured KPI, sentiment, and risk dashboard in about 60 seconds, fully on-device.
Premise: earnings calls are dense and slow to read at portfolio scale, and cloud LLMs raise privacy and cost questions for market-sensitive text.
Runs a local LLM (Ollama, Qwen2.5) with JSON-schema-constrained decoding to extract themes, risks, and evidence, rendered in a Streamlit dashboard. It's an end-to-end Python data-and-AI pipeline where the transcript never leaves the machine, zero marginal cost and full control of prompt and schema.
Relevant to
Local LLM · NLP · Data pipeline
Python · Streamlit · Ollama
Project 06 · Applied AI · Trustworthy AI
Reconcile: an AI spending review you can audit.
A one-month spending analysis where a frontier model and a hand-written rules engine categorize every transaction independently, and the app surfaces the disagreements for a human instead of resolving them silently.
Premise: an LLM is useful on financial data but should not be trusted blindly, so the categorization runs twice and its accuracy is measured against a hand-labelled ground truth rather than asserted.
The model reached 96.9% accuracy, and every model-vs-rules disagreement is shown with who was right. Built in Python with a static, offline-first front end and an optional Cloudflare Workers AI endpoint that degrades gracefully. Human-in-the-loop by design.
Relevant to
LLM evaluation · Human-in-the-loop · Cross-check
Python · Cloudflare Workers AI
Project 07 · Data Science · Key-Driver Analysis
Member Experience Key-Driver Analysis: what actually moves "would you recommend".
An NPS-style root-cause analysis built end to end from raw public survey data in SQL, ranking which experience drivers move the recommendation rate and where an operations team should spend first.
Premise: for a high-touch service, the lowest-scoring dimension is rarely the highest-impact lever. The job is to prioritize by derived importance, not by the worst score.
Built from CMS HCAHPS survey data (about 3,956 reporting hospitals and 2.3M completed surveys). The original analysis runs end to end in DuckDB and SQL; the live dashboard pulls the same survey file from the CMS Provider Data Catalog and rolls it up in Python. It computes survey-weighted top-box means, then measures importance with Johnson relative weights (model R-squared 0.57), which stay stable even though the experience dimensions are strongly correlated. Communication dimensions, led by discharge information and nurse communication, drive recommendation far more than the physical environment. Quietness scores lowest, near 56%, yet is one of the weakest levers, so the analysis argues against leading with it. Cited to the literature (AHRQ, Doyle et al. BMJ Open 2013, Reichheld HBR 2003).
Relevant to
Key-driver regression · NPS · Root-cause
DuckDB · SQL · Survey weighting
Python · statsmodels
Project 08 · Data Science · Uncertainty Modeling
Reclaimed Lumber Intelligence: where salvageable wood emerges, and what it is worth.
A salvageable-lumber intelligence layer for Circular Construction Canada, estimating where reclaimable wood will emerge and what it is worth across Canada's 25 largest metro areas.
Premise: a single point estimate implies a precision this data can't support. The work is to source every coefficient and propagate its uncertainty into a range a decision-maker can act on.
Built in Python and Streamlit across 25 census metropolitan areas. Demolition activity and real StatCan housing-stock vintage feed a framing-based recovery cascade and a value layer. A Monte Carlo engine draws 4,000 samples across every sourced coefficient, kept correlated across metros so national error doesn't falsely diversify away, and reports P10/P50/P90 instead of a single number. A sensitivity tornado shows that recovery method is the highest-leverage assumption. Toronto demolition permits pull live from Toronto Open Data, with a cached fallback when the feed is down. Every coefficient traces to a dated source such as USDA FPL and StatCan.
Relevant to
Monte Carlo · Uncertainty quantification
Forecasting · Sensitivity analysis
Python · Streamlit · Toronto Open Data
Project 09 · Data Engineering · Capital Markets
Corroborate: a queryable record of 63,505 market events.
An event store built for retrieval rather than storage, where the query path had to survive a corpus an order of magnitude larger than the vector index could hold.
Method: 63,505 events across macro, markets and micro, indexed with FTS5 in SQLite so full-corpus search stays unmetered per query. Sampling for the timeline uses window functions partitioned by time slice and category, because ranking by importance alone starved whole categories out of the view and truncating to the newest rows collapsed five years into one dense blob.
Market capitalisation is split-adjusted back to today's share basis, which matters more than it sounds: over five years H&R Block's share count fell 28.8% and Imperial Oil's 30.5%, so price and market cap diverge by exactly the buyback. Embeddings batch 100 texts per call to keep a batch to one subrequest, with a length guard on the response because results map positionally and a mismatch silently attaches the wrong meaning to an event.
Type
SQLite FTS5 · Window functions · Embeddings
63,505 events · 5-year history