← Back to Home
Trading with Conviction A Deep Dive into Covariance-Adjusted Triple EMA (CATEMA)

Trading with Conviction A Deep Dive into Covariance-Adjusted Triple EMA (CATEMA)

Traditional moving averages, while foundational, often face a trade-off: responsiveness versus smoothness. A Triple Exponential Moving Average (TEMA) aims to reduce the lag inherent in simpler MAs. But can we push adaptivity further? This article investigates a strategy that modulates the TEMA’s underlying smoothing based on the co-movement between price and volume. The hypothesis is that when price changes are strongly supported by corresponding volume changes (high price-volume covariance), the prevailing move has conviction, and our TEMA should react faster. Conversely, if price moves on weak or contradictory volume, the TEMA should be more cautious and smooth out potential noise. We’ll explore the construction of this “CATEMA,” its trading logic, and analyze a backtest performed on ETH-USD from 2020 to 2024.


Core Components of the CATEMA Strategy

  1. Triple Exponential Moving Average (TEMA):

    TEMA was designed by Patrick Mulloy to offer a moving average with less lag than traditional EMAs. It achieves this by applying multiple layers of exponential smoothing and then adjusting the result:

    • EMA1​=EMA(Price,period)
    • EMA2​=EMA(EMA1​,period)
    • EMA3​=EMA(EMA2​,period)
    • TEMA=(3×EMA1​)−(3×EMA2​)+EMA3​ Typically, a single period is used for all three underlying EMAs. Our strategy will make this period adaptive.
  2. Price-Volume Covariance: Measuring Co-movement:

    The strength and conviction behind a price move are often gauged by accompanying volume.

    • High positive covariance between price changes and volume changes (e.g., price up on rising volume, or price down with rising volume during a panic) generally suggests stronger conviction in the price move.
    • Low or negative covariance (e.g., price up on falling volume) might indicate a weaker, less sustainable move. Our strategy calculates a rolling covariance between price changes (e.g., Close.diff()) and volume percentage changes (Volume.pct_change()) over a lookback window (e.g., 30 days).
  3. The Adaptive Mechanism: Modulating TEMA’s Speed:

    The core innovation is to use the normalized price-volume covariance to adjust the effective period of the TEMA’s underlying EMAs.

    • When normalized covariance is high (strong positive co-movement), the TEMA will use a shorter effective period (e.g., 7 days in the script), making it faster and more responsive.
    • When normalized covariance is low (weak or negative co-movement), the TEMA will use a longer effective period (e.g., 90 days), making it smoother and filtering more noise. This is achieved by mapping the normalized covariance (scaled to a 0-1 range over a 90-day window) to a period between period_tema_min and period_tema_max.

Python Implementation Insights

Let’s look at key code segments that bring this adaptive mechanism to life.

Snippet 1: Calculating and Normalizing Price-Volume Covariance

This shows how daily price changes and volume percentage changes are used to compute a rolling covariance, which is then normalized to a 0-1 scale.

Python

# --- Parameters from the script for ETH-USD ---
# cov_window = 30
# cov_norm_window = 90

# --- Column Names ---
# price_change_cov_col = "Price_Change_For_Cov"
# volume_change_cov_col = "Volume_Change_For_Cov"
# price_volume_cov_col = f"PriceVol_Cov_{cov_window}d"
# normalized_cov_col = f"Normalized_Cov_{cov_norm_window}d"

# --- Indicator Calculation (within pandas DataFrame 'df') ---
# Inputs for Covariance
df[price_change_cov_col] = df['Close'].diff() # Simple price change
df[volume_change_cov_col] = df['Volume'].pct_change() # Percentage volume change
df.fillna({price_change_cov_col: 0, volume_change_cov_col: 0}, inplace=True)

# Rolling Price-Volume Covariance
df[price_volume_cov_col] = df[price_change_cov_col].rolling(window=cov_window).cov(df[volume_change_cov_col])

# Normalize Covariance (0-1 range, higher means stronger positive co-movement)
rolling_min_cov = df[price_volume_cov_col].rolling(window=cov_norm_window).min()
rolling_max_cov = df[price_volume_cov_col].rolling(window=cov_norm_window).max()
range_cov = rolling_max_cov - rolling_min_cov

# Handle division by zero if range_cov is 0, then fillna with neutral 0.5
df[normalized_cov_col] = ((df[price_volume_cov_col] - rolling_min_cov) / range_cov.replace(0, np.nan)).fillna(0.5)
df[normalized_cov_col] = np.clip(df[normalized_cov_col], 0, 1) # Ensure strictly 0-1

The normalized_cov_col gives us a bounded (0 to 1) measure of recent price-volume co-movement strength, where 1 indicates the strongest positive covariance in the normalization window.

Snippet 2: Determining the Adaptive TEMA Period and Iterative CATEMA Calculation

The normalized covariance (from the previous day) dictates the EMA period for the current day’s TEMA calculation. High covariance leads to a shorter period, low covariance to a longer one. The TEMA itself (CATEMA) is then built iteratively.

Python

# --- Parameters from the script ---
# period_tema_min = 7
# period_tema_max = 90

# --- Column Names ---
# adaptive_tema_period_col = "Adaptive_TEMA_Period"
# catema_col = "CATEMA"
# normalized_cov_col = ... (from previous snippet)

# 1. Map Normalized Covariance to Adaptive TEMA Period (using lagged covariance)
# High normalized_cov (strong co-movement) -> period_tema_min (faster)
# Low normalized_cov (weak co-movement) -> period_tema_max (slower)
df[adaptive_tema_period_col] = period_tema_max - df[normalized_cov_col].shift(1) * (period_tema_max - period_tema_min)
df[adaptive_tema_period_col] = np.round(df[adaptive_tema_period_col]).fillna( (period_tema_min + period_tema_max) / 2 ).astype(int)
df[adaptive_tema_period_col] = np.clip(df[adaptive_tema_period_col], period_tema_min, period_tema_max)

# 2. Iteratively Calculate Covariance-Adjusted TEMA (CATEMA)
# (Conceptual structure; full loop is in the main script)
df['EMA1_cat'] = np.nan; df['EMA2_cat'] = np.nan; df['EMA3_cat'] = np.nan
df[catema_col] = np.nan

# Seed initial EMAs and CATEMA (e.g., at first valid adaptive_period_col)
# ... (seeding logic as in the full script) ...

# Example of one iteration within the loop (from the full script):
# for k_idx in range(start_loc + 1, len(df)):
#     idx_today = df.index[k_idx]
#     idx_prev = df.index[k_idx-1]
#     current_period = df.loc[idx_today, adaptive_tema_period_col] # Based on prev day's cov
#     alpha = 2 / (current_period + 1)
#     close_today = df.loc[idx_today, 'Close']
#     prev_ema1 = df.loc[idx_prev, 'EMA1_cat'] # ... and for EMA2, EMA3
#
#     ema1_today = alpha * close_today + (1 - alpha) * prev_ema1
#     ema2_today = alpha * ema1_today + (1 - alpha) * prev_ema2
#     ema3_today = alpha * ema2_today + (1 - alpha) * prev_ema3
#     catema_today = (3 * ema1_today) - (3 * ema2_today) + ema3_today
#
#     df.loc[idx_today, 'EMA1_cat'] = ema1_today # ... and for EMA2, EMA3, CATEMA

# print("# Full iterative CATEMA calculation is performed in the main script's loop.")

This iterative calculation ensures that each day’s TEMA uses an α (smoothing constant) derived from the adaptive_tema_period_col, which in turn is based on the prior day’s price-volume covariance.

Trading Strategy: Crossover and ATR Risk Control

The trading signals are generated by the price crossing the CATEMA:

Risk Management: An ATR-based trailing stop loss is employed. The script uses a 14-period ATR and a tight multiplier of 1.0. This stop trails the price to protect profits and limit losses.

Empirical Investigation: ETH-USD (2020-2024)

The backtest results provided for ETH-USD (January 2020 - December 2024) are striking:

Pasted image 20250526131703.png

Interpreting These Results – A Researcher’s Perspective:

  1. Exceptional Outperformance: The CATEMA strategy, as configured, shows phenomenal outperformance over buy-and-hold for ETH-USD during this highly volatile and generally bullish period for cryptocurrencies. A Sharpe ratio of 2.10 is very high.
  2. Increased Volatility for Higher Returns: The strategy achieved its returns with higher annualized volatility (96.03%) compared to buy-and-hold (79.49%). The superior Sharpe ratio suggests this extra risk was well compensated.
  3. Role of Covariance Adaptation: The plots generated by the script (showing raw covariance, normalized covariance, and the adaptive TEMA period) would be essential to verify that the adaptive mechanism was actively changing the TEMA’s character in response to market conditions.
  4. The ATR Stop Multiplier (1.0x): This is a very aggressive (tight) stop-loss. Such tight stops can lead to:
    • Many small losses and quick exits: This might fortunately cut many losing trades short.
    • Premature exits from winning trades: Potentially missing out on larger extensions of moves.
    • High trading frequency: The “Final Position counts” (Long: 702, Short: 699, Flat: 330 over ~5 years) confirm very frequent trading. The exceptional performance might be highly sensitive to this tight stop interacting favorably with ETH-USD’s specific price dynamics during this period.
  5. Caveats are Paramount:
    • Overfitting Potential: With multiple parameters (cov_window, cov_norm_window, period_tema_min, period_tema_max, ATR settings), the risk of finding a combination that performed exceptionally well historically by chance is significant.
    • Transaction Costs & Slippage: For a strategy trading this frequently, real-world trading costs (commissions, bid-ask spread, slippage on entry/exit) would drastically reduce the reported gross returns. These are not modeled in the script.
    • Specific Market Period: The 2020-2024 period for ETH-USD included massive bull runs and high volatility. The strategy’s performance might differ substantially in other market regimes or on other assets.

Discussion and Directions for Further Inquiry

The CATEMA concept – dynamically adjusting a TEMA’s responsiveness using price-volume covariance – is an intuitive attempt to align the indicator with perceived market conviction.

Potential Strengths:

Critical Areas for Research & Due Diligence:

  1. Covariance Definition: The choice of Close.diff() for price change and Volume.pct_change() for volume change in the covariance calculation is one of many possibilities. Others (e.g., log returns, raw volume, detrended price/volume) could be explored.
  2. Normalization Method: The rolling min-max normalization for covariance is sensitive to the cov_norm_window. Other methods like Z-scoring or rank-based normalization could be investigated.
  3. Parameter Robustness: Extensive sensitivity analysis is needed for all parameters. How do results change with different cov_windows, TEMA period ranges, and especially the atr_multiplier_sl? A multiplier of 1.0 is unusual and its impact needs careful study.
  4. Out-of-Sample Testing: Validating the strategy on different time periods and other volatile assets is crucial.
  5. True Cost of Trading: A realistic simulation including estimated transaction costs is essential.
  6. Statistical Significance: The observed alpha needs to be rigorously tested.

Conclusion

The Covariance-Adjusted Triple EMA (CATEMA) strategy offers an advanced, adaptive approach to trend following. By modulating the TEMA’s speed based on the strength of price-volume co-movement, it seeks to enhance signal quality. The backtest results on ETH-USD for the 2020-2024 period are, at face value, extraordinarily strong. However, any researcher or practitioner would treat such figures as a starting point for a much deeper investigation. The path from a compelling backtest to a consistently profitable live strategy requires thorough validation, an understanding of all assumptions (especially regarding execution and costs), and a healthy skepticism towards parameters that seem “too good to be true,” like a 1.0x ATR multiplier often is. This adaptive framework nonetheless provides a rich field for further quantitative exploration.