Skip to content

Latest commit

 

History

History
427 lines (322 loc) · 12.6 KB

File metadata and controls

427 lines (322 loc) · 12.6 KB

Enhanced MA Crossover Strategy - Implementation Plan

Date: 2026-02-24
Author: AI Assistant
Status: Planning Phase


Executive Summary

This document outlines a plan to enhance the existing Moving Average (MA) Crossover strategy by adding multiple confirmation filters to reduce false signals and improve risk-adjusted returns. The enhanced strategy will be implemented as a new Jupyter notebook: EnhancedStrategy.ipynb.


Current Strategy Review

Existing MA Crossover Strategy

  • Signal Generation: Buy when Fast MA (5-day) crosses above Slow MA (20-day)
  • Exit Signal: Sell when Fast MA crosses below Slow MA
  • Entry Timing: Buy at next day's open (2-day shift to avoid look-ahead bias)
  • Position: Binary (1 = long, 0 = cash)

Observed Performance Issues

From the analysis of 18 stocks (2020-2025):

  • Average Strategy Return: 2.35% annualized
  • Average Market Return: 9.80% annualized
  • Underperformance: -7.45% on average
  • Success Rate: 12/18 profitable vs 13/18 for buy-and-hold
  • Positive: Lower volatility (49.19% vs 67.39%)

Key Problems to Address

  1. False signals in choppy/sideways markets
  2. Late entries after trend has already moved significantly
  3. Whipsaw losses from frequent crossovers
  4. No volume confirmation for move validity
  5. Missing strong trends due to conservative signal shifting

Enhancement Strategy

Core Enhancements

1. Volume Confirmation Filter

Rationale: Genuine breakouts typically occur with above-average volume

# Calculate volume moving average
df['Volume_MA'] = df['Volume'].rolling(window=20).mean()

# Volume filter: require 1.2x average volume for signal confirmation
df['Volume_Confirmed'] = df['Volume'] > (1.2 * df['Volume_MA'])

Impact: Filters out weak signals in low-liquidity conditions

2. Trend Strength Filter (ADX-like)

Rationale: Only trade when there's a clear trend, avoid choppy markets

# Calculate average directional movement
df['Price_Change'] = df['Close'].diff()
df['Trend_Strength'] = df['Price_Change'].rolling(window=14).std()

# Normalize to percentage
df['Trend_Strength_Pct'] = df['Trend_Strength'] / df['Close']

# Require minimum trend strength (e.g., > 1% daily volatility)
df['Strong_Trend'] = df['Trend_Strength_Pct'] > 0.01

Impact: Reduces whipsaw in ranging markets

3. Price Distance Filter

Rationale: Avoid buying after price has moved too far from MA (avoid FOMO entries)

# Calculate price distance from slow MA
df['Price_Distance'] = (df['Close'] - df['Slow_MA']) / df['Slow_MA']

# Only enter if within reasonable distance (e.g., < 5%)
df['Price_Reasonable'] = abs(df['Price_Distance']) < 0.05

Impact: Better entry prices, reduced risk of buying tops

4. Momentum Confirmation (Rate of Change)

Rationale: Ensure the trend has momentum behind it

# Calculate 5-day rate of change
df['ROC_5'] = df['Close'].pct_change(periods=5)

# Require positive momentum for long signals
df['Positive_Momentum'] = df['ROC_5'] > 0

Impact: Confirms trend direction before entry

5. Stop-Loss and Take-Profit Levels

Rationale: Protect capital and lock in gains

# Implement trailing stop-loss (e.g., 5%)
# Implement take-profit target (e.g., 10%)
# Will require iterative row-by-row processing

Impact: Better risk management, reduced drawdowns


Combined Signal Logic

Signal Generation Hierarchy

def enhanced_ma_crossover_strategy(data, fast_window=5, slow_window=20):
    """
    Enhanced MA Crossover with multiple confirmation filters.
    """
    df = data.copy()
    
    # 1. Calculate base indicators
    df['Fast_MA'] = df['Close'].rolling(window=fast_window).mean()
    df['Slow_MA'] = df['Close'].rolling(window=slow_window).mean()
    
    # 2. Basic crossover signal
    df['MA_Signal'] = np.where(df['Fast_MA'] > df['Slow_MA'], 1, 0)
    df['MA_Crossover'] = df['MA_Signal'].diff()
    
    # 3. Volume confirmation
    df['Volume_MA'] = df['Volume'].rolling(window=20).mean()
    df['Volume_Confirmed'] = df['Volume'] > (1.2 * df['Volume_MA'])
    
    # 4. Trend strength filter
    df['Price_Change'] = df['Close'].diff()
    df['Trend_Strength'] = df['Price_Change'].rolling(window=14).std()
    df['Trend_Strength_Pct'] = df['Trend_Strength'] / df['Close']
    df['Strong_Trend'] = df['Trend_Strength_Pct'] > 0.01
    
    # 5. Price distance filter
    df['Price_Distance'] = (df['Close'] - df['Slow_MA']) / df['Slow_MA']
    df['Price_Reasonable'] = abs(df['Price_Distance']) < 0.05
    
    # 6. Momentum confirmation
    df['ROC_5'] = df['Close'].pct_change(periods=5)
    df['Positive_Momentum'] = df['ROC_5'] > 0
    
    # 7. Combined signal (all filters must be True)
    df['Enhanced_Signal'] = (
        (df['MA_Signal'] == 1) &
        df['Volume_Confirmed'] &
        df['Strong_Trend'] &
        df['Price_Reasonable'] &
        df['Positive_Momentum']
    ).astype(int)
    
    # 8. Calculate returns
    df['Open_Returns'] = df['Open'].pct_change()
    df['Close_Returns'] = df['Close'].pct_change()
    
    # Original strategy (for comparison)
    df['Original_Strategy_Returns'] = df['MA_Signal'].shift(2) * df['Open_Returns']
    
    # Enhanced strategy
    df['Enhanced_Strategy_Returns'] = df['Enhanced_Signal'].shift(2) * df['Open_Returns']
    
    # 9. Cumulative returns
    df['Cumulative_Market'] = (1 + df['Close_Returns']).cumprod() - 1
    df['Cumulative_Original'] = (1 + df['Original_Strategy_Returns']).cumprod() - 1
    df['Cumulative_Enhanced'] = (1 + df['Enhanced_Strategy_Returns']).cumprod() - 1
    
    df.dropna(inplace=True)
    
    return df

Notebook Structure

File: EnhancedStrategy.ipynb

Section 1: Introduction and Imports

  • Project description
  • Import statements
  • Helper function definitions

Section 2: Strategy Implementation

  • enhanced_ma_crossover_strategy() function
  • Individual filter explanations with examples

Section 3: Single Stock Demonstration

  • Apply to AAPL as example
  • Visualize signals and filters
  • Show entry/exit points on price chart

Section 4: Performance Comparison

  • Original MA crossover vs Enhanced strategy
  • Side-by-side returns comparison
  • Metrics table (returns, volatility, Sharpe ratio)

Section 5: Multi-Stock Backtesting

  • Apply to same 18-stock portfolio
  • Comparative performance analysis
  • Statistical summary

Section 6: Filter Impact Analysis

  • Ablation study: remove one filter at a time
  • Measure impact of each filter
  • Determine which filters add most value

Section 7: Parameter Optimization (Optional)

  • Test different threshold values
  • Grid search for optimal parameters
  • Validation on hold-out data

Section 8: Conclusions and Next Steps

  • Summary of findings
  • Recommendations
  • Ideas for further enhancement

Metrics and Validation

Performance Metrics to Calculate

  1. Total Return (original, enhanced, market)
  2. Annualized Return
  3. Volatility (annualized standard deviation)
  4. Sharpe Ratio (risk-adjusted return)
  5. Maximum Drawdown (peak-to-trough decline)
  6. Win Rate (% of profitable trades)
  7. Average Trade Duration
  8. Number of Trades (to assess overtrading)

Comparison Framework

def compare_strategies(df):
    """
    Compare original vs enhanced strategy performance.
    """
    metrics = {
        'Original Strategy': generate_metric(df, 'Original'),
        'Enhanced Strategy': generate_metric(df, 'Enhanced'),
        'Market (Buy & Hold)': generate_metric(df, 'Market')
    }
    return pd.DataFrame(metrics).T

Success Criteria

The enhanced strategy should demonstrate:

  • Higher risk-adjusted returns (better Sharpe ratio)
  • Lower maximum drawdown (better risk management)
  • Fewer but higher-quality trades (reduced whipsaw)
  • Better performance in volatile periods (2020-2021, 2025)
  • Comparable or better absolute returns than original strategy

Implementation Timeline

Phase 1: Core Implementation (First Session)

  1. ✅ Create EnhancedStrategy.ipynb
  2. ✅ Implement enhanced_ma_crossover_strategy() function
  3. ✅ Test on AAPL with visualizations

Phase 2: Validation (First Session)

  1. ✅ Apply to full 18-stock portfolio
  2. ✅ Generate comparison metrics
  3. ✅ Create performance visualizations

Phase 3: Analysis (Optional - Second Session)

  1. ⏳ Filter ablation study
  2. ⏳ Parameter optimization
  3. ⏳ Additional stocks testing

Phase 4: Documentation (Second Session)

  1. ⏳ Final conclusions
  2. ⏳ Update AGENTS.md with new patterns
  3. ⏳ Create summary report

Potential Challenges and Mitigations

Challenge 1: Over-Filtering (Too Few Trades)

Risk: Filters may be too strict, leading to missed opportunities Mitigation:

  • Start with relaxed thresholds
  • Monitor trade frequency
  • Adjust parameters based on results

Challenge 2: Look-Ahead Bias

Risk: Using future information in signal generation Mitigation:

  • Maintain 2-day signal shift
  • Ensure all indicators use only historical data
  • Document calculation order

Challenge 3: Overfitting to Historical Data

Risk: Strategy works on 2020-2025 but fails in future Mitigation:

  • Use simple, intuitive filters
  • Avoid excessive parameter tuning
  • Test across different market regimes
  • Consider walk-forward validation

Challenge 4: Computational Complexity

Risk: Strategy too slow for real-time application Mitigation:

  • Use vectorized pandas operations
  • Avoid row-by-row iteration where possible
  • Profile code for bottlenecks

Code Quality Standards

Following AGENTS.md guidelines:

Function Documentation

def enhanced_ma_crossover_strategy(
    data: pd.DataFrame, 
    fast_window: int = 5, 
    slow_window: int = 20,
    volume_threshold: float = 1.2,
    trend_threshold: float = 0.01,
    distance_threshold: float = 0.05
) -> pd.DataFrame:
    """
    Enhanced MA crossover strategy with multiple confirmation filters.
    
    Args:
        data (pd.DataFrame): OHLCV price data
        fast_window (int): Fast moving average window
        slow_window (int): Slow moving average window
        volume_threshold (float): Volume multiplier for confirmation
        trend_threshold (float): Minimum trend strength (% volatility)
        distance_threshold (float): Maximum price distance from MA (%)
        
    Returns:
        pd.DataFrame: Original data with strategy signals and returns
    """

Variable Naming

  • Clear, descriptive names
  • Follow snake_case convention
  • Add _pct suffix for percentages
  • Use df for DataFrames

Testing Approach

  • Visual validation of signals
  • Sanity checks on return calculations
  • Compare against known benchmarks
  • Print intermediate values for debugging

Expected Outcomes

Quantitative Goals

  • Sharpe Ratio Improvement: +0.2 to +0.5 vs original strategy
  • Reduced Volatility: 5-10% lower than original
  • Better Win Rate: 55-60% of trades profitable
  • Lower Drawdown: Maximum drawdown < 25%

Qualitative Goals

  • More intuitive signal generation
  • Better risk management
  • Reusable filter components
  • Educational value for understanding technical analysis

References and Resources

Technical Indicators

  • Moving Averages: Simple vs Exponential
  • Volume Analysis in Technical Trading
  • Trend Strength Indicators (ADX concept)
  • Rate of Change (ROC) momentum indicator

Libraries

  • pandas for data manipulation
  • numpy for numerical operations
  • matplotlib for visualization
  • yfinance for data fetching

Further Reading

  • "Technical Analysis of the Financial Markets" - John Murphy
  • "Evidence-Based Technical Analysis" - David Aronson
  • Python for Finance (O'Reilly)

Next Steps

  1. Review this plan and provide feedback
  2. Create the notebook EnhancedStrategy.ipynb
  3. Implement the strategy following this specification
  4. Run backtests on the 18-stock portfolio
  5. Analyze results and iterate if needed

Appendix: Filter Parameter Ranges for Testing

If we proceed to optimization phase:

Filter Parameter Conservative Moderate Aggressive
Volume Threshold 1.5x 1.2x 1.0x
Trend Strength Min Volatility 1.5% 1.0% 0.5%
Price Distance Max Distance 3% 5% 8%
Momentum ROC Period 10 days 5 days 3 days

Initial Recommendation: Start with "Moderate" parameters


End of Plan

Ready to proceed with implementation? Please review and let me know if you'd like any modifications to this plan before we create the notebook.