Skip to content
Finance Lessons

Graph Neural Networks for Financial Networks & Systemic Risk

Markets Are Graphs, Not Tables

Most ML in finance flattens an interconnected world into a feature table and severs the relationships. This is the representation shift: nodes and edges, directed vs undirected, weighted vs binary, the node/edge/graph feature stack, and the four canonical finance graphs — interbank lending, supply chains, asset-correlation networks, and on-chain wallet/transaction graphs.

18 min Updated Jun 23, 2026

You spent a whole course teaching neural nets to read sequences — one asset’s price, one bank’s balance sheet, one address’s transaction history, marched through time. The nets got good. Then 2008 happened, and a single mid-sized investment bank failing took the rest of the system down with it, and not one of your beautiful per-asset sequence models saw it coming. Why would they? You never told them the banks were connected.

Here’s the uncomfortable truth this course opens with: the most expensive risks in finance live in the relationships between entities, and the standard ML pipeline deletes those relationships in step one. You load a CSV. Each row is a bank, a firm, a stock, a wallet. Each column is a feature. And the instant you do that, you have committed a small act of vandalism — you have taken a richly interconnected world and smeared it flat, severing every link that made it interesting.

This lesson is the representation shift. Before we touch a single graph neural network (GNN) — a model that learns directly on nodes-and-edges structure rather than on flat rows — you need to see markets as graphs. Once you do, you can’t unsee it, and the rest of the course becomes a tour of what to do about it.

The vandalism of flattening to a table

Before you read — take a guess

You build a feature table with one row per bank — assets, leverage, deposits, capital ratio. What does this representation fundamentally throw away?

Analogy. Imagine describing a city’s traffic by handing someone a spreadsheet: one row per intersection, columns for “cars per hour” and “average speed.” Useful, until a crash on one road backs up six others. The spreadsheet cannot represent that, because it never recorded which roads connect to which. You measured the intersections and deleted the streets. A feature table of banks does the same thing — it measures the banks and deletes the loans.

Definition. A feature table (also called tabular or flat data) represents a dataset as a matrix where each row is one entity and each column is one attribute of that entity, measured in isolation. Formally, entity ii is the vector xiRdx_i \in \mathbb{R}^d, and the dataset is the stack XRn×dX \in \mathbb{R}^{n \times d}. The crucial omission: nowhere in XX is there any cell that says “entity ii is related to entity jj.” That relational information — the adjacency — is structurally unrepresentable in a flat table. It is not lost to noise; it is lost to the shape of the container.

Worked example. Take four banks: A, B, C, D. The feature table looks like this.

BankAssets ($bn)LeverageCapital ratio
A100128%
B40205%
C60157%
D30254%

Now suppose the real situation is: A lent $20bn to D, and D is about to default. A model trained on this table sees A as a large, modestly leveraged, healthy-looking bank and predicts: fine. It has no column for “A is owed $20bn by the riskiest bank in the set,” because the loan from A to D is a relationship, and the table has no place to put relationships. The single most important fact for A’s risk — its exposure to D — is exactly the fact the representation discarded. The arithmetic the model can do (8% capital, 12x leverage → looks safe) is arithmetic on the wrong inputs.

Warning:

The flattening is silent

Flattening to a table never throws an error. The pipeline runs, the model trains, the metrics look fine on rows that happen to be independent. The damage only surfaces when a relationship matters — a counterparty defaults, a supplier halts, a correlated cluster moves together — and your model, having never been shown the links, is blindsided. A silent representation bug is the most dangerous kind, because nothing tells you it happened.

When to use it

A feature table is the right representation when entities really are independent — when predicting one row genuinely doesn’t depend on any other row. Predicting whether this customer churns from this customer’s behavior? Tabular is fine. The moment the answer for entity ii depends on who ii is connected to — counterparty risk, contagion, co-movement, fund flows — a table is the wrong container, and you should reach for a graph.

Fill in what a flat feature table cannot represent.

Pick the right option for each blank, then check.

A feature table stores each entity's own attributes but structurally cannot store the , which is exactly where contagion and systemic risk live.

Nodes and edges: what a graph actually is

Before you read — take a guess

A graph is written G = (V, E). In a network of banks connected by loans, what are V and E?

Analogy. A subway map is a graph you already read fluently. The stations are nodes; the rail lines connecting them are edges. The map deliberately distorts geography — distances are wrong, angles are wrong — because what matters is what connects to what, not the flat coordinates. A graph keeps the connections and drops the pretense that entities float in isolation.

Definition. A graph is the pair G=(V,E)G = (V, E), where VV is a set of nodes (vertices) — the entities — and EV×VE \subseteq V \times V is a set of edges — the relationships, each edge being a pair of nodes (i,j)(i, j). On top of this skeleton sit three layers of features:

  • Node features xix_i: attributes of entity ii (a bank’s assets, leverage, capital ratio) — exactly the columns of the old feature table, now attached to nodes.
  • Edge features eije_{ij}: attributes of the relationship between ii and jj (the size of a loan, the strength of a correlation) — the layer that has no home in a table.
  • Graph-level features: attributes of the whole structure (total number of edges, overall connectedness, how clustered the network is).

The relationships are commonly stored in the adjacency matrix AA, an n×nn \times n matrix where Aij=1A_{ij} = 1 if there is an edge from ii to jj and Aij=0A_{ij} = 0 otherwise. A graph is therefore the old feature table XX plus the adjacency AA — and that AA is the whole point.

Worked example. Take the same four banks, A, B, C, D, indexed 1, 2, 3, 4. Suppose the (undirected, for now) lending links are: A–B, A–C, and C–D. Building the adjacency matrix, we put a 1 wherever two banks are linked and 0 otherwise, with rows/columns in order A, B, C, D:

A=(0110100010010010)A = \begin{pmatrix} 0 & 1 & 1 & 0 \\ 1 & 0 & 0 & 0 \\ 1 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \end{pmatrix}

Read it row by row. Row A (top): A12=1A_{12} = 1 (A–B), A13=1A_{13} = 1 (A–C), so A links to B and C. Row B: only A21=1A_{21} = 1, so B links only to A. Row C: A31=1A_{31} = 1 and A34=1A_{34} = 1, so C links to A and D. Row D: only A43=1A_{43} = 1, so D links only to C. Because the links are undirected, the matrix is symmetric: Aij=AjiA_{ij} = A_{ji}, which is why the 1s mirror across the diagonal. The diagonal is all zeros — no bank lends to itself.

Info:

The table never left; it got a partner

A graph does not replace your features — it augments them. The node feature vectors are still your old columns. What’s new is the adjacency matrix riding alongside, encoding who connects to whom. Everything you learned about feature engineering still applies to the nodes; you’ve just stopped pretending they sit in separate rooms.

When to use it

Reach for the explicit G=(V,E)G = (V, E) framing the moment you can name the entities and name the relationship that links them. If you can finish the sentence “entity X is ___ to entity Y” with a real relation (lends to, supplies, correlates with, sends funds to), you have edges, and you have a graph. If you can’t, you may genuinely have tabular data — don’t force structure that isn’t there.

Pick a term, then click its definition.

Directed vs undirected, weighted vs binary

Before you read — take a guess

Bank A lends 20 billion dollars to bank D. How should that edge be represented?

Analogy. Friendship is undirected — if you’re my friend, I’m yours, symmetric. Owing money is directed — me owing you $100 is a very different state of the world from you owing me $100, and pretending they’re the same is how you lose $200. “Weighted vs binary” is the difference between “I owe you something” (binary, useless) and “I owe you $100” (weighted, actionable).

Definition. Edges come in two independent flavors, giving four combinations:

  • Undirected: the edge (i,j)(i, j) is the same as (j,i)(j, i); the adjacency matrix is symmetric (Aij=AjiA_{ij} = A_{ji}). Use it for mutual relationships — correlation between two assets is the same in both directions.
  • Directed: (i,j)(i, j) differs from (j,i)(j, i); the matrix is generally not symmetric. Use it for one-way relationships — A lends to D, D does not thereby lend to A.
  • Binary: edge entries are 0 or 1 — the link either exists or it doesn’t.
  • Weighted: edge entries are real numbers WijW_{ij} carrying magnitude — the loan size, the correlation strength. The matrix is then a weight matrix WW rather than a plain 0/1 adjacency.

Worked example. Now treat the bank loans as what they are: directed and weighted. Suppose A lent $20bn to D, A lent $5bn to C, and C lent $8bn to B. We index A, B, C, D as 1, 2, 3, 4 and put the amount lent from row to column in each cell:

W=(00520000008000000)W = \begin{pmatrix} 0 & 0 & 5 & 20 \\ 0 & 0 & 0 & 0 \\ 0 & 8 & 0 & 0 \\ 0 & 0 & 0 & 0 \end{pmatrix}

Read row A: W13=5W_{13} = 5 and W14=20W_{14} = 20 — A is owed by C and D. Read row C: W32=8W_{32} = 8 — C is owed by B. Rows B and D are all zeros: B and D lent to no one (they are pure borrowers). The matrix is not symmetricW14=20W_{14} = 20 but W41=0W_{41} = 0 — which correctly encodes that A is exposed to D, not the reverse. Compare with a correlation network on the same four entities: there, Wij=WjiW_{ij} = W_{ji} always, because if asset A correlates 0.6 with asset D, then D correlates 0.6 with A by definition.

PropertyInterbank loanAsset correlation
DirectionDirected (A → D)Undirected (A ↔ D)
WeightExposure in dollarsCorrelation magnitude
Matrix symmetryAsymmetricSymmetric
Self-loopsNone (no bank lends to itself)Diagonal is 1 (self-correlation)
Warning:

Direction is risk direction

Symmetrizing a directed financial graph for convenience — pretending A→D and D→A are the same — is not a harmless simplification. It tells your model that A’s and D’s exposures are interchangeable when they are opposite. In contagion analysis, direction is the mechanism: losses flow from borrower to lender along the arrow. Drop the arrow and you’ve deleted the physics.

When to use it

Pick directed whenever the relationship has a giver and a receiver (loans, supply flows, fund transfers, ownership). Pick undirected for genuinely mutual relations (correlation, co-membership, similarity). Pick weighted whenever how much changes the answer (it almost always does in finance), and reserve binary for the rare case where mere existence is all that matters — and even then, ask whether a weight is hiding in plain sight.

Sort each financial relationship by how its edge should be represented.

Place each item in the right group.

  • Correlation between two stocks
  • Two firms share the same board member
  • Bank A lends to bank D
  • Supplier ships parts to a manufacturer
  • Wallet sends crypto to another wallet
  • Two assets co-move in the same risk cluster

Degree, neighbourhood, paths and hops

Before you read — take a guess

A bank is connected to 9 other banks — the highest degree in the network. Does that make it the most systemically dangerous one?

Analogy. Degree is your number of contacts in your phone. Being popular (high degree) is not the same as being important — the one banker who holds half the city’s debt matters more than the influencer with 50,000 shallow follows. Counting connections tells you how busy a node is, not how much the system depends on it.

Definition. Three structural quantities, built straight from the adjacency matrix:

  • Degree did_i: the number of edges touching node ii. For an undirected binary graph, di=jAijd_i = \sum_j A_{ij} — sum across row ii. Directed graphs split this into in-degree (edges arriving) and out-degree (edges leaving).
  • Neighbourhood N(i)N(i): the set of nodes directly connected to ii — its immediate neighbors, one edge away.
  • Path and hops: a path is a sequence of edges connecting two nodes; a hop is one edge-step along it. The kk-hop neighbourhood of ii is every node reachable within kk steps. (Hold onto this — message-passing GNNs in the next lessons work by pulling information inward from a node’s kk-hop neighbourhood, one hop per layer.)

Worked example. Back to the undirected graph with edges A–B, A–C, C–D and its adjacency

A=(0110100010010010)A = \begin{pmatrix} 0 & 1 & 1 & 0 \\ 1 & 0 & 0 & 0 \\ 1 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \end{pmatrix}

Compute each degree by summing the row: dA=0+1+1+0=2d_A = 0+1+1+0 = 2, dB=1+0+0+0=1d_B = 1+0+0+0 = 1, dC=1+0+0+1=2d_C = 1+0+0+1 = 2, dD=0+0+1+0=1d_D = 0+0+1+0 = 1. So A and C are the hubs (degree 2); B and D are leaves (degree 1). The total degree 2+1+2+1=62+1+2+1 = 6 equals twice the edge count (3 edges) — a handy check, since every edge contributes to two nodes’ degrees.

Now 2-hop reach from B. B’s 1-hop neighbourhood is N(B)={A}N(B) = \{A\}. From A, one more hop reaches {B,C}\{B, C\}. So B’s 2-hop neighbourhood (excluding B itself) is {A,C}\{A, C\} — B can “feel” C even though it never lends to C directly, because the influence travels B→A→C. That is the entire intuition behind why a GNN with two layers lets a node sense its neighbors’ neighbors: information propagates one hop per layer.

NodeDegree1-hop neighboursReachable within 2 hops
A2B, CB, C, D
B1AA, C
C2A, DA, B, D
D1CC, A
Warning:

High degree is not high importance

The seductive shortcut “rank banks by number of connections, that’s your systemic-risk list” is wrong, and expensively so. A node’s importance depends on the weights of its edges and the fragility of its neighbors — a few huge exposures to shaky counterparties beat many tiny ones to healthy ones. Later in this course, DebtRank and related measures formalize exactly this: importance is a weighted, recursive property, not a headcount.

When to use it

Use degree as a first, cheap descriptor of how connected a node is — a fine starting filter, never a final ranking. Use neighbourhood and kk-hop thinking when you’re reasoning about reach: how far a shock can travel, or how many layers of message passing a GNN needs to let relevant information arrive. If the thing you care about is two hops away, a one-layer model is structurally blind to it.

If bank B never lends to bank C, why should B’s risk model care about C at all?

Answer. Because B lends to A, and A is heavily exposed to C. If C defaults, A takes a loss, A’s own solvency wobbles, and B’s loan to A is now riskier. The shock travels B ← A ← C along the path, even though no direct B–C edge exists. This is precisely why B’s 2-hop neighbourhood matters: contagion does not respect the boundary of direct connections. A model that only looks at B’s own row — or even only at B’s direct neighbors — cannot see the second-order exposure that a 2-hop view reveals.

The four canonical finance graphs

Before you read — take a guess

Which question can ONLY be answered with a graph representation, never with a flat feature table?

Analogy. Four different cities, four different subway maps — but all of them are stations-and-lines, all of them are graphs. Once you have the G=(V,E)G = (V, E) lens, finance stops looking like four unrelated problems and starts looking like one problem (structure) wearing four costumes. Learn to read the map and you can ride any of these networks.

Definition. Four graph types cover the overwhelming majority of financial network problems. Each fixes what counts as a node, what counts as an edge, whether edges are directed, and whether they’re weighted.

GraphNodesEdgesDirectionWeightA question only the graph answers
Interbank lendingBanksLoans / exposuresDirectedExposure amountIf bank D defaults, which lenders absorb the loss, and does it cascade?
Supply chainFirmsSupplier → customerDirectedOrder volume / dependencyIf a key supplier halts, which downstream firms stall?
Asset-correlationAssetsCorrelation above a thresholdUndirectedCorrelation magnitudeWhich assets form a hidden cluster that will all crash together?
On-chain wallet/txWallets / addressesTransfersDirectedAmount transferredWhich wallets are funneling funds through this address into a mixer?

Worked example — building a correlation network. Suppose four assets have these pairwise correlations: A–B = 0.82, A–C = 0.15, A–D = 0.71, B–C = 0.10, B–D = 0.68, C–D = 0.05. To build the graph we set a threshold, say 0.5, and draw an undirected weighted edge only when the absolute correlation clears it. Checking each pair: A–B (0.82 ✓), A–C (0.15 ✗), A–D (0.71 ✓), B–C (0.10 ✗), B–D (0.68 ✓), C–D (0.05 ✗). So the edges are A–B, A–D, B–D — a tightly correlated triangle of A, B, D — while C sits isolated, correlated with no one above 0.5. The risk read: A, B, D are a hidden cluster that will move together (diversifying across them buys you little), and C is the genuine diversifier. That cluster structure is invisible in a table of per-asset volatilities; it lives entirely in the edges.

Tip:

Same lens, four costumes

Notice what changed across the four graphs and what didn’t. What changed: the nouns (banks, firms, assets, wallets), the direction, the weight meaning. What stayed identical: nodes plus edges plus an adjacency matrix, and a class of questions about propagation and clustering that a flat table simply cannot phrase. Master the lens once and you’ve unlocked all four — which is exactly why this whole course is built on graphs, not on four separate playbooks.

When to use it

Match the graph to the question. Asking about cascades and who-absorbs-losses → interbank lending. Asking about operational disruption flowing downstream → supply chain. Asking about hidden co-movement and false diversification → asset-correlation. Asking about fund flows, laundering, and address behavior → on-chain transaction graph. If your question is about a single entity’s own numbers, you don’t need a graph at all — go back to the table.

Fill in the defining feature of each canonical finance graph.

Pick the right option for each blank, then check.

An asset-correlation network uses edges weighted by correlation magnitude, while an interbank lending network uses edges weighted by exposure.

Why this matters now: relational beats temporal-alone

Before you read — take a guess

The prerequisite course taught sequence models that learn one asset's history through time. How does a graph model differ in what it captures?

Analogy. Your prerequisite course gave each patient a heart-rate monitor — a beautiful time series of one person’s vitals. This course hands you the contact-tracing map — who’s near whom, who infected whom. For a contagious disease, the time series of one patient tells you they’re getting sick; the contact graph tells you who’s next. You want both monitors, and pointing the heart-rate monitor at the question “who catches it next?” will never answer it — that’s a graph question.

Definition. Temporal structure is how a single entity’s features evolve over time — the domain of sequence models (RNNs, temporal convolutions, attention over time) from Deep Learning for Market Data. Relational structure is how entities are wired to each other at a point in time — the domain of graph models. They live on orthogonal axes: one runs along time within a node, the other runs across edges between nodes. Neither subsumes the other. A pure sequence model, fed one asset at a time, is structurally incapable of seeing contagion; a pure (static) graph model is blind to how the network rewires over time.

Worked example. Consider predicting whether bank D defaults next quarter, given two modeling choices:

ModelWhat it seesWhat it missesVerdict on D
Sequence model (per-bank)D’s own 12-quarter history of leverage, deposits, capitalThat D owes A nothing but B and C lean heavily on D”D looks stressed but stable”
Graph model (static snapshot)The full lending network this quarter, D’s neighbors’ fragilityHow that network changed over the last year”D is a load-bearing node in a fragile cluster”
Temporal GNN (both axes)Each bank’s history and the evolving network“D’s centrality is rising while its capital falls — flag it”

The sequence model and the static graph each catch half the story. The temporal GNN — the destination this course builds toward — fuses them: per-node histories plus the evolving wiring. The point of this opening lesson is that you cannot get there until you stop flattening the network away in step one.

Info:

Where this course is headed

This lesson is the representation shift; it deliberately has no GNN in it yet. From here the course teaches message passing (how nodes pull information from their neighbourhoods), the core GNN architectures, then systemic-risk measures like DebtRank, and finally temporal GNNs that put the time axis back on top of the structure. Everything rests on one habit you should now own: when you meet a financial problem, ask first whether the entities are connected — and if they are, refuse to flatten them.

When to use it

Use a sequence model when the question is about one entity’s trajectory through time and connections are irrelevant. Use a graph model when the question is about structure and propagation at a moment. Use a temporal GNN when both matter — which, for systemic risk, contagion, and co-movement, is most of the time. The cardinal sin is using a sequence model alone for a question that is fundamentally relational, then wondering why it never saw the cascade coming.

Pick a term, then click its definition.

Recap

You came in able to model one asset, one bank, one wallet through time — and you learned why that, alone, is a blindfold. The expensive risks live in the relationships, and the standard feature-table pipeline deletes them silently in step one. A graph G=(V,E)G = (V, E) keeps them: nodes carry the old features, edges carry the relationships, and the adjacency matrix encodes who connects to whom. Edges can be directed or undirected, weighted or binary — and in finance the choice is never cosmetic, because direction is risk direction and weight is risk magnitude. Degree, neighbourhood, and kk-hop reach describe the structure, with the warning that a headcount of connections is not systemic importance. Four canonical graphs — interbank lending, supply chains, asset correlations, and on-chain transactions — cover most of finance, all the same lens in different costumes. And graphs don’t replace the sequence models you already know; they’re the orthogonal axis the best models fuse with time.

Big picture

Markets are graphs, not tables

  • Markets as graphs
    • Flattening is vandalism
      • Table = entities in isolation
      • Deletes the adjacency
      • Fails silently until a link matters
    • Graph G = (V, E)
      • Nodes = entities
      • Edges = relationships
      • Node / edge / graph features
      • Adjacency matrix A
    • Edge types
      • Directed vs undirected
      • Weighted vs binary
      • Direction = risk direction
    • Structure measures
      • Degree (a count, not importance)
      • Neighbourhood
      • k-hop reach (contagion travels)
    • Four finance graphs
      • Interbank lending (directed, weighted)
      • Supply chain (directed)
      • Asset correlation (undirected, weighted)
      • On-chain wallets (directed)
    • Relational vs temporal
      • Sequence = time within a node
      • Graph = structure across nodes
      • Temporal GNN fuses both
Build the map: the representation shift, the graph vocabulary, the four canonical finance graphs, and where it joins the time axis.

Mixed check: can you see the graph now?

Question 1 of 50 correct

In the four-bank undirected graph with edges A–B, A–C, and C–D, what is the degree of node A?

Check your answer to continue.

Mark lesson as complete