import os import pandas as pd import pandas_ta as ta from dotenv import load_dotenv from datetime import datetime, timedelta from backtesting import Backtest, Strategy from backtesting.lib import crossover from alpaca.data.historical import StockHistoricalDataClient from alpaca.data.requests import StockBarsRequest from alpaca.data.timeframe import TimeFrame # --- 1. DATEN HOLEN --- load_dotenv() API_KEY = os.getenv('ALPACA_API_KEY') SECRET_KEY = os.getenv('ALPACA_SECRET_KEY') def get_data(symbol, days=365): client = StockHistoricalDataClient(API_KEY, SECRET_KEY) start_date = datetime.now() - timedelta(days=days) request_params = StockBarsRequest(symbol_or_symbols=[symbol], timeframe=TimeFrame.Day, start=start_date) df = client.get_stock_bars(request_params).df df = df.reset_index(level=0, drop=True) df.columns = [c.capitalize() for c in df.columns] df.index = df.index.tz_localize(None) return df # --- 2. STRATEGIE MIT OPTIMIERBAREN PARAMETERN --- class RsiStrategy(Strategy): # Diese Klassenvariablen werden von der Optimize-Funktion überschrieben rsi_period = 14 rsi_lower = 30 rsi_upper = 70 def init(self): # Wichtig: Wir übergeben die Parameter an pandas_ta self.rsi = self.I(ta.rsi, pd.Series(self.data.Close), length=self.rsi_period) def next(self): if crossover(self.rsi, self.rsi_lower): self.buy() elif crossover(self.rsi_upper, self.rsi): if self.position: self.position.close() # --- 3. OPTIMIERUNGS-ENGINE --- def run_optimized_backtest(symbol): data = get_data(symbol) bt = Backtest(data, RsiStrategy, cash=10000, commission=0.001) print(f"--- Starte Optimierung für {symbol} ---") # Hier passiert die Magie: stats = bt.optimize( rsi_period=range(7, 30, 2), # Teste Perioden von 7 bis 29 in 2er Schritten rsi_lower=range(20, 40, 5), # Teste Kaufsignale von 20 bis 35 rsi_upper=range(60, 80, 5), # Teste Verkaufsignale von 60 bis 75 maximize='Return [%]', # Wir wollen den höchsten Gewinn (oder 'Sharpe Ratio') constraint=lambda p: p.rsi_upper > p.rsi_lower # Logik-Check ) print("\n--- BESTE PARAMETER GEFUNDEN ---") print(stats) print("\nDetails der besten Strategie:") print(f"RSI Periode: {stats._strategy.rsi_period}") print(f"RSI Untergrenze: {stats._strategy.rsi_lower}") print(f"RSI Obergrenze: {stats._strategy.rsi_upper}") # Speichere den Chart der besten Strategie bt.plot(filename=f"optimized_report_{symbol}.html", open_browser=False) if __name__ == "__main__": run_optimized_backtest("AAPL")