73 lines
2.6 KiB
Python
73 lines
2.6 KiB
Python
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") |