Der Aufbau eines quantitativen Krypto-Backtesting-Systems ist eine der anspruchsvollsten, aber auch lohnendsten Aufgaben im Bereich des algorithmischen Handels. In diesem umfassenden Tutorial zeige ich Ihnen, wie Sie ein vollständiges System von Grund auf entwickeln – von der Datenbeschaffung über die Strategieimplementierung bis hin zur KI-gestützten Signalgenerierung. Dabei integrieren wir HolySheep AI als kostengünstige und schnelle API-Lösung für die Signalverarbeitung und Strategieoptimierung.
HolySheep AI vs. Offizielle APIs vs. Andere Relay-Dienste
| Kriterium | HolySheep AI | Offizielle OpenAI API | Offizielle Anthropic API | Andere Relay-Dienste |
|---|---|---|---|---|
| Preis (GPT-4.1) | $8/MTok | $15/MTok | $15/MTok | $10-12/MTok |
| Preis (Claude Sonnet 4.5) | $15/MTok | $18/MTok | $15/MTok | $12-14/MTok |
| DeepSeek V3.2 | $0.42/MTok | Nicht verfügbar | Nicht verfügbar | $0.80-1.20/MTok |
| Latenz | <50ms | 100-300ms | 150-400ms | 80-200ms |
| Zahlungsmethoden | WeChat, Alipay, USDT, Kreditkarte | Nur Kreditkarte | Nur Kreditkarte | Variiert |
| Kostenlose Credits | Ja, bei Registrierung | $5 Willkommensbonus | Nein | Variiert |
| Sparpotenzial | Bis zu 85%+ günstiger | Standardpreis | Standardpreis | 10-30% günstiger |
| Chinesische Märkte | Optimiert für CNY/USD | Standard | Standard | Variiert |
Geeignet / Nicht geeignet für
Perfekt geeignet für:
- Privat Trader und Quant-Fonds: Die extrem niedrige Latenz (<50ms) und die günstigen Preise machen HolySheep ideal für Hochfrequenz-Strategien und Daytrading.
- Forschungsteams: Mit kostenlosen Credits können Sie ohne finanzielles Risiko experimentieren und Prototypen entwickeln.
- Chinesische Entwickler: WeChat- und Alipay-Unterstützung eliminieren Währungsprobleme und Zahlungshürden.
- Enterprise-Anwendungen: Die stabile API und die hohen Limits unterstützen produktive Umgebungen mit hohem Volumen.
- Backtesting-Frameworks: Die Kombination aus DeepSeek V3.2 ($0.42/MTok) und GPT-4.1 ermöglicht kosteneffiziente Strategieoptimierung.
Weniger geeignet für:
- Regulierte Finanzinstitutionen: Falls Sie ausschließlich offizielle SDKs mit bestimmten Zertifizierungen benötigen.
- Maximale Modellvielfalt: Für den Zugriff auf experimentelle oder sehr neue Modelle, die noch nicht bei HolySheep verfügbar sind.
Systemarchitektur des Krypto-Backtesting-Systems
Bevor wir mit dem Code beginnen, ist es wichtig, die Gesamtarchitektur zu verstehen. Ein robustes Backtesting-System besteht aus mehreren Schichten:
- Datenbeschaffungsschicht: Historische und Echtzeit-Kursdaten von Krypto-Börsen
- Datenspeicherungsschicht: Effiziente Datenhaltung für schnelle Abfragen
- Strategie-Engine: Implementierung und Ausführung von Handelsstrategien
- KI-Integrationsschicht: Nutzung von LLMs für Sentiment-Analyse und Signalgenerierung
- Backtesting-Engine: Simulation von Handelsausführungen mit historischen Daten
- Analyse und Visualisierung: Performance-Metriken und Reporting
Datenbeschaffung und Vorbereitung
Der erste und kritischste Schritt ist die Beschaffung hochqualitativer historischer Daten. Ich empfehle die Verwendung von ccxt, einer standardisierten Python-Bibliothek, die Zugriff auf über 100 Krypto-Börsen bietet.
# requirements.txt
ccxt==4.2.100
pandas==2.1.4
numpy==1.26.3
ta-lib==0.4.28
holysheepai==0.1.5 # Offizielle HolySheep Python SDK
matplotlib==3.8.2
backtrader==1.9.78.123
pip install -r requirements.txt
import ccxt
import pandas as pd
from datetime import datetime, timedelta
from typing import Optional, List
class CryptoDataFetcher:
"""Holt historische und Echtzeit-Kryptodaten von Börsen"""
def __init__(self, exchange_id: str = 'binance'):
self.exchange = getattr(ccxt, exchange_id)({
'enableRateLimit': True,
'options': {'defaultType': 'spot'}
})
self.timeframes = {
'1m': '1m', '5m': '5m', '15m': '15m',
'1h': '1h', '4h': '4h', '1d': '1d'
}
def fetch_ohlcv(
self,
symbol: str,
timeframe: str = '1h',
since: Optional[int] = None,
limit: int = 1000
) -> pd.DataFrame:
"""
Fetches OHLCV data (Open, High, Low, Close, Volume)
from the specified exchange.
"""
try:
# Konvertiere Zeitstempel falls nötig
if since is None:
since = self.exchange.parse8601(
(datetime.now() - timedelta(days=365)).isoformat()
)
all_ohlcv = []
while True:
ohlcv = self.exchange.fetch_ohlcv(
symbol, timeframe, since, limit
)
if not ohlcv:
break
all_ohlcv.extend(ohlcv)
since = ohlcv[-1][0] + 1
# Begrenze auf 2 Jahre historische Daten
if len(all_ohlcv) > 17520: # ~2 Jahre bei 1h
break
if len(ohlcv) < limit:
break
df = pd.DataFrame(
all_ohlcv,
columns=['timestamp', 'open', 'high', 'low', 'close', 'volume']
)
df['datetime'] = pd.to_datetime(df['timestamp'], unit='ms')
df.set_index('datetime', inplace=True)
return df.drop('timestamp', axis=1)
except ccxt.NetworkError as e:
print(f"Netzwerkfehler: {e}")
raise
except ccxt.ExchangeError as e:
print(f"Börsenfehler: {e}")
raise
def add_technical_indicators(self, df: pd.DataFrame) -> pd.DataFrame:
"""Fügt technische Indikatoren hinzu"""
# Gleitende Durchschnitte
df['sma_20'] = df['close'].rolling(window=20).mean()
df['sma_50'] = df['close'].rolling(window=50).mean()
df['sma_200'] = df['close'].rolling(window=200).mean()
# RSI (Relative Strength Index)
delta = df['close'].diff()
gain = (delta.where(delta > 0, 0)).rolling(window=14).mean()
loss = (-delta.where(delta < 0, 0)).rolling(window=14).mean()
rs = gain / loss
df['rsi'] = 100 - (100 / (1 + rs))
# MACD
exp1 = df['close'].ewm(span=12, adjust=False).mean()
exp2 = df['close'].ewm(span=26, adjust=False).mean()
df['macd'] = exp1 - exp2
df['signal'] = df['macd'].ewm(span=9, adjust=False).mean()
# Bollinger Bands
df['bb_middle'] = df['close'].rolling(window=20).mean()
bb_std = df['close'].rolling(window=20).std()
df['bb_upper'] = df['bb_middle'] + (bb_std * 2)
df['bb_lower'] = df['bb_middle'] - (bb_std * 2)
# Volatilität
df['volatility'] = df['close'].rolling(window=20).std()
return df.dropna()
Verwendung
fetcher = CryptoDataFetcher('binance')
btcusd_data = fetcher.fetch_ohlcv('BTC/USDT', timeframe='1h', limit=5000)
btcusd_data = fetcher.add_technical_indicators(btcusd_data)
print(f"Daten geladen: {len(btcusd_data)} Kerzen")
print(btcusd_data.tail())
KI-gestützte Signalgenerierung mit HolySheep AI
Der entscheidende Vorteil unseres Systems ist die Integration von KI für die Sentiment-Analyse und Signalgenerierung. HolySheep AI bietet hier massive Kostenvorteile: DeepSeek V3.2 kostet nur $0.42/MTok im Vergleich zu $15-18 bei offiziellen APIs. Das bedeutet bei 10.000 API-Aufrufen eine Ersparnis von über 97%!
import os
from typing import Dict, List, Tuple
from dataclasses import dataclass
from enum import Enum
HolySheep API Konfiguration
Registrieren Sie sich hier: https://www.holysheep.ai/register
HOLYSHEEP_API_KEY = os.environ.get('HOLYSHEEP_API_KEY', 'YOUR_HOLYSHEEP_API_KEY')
HOLYSHEEP_BASE_URL = 'https://api.holysheep.ai/v1'
import requests
class SignalType(Enum):
STRONG_BUY = "STRONG_BUY"
BUY = "BUY"
HOLD = "HOLD"
SELL = "SELL"
STRONG_SELL = "STRONG_SELL"
@dataclass
class TradingSignal:
symbol: str
signal_type: SignalType
confidence: float
reasoning: str
timestamp: str
indicators_snapshot: Dict
class AITradingAdvisor:
"""
KI-gestützter Handelsberater mit HolySheep AI Integration.
Nutzt LLMs für fundamentale und sentiment-basierte Analyse.
"""
def __init__(self, api_key: str = HOLYSHEEP_API_KEY):
self.api_key = api_key
self.base_url = HOLYSHEEP_BASE_URL
self.headers = {
'Authorization': f'Bearer {api_key}',
'Content-Type': 'application/json'
}
def analyze_market_sentiment(
self,
symbol: str,
price_data: Dict,
news_headlines: List[str] = None
) -> TradingSignal:
"""
Analysiert Marktdaten und generiert Handelssignale.
Nutzt HolySheep AI für die Verarbeitung.
"""
# Erstelle Analyse-Prompt
indicators_text = self._format_indicators(price_data)
prompt = f"""Analysiere die folgenden Marktdaten für {symbol}:
{indicators_text}
Basierend auf diesen technischen Indikatoren:
1. Trend-Analyse (SMA-Cross, MACD)
2. Momentum (RSI)
3. Volatilität (Bollinger Bands)
4. Volumen-Analyse
Gib ein klares Handelssignal mit:
- Signal-Typ (STRONG_BUY, BUY, HOLD, SELL, STRONG_SELL)
- Konfidenzgrad (0.0-1.0)
- Begründung (kurz und präzise)
Antworte im JSON-Format:
{{"signal": "...", "confidence": 0.XX, "reasoning": "..."}}"""
try:
response = requests.post(
f'{self.base_url}/chat/completions',
headers=self.headers,
json={
'model': 'deepseek-chat', # Günstigste Option: $0.42/MTok
'messages': [
{'role': 'system', 'content': 'Du bist ein erfahrener Krypto-Analyst.'},
{'role': 'user', 'content': prompt}
],
'temperature': 0.3, # Niedrig für konsistente Analysen
'max_tokens': 500
},
timeout=30
)
if response.status_code == 200:
result = response.json()
content = result['choices'][0]['message']['content']
return self._parse_signal(symbol, content, price_data)
else:
print(f"API Fehler: {response.status_code} - {response.text}")
return self._fallback_signal(symbol, price_data)
except requests.exceptions.Timeout:
print("Timeout bei HolySheep API - verwende Fallback")
return self._fallback_signal(symbol, price_data)
except Exception as e:
print(f"Fehler: {e}")
return self._fallback_signal(symbol, price_data)
def _format_indicators(self, data: Dict) -> str:
"""Formatiert Indikatoren für den Prompt"""
return f"""
- Aktueller Preis: ${data.get('close', 0):.2f}
- SMA 20: ${data.get('sma_20', 0):.2f}
- SMA 50: ${data.get('sma_50', 0):.2f}
- SMA 200: ${data.get('sma_200', 0):.2f}
- RSI (14): {data.get('rsi', 50):.2f}
- MACD: {data.get('macd', 0):.4f}
- MACD Signal: {data.get('signal', 0):.4f}
- Bollinger Upper: ${data.get('bb_upper', 0):.2f}
- Bollinger Lower: ${data.get('bb_lower', 0):.2f}
- Volatilität (20): {data.get('volatility', 0):.4f}
"""
def _parse_signal(
self,
symbol: str,
content: str,
data: Dict
) -> TradingSignal:
"""Parst die API-Antwort"""
import json
import re
# Extrahiere JSON aus der Antwort
json_match = re.search(r'\{.*\}', content, re.DOTALL)
if json_match:
try:
parsed = json.loads(json_match.group())
signal = SignalType(parsed.get('signal', 'HOLD'))
confidence = float(parsed.get('confidence', 0.5))
reasoning = parsed.get('reasoning', 'Keine Begründung')
return TradingSignal(
symbol=symbol,
signal_type=signal,
confidence=confidence,
reasoning=reasoning,
timestamp=pd.Timestamp.now().isoformat(),
indicators_snapshot=data
)
except json.JSONDecodeError:
pass
return self._fallback_signal(symbol, data)
def _fallback_signal(
self,
symbol: str,
data: Dict
) -> TradingSignal:
"""Fallback-Signal basierend auf einfachen Regeln"""
rsi = data.get('rsi', 50)
sma_20 = data.get('sma_20', 0)
sma_50 = data.get('sma_50', 0)
close = data.get('close', 0)
if rsi < 30 and sma_20 > sma_50:
signal = SignalType.BUY
confidence = 0.7
reasoning = "RSI überverkauft, Aufwärtstrend bestätigt"
elif rsi > 70 and sma_20 < sma_50:
signal = SignalType.SELL
confidence = 0.7
reasoning = "RSI überkauft, Abwärtstrend bestätigt"
else:
signal = SignalType.HOLD
confidence = 0.5
reasoning = "Kein klares Signal"
return TradingSignal(
symbol=symbol,
signal_type=signal,
confidence=confidence,
reasoning=reasoning,
timestamp=pd.Timestamp.now().isoformat(),
indicators_snapshot=data
)
Beispiel-Verwendung
advisor = AITradingAdvisor()
Analysiere aktuelle Marktdaten
latest_data = {
'close': btcusd_data['close'].iloc[-1],
'sma_20': btcusd_data['sma_20'].iloc[-1],
'sma_50': btcusd_data['sma_50'].iloc[-1],
'sma_200': btcusd_data['sma_200'].iloc[-1],
'rsi': btcusd_data['rsi'].iloc[-1],
'macd': btcusd_data['macd'].iloc[-1],
'signal': btcusd_data['signal'].iloc[-1],
'bb_upper': btcusd_data['bb_upper'].iloc[-1],
'bb_lower': btcusd_data['bb_lower'].iloc[-1],
'volatility': btcusd_data['volatility'].iloc[-1]
}
signal = advisor.analyze_market_sentiment('BTC/USDT', latest_data)
print(f"\n📊 KI-Signal für {signal.symbol}:")
print(f" Typ: {signal.signal_type.value}")
print(f" Konfidenz: {signal.confidence:.1%}")
print(f" Begründung: {signal.reasoning}")
Backtesting-Engine implementieren
Jetzt implementieren wir die Backtesting-Engine, die unsere Strategien against historischen Daten testet. Wir verwenden eine modulare Architektur, die verschiedene Strategietypen unterstützt.
from dataclasses import dataclass, field
from typing import List, Dict, Optional, Callable
from datetime import datetime
from enum import Enum
import numpy as np
import matplotlib.pyplot as plt
class PositionType(Enum):
LONG = "LONG"
SHORT = "SHORT"
FLAT = "FLAT"
@dataclass
class Trade:
entry_time: datetime
exit_time: datetime
entry_price: float
exit_price: float
position_type: PositionType
quantity: float
pnl: float
pnl_percent: float
@dataclass
class Portfolio:
initial_capital: float = 10000.0
cash: float = 10000.0
positions: Dict[str, float] = field(default_factory=dict)
trades: List[Trade] = field(default_factory=list)
equity_curve: List[float] = field(default_factory=list)
def current_equity(self, current_prices: Dict[str, float]) -> float:
position_value = sum(
qty * current_prices.get(symbol, 0)
for symbol, qty in self.positions.items()
)
return self.cash + position_value
@dataclass
class BacktestResult:
total_trades: int
winning_trades: int
losing_trades: int
win_rate: float
total_pnl: float
total_pnl_percent: float
max_drawdown: float
sharpe_ratio: float
avg_trade_duration: float
largest_win: float
largest_loss: float
trades: List[Trade]
equity_curve: List[float]
class BacktestingEngine:
"""
High-Performance Backtesting-Engine für Krypto-Strategien.
Unterstützt Long/Short Positionen und komplexe Gebührenmodelle.
"""
def __init__(
self,
initial_capital: float = 10000.0,
maker_fee: float = 0.001, # 0.1%
taker_fee: float = 0.001, # 0.1%
slippage: float = 0.0005 # 0.05%
):
self.initial_capital = initial_capital
self.maker_fee = maker_fee
self.taker_fee = taker_fee
self.slippage = slippage
def run_backtest(
self,
data: pd.DataFrame,
strategy_func: Callable,
position_size_pct: float = 0.1,
verbose: bool = True
) -> BacktestResult:
"""
Führt Backtest mit gegebener Strategie-Funktion aus.
Args:
data: DataFrame mit OHLCV + Indikatoren
strategy_func: Funktion, die (data, index) -> SignalType
position_size_pct: Prozent des Kapitals pro Trade
verbose: Ausgabe der Fortschritte
"""
portfolio = Portfolio(initial_capital=self.initial_capital)
current_position = None # {'symbol': str, 'qty': float, 'entry': float}
for i in range(len(data)):
current_row = data.iloc[i]
current_time = current_row.name
current_price = current_row['close']
# Generiere Signal von KI oder technischer Strategie
signal = strategy_func(data, i)
# Position prüfen und ggf. schließen
if current_position is not None:
exit_signal = self._should_exit(
current_position, signal, current_price
)
if exit_signal:
trade = self._close_position(
portfolio, current_position, current_price,
current_time, signal
)
if trade:
portfolio.trades.append(trade)
current_position = None
# Position eröffnen
if current_position is None:
if signal in [SignalType.BUY, SignalType.STRONG_BUY]:
self._open_position(
portfolio, 'CRYPTO', position_size_pct,
current_price, current_time
)
# Simuliere Long-Position
position_value = portfolio.cash * position_size_pct
current_position = {
'type': PositionType.LONG,
'qty': position_value / current_price,
'entry': current_price
}
elif signal in [SignalType.SELL, SignalType.STRONG_SELL]:
# Short-Position (vereinfacht)
pass # Kurzversion ohne Short
# Aktualisiere Equity Curve
prices = {'CRYPTO': current_price}
portfolio.equity_curve.append(
portfolio.current_equity(prices)
)
if verbose and i % 500 == 0:
print(f"Progress: {i}/{len(data)} | "
f"Equity: ${portfolio.equity_curve[-1]:.2f}")
return self._calculate_metrics(portfolio)
def _should_exit(
self,
position: Dict,
signal: SignalType,
current_price: float
) -> bool:
"""Entscheidet ob Position geschlossen werden soll"""
if signal in [SignalType.SELL, SignalType.STRONG_SELL]:
return True
# Stop-Loss bei 5%
entry = position['entry']
if position['type'] == PositionType.LONG:
if current_price < entry * 0.95:
return True
# Take-Profit bei 10%
if position['type'] == PositionType.LONG:
if current_price > entry * 1.10:
return True
return False
def _open_position(
self,
portfolio: Portfolio,
symbol: str,
size_pct: float,
price: float,
time: datetime
):
"""Eröffnet neue Position mit Slippage und Gebühren"""
execution_price = price * (1 + self.slippage)
position_value = portfolio.cash * size_pct
fee = position_value * self.taker_fee
portfolio.cash -= (position_value + fee)
portfolio.positions[symbol] = position_value / execution_price
def _close_position(
self,
portfolio: Portfolio,
position: Dict,
current_price: float,
current_time: datetime,
exit_signal: SignalType
) -> Optional[Trade]:
"""Schließt Position und berechnet PnL"""
execution_price = current_price * (1 - self.slippage)
quantity = position['qty']
entry_price = position['entry']
pnl = (execution_price - entry_price) * quantity
pnl_pct = (execution_price / entry_price - 1) * 100
return Trade(
entry_time=position.get('entry_time', current_time),
exit_time=current_time,
entry_price=entry_price,
exit_price=execution_price,
position_type=position['type'],
quantity=quantity,
pnl=pnl,
pnl_percent=pnl_pct
)
def _calculate_metrics(self, portfolio: Portfolio) -> BacktestResult:
"""Berechnet Performance-Metriken"""
trades = portfolio.trades
if not trades:
return BacktestResult(
total_trades=0, winning_trades=0, losing_trades=0,
win_rate=0, total_pnl=0, total_pnl_percent=0,
max_drawdown=0, sharpe_ratio=0, avg_trade_duration=0,
largest_win=0, largest_loss=0, trades=[], equity_curve=[]
)
winning_trades = [t for t in trades if t.pnl > 0]
losing_trades = [t for t in trades if t.pnl <= 0]
total_pnl = sum(t.pnl for t in trades)
total_pnl_pct = (total_pnl / self.initial_capital) * 100
# Max Drawdown berechnen
equity = np.array(portfolio.equity_curve)
running_max = np.maximum.accumulate(equity)
drawdown = (equity - running_max) / running_max
max_drawdown = abs(np.min(drawdown)) * 100
# Sharpe Ratio (vereinfacht)
returns = np.diff(equity) / equity[:-1]
sharpe_ratio = np.mean(returns) / np.std(returns) * np.sqrt(365 * 24) if np.std(returns) > 0 else 0
return BacktestResult(
total_trades=len(trades),
winning_trades=len(winning_trades),
losing_trades=len(losing_trades),
win_rate=len(winning_trades) / len(trades) * 100,
total_pnl=total_pnl,
total_pnl_percent=total_pnl_pct,
max_drawdown=max_drawdown,
sharpe_ratio=sharpe_ratio,
avg_trade_duration=0, # Würde datetime-Differenz benötigen
largest_win=max((t.pnl for t in trades), default=0),
largest_loss=min((t.pnl for t in trades), default=0),
trades=trades,
equity_curve=portfolio.equity_curve
)
def plot_results(self, result: BacktestResult):
"""Visualisiert Backtest-Ergebnisse"""
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# Equity Curve
axes[0, 0].plot(result.equity_curve, color='blue')
axes[0, 0].axhline(y=self.initial_capital, color='gray', linestyle='--')
axes[0, 0].set_title('Equity Curve')
axes[0, 0].set_xlabel('Zeit')
axes[0, 0].set_ylabel('Kapital ($)')
axes[0, 0].grid(True)
# Drawdown
equity = np.array(result.equity_curve)
running_max = np.maximum.accumulate(equity)
drawdown = (equity - running_max) / running_max * 100
axes[0, 1].fill_between(range(len(drawdown)), drawdown, 0, color='red', alpha=0.3)
axes[0, 1].set_title('Drawdown')
axes[0, 1].set_xlabel('Zeit')
axes[0, 1].set_ylabel('Drawdown (%)')
axes[0, 1].grid(True)
# Trade PnL
if result.trades:
pnls = [t.pnl for t in result.trades]
colors = ['green' if p > 0 else 'red' for p in pnls]
axes[1, 0].bar(range(len(pnls)), pnls, color=colors, alpha=0.7)
axes[1, 0].set_title('Trade PnL')
axes[1, 0].set_xlabel('Trade #')
axes[1, 0].set_ylabel('PnL ($)')
axes[1, 0].axhline(y=0, color='black', linestyle='-', linewidth=0.5)
axes[1, 0].grid(True)
# Summary Stats
summary_text = f"""
Backtest Zusammenfassung
========================
Anfangskapital: ${self.initial_capital:,.2f}
Endkapital: ${result.equity_curve[-1]:,.2f}
Gesamt-PnL: ${result.total_pnl:,.2f} ({result.total_pnl_percent:.2f}%)
Gesamttrades: {result.total_trades}
Win Rate: {result.win_rate:.1f}%
Max Drawdown: {result.max_drawdown:.2f}%
Sharpe Ratio: {result.sharpe_ratio:.2f}
Größter Gewinn: ${result.largest_win:,.2f}
Größter Verlust: ${result.largest_loss:,.2f}
"""
axes[1, 1].text(0.1, 0.5, summary_text, fontsize=12,
family='monospace', verticalalignment='center')
axes[1, 1].axis('off')
plt.tight_layout()
plt.savefig('backtest_results.png', dpi=150)
plt.show()
Verwendung des Backtests
def simple_ma_strategy(data: pd.DataFrame, i: int) -> SignalType:
"""Einfache SMA-Crossover-Strategie"""
if i < 50:
return SignalType.HOLD
row = data.iloc[i]
prev_row = data.iloc[i-1]
# Golden Cross (SMA20 > SMA50)
if prev_row['sma_20'] <= prev_row['sma_50'] and row['sma_20'] > row['sma_50']:
return SignalType.BUY
# Death Cross (SMA20 < SMA50)
elif prev_row['sma_20'] >= prev_row['sma_50'] and row['sma_20'] < row['sma_50']:
return SignalType.SELL
return SignalType.HOLD
Starte Backtest
engine = BacktestingEngine(
initial_capital=10000,
maker_fee=0.001,
taker_fee=0.001
)
result = engine.run_backtest(
data=btcusd_data,
strategy_func=simple_ma_strategy,
position_size