1. Introduction: Single-Asset vs. Multi-Asset Impact
In quantitative execution, modeling transaction costs is usually performed on an asset-by-asset basis: the price of asset $i$ is assumed to depend solely on the trading speed of asset $i$. While this approximation is useful for isolated executions, it fails when trading multi-asset portfolios containing highly correlated or linked assets (e.g., executing large blocks of BTC and ETH simultaneously, or liquidation of closely tied equities).
Under a multi-asset setup, executing a large trade in one asset triggers price updates and order cancellations in correlated assets. This phenomenon is known as **cross-impact** or **price spillover**. Neglecting these cross-impact terms leads to underestimating execution slippage and miscalculating optimal execution trajectories.
2. Mathematical Formulation: The Cross-Impact Matrix
To model cross-impact, we generalize the classical linear execution models (like Almgren-Chriss) to a vector-matrix framework. Let $Q$ be the vector of share volumes we need to execute across $d$ assets. The trading speed vector at step $t$ is $v_t = u_t / \tau$.
The price vector change $\Delta P_t$ over time interval $\tau$ is modeled as:
$\Delta P_t = \Gamma \cdot u_t + \tau^{1/2} \cdot \Sigma \cdot \xi_t$
Where $\Gamma$ is the $d \times d$ **permanent cross-impact matrix**, $\Sigma$ is the co-volatility Cholesky factor, and $\xi_t$ is a vector of independent standard Gaussian noise. The execution price vector $\tilde{P}_t$ is affected by the $d \times d$ **temporary cross-impact matrix** $H$:
$\tilde{P}_t = P_t - H \cdot v_t$
The off-diagonal elements of $\Gamma$ and $H$ represent the cross-impact parameters. For instance, $\Gamma_{ij}$ represents the permanent price impact on asset $i$ caused by trading unit volume of asset $j$.
| Matrix Type | Representation | Economic Driver | Systemic Effect |
|---|---|---|---|
| Permanent Cross-Impact $\Gamma$ | $d \times d$ asymmetric matrix | Information spillovers, asset substitution, and cross-asset arbitrage. | Long-term price shifts across correlated books. |
| Temporary Cross-Impact $H$ | $d \times d$ positive definite matrix | Shared liquidity pools, high-frequency market-making inventories, and correlation desk hedging. | Short-term spread widening during execution. |
3. Optimal Portfolio Liquidation
The objective is to find the sequence of inventory vectors $X_t$ that minimizes the portfolio expected shortfall $E[x]$ and variance $V[x]$ adjusted by a risk aversion parameter $\lambda$. When cross-impact matrices are positive definite, the optimal liquidation trajectory exhibits a coordinated decay: assets with higher cross-impact are liquidated slower or faster depending on whether their joint execution offsets portfolio variance risk.
Ignoring the cross-impact terms leads to sub-optimal scheduling, especially in market stress regimes where correlations spike toward unity. A correctly calibrated cross-impact model can reduce total execution cost by 12% to 18% compared to independent single-asset models.
4. Python Implementation: Simulating Multi-Asset Cross-Impact
The following Python script simulates price changes for a 2-asset portfolio under permanent and temporary cross-impact effects during execution:
import numpy as np
def simulate_cross_impact(inventory_trajectory, gamma_matrix, h_matrix, sigma_cov, steps=10):
"""
Simulates price paths of 2 assets under execution cross-impact.
inventory_trajectory: shape (steps+1, 2)
"""
prices = np.zeros((steps + 1, 2))
prices[0] = [100.0, 50.0] # Initial mid-prices
for t in range(1, steps + 1):
# Calculate trade speeds (change in inventory)
u_t = inventory_trajectory[t-1] - inventory_trajectory[t]
# 1. Generate random price shock using co-volatility
shock = np.random.multivariate_normal([0, 0], sigma_cov)
# 2. Permanent cross-impact price shift
perm_impact = np.dot(gamma_matrix, u_t)
prices[t] = prices[t-1] + perm_impact + shock
# 3. Execution price incorporating temporary cross-impact
exec_price = prices[t] - np.dot(h_matrix, u_t)
print(f"Step {t} - Asset A Mid: {prices[t][0]:.2f} | Exec: {exec_price[0]:.2f}")
print(f" Asset B Mid: {prices[t][1]:.2f} | Exec: {exec_price[1]:.2f}")
return prices
# Example setup: 2 assets, correlated volatility
gamma = np.array([[1e-5, 0.4e-5],
[0.4e-5, 2e-5]]) # Permanent Cross-Impact Matrix
h = np.array([[2e-5, 0.8e-5],
[0.8e-5, 3e-5]]) # Temporary Cross-Impact Matrix
cov = np.array([[0.04, 0.01],
[0.01, 0.09]]) # Co-volatility matrix
# Inventory paths: Linear liquidation of 10k of Asset A, 5k of Asset B
trajectory = np.column_stack([np.linspace(10000, 0, 11), np.linspace(5000, 0, 11)])
simulate_cross_impact(trajectory, gamma, h, cov, steps=10)
5. Conclusion
As markets grow more integrated and execution desks process larger, correlated portfolios, modeling cross-impact is no longer optional. Incorporating multi-asset spillovers into optimal execution schedulers allows trading systems to control joint risk, reduce execution drag, and scale trading capacity across global electronic venues.