Cryptocurrency Markets and Quant Trading › Quantitative Strategies in Crypto

Michael BrenndoerferJanuary 5, 202620 min read
Quantitative FinanceAll chapters
Part 13 of 15Machine Learning and Alternative Data
Chapter 72Cryptocurrency Markets and Quant Trading › Quantitative Strategies in Crypto
Reading section 5 of 11 · Quantitative Strategies in Crypto · 20 minSection 5 of 11 · 20 min

Book contents

Section 5 of 11 · 20 min read

Cryptocurrency Markets and Quant Trading › Quantitative Strategies in CryptoOne section · Sections in this chapter5 / 11 ↓
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

The quantitative strategies we have studied throughout Part VI all have applications in cryptocurrency markets, though each requires adaptation to account for the unique characteristics we have discussed.

Statistical Arbitrage Across Exchanges

The fragmentation of crypto markets across hundreds of exchanges creates persistent price discrepancies. As we discussed in our chapter on statistical arbitrage, these discrepancies can be exploited, but the mechanics are more complex in crypto.

The basic cross-exchange arbitrage opportunity occurs when the same asset trades at different prices on different exchanges. At first glance, this seems like free money: buy where the asset is cheap, sell where it is expensive, and pocket the difference. However, several frictions stand between observation and profit. Trading fees consume a portion of the spread, and transferring assets between exchanges takes time and costs money. During that transfer window, prices can move against you. The potential profit πarb\pi_{\text{arb}} must account for all of these factors:

πarb=Phigh−Plow−Ctransaction−Ctransfer\pi_{\text{arb}} = P_{\text{high}} - P_{\text{low}} - C_{\text{transaction}} - C_{\text{transfer}}

where:

  • πarb\pi_{\text{arb}}: net profit from the arbitrage loop
  • PhighP_{\text{high}}: price on the exchange where the asset is expensive
  • PlowP_{\text{low}}: price on the exchange where the asset is cheap
  • CtransactionC_{\text{transaction}}: total trading fees (maker and taker) across both venues
  • CtransferC_{\text{transfer}}: estimated cost of transferring assets (network fees and time delay risk)

This formula captures the static economics of arbitrage, but the real challenge is dynamic. The prices PhighP_{\text{high}} and PlowP_{\text{low}} are not fixed during execution. Between the moment you identify the opportunity and the moment you complete both legs of the trade, prices will move. If Bitcoin is trading at $45,000 on Binance and $45,100 on Coinbase, the $100 gross spread looks attractive. But if it takes 30 minutes to transfer Bitcoin between exchanges, and Bitcoin's hourly volatility is 1%, there is substantial risk that the price on the expensive exchange will have fallen before you can sell.

We implement this in the CrossExchangeArbitrage class below. The calculate_opportunity method identifies the best buying and selling venues, computes the net profit after all fees, and applies a risk adjustment based on the asset's volatility and the estimated transfer time. The risk adjustment uses a 2-sigma buffer, meaning we subtract two standard deviations of expected price movement from our profit estimate, so we only execute when expected net profit remains positive after the adverse-move buffer:

In[11]:
Code
class CrossExchangeArbitrage:
    """
    Identify and analyze cross-exchange arbitrage opportunities.
    """

    def __init__(self, exchange_fees, transfer_cost_pct, transfer_time_hours):
        self.exchange_fees = exchange_fees
        self.transfer_cost = transfer_cost_pct
        self.transfer_time = transfer_time_hours

    def calculate_opportunity(self, prices_dict, volatility_hourly):
        """
        Calculate arbitrage profitability accounting for costs and risks.

        Parameters:
        -----------
        prices_dict : dict
            Exchange name -> current price
        volatility_hourly : float
            Hourly volatility for risk calculation
        """
        exchanges = list(prices_dict.keys())
        prices = list(prices_dict.values())

        # Find best bid and ask
        best_buy_exchange = exchanges[np.argmin(prices)]
        best_sell_exchange = exchanges[np.argmax(prices)]

        buy_price = min(prices)
        sell_price = max(prices)

        # Gross spread
        gross_spread_pct = (sell_price - buy_price) / buy_price * 100

        # Total costs
        buy_fee = self.exchange_fees.get(best_buy_exchange, 0.001)
        sell_fee = self.exchange_fees.get(best_sell_exchange, 0.001)
        total_costs = (buy_fee + sell_fee + self.transfer_cost) * 100

        # Net profit
        net_profit_pct = gross_spread_pct - total_costs

        # Risk: price can move during transfer
        transfer_risk = volatility_hourly * np.sqrt(self.transfer_time) * 100
        risk_adjusted_profit = (
            net_profit_pct - 2 * transfer_risk
        )  # 2 sigma buffer

        return {
            "buy_exchange": best_buy_exchange,
            "sell_exchange": best_sell_exchange,
            "gross_spread_pct": gross_spread_pct,
            "total_costs_pct": total_costs,
            "net_profit_pct": net_profit_pct,
            "transfer_risk_pct": transfer_risk,
            "risk_adjusted_profit_pct": risk_adjusted_profit,
            "executable": risk_adjusted_profit > 0,
        }


# Example: BTC prices across exchanges
exchange_fees = {
    "Binance": 0.001,
    "Coinbase": 0.004,
    "Kraken": 0.002,
    "Bitstamp": 0.003,
}

# Simulate price differences (typically small but persistent)
base_price = 45000
prices = {
    "Binance": base_price * 1.0000,
    "Coinbase": base_price * 1.0015,
    "Kraken": base_price * 1.0008,
    "Bitstamp": base_price * 1.0003,
}

arb = CrossExchangeArbitrage(
    exchange_fees=exchange_fees,
    transfer_cost_pct=0.0005,  # Blockchain fee as % of trade
    transfer_time_hours=1,  # Time to move BTC between exchanges
)

# BTC hourly volatility (approximately)
btc_hourly_vol = 0.65 / np.sqrt(252 * 24)  # Annual vol to hourly

opportunity = arb.calculate_opportunity(prices, btc_hourly_vol)
Out[12]:
Console
Cross-Exchange Arbitrage Analysis: BTC
==================================================

Exchange Prices:
  Binance     : $45,000.00
  Coinbase    : $45,067.50
  Kraken      : $45,036.00
  Bitstamp    : $45,013.50

Best Strategy: Buy on Binance, Sell on Coinbase
Gross Spread:         0.150%
Total Costs:          0.550%
Net Profit:           -0.400%
Transfer Risk (2σ):   0.836%
Risk-Adjusted Profit: -2.072%
Executable:           False

The challenge with cross-exchange arbitrage is that opportunities are typically small and fleeting. The transfer time between exchanges (which can range from minutes to hours depending on blockchain congestion) introduces significant execution risk. Sophisticated arbitrageurs maintain balances on multiple exchanges to execute immediately, then rebalance during quieter periods. This pre-positioning strategy eliminates transfer risk but requires substantial capital deployment across venues, each of which carries counterparty risk.

Key Parameters

The key parameters for the Cross-Exchange Arbitrage model are:

  • Fees: Trading fees (maker and taker) charged by exchanges. High fees increase the spread required for profitability and can turn a seemingly attractive opportunity into a loss.
  • Transfer Cost: The cost to move assets between exchanges, including blockchain network fees. During periods of network congestion, these fees can spike dramatically.
  • Transfer Time: The duration of the transfer, which exposes you to price risk while assets are in transit. The risk grows with the square root of time, as reflected in the volatility adjustment.
  • Volatility: The asset's volatility, used to calculate the risk buffer required to protect against price moves during transfer. Higher volatility demands larger spreads to justify the risk.

Triangular Arbitrage

Within a single exchange, triangular arbitrage exploits pricing inconsistencies across trading pairs. If you can buy BTC with USD, sell BTC for ETH, and sell ETH for USD at prices that net more than your starting USD, a risk-free profit exists. The beauty of triangular arbitrage is that all three trades can execute nearly simultaneously on the same exchange, eliminating the transfer risk that plagues cross-exchange strategies.

To understand why triangular arbitrage opportunities exist, consider that each trading pair on an exchange is essentially an independent market with its own supply and demand dynamics. When a large buyer enters the BTC/USD market, the BTC price rises against USD. But the ETH/BTC market may not adjust immediately, creating a brief window where the implied BTC price through the ETH/BTC pair differs from the direct BTC/USD price.

For three currencies A, B, and C with exchange rates RABR_{AB}, RBCR_{BC}, and RCAR_{CA}, the arbitrage return rarbr_{\text{arb}} is:

rarb=RAB×RBC×RCA−1r_{\text{arb}} = R_{AB} \times R_{BC} \times R_{CA} - 1

where:

  • rarbr_{\text{arb}}: arbitrage profit (positive values indicate a profitable loop)
  • RABR_{AB}: exchange rate to convert currency A to B
  • RBCR_{BC}: exchange rate to convert currency B to C
  • RCAR_{CA}: exchange rate to convert currency C back to A

The intuition behind this formula is that if markets are perfectly efficient, converting A to B to C and back to A should return exactly your starting amount, making the product of the three rates equal to 1. Any deviation from 1 represents mispricing that can be exploited. If this expression is positive after accounting for fees, an arbitrage opportunity exists. In practice, each trade incurs a fee that compounds through the loop, so the gross mispricing must exceed three times the single-trade fee rate.

The find_triangular_arbitrage function below evaluates this relationship for a specific triangular path (e.g., USD to BTC to ETH to USD). It calculates the potential return for both directions of the loop, factoring in trading fees at each step. Checking both directions is important because while one direction may show a loss, the reverse direction might be profitable:

In[13]:
Code
def find_triangular_arbitrage(rates, fee_pct=0.001):
    """
    Find triangular arbitrage opportunities given exchange rates.

    Parameters:
    -----------
    rates : dict
        Dictionary of rates, e.g., {'BTC/USD': 45000, 'ETH/USD': 2500, 'ETH/BTC': 0.055}
    fee_pct : float
        Trading fee per leg
    """
    # Extract rates (assuming standard naming convention)
    btc_usd = rates.get("BTC/USD", 45000)
    eth_usd = rates.get("ETH/USD", 2500)
    eth_btc = rates.get("ETH/BTC", 0.055)

    # Path 1: USD -> BTC -> ETH -> USD
    # Start with $1000
    start = 1000

    # Buy BTC with USD
    btc_amount = (start / btc_usd) * (1 - fee_pct)

    # Sell BTC for ETH
    eth_amount = (btc_amount / eth_btc) * (1 - fee_pct)

    # Sell ETH for USD
    final_usd = (eth_amount * eth_usd) * (1 - fee_pct)

    path1_profit = final_usd - start
    path1_return = (final_usd / start - 1) * 100

    # Path 2: USD -> ETH -> BTC -> USD (reverse)
    eth_amount_2 = (start / eth_usd) * (1 - fee_pct)
    btc_amount_2 = (eth_amount_2 * eth_btc) * (1 - fee_pct)
    final_usd_2 = (btc_amount_2 * btc_usd) * (1 - fee_pct)

    path2_profit = final_usd_2 - start
    path2_return = (final_usd_2 / start - 1) * 100

    # Implied fair rate for ETH/BTC
    implied_eth_btc = eth_usd / btc_usd
    mispricing = (eth_btc - implied_eth_btc) / implied_eth_btc * 100

    return {
        "path1_profit": path1_profit,
        "path1_return_pct": path1_return,
        "path2_profit": path2_profit,
        "path2_return_pct": path2_return,
        "implied_eth_btc": implied_eth_btc,
        "actual_eth_btc": eth_btc,
        "mispricing_pct": mispricing,
    }


# Scenario: Slight mispricing in ETH/BTC
rates = {
    "BTC/USD": 45000,
    "ETH/USD": 2500,
    "ETH/BTC": 0.0558,  # Slightly off from 2500/45000 = 0.0556
}

result = find_triangular_arbitrage(rates, fee_pct=0.001)
Out[14]:
Console
Triangular Arbitrage Analysis
==================================================

Market Rates:
  BTC/USD: $45,000.00
  ETH/USD: $2,500.00
  ETH/BTC: 0.0558

Implied ETH/BTC (from USD rates): 0.0556
Actual ETH/BTC: 0.0558
Mispricing: 0.440%

Path Analysis (starting with $1000):
  USD->BTC->ETH->USD: -0.7365%
  USD->ETH->BTC->USD: +0.1390%

In practice, triangular arbitrage opportunities in crypto are captured quickly by automated systems. The opportunities tend to be larger during periods of high volatility when market makers widen spreads asymmetrically across pairs. The key to profitability is execution speed: you who can identify and execute the triangular trade fastest capture the profit before prices adjust. This makes triangular arbitrage a game of latency optimization, similar to high-frequency trading in traditional markets.

Key Parameters

The key parameters for the Triangular Arbitrage model are:

  • Rates: Exchange rates for the currency pairs involved in the triangle. Small deviations from the no-arbitrage relationship create opportunities.
  • Fee: Trading fee percentage charged on each leg of the trade. Fees compound through the loop, so a 0.1% fee per leg results in approximately 0.3% total cost for the round trip.
  • Spread: The difference between the implied cross-rate and the actual cross-rate, which drives the opportunity. This spread must exceed the total fees for the trade to be profitable.

Momentum and Trend Following

As we explored in our chapter on trend following, cryptocurrency markets exhibit strong momentum characteristics. The retail-dominated nature of the market and the influence of social media create trend persistence that can be exploited. Unlike institutional-dominated markets where sophisticated participants quickly arbitrage away mispricings, crypto markets can trend for extended periods as waves of retail traders chase performance.

The psychological dynamics underlying crypto momentum are particularly pronounced. When Bitcoin rises 10% in a week, mainstream media coverage increases, which attracts new retail investors, who buy and push prices higher, generating more media coverage in a self-reinforcing cycle. The same dynamics work in reverse during downtrends, with fear and negative headlines driving selling. These behavioral patterns create momentum that systematic strategies can capture.

The CryptoMomentumStrategy class implements a volatility-scaled trend following approach. It generates buy/sell signals based on the lookback return sign, scales position sizes inversely to volatility to maintain a constant risk target, and applies a leverage cap to prevent excessive exposure. The volatility scaling is particularly important in crypto because volatility can double or triple within days. Without this adjustment, a fixed position size would expose the strategy to unacceptable risk during high-volatility periods:

In[15]:
Code
class CryptoMomentumStrategy:
    """
    Momentum strategy adapted for crypto markets.
    """

    def __init__(
        self, lookback_days=20, volatility_lookback=30, risk_target=0.20
    ):
        self.lookback = lookback_days
        self.vol_lookback = volatility_lookback
        self.risk_target = risk_target

    def generate_signals(self, prices):
        """
        Generate momentum signals with volatility scaling.
        """
        returns = prices.pct_change()

        # Momentum signal: sign of lookback return
        momentum = prices.pct_change(self.lookback)
        signal = np.sign(momentum)

        # Volatility for position scaling
        volatility = returns.rolling(self.vol_lookback).std() * np.sqrt(252)

        # Position size: scale inversely with volatility
        position = signal * (self.risk_target / volatility)

        # Cap positions at 2x leverage
        position = position.clip(-2, 2)

        return pd.DataFrame(
            {
                "price": prices,
                "momentum": momentum,
                "signal": signal,
                "volatility": volatility,
                "position": position,
            }
        )

    def backtest(self, prices):
        """
        Simple backtest of momentum strategy.
        """
        signals = self.generate_signals(prices)

        # Strategy return: position(t-1) * return(t)
        signals["return"] = prices.pct_change()
        signals["strategy_return"] = (
            signals["position"].shift(1) * signals["return"]
        )

        # Account for transaction costs (estimate)
        signals["position_change"] = signals["position"].diff().abs()
        signals["costs"] = (
            signals["position_change"] * 0.001
        )  # 10 bps per unit traded
        signals["net_return"] = signals["strategy_return"] - signals["costs"]

        # Cumulative returns
        signals["cumulative_bh"] = (1 + signals["return"]).cumprod()
        signals["cumulative_strategy"] = (1 + signals["net_return"]).cumprod()

        return signals


# Apply to our simulated BTC series
btc_prices = pd.Series(price_btc, index=dates)
strategy = CryptoMomentumStrategy(lookback_days=20, risk_target=0.20)
backtest_results = strategy.backtest(btc_prices)
Out[16]:
Visualization
Dual-axis chart with simulated Bitcoin price and a filled momentum position that varies between long and short exposure.
Simulated Bitcoin price and momentum exposure. The strategy changes sign with the 20-day trend, scales exposure inversely to realized volatility, and caps absolute leverage at 2x.
Line chart in which buy-and-hold finishes well above the momentum strategy after a strong late rally.
Cumulative performance in this simulated path. Momentum protects capital during the early decline but misses much of the subsequent rally and finishes below buy-and-hold after transaction costs.
Line chart showing the 63-day rolling Sharpe ratio fluctuating materially above and below zero.
Rolling momentum Sharpe ratio. The 63-day estimate repeatedly crosses zero, illustrating how trend-following performance depends on the prevailing market regime.

The key adaptations for crypto momentum strategies include:

  • Faster lookback periods: Given higher volatility and faster-moving trends, lookback periods of 10-30 days often work better than the 3-12 month horizons common in equity momentum.
  • Volatility scaling: Position sizing based on realized volatility is essential to avoid blow-ups during volatile periods.
  • Regime awareness: Crypto markets alternate between trending and mean-reverting regimes more dramatically than traditional markets.

Key Parameters

The key parameters for the Crypto Momentum Strategy are:

  • Lookback: Period for calculating momentum signal. Shorter windows (10-30 days) often suit crypto's fast cycles because trends develop and exhaust more quickly than in traditional markets.
  • Volatility Window: Lookback period for volatility calculation. Used to normalize risk and ensure consistent exposure across varying market conditions.
  • Risk Target: Target annualized volatility contribution for the position. A 20% risk target means the position is sized so that, given current volatility, the expected annualized standard deviation of returns is 20%.
  • Leverage Cap: Maximum absolute position size allowed to prevent excessive exposure. This hard limit protects against model errors when volatility estimates are stale or unusually low.

Market Making in Crypto

Market making, as we discussed in Part VI, involves continuously quoting bid and ask prices to earn the spread. In crypto markets, the high volatility and relatively thin liquidity create both opportunities and risks for market makers. The opportunity lies in wider spreads: while equity market makers might earn 1-2 basis points per trade, crypto market makers can earn 5-15 basis points or more. The risk is that inventory can quickly accumulate and move against you in a volatile market.

The fundamental market-making model adapts the classic inventory-based approach developed by Avellaneda and Stoikov. The core insight is that you should adjust your quotes based on your current inventory. If you are already long the asset, you want to encourage sales (to reduce your inventory) by quoting a more attractive bid price, and discourage purchases by quoting a less attractive ask price. Conversely, if you are short, you want to encourage purchases and discourage sales.

The optimal bid and ask prices around mid-price mm depend on inventory qq:

pbid=m−s2−γσ2qpask=m+s2−γσ2q\begin{aligned} p_{\text{bid}} &= m - \frac{s}{2} - \gamma \sigma^2 q \\ p_{\text{ask}} &= m + \frac{s}{2} - \gamma \sigma^2 q \end{aligned}

where:

  • pbid,paskp_{\text{bid}}, p_{\text{ask}}: optimal bid and ask quotes
  • mm: current mid-market price
  • ss: base bid-ask spread
  • γ\gamma: risk aversion parameter
  • σ\sigma: volatility of the asset
  • qq: current inventory position (signed quantity)

The structure of these formulas deserves careful attention. The first two terms on the right side of each equation represent the symmetric spread around mid-price: the bid is half a spread below mid, and the ask is half a spread above. The third term, −γσ2q-\gamma \sigma^2 q, is the inventory adjustment that skews both quotes in the same direction. Notice that this adjustment appears with the same sign in both formulas, meaning it shifts the entire quote structure either up or down depending on inventory.

The inventory term qq causes you to skew quotes to rebalance your position. For example, if you hold a long position (q>0q > 0), the inventory adjustment −γσ2q-\gamma \sigma^2 q is negative, shifting both bid and ask prices down. Lower prices discourage sellers from hitting the bid (preventing more buying) and encourage buyers to hit the ask (facilitating selling), thus reducing the inventory. The magnitude of this adjustment depends on γσ2\gamma \sigma^2: higher risk aversion or higher volatility leads to more aggressive inventory management, as the cost of holding a position in a volatile market is higher.

We model this dynamic in the CryptoMarketMaker class. The compute_quotes method calculates optimal bid and ask prices based on the current mid-price, volatility, and inventory level, while simulate_day models the interaction with incoming flow. The simulation assumes a simple model where orders arrive randomly with equal probability of buying or selling, allowing us to observe how inventory evolves and how profits accumulate:

In[17]:
Code
class CryptoMarketMaker:
    """
    Simple market making model for crypto.
    """

    def __init__(self, base_spread_bps=10, gamma=0.1, max_inventory=10):
        self.base_spread = base_spread_bps / 10000
        self.gamma = gamma
        self.max_inventory = max_inventory

    def compute_quotes(self, mid_price, volatility, inventory):
        """
        Compute optimal bid/ask quotes given current state.
        """
        half_spread = self.base_spread * mid_price / 2

        # Inventory adjustment
        inventory_adj = self.gamma * (volatility**2) * inventory * mid_price

        bid = mid_price - half_spread - inventory_adj
        ask = mid_price + half_spread - inventory_adj

        # Ensure bid < ask
        if bid >= ask:
            spread_adj = (ask - bid) / 2 + 0.01 * mid_price
            bid -= spread_adj
            ask += spread_adj

        return bid, ask

    def simulate_day(self, mid_prices, volatility, n_trades=100):
        """
        Simulate a day of market making.
        """
        np.random.seed(123)

        inventory = 0
        pnl = 0
        trades = []

        for i in range(n_trades):
            # Get current mid price
            price_idx = int(i / n_trades * len(mid_prices))
            mid = mid_prices[price_idx]

            bid, ask = self.compute_quotes(mid, volatility, inventory)

            # Simulate incoming order (50% buy, 50% sell from customer perspective)
            # Customer buys at our ask, customer sells at our bid
            if np.random.random() < 0.5:
                # Customer buys, we sell
                if inventory > -self.max_inventory:
                    trade_price = ask
                    inventory -= 1
                    pnl += trade_price
                    trades.append(
                        {
                            "type": "sell",
                            "price": trade_price,
                            "inventory": inventory,
                        }
                    )
            else:
                # Customer sells, we buy
                if inventory < self.max_inventory:
                    trade_price = bid
                    inventory += 1
                    pnl -= trade_price
                    trades.append(
                        {
                            "type": "buy",
                            "price": trade_price,
                            "inventory": inventory,
                        }
                    )

        # Mark to market final inventory
        final_mid = mid_prices[-1]
        mtm_pnl = pnl + inventory * final_mid

        return {
            "trades": len(trades),
            "final_inventory": inventory,
            "realized_pnl": pnl,
            "mtm_pnl": mtm_pnl,
            "trade_log": trades,
        }


# Simulate for different volatility regimes
mm = CryptoMarketMaker(base_spread_bps=15, gamma=0.05, max_inventory=20)

# Normal volatility day
normal_vol = 0.02  # 2% daily vol
normal_prices = 45000 * (
    1 + np.cumsum(np.random.normal(0, normal_vol / 100, 1000))
)
result_normal = mm.simulate_day(normal_prices, normal_vol)

# High volatility day
high_vol = 0.08  # 8% daily vol
high_prices = 45000 * (1 + np.cumsum(np.random.normal(0, high_vol / 100, 1000)))
result_high = mm.simulate_day(high_prices, high_vol)
Out[18]:
Console
Market Making Simulation Results
==================================================

Normal Volatility Day (2% daily vol):
  Trades executed: 100
  Final inventory: 2
  Mark-to-market P&L: $3,141.27

High Volatility Day (8% daily vol):
  Trades executed: 100
  Final inventory: 2
  Mark-to-market P&L: $-5,636.37

Inventory management directly affects profitability. As you absorb flow, your inventory fluctuates, creating risk. The following visualization tracks the inventory and accumulated profit-and-loss (PnL) during the high-volatility simulation. Notice how PnL is volatile due to mark-to-market changes in the inventory value, even as the strategy attempts to capture the spread.

Out[19]:
Visualization
Dual-axis chart with mark-to-market PnL as a line and inventory as bars across sequential trades; the PnL line ends in a loss.
Market-maker inventory and mark-to-market PnL during the high-volatility simulation. Inventory changes with executed order flow, and the resulting exposure produces a volatile PnL path that finishes below zero in this run.

The challenge for you as a market maker is that adverse selection is severe: informed traders or arbitrageurs are more likely to hit your quotes when prices are about to move against you. This means that the flow you receive is not random; it is biased toward trades that will lose money for you. Successful market making requires optimal quote placement and the ability to detect when incoming flow is likely to be informed, then adjust quotes or withdraw from the market accordingly. This makes quote management and latency critical. We will explore these execution challenges further in Part VII when we discuss market microstructure and execution algorithms.

Key Parameters

The key parameters for the Market Making model are:

  • Spread (ss): The distance between bid and ask quotes. Wider spreads compensate for volatility risk and adverse selection, but reduce the probability of execution.
  • γ\gamma: Risk aversion parameter. Higher values lead to more aggressive inventory management, meaning you will skew quotes more strongly to reduce inventory exposure.
  • Inventory (qq): Current net position. Non-zero inventory skews quotes to encourage balancing trades. The further from zero, the more aggressive the skew.
  • σ\sigma: Volatility of the asset. High volatility widens the optimal spread to protect against adverse selection and increases the cost of holding inventory, leading to more aggressive inventory management.