Transaction Costs & Market Impact: Models & Analysis › Strategy Capacity and Scalability

Michael BrenndoerferJanuary 8, 20263 min read
Quantitative FinanceAll chapters
Part 14 of 15Strategy Development and Backtesting
Chapter 74Transaction Costs & Market Impact: Models & Analysis › Strategy Capacity and Scalability
Reading section 12 of 16 · Strategy Capacity and Scalability · 3 minSection 12 of 16 · 3 min

Book contents

Section 12 of 16 · 3 min read

Transaction Costs & Market Impact: Models & Analysis › Strategy Capacity and ScalabilityOne section · Sections in this chapter12 / 16 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Understanding transaction costs leads naturally to questions about strategy capacity: how much capital can a strategy manage before costs erode its edge? This question is central to both strategy development and fund management. A strategy that generates attractive returns at small scale may become mediocre or even unprofitable at larger scale due to the nonlinear relationship between trade size and impact costs.

Strategy Capacity

Strategy Capacity is the maximum capital a strategy can manage while maintaining acceptable risk-adjusted returns. Beyond this capacity, market impact costs grow faster than the alpha generated, causing net performance to deteriorate.

The square-root impact model implies that market impact grows with the square root of trade size, but total impact (in dollars) grows with size raised to the power 1+γ1 + \gamma, typically around 1.51.5. This means doubling your capital roughly triples your impact costs, creating a natural ceiling on strategy size. To understand this relationship mathematically, consider that impact per dollar traded scales as QγQ^{\gamma} where γ≈0.5\gamma \approx 0.5. When you double your capital, you double QQ, so impact per dollar becomes 20.5≈1.412^{0.5} \approx 1.41 times larger. But you're also trading twice as many dollars, so total impact costs become 2×1.41≈2.822 \times 1.41 \approx 2.82 times larger, which is roughly tripling.

In[31]:
Code
from scipy.optimize import brentq


def estimate_strategy_capacity(
    gross_alpha,
    turnover,
    daily_volume,
    volatility,
    eta=0.1,
    gamma=0.5,
    fixed_cost_bps=5,
    min_net_alpha=0.02,
):
    """
    Estimate strategy capacity based on market impact model.

    Parameters:
    -----------
    gross_alpha : float
        Expected gross alpha (annualized)
    turnover : float
        Annual turnover (as multiple of AUM)
    daily_volume : float
        Daily trading volume in the market
    volatility : float
        Daily volatility
    eta, gamma : float
        Impact model parameters
    fixed_cost_bps : float
        Fixed costs in basis points
    min_net_alpha : float
        Minimum acceptable net alpha

    Returns:
    --------
    capacity : float
        Estimated strategy capacity in dollars
    """
    # Convert annual to daily
    daily_turnover = turnover / 252
    fixed_cost = fixed_cost_bps / 10000

    # Capacity where net alpha = min_net_alpha
    # gross_alpha - fixed_cost * turnover - impact_cost * turnover = min_net_alpha
    # impact_cost = vol * eta * (AUM * daily_turnover / daily_volume)^gamma

    # Solve for AUM numerically
    def net_alpha(aum):
        daily_trade = aum * daily_turnover
        participation = daily_trade / daily_volume
        impact = volatility * eta * (participation**gamma)
        annual_impact_cost = impact * turnover
        annual_fixed_cost = fixed_cost * turnover
        return (
            gross_alpha - annual_fixed_cost - annual_impact_cost - min_net_alpha
        )

    try:
        capacity = brentq(net_alpha, 1e4, 1e12)
    except ValueError:
        capacity = np.inf if net_alpha(1e4) > 0 else 0

    return capacity


# Estimate capacity for different strategy types
strategies_capacity = [
    ("Value (low turnover)", 0.08, 0.5, 50_000_000, 0.02),
    ("Momentum", 0.12, 4.0, 20_000_000, 0.02),
    ("Stat arb", 0.20, 20.0, 10_000_000, 0.025),
    ("Intraday momentum", 0.30, 100.0, 5_000_000, 0.03),
]

capacity_results = []
for name, alpha, turnover, volume, vol in strategies_capacity:
    capacity = estimate_strategy_capacity(alpha, turnover, volume, vol)
    capacity_results.append(
        {
            "Strategy": name,
            "Gross Alpha": alpha,
            "Turnover": turnover,
            "Capacity ($M)": capacity / 1e6,
        }
    )

capacity_df = pd.DataFrame(capacity_results)
capacity_df["Gross Alpha Pct"] = capacity_df["Gross Alpha"] * 100
Out[32]:
Console
Estimated Strategy Capacity:
=================================================================
Strategy                     Gross α   Turnover        Capacity
=================================================================
Value (low turnover)              8%         0x           >$10B
Momentum                         12%         4x           >$10B
Stat arb                         20%        20x          $1457M
Intraday momentum                30%       100x             $7M

The low-turnover value strategy has essentially unlimited capacity because its trading costs are minimal. In contrast, the high-turnover intraday momentum strategy can only manage several million before impact costs erode its edge. This explains why some of the most successful strategies remain small and capacity-constrained.