Arbitrage Trading Implementation
Relevant source files
The following files were used as context for generating this wiki page:
The Arbitrage Trading Implementation within the backtrader framework focuses on statistical arbitrage and pair trading strategies. It leverages historical data to identify price inefficiencies between two or more related assets, often referred to as a "spread." The implementation includes various mathematical models such as CUSUM (Cumulative Sum), Kalman Filters, and Bollinger Bands to trigger mean-reversion entries and exits.
Sources: arbitrage/JM_J_strategy_CUSUM.py, arbitrage/Kalman.py, contrib/samples/pair-trading/pair-trading.py
Core Mathematical Models
The project implements three primary methods for calculating and trading spreads between assets.
Kalman Filter Dynamic Hedge Ratio
The Kalman Filter is used to calculate a dynamic hedge ratio ($ \beta $) between two assets (e.g., J and JM futures). Unlike a static ratio, the Kalman Filter updates the relationship between the assets at every time step, allowing the strategy to adapt to changing market correlations.
Sources: arbitrage/Kalman.py:23-49
CUSUM (Cumulative Sum) Logic
The CUSUM strategy identifies structural changes in the mean of the spread. It tracks positive and negative cumulative sums of the spread's deviation from its rolling mean. A position is opened when these sums exceed a threshold $ h $, which is typically a multiple of the spread's standard deviation.
| Parameter | Logic | Description |
|---|---|---|
kappa | k_coeff * sigma | The slack variable to detect small shifts. |
h | h_coeff * sigma | The threshold for signal generation. |
g_pos | max(0, g_pos + s_t_corrected - kappa) | Cumulative positive deviation. |
g_neg | max(0, g_neg - s_t_corrected - kappa) | Cumulative negative deviation. |
Sources: arbitrage/JM_J_strategy_CUSUM.py:165-177
Bollinger Band Spread Trading
This implementation utilizes classic technical indicators applied to a synthetic spread instrument. Entry occurs when the spread deviates significantly from the moving average (middle band) and hits the upper or lower bands.
Sources: arbitrage/classic_indicators/bollingband.py:12-46, arbitrage/test_feedspread_yearly.py:82-120
Architecture and Data Flow
The arbitrage module requires data alignment to ensure that prices for Asset A and Asset B are synchronized by timestamp before calculating the spread.
Component Specifications
Spread Calculation Utilities
The system provides utility functions to generate spread dataframes that are compatible with backtrader.feeds.PandasData.
- Alignment:
check_and_align_dataperforms an intersection of indices to handle missing data points between two assets. - Vectorized Spread: Spread is calculated using the formula $ Spread = n \cdot AssetA - m \cdot AssetB $, where $ n $ and $ m $ are trading sizes or hedge ratios.
Sources: arbitrage/test_feedspread_yearly.py:17-57, arbitrage/JM_J_strategy_CUSUM.py:104-113
Key Classes and Indicators
| Class | File Path | Purpose |
|---|---|---|
SpreadData | arbitrage/JM_J_strategy_CUSUM.py | Custom data feed that includes a beta line for dynamic sizing. |
DynamicSpreadCUSUMStrategy | arbitrage/JM_J_strategy_CUSUM.py | Implements dynamic holding days based on signal strength. |
KalmanPairTradingStrategy | arbitrage/Kalman.py | Uses Z-scores of the Kalman-calculated spread for mean reversion. |
PairTradingStrategy | contrib/samples/pair-trading/pair-trading.py | Uses OLS_TransformationN to generate Z-scores for trading PEP/KO spreads. |
Sources: arbitrage/JM_J_strategy_CUSUM.py:104-123, arbitrage/Kalman.py:73-86, contrib/samples/pair-trading/pair-trading.py:27-58
Position Sizing and Execution
Execution in these strategies is atomic; orders for both assets must be sent simultaneously to maintain a hedged position.
def _open_position(self, short, signal_strength):
if short: # Short spread
self.sell(data=self.data0, size=self.size0)
self.buy(data=self.data1, size=self.size1)
else: # Long spread
self.buy(data=self.data0, size=self.size0)
self.sell(data=self.data1, size=self.size1)
Sources: arbitrage/JM_J_strategy_CUSUM.py:137-145
- Dynamic Sizing: The Kalman strategy adjusts
size1usinground(self.p.size0 * abs(hedge_ratio))to maintain the correct dollar-neutral or beta-neutral stance. - Exit Logic: Strategies typically exit when the spread returns to the mean (Z-score = 0) or when a pre-calculated
target_holding_daysis reached.
Sources: arbitrage/Kalman.py:101-105, arbitrage/JM_J_strategy_CUSUM.py:155-162
Summary
Arbitrage Trading Implementation in this project is built around statistical relationships between pairs. By utilizing pre-aligned data and dynamic indicators like the Kalman Filter and CUSUM, the system detects mean-reversion opportunities while managing hedge ratios through custom backtrader data lines.