File size: 3,402 Bytes
d5b7ee9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#!/usr/bin/env python3
"""
Multi-stock backtesting script for strategy evolution.
Tests one or more strategies across multiple symbols and timeframes.
"""

import sys
import os
from datetime import datetime, timedelta
import pandas as pd
import numpy as np
import logging

# Add project root to path
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

from trading_cli.backtest.engine import BacktestEngine
from trading_cli.strategy.strategy_factory import create_trading_strategy, available_strategies
from trading_cli.data.market import fetch_ohlcv_yfinance

# Configure logging
logging.basicConfig(level=logging.WARNING)
logger = logging.getLogger(__name__)

DEFAULT_SYMBOLS = ["AAPL", "MSFT", "GOOGL", "AMZN", "TSLA", "NVDA", "META", "AMD", "COIN", "MARA"]
DEFAULT_DAYS = 365

def run_multi_backtest(symbols, strategy_ids, days=DEFAULT_DAYS, config=None):
    if config is None:
        config = {
            "signal_buy_threshold": 0.2,
            "signal_sell_threshold": -0.15,
            "risk_pct": 0.02,
            "stop_loss_pct": 0.05,
        }
    
    results = []
    
    print(f"{'Symbol':<8} | {'Strategy':<15} | {'Return %':>10} | {'Sharpe':>8} | {'Win%':>6} | {'Trades':>6}")
    print("-" * 70)
    
    for symbol in symbols:
        # Fetch data once per symbol
        ohlcv = fetch_ohlcv_yfinance(symbol, days=days)
        if ohlcv.empty:
            print(f"Failed to fetch data for {symbol}")
            continue
            
        for strategy_id in strategy_ids:
            # Create strategy
            strat_config = config.copy()
            strat_config["strategy_id"] = strategy_id
            strategy = create_trading_strategy(strat_config)
            
            # Run backtest
            engine = BacktestEngine(
                config=strat_config,
                use_sentiment=False,  # Skip sentiment for pure technical baseline
                strategy=strategy
            )
            
            res = engine.run(symbol, ohlcv, initial_capital=100_000.0)
            
            print(f"{symbol:<8} | {strategy_id:<15} | {res.total_return_pct:>9.2f}% | {res.sharpe_ratio:>8.2f} | {res.win_rate:>5.1f}% | {res.total_trades:>6}")
            
            results.append({
                "symbol": symbol,
                "strategy": strategy_id,
                "return_pct": res.total_return_pct,
                "sharpe": res.sharpe_ratio,
                "win_rate": res.win_rate,
                "trades": res.total_trades,
                "max_drawdown": res.max_drawdown_pct
            })
            
    # Aggregate results by strategy
    df = pd.DataFrame(results)
    if not df.empty:
        summary = df.groupby("strategy").agg({
            "return_pct": ["mean", "std"],
            "sharpe": "mean",
            "win_rate": "mean",
            "trades": "sum"
        })
        print("\n--- Summary ---")
        print(summary)
    
    return df

if __name__ == "__main__":
    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument("--symbols", nargs="+", default=DEFAULT_SYMBOLS)
    parser.add_argument("--strategies", nargs="+", default=["hybrid", "mean_reversion", "momentum", "trend_following"])
    parser.add_argument("--days", type=int, default=DEFAULT_DAYS)
    args = parser.parse_args()
    
    run_multi_backtest(args.symbols, args.strategies, args.days)