Cascade
Graph Intelligence / ML | 2026

The graph grows itself. The forecaster stays honest.
Designed and built the entire stack: a schema-driven Python backend (FastAPI, LightGBM, a PyTorch GNN, NetworkX), a leak-free evaluation harness, and an interactive Next.js graph workspace with a force-directed canvas and background training jobs. Solo build.
Cascade is a domain-agnostic graph intelligence platform. Given any networked entity, it builds a living knowledge graph of everything that influences it, trains quantile forecasters on that graph, validates them out-of-sample, and writes a structured decision brief automatically. Every node type, edge type, prediction target, and UI panel is declared in YAML, so a new domain is a config file, not a code change.
The thesis is that a decision scientist's weekly workflow (refresh the influence model, re-fit forecasters, validate, brief stakeholders) is fully automatable if you build it right. Cascade ships three production worlds (an 86-node equity and macro market graph, a logistics hub network, and a stock-equity demo) and an autonomous analyst loop that runs the whole pipeline on a schedule. No public launch yet; built toward a decision-science portfolio review.
Graph-aware forecasting, evaluated honestly.
Cascade built the infrastructure for leak-free, graph-aware time-series forecasting and automated the full decision-science loop: expand the influence graph, retrain, backtest, and write the brief, as a scheduled pipeline. The headline result is measured inside the disruption window where graph context is supposed to help, and reported exactly where it does not. Every design decision is captured across 22 architecture decision records.
0.098 vs 0.151 MAE), so LightGBM stays the default and the GNN is the long-train path, not the headline. Every result runs through purged, embargoed time-series cross-validation.q10/q90 bands were badly overconfident (52% coverage against an 80% target). Conformalized Quantile Regression with purged calibration slices brought that to 71-78% across multi-window evaluation. Forecasts now ship a band you can trust.expand → retrain → backtest → forecast → brief → persist) so a dated decision brief appears with zero human intervention.Most forecasting demos quietly train on the future.
Logistics and decision-science teams run manual weekly cadences: someone pulls data from several sources, engineers features, fits a model, eyeballs a backtest, and writes a stakeholder brief. There is no standard tooling for it. Meanwhile most portfolio projects in this space commit the same sin: they shuffle time-series rows, test on data the model has effectively already seen, and quote accuracy numbers that collapse under honest evaluation. The gap is an automated, rigorous platform that tells the truth about what graphs actually help predict.
“Purge and embargo your folds, or your backtest is fiction.”
“Gradient-boosted trees beat every deep model on tabular forecasting.”
“My LSTM crushes the backtest but dies live.”
Build it so the truth is cheaper than the lie.
Five constraints shaped every architectural decision. The hard one is the second: honest evaluation had to be the path of least resistance, or it would quietly erode the first time a number looked disappointing.
asyncio.to_thread with per-entity locks.Four pivots, each one a result I didn't want.
The suspiciously clean number
The first ablation used random row shuffles and reported an 11.4% MAE improvement on logistics. Too clean. The diagnosis: training on the future, testing on the past. Switching to purged chronological evaluation everywhere dropped it to an honest 4.4% overall (7-19% at short horizons). A weaker number, a far stronger story.
Node2Vec memorized instead of generalizing
Adding 128-dim structural embeddings to the 11-node stock model measurably degraded out-of-sample performance on FDX. With that few nodes, the embeddings memorize node identity. Fix: a schema flag, use_embeddings: false for small graphs, on for the 60+ node logistics network where structural roles actually generalize.
What does my trained model actually know?
Users training models had no visibility into what was trained. I added a model_info endpoint and a Model card in the UI showing family, profile, tree count, calibration method, coverage, and a top-feature importance chart. An invisible process became an inspectable artifact.
From pieces to a pipeline
Every component existed in isolation: living graph, retrained models, backtester, LLM client. Wiring them into a scheduled analyst_loop (expand, retrain, backtest, forecast, brief, persist) is the moment the project went from an interesting demo to something that replaces a human workflow.
One pipeline, declared in YAML, run on a schedule.
Data flows in one direction: a YAML schema drives a feature builder over the graph, a quantile model, conformal calibration, a purged backtester, and finally the analyst loop that narrates the result. Swap the schema and the same pipeline retargets to a new domain.
EntitySchema.from_dict turns a YAML file into node types, edge types, prediction targets, capabilities, and UI panels. Zero domain logic lives in Python.q10/q50/q90) wrapped in Conformalized Quantile Regression, with a PyTorch temporal GNN as the long-train path.# Adding a domain is config, not code.
entity: logistics_network
node_types: [hub, lane, carrier, weather, fuel]
edge_types: [feeds, delays, correlates]
target: delay_hours
use_embeddings: true # 60+ nodes, roles generalize
capabilities: [forecast, backtest, optimize]The workspace, end to end.
The live Cascade Console: the influence graph, the node inspector with causal edge metadata, the model and backtest panels, the autonomous analyst loop, and the provider settings that keep it portable.





The negative result became the credibility.
What worked
What I'd do differently
The lead-lag feature shift made the forecast worse. The Granger engine correctly recovers planted structure on synthetic logistics data (including a 3-hour weather-to-delay lead), but using that discovered lag to shift each neighbor's signal dropped the logistics improvement from 4.21% to 2.64%. A node's composite signal averages attributes with different natural lags, so one global shift misaligns the rest. Causal discovery is valuable as edge metadata; exploiting it in predictions needs per-attribute lagged features, not a single composite shift. The gap between “causally discovered” and “predictively useful” was the biggest technical surprise of the project.