BKT Basket Trading
PCA-driven baskets — extracting mean-reverting components from multi-asset portfolios
Learning Objectives
- •Understand PCA-based basket construction
- •Apply PCA to extract mean-reverting components from correlated assets
- •Implement practical basket trading strategies
Explain Like I'm 5
Instead of trading pairs (2 assets), basket trading extends to N assets using PCA (Principal Component Analysis). PCA decomposes a group of correlated assets into independent components. The first component (PC1) captures the market factor — it trends. The higher components (PC2, PC3) capture relative value — they mean-revert. Trade the mean-reverting components, ignore the trending one. You just turned N correlated assets into clean, independent signals.
Think of It This Way
Imagine an orchestra. PCA identifies: the whole orchestra playing louder/softer (PC1 — the market trend), then violins being louder than cellos (PC2 — relative value between sections), then the brass section slightly offbeat (PC3 — another relative relationship). You don't want to bet on volume changes (PC1). You want to bet on the orchestra getting back in balance (PC2, PC3). Those components mean-revert.
1PCA-Based Baskets
2Practical Basket Construction
Key Formulas
PCA Decomposition
The covariance matrix of returns is decomposed into eigenvectors (W) and eigenvalues (Lambda). Each principal component k is a weighted combination of individual returns, where the weights come from the k-th eigenvector.
Hands-On Code
PCA Basket Construction
import numpy as np
from sklearn.decomposition import PCA
def pca_basket(returns_matrix, asset_names, n_components=3):
"""Construct PCA-based trading baskets from correlated assets.
returns_matrix: (n_obs, n_assets) array of returns
"""
pca = PCA(n_components=n_components)
components = pca.fit_transform(returns_matrix)
print(f"=== PCA BASKET ANALYSIS ===")
print(f"Assets: {', '.join(asset_names)}")
print(f"Observations: {returns_matrix.shape[0]}")
print(f"")
for i in range(n_components):
var_pct = pca.explained_variance_ratio_[i] * 100
loadings = pca.components_[i]
print(f"PC{i+1} ({var_pct:.1f}% variance):")
for name, w in zip(asset_names, loadings):
direction = 'LONG' if w > 0 else 'SHORT'
print(f" {name}: {w:+.3f} ({direction})")
print()
# Use PC2 as the relative-value basket
rv_basket = components[:, 1] # PC2 values over time
z = (rv_basket - np.mean(rv_basket)) / np.std(rv_basket)
print(f"PC2 Basket (Relative Value):")
print(f" Current z-score: {z[-1]:.2f}")
if abs(z[-1]) > 2.0:
print(f" [SIGNAL] Trade the basket")
else:
print(f" No trade signal")
return components, pca.components_, zConstructs PCA-based baskets from multiple correlated assets, identifies the mean-reverting components, and generates trading signals on the relative-value basket.
Knowledge Check
Q1.In PCA of G10 FX returns, what does PC1 typically represent?
Assignment
Build a PCA-based basket from 5+ correlated FX pairs. Identify which principal components mean-revert. Backtest a z-score strategy on the relative-value component.