| """ | |
| Advanced MACD Trading Strategy - Complete Example | |
| Demonstrates all features: backtesting, market scanning, risk management | |
| """ | |
| import pandas as pd | |
| import yfinance as yf | |
| import warnings | |
| from src.core.trading import AdvancedMACDStrategy, VectorizedBacktest, RiskEngine | |
| warnings.filterwarnings('ignore') | |
| def load_data(ticker: str, period: str = '2y') -> pd.DataFrame: | |
| """Load historical data using yfinance""" | |
| return yf.Ticker(ticker).history(period=period) | |
| def main(): | |
| print("=" * 70) | |
| print("π ADVANCED MACD STRATEGY - COMPLETE EXAMPLE") | |
| print("=" * 70) | |
| strategy = AdvancedMACDStrategy( | |
| ema_period=200, | |
| macd_fast=12, | |
| macd_slow=26, | |
| macd_signal=9, | |
| atr_period=14, | |
| atr_multiplier_sl=1.5, | |
| atr_multiplier_tp=3.0, | |
| adx_period=14, | |
| adx_threshold=25, | |
| volume_period=20, | |
| rsi_period=14, | |
| use_divergences=False, | |
| cooldown_candles=5 | |
| ) | |
| risk_engine = RiskEngine( | |
| max_risk_per_trade=0.02, | |
| max_portfolio_heat=0.06, | |
| max_drawdown=0.15, | |
| kelly_fraction=0.25 | |
| ) | |
| print("\nπ§ STRATEGY SETTINGS:") | |
| print(f" β’ EMA Period: {strategy.ema_period}") | |
| print(f" β’ MACD: {strategy.macd_fast}/{strategy.macd_slow}/{strategy.macd_signal}") | |
| print(f" β’ ATR Stop-Loss: {strategy.atr_multiplier_sl}x") | |
| print(f" β’ ATR Take-Profit: {strategy.atr_multiplier_tp}x") | |
| print(f" β’ ADX Threshold: {strategy.adx_threshold}") | |
| print("\nπ‘οΈ RISK MANAGEMENT:") | |
| print(f" β’ Risk per Trade: {risk_engine.max_risk_per_trade*100}%") | |
| print(f" β’ Max Portfolio Heat: {risk_engine.max_portfolio_heat*100}%") | |
| print(f" β’ Max Drawdown: {risk_engine.max_drawdown*100}%") | |
| backtest_ticker = 'AAPL' | |
| print(f"\n{'=' * 70}") | |
| print(f"π§ͺ BACKTESTING: {backtest_ticker}") | |
| print(f"{'=' * 70}\n") | |
| data = load_data(backtest_ticker, period='2y') | |
| if len(data) >= strategy.ema_period: | |
| backtest = VectorizedBacktest( | |
| strategy=strategy, | |
| risk_engine=risk_engine, | |
| initial_capital=100000, | |
| commission=0.001 | |
| ) | |
| metrics = backtest.run(data, backtest_ticker) | |
| backtest.print_report() | |
| trades_df = backtest.get_trades_df() | |
| if not trades_df.empty: | |
| print(f"\nπ LAST 10 TRADES:") | |
| cols = ['Type', 'Entry_Date', 'Exit_Date', 'Entry_Price', | |
| 'Exit_Price', 'PnL', 'PnL_Pct', 'Hit'] | |
| print(trades_df[cols].tail(10).to_string(index=False)) | |
| else: | |
| print(f"β Not enough data for {backtest_ticker}") | |
| print(f"\n{'=' * 70}") | |
| print("π MARKET SCANNER") | |
| print(f"{'=' * 70}\n") | |
| tickers = ['AAPL', 'MSFT', 'GOOGL', 'AMZN', 'TSLA', | |
| 'NVDA', 'META', 'JPM', 'V', 'WMT'] | |
| print(f"π Scanning {len(tickers)} tickers...\n") | |
| signals = strategy.scan_market(tickers, load_data, period='6mo') | |
| if not signals.empty: | |
| print("\nπ― FOUND SIGNALS:\n") | |
| print(signals.to_string(index=False)) | |
| print(f"\nπ STATISTICS:") | |
| print(f" β’ Total Signals: {len(signals)}") | |
| print(f" β’ LONG: {len(signals[signals['Signal'] == 'LONG'])}") | |
| print(f" β’ SHORT: {len(signals[signals['Signal'] == 'SHORT'])}") | |
| print(f" β’ STRONG: {len(signals[signals['Strength'] == 'STRONG'])}") | |
| print(f" β’ Avg ADX: {signals['ADX'].mean():.1f}") | |
| print(f" β’ Avg RSI: {signals['RSI'].mean():.1f}") | |
| print(f" β’ Avg RR: {signals['RR_Ratio'].mean():.2f}") | |
| if len(signals) > 0: | |
| ticker = signals.iloc[0]['Ticker'] | |
| print(f"\n{'=' * 70}") | |
| print(f"π¬ DETAILED ANALYSIS: {ticker}") | |
| print(f"{'=' * 70}\n") | |
| data = load_data(ticker, period='6mo') | |
| df = strategy.generate_signals(data, ticker=ticker) | |
| key_cols = ['Close', 'EMA_200', 'Impulse_MACD', 'ZeroLag_MACD', | |
| 'ADX', 'RSI', 'ATR_Pct', 'Signal_Long', 'Signal_Short'] | |
| print(df[key_cols].tail(10).to_string()) | |
| last = df.iloc[-1] | |
| signal_type = 'LONG' if last['Signal_Long'] else 'SHORT' | |
| print(f"\nπΌ TRADE PARAMETERS:") | |
| print(f" Type: {signal_type}") | |
| print(f" Entry: ${last['Close']:.2f}") | |
| print(f" Stop-Loss: ${last['Stop_Loss_Long' if signal_type == 'LONG' else 'Stop_Loss_Short']:.2f}") | |
| print(f" Take-Profit: ${last['Take_Profit_Long' if signal_type == 'LONG' else 'Take_Profit_Short']:.2f}") | |
| print(f" Risk/Reward: {last['RR_Ratio_Long']:.2f}") | |
| print(f"\nπ INDICATORS:") | |
| print(f" ADX: {last['ADX']:.1f} ({'STRONG β ' if last['ADX'] > 25 else 'WEAK β οΈ'})") | |
| print(f" RSI: {last['RSI']:.1f}") | |
| print(f" ATR%: {last['ATR_Pct']:.2f}%") | |
| print(f" Volume Ratio: {last['Volume'] / last['Avg_Volume']:.2f}x") | |
| print(f" Volatility: {'HIGH β ' if last['High_Volatility'] else 'LOW β οΈ'}") | |
| account_value = 100000 | |
| entry_price = last['Close'] | |
| stop_loss = last['Stop_Loss_Long' if signal_type == 'LONG' else 'Stop_Loss_Short'] | |
| position_size = risk_engine.calculate_position_size( | |
| account_value=account_value, | |
| entry_price=entry_price, | |
| stop_loss=stop_loss | |
| ) | |
| risk_amount = position_size * abs(entry_price - stop_loss) | |
| risk_pct = (risk_amount / account_value) * 100 | |
| print(f"\nπ° RISK ENGINE (for ${account_value:,.0f}):") | |
| print(f" Position Size: {position_size} shares") | |
| print(f" Investment: ${position_size * entry_price:,.2f}") | |
| print(f" Risk: ${risk_amount:,.2f} ({risk_pct:.2f}%)") | |
| tp = last['Take_Profit_Long' if signal_type == 'LONG' else 'Take_Profit_Short'] | |
| print(f" Potential P&L: ${position_size * abs(entry_price - tp):,.2f}") | |
| else: | |
| print("\nβ No signals found") | |
| print(f"\n{'=' * 70}") | |
| print("β EXAMPLE COMPLETED") | |
| print(f"{'=' * 70}") | |
| print(""" | |
| π KEY FEATURES: | |
| 1. Zero-Lag MACD - Reduces lag for faster signal generation | |
| 2. Impulse MACD - More sensitive, less false signals in sideways markets | |
| 3. ATR Volatility Filter - Only trades when volatility is elevated | |
| 4. ADX Trend Strength - Confirms trend strength > threshold | |
| 5. Volume Filter - Confirms movement with above-average volume | |
| 6. RSI & MACD Divergence - Optional: detect price/indicator divergence | |
| 7. Risk Management - Position sizing, portfolio heat, drawdown control | |
| 8. Kelly Criterion - Optimal position sizing based on strategy stats | |
| π INDICATORS USED: | |
| β’ EMA 200: Trend direction | |
| β’ MACD: Momentum and reversal points | |
| β’ ATR: Volatility measurement | |
| β’ ADX: Trend strength (>20-30 = strong trend) | |
| β’ RSI: Overbought/oversold | |
| β’ Volume: Trade confirmation | |
| π― SIGNAL GENERATION: | |
| LONG SIGNAL: | |
| β MACD bullish cross (histogram crosses above 0) | |
| β Price > EMA 200 | |
| β High volatility (ATR% > mean) | |
| β Strong trend (ADX > 25) | |
| β High volume (> 20-day average) | |
| SHORT SIGNAL: | |
| β MACD bearish cross (histogram crosses below 0) | |
| β Price < EMA 200 | |
| β High volatility | |
| β Strong trend | |
| β High volume | |
| πΌ RISK MANAGEMENT: | |
| β’ Stop-Loss: 1.5x ATR below entry (LONG) / above entry (SHORT) | |
| β’ Take-Profit: 3.0x ATR above entry (LONG) / below entry (SHORT) | |
| β’ Risk/Reward Ratio: 1:2 (risking 1 to make 2) | |
| β’ Fixed Risk: Max 2% risk per trade | |
| β’ Portfolio Heat: Max 6% total risk | |
| β’ Max Drawdown: 15% threshold to stop trading | |
| π§ CUSTOMIZATION: | |
| 1. Adjust parameters in AdvancedMACDStrategy: | |
| - EMA period for trend | |
| - MACD periods for sensitivity | |
| - ATR multipliers for risk/reward | |
| - ADX threshold for trend strength | |
| - Volume period for filter | |
| 2. Enable divergence detection: | |
| strategy.use_divergences = True | |
| 3. Adjust risk parameters in RiskEngine: | |
| - Max risk per trade | |
| - Portfolio heat limit | |
| - Max drawdown | |
| - Kelly fraction | |
| π NEXT STEPS: | |
| 1. Run backtest on different timeframes | |
| 2. Scan multiple markets for signals | |
| 3. Test parameter combinations | |
| 4. Implement walk-forward analysis | |
| 5. Add position management (trailing stop, etc.) | |
| 6. Connect to live market data | |
| 7. Paper trade before live trading | |
| """) | |
| if __name__ == '__main__': | |
| main() | |