Compare commits

..

4 Commits

Author SHA1 Message Date
admin 1af18f1029 Merge pull request #17 from metacube2/claude/link-sharing-platform-01MxxjTZD3mi1H7nAVq16TYy
Build internal link sharing platform
2025-12-06 11:02:01 +01:00
admin 05295f4b2a Merge pull request #16 from metacube2/claude/bitcoin-trading-signals-01UzsK9jXmmNYJqv5mayUdNq
Bitcoin trading signals with market analysis
2025-12-06 10:21:28 +01:00
Claude bcc19577eb Add project backup ZIP archive
Created backup archive for download containing all project files
2025-12-06 09:18:27 +00:00
Claude ef7ea500a9 Add Bitcoin Trading Signal System with MACD and News Sentiment Analysis
- Implement comprehensive Bitcoin trading signal system
- Add MACD (Moving Average Convergence Divergence) indicator
- Integrate news sentiment analysis from CryptoCompare
- Combine technical analysis with market sentiment
- Generate trading recommendations (Strong Buy, Buy, Hold, Sell, Strong Sell)

Features:
- Real-time Bitcoin price data from Binance and CoinGecko APIs
- Historical data analysis with MACD indicator
- News sentiment analysis with keyword-based scoring
- Weighted signal combination (60% MACD, 40% Sentiment)
- Confidence scoring for each recommendation
- Detailed reasoning for trading signals
- CLI interface with verbose and quick modes

Components:
- data_fetcher.py: Bitcoin price and market data retrieval
- macd_indicator.py: MACD calculation and signal generation
- news_sentiment.py: News analysis and sentiment scoring
- signal_generator.py: Combined signal generation
- bitcoin_trader.py: Main CLI application

Usage:
  python bitcoin_trading/bitcoin_trader.py [--verbose] [--days N] [--quick]

Documentation in bitcoin_trading/README.md
2025-12-02 22:45:17 +00:00
10 changed files with 1595 additions and 0 deletions
Binary file not shown.
+39
View File
@@ -0,0 +1,39 @@
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
env/
venv/
ENV/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
# Environment
.env
.env.local
# OS
.DS_Store
Thumbs.db
+274
View File
@@ -0,0 +1,274 @@
# 🪙 Bitcoin Trading Signal System
Ein intelligentes Trading-Signal-System für Bitcoin, das **technische Analyse (MACD)** mit **News-Sentiment-Analyse** kombiniert, um fundierte Kauf- und Verkaufsempfehlungen zu generieren.
## 📋 Features
### 🔍 Technische Analyse
- **MACD-Indikator** (Moving Average Convergence Divergence)
- Erkennung von Bullish/Bearish Crossovers
- Histogramm-Analyse für Momentum-Erkennung
- Trend-Analyse über multiple Zeitperioden
### 📰 Sentiment-Analyse
- Echtzeit-Analyse von Bitcoin-News
- Keyword-basierte Sentiment-Bewertung
- Multiple News-Quellen (CryptoCompare, optional NewsAPI)
- Aggregierung von positiven/negativen Marktsignalen
### 🎯 Kombinierte Signale
- Gewichtete Kombination aus MACD + Sentiment
- 5 Signal-Stufen: Starker Kauf, Kauf, Halten, Verkauf, Starker Verkauf
- Konfidenz-Bewertung für jedes Signal
- Detaillierte Begründungen für Empfehlungen
## 🚀 Installation
### Voraussetzungen
- Python 3.8 oder höher
- pip (Python Package Manager)
### 1. Dependencies installieren
```bash
cd bitcoin_trading
pip install -r requirements.txt
```
### 2. Optional: NewsAPI-Schlüssel
Für erweiterte News-Analyse kannst du einen kostenlosen NewsAPI-Schlüssel erhalten:
1. Registriere dich auf [NewsAPI.org](https://newsapi.org)
2. Hole dir deinen API-Schlüssel
3. Verwende ihn mit `--newsapi-key` Parameter
## 💻 Verwendung
### Basis-Analyse (empfohlen)
```bash
python bitcoin_trader.py
```
Dies führt eine vollständige Analyse durch mit:
- Aktuellen Bitcoin-Preisdaten
- 30 Tage historische MACD-Daten
- Aktuelle News-Sentiment-Analyse
- Kombinierter Trading-Empfehlung
### Erweiterte Optionen
**Ausführliche Ausgabe mit Ladestatus:**
```bash
python bitcoin_trader.py --verbose
```
**Mehr historische Daten (z.B. 60 Tage):**
```bash
python bitcoin_trader.py --days 60
```
**Schnelles Signal (nur Empfehlung):**
```bash
python bitcoin_trader.py --quick
```
**Mit NewsAPI-Schlüssel:**
```bash
python bitcoin_trader.py --newsapi-key YOUR_API_KEY
```
**Alle Optionen kombiniert:**
```bash
python bitcoin_trader.py --verbose --days 90 --newsapi-key YOUR_KEY
```
### Als Python-Modul verwenden
```python
from bitcoin_trading import BitcoinTrader
# Initialisiere Trader
trader = BitcoinTrader(verbose=True)
# Führe Analyse durch
trader.run_analysis(days=30)
# Oder hole schnelles Signal
signal = trader.get_quick_signal()
print(signal)
```
## 📊 Output-Beispiel
```
╔══════════════════════════════════════════════════════════════════╗
║ BITCOIN TRADING SIGNAL - 2024-12-02 15:30 ║
╚══════════════════════════════════════════════════════════════════╝
📊 EMPFEHLUNG: 🟢 KAUF
💯 KONFIDENZ: 72%
💰 AKTUELLER PREIS: $42,583.50
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📈 TECHNISCHE ANALYSE (MACD)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Signal: KAUF
MACD: 125.34
Signal Line: 98.21
Histogram: 27.13
Preis-Änderung (10 Tage): +5.67%
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📰 SENTIMENT-ANALYSE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Markt-Sentiment: POSITIV
Sentiment-Score: 0.425
Analysierte Artikel: 28
├─ Positiv: 16
├─ Neutral: 8
└─ Negativ: 4
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📋 BEGRÜNDUNG
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. MACD-Signal: KAUF (Konfidenz: 70%)
2. Bullish Crossover: MACD kreuzt Signal-Linie von unten
3. Positives Momentum: Histogramm steigt
4. Markt-Sentiment: POSITIV (Konfidenz: 75%, Score: 0.425)
5. ✅ MACD und Sentiment stimmen überein → Starkes Signal
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
💡 HANDLUNGSEMPFEHLUNG
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🟢 KAUFGELEGENHEIT
→ Erwäge einen Einstieg mit kleiner Position
→ Warte ggf. auf Bestätigung durch weitere Signale
⚠️ Risiko-Hinweis: Diese Analyse hat eine Konfidenz von 72%
⚠️ Keine Anlageberatung - Trading auf eigenes Risiko!
╚══════════════════════════════════════════════════════════════════╝
```
## 🔧 Technische Details
### MACD-Parameter
- **Fast EMA**: 12 Perioden
- **Slow EMA**: 26 Perioden
- **Signal Line**: 9 Perioden
### Signal-Logik
- **Starker Kauf**: Bullish Crossover im negativen Bereich
- **Kauf**: Bullish Crossover oder positives Momentum
- **Halten**: Keine klare Richtung
- **Verkauf**: Bearish Crossover oder negatives Momentum
- **Starker Verkauf**: Bearish Crossover im positiven Bereich
### Gewichtung
- MACD (Technische Analyse): **60%**
- News-Sentiment: **40%**
- Bonus bei übereinstimmenden Signalen: **+10%**
## 📁 Projektstruktur
```
bitcoin_trading/
├── __init__.py # Package Initialisierung
├── bitcoin_trader.py # Hauptprogramm (CLI)
├── data_fetcher.py # Bitcoin-Preisdaten-Abruf
├── macd_indicator.py # MACD-Indikator-Berechnung
├── news_sentiment.py # News-Sentiment-Analyse
├── signal_generator.py # Signal-Kombination & Empfehlung
├── requirements.txt # Python-Dependencies
└── README.md # Diese Datei
```
## 🔌 API-Quellen
### Preisdaten
- **Binance API** (primär) - Schnelle, zuverlässige Preisdaten
- **CoinGecko API** (fallback) - Backup-Datenquelle
### News
- **CryptoCompare News API** (kostenlos) - Crypto-spezifische News
- **NewsAPI** (optional) - Erweiterte News-Abdeckung
## ⚠️ Wichtige Hinweise
### Disclaimer
- **Dies ist KEINE Anlageberatung**
- Trading mit Kryptowährungen ist hochriskant
- Vergangene Performance garantiert keine zukünftigen Ergebnisse
- Investiere nur Geld, das du dir leisten kannst zu verlieren
- Führe deine eigene Due Diligence durch
### Risiken
- Marktvolatilität kann Signale schnell ungültig machen
- Technische Indikatoren sind nicht 100% zuverlässig
- News-Sentiment kann manipuliert sein
- API-Ausfälle können Daten beeinträchtigen
### Best Practices
- Verwende Signale als einen von mehreren Faktoren
- Setze immer Stop-Loss-Orders
- Diversifiziere dein Portfolio
- Handel nur mit klarem Kopf
- Dokumentiere deine Trades
## 🐛 Troubleshooting
### Fehler: "Konnte Bitcoin-Preis nicht abrufen"
- Überprüfe Internetverbindung
- APIs könnten temporär down sein
- Warte kurz und versuche es erneut
### Fehler: "Nicht genug Daten für MACD"
- Erhöhe `--days` Parameter (mindestens 30 Tage empfohlen)
- Stelle sicher, dass historische Daten geladen werden
### Sentiment zeigt immer "NEUTRAL"
- Möglicherweise keine aktuellen News verfügbar
- Verwende `--newsapi-key` für mehr News-Quellen
- News-APIs könnten Rate-Limits haben
## 🔄 Updates & Erweiterungen
### Geplante Features
- [ ] RSI (Relative Strength Index) Integration
- [ ] Bollinger Bands Analyse
- [ ] Machine Learning Modelle
- [ ] Email/Telegram Benachrichtigungen
- [ ] Backtesting-Funktionalität
- [ ] WebSocket Real-time Updates
- [ ] Multi-Coin Support (ETH, etc.)
### Erweiterungsmöglichkeiten
- Integration weiterer technischer Indikatoren
- Social Media Sentiment (Twitter/Reddit)
- On-Chain-Metriken (Wallet-Bewegungen)
- Advanced ML/AI Modelle
- Portfolio-Management-Features
## 📝 Lizenz
Dieses Projekt ist Teil des GetYourBand-Projekts.
## 🤝 Beitragen
Contributions sind willkommen! Bitte öffne ein Issue oder Pull Request.
## 📧 Support
Bei Fragen oder Problemen erstelle ein Issue im Repository.
---
**Made with 📊 and ₿ for informed trading decisions**
⚠️ **Remember: Don't invest more than you can afford to lose!**
+26
View File
@@ -0,0 +1,26 @@
"""
Bitcoin Trading Signal System
Ein System zur Generierung von Kauf-/Verkaufsempfehlungen für Bitcoin
basierend auf MACD-Indikatoren und News-Sentiment-Analyse
"""
__version__ = "1.0.0"
__author__ = "Bitcoin Trading Signal System"
from .data_fetcher import BitcoinDataFetcher
from .macd_indicator import MACDIndicator, MACDSignal
from .news_sentiment import NewsSentimentAnalyzer, SentimentScore
from .signal_generator import SignalGenerator, TradingAction, TradingSignal
from .bitcoin_trader import BitcoinTrader
__all__ = [
'BitcoinDataFetcher',
'MACDIndicator',
'MACDSignal',
'NewsSentimentAnalyzer',
'SentimentScore',
'SignalGenerator',
'TradingAction',
'TradingSignal',
'BitcoinTrader',
]
+212
View File
@@ -0,0 +1,212 @@
#!/usr/bin/env python3
"""
Bitcoin Trading Signal System
Hauptprogramm für Bitcoin Trading-Empfehlungen basierend auf MACD und News-Sentiment
"""
import sys
import argparse
from datetime import datetime
from typing import Optional
from data_fetcher import BitcoinDataFetcher
from signal_generator import SignalGenerator
class BitcoinTrader:
"""
Haupt-Klasse für das Bitcoin Trading Signal System
"""
def __init__(self, newsapi_key: Optional[str] = None, verbose: bool = False):
"""
Args:
newsapi_key: Optional NewsAPI-Schlüssel
verbose: Ausführliche Ausgabe
"""
self.data_fetcher = BitcoinDataFetcher()
self.signal_generator = SignalGenerator(newsapi_key=newsapi_key)
self.verbose = verbose
def run_analysis(self, days: int = 30) -> None:
"""
Führt komplette Trading-Analyse durch
Args:
days: Anzahl Tage für historische Daten
"""
print("╔══════════════════════════════════════════════════════════════════╗")
print("║ BITCOIN TRADING SIGNAL SYSTEM v1.0 ║")
print("╚══════════════════════════════════════════════════════════════════╝")
print()
# 1. Lade aktuelle Preisdaten
if self.verbose:
print("📊 Lade aktuelle Bitcoin-Preisdaten...")
current_price = self.data_fetcher.get_current_price()
if not current_price:
print("❌ Fehler: Konnte aktuellen Bitcoin-Preis nicht abrufen!")
sys.exit(1)
if self.verbose:
print(f"✓ Aktueller BTC-Preis: ${current_price:,.2f}")
# 2. Lade historische Daten
if self.verbose:
print(f"📈 Lade historische Daten ({days} Tage)...")
price_df = self.data_fetcher.get_historical_data(days=days)
if price_df.empty:
print("❌ Fehler: Konnte historische Daten nicht abrufen!")
sys.exit(1)
if self.verbose:
print(f"{len(price_df)} Datenpunkte geladen")
# 3. Lade Marktdaten (optional)
if self.verbose:
print("💹 Lade erweiterte Marktdaten...")
market_data = self.data_fetcher.get_market_data()
if market_data and self.verbose:
print(f"✓ Marktdaten geladen")
if market_data.get('price_change_24h'):
change_24h = market_data['price_change_24h']
emoji = "📈" if change_24h > 0 else "📉"
print(f" {emoji} 24h Veränderung: {change_24h:+.2f}%")
# 4. Generiere Trading-Signal
if self.verbose:
print("\n🔍 Analysiere MACD-Indikatoren...")
print("📰 Analysiere News-Sentiment...")
print("🎯 Generiere Trading-Signal...\n")
signal = self.signal_generator.generate_signal(price_df, current_price)
# 5. Zeige Empfehlung
recommendation = self.signal_generator.get_recommendation_text(signal)
print(recommendation)
# 6. Zusätzliche Marktinformationen
if market_data and self.verbose:
print("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
print("📊 ZUSÄTZLICHE MARKTINFORMATIONEN")
print("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n")
if market_data.get('market_cap'):
print(f" Marktkapitalisierung: ${market_data['market_cap']:,.0f}")
if market_data.get('total_volume'):
print(f" 24h Handelsvolumen: ${market_data['total_volume']:,.0f}")
if market_data.get('high_24h') and market_data.get('low_24h'):
print(f" 24h Hoch: ${market_data['high_24h']:,.2f}")
print(f" 24h Tief: ${market_data['low_24h']:,.2f}")
if market_data.get('price_change_7d'):
print(f" 7-Tage Veränderung: {market_data['price_change_7d']:+.2f}%")
if market_data.get('price_change_30d'):
print(f" 30-Tage Veränderung: {market_data['price_change_30d']:+.2f}%")
print()
def get_quick_signal(self) -> str:
"""
Gibt schnelles Trading-Signal zurück (nur Empfehlung)
Returns:
Signal-String
"""
current_price = self.data_fetcher.get_current_price()
if not current_price:
return "❌ Fehler beim Abrufen der Daten"
price_df = self.data_fetcher.get_historical_data(days=30)
if price_df.empty:
return "❌ Fehler beim Abrufen der Daten"
signal = self.signal_generator.generate_signal(price_df, current_price)
return f"{signal.action.value} (Konfidenz: {signal.confidence}%) @ ${signal.price:,.2f}"
def main():
"""Hauptfunktion"""
parser = argparse.ArgumentParser(
description='Bitcoin Trading Signal System - MACD + News Sentiment Analyse',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Beispiele:
%(prog)s # Standard-Analyse
%(prog)s --verbose # Ausführliche Ausgabe
%(prog)s --days 60 # 60 Tage historische Daten
%(prog)s --quick # Schnelles Signal
%(prog)s --newsapi-key YOUR_KEY # Mit NewsAPI-Schlüssel
Hinweis:
- NewsAPI-Schlüssel optional (erhöht News-Quellen)
- Kostenlos bei https://newsapi.org
"""
)
parser.add_argument(
'-v', '--verbose',
action='store_true',
help='Ausführliche Ausgabe mit Ladestatus'
)
parser.add_argument(
'-d', '--days',
type=int,
default=30,
help='Anzahl Tage für historische Daten (Standard: 30)'
)
parser.add_argument(
'-q', '--quick',
action='store_true',
help='Schnelles Signal ohne Details'
)
parser.add_argument(
'--newsapi-key',
type=str,
default=None,
help='NewsAPI-Schlüssel für erweiterte News-Analyse'
)
args = parser.parse_args()
# Initialisiere Trader
trader = BitcoinTrader(
newsapi_key=args.newsapi_key,
verbose=args.verbose
)
try:
if args.quick:
# Schnelles Signal
signal = trader.get_quick_signal()
print(signal)
else:
# Vollständige Analyse
trader.run_analysis(days=args.days)
except KeyboardInterrupt:
print("\n\n⚠️ Analyse abgebrochen durch Benutzer")
sys.exit(0)
except Exception as e:
print(f"\n❌ Fehler: {e}")
if args.verbose:
import traceback
traceback.print_exc()
sys.exit(1)
if __name__ == "__main__":
main()
+175
View File
@@ -0,0 +1,175 @@
"""
Bitcoin Price Data Fetcher
Ruft aktuelle und historische Bitcoin-Preisdaten von verschiedenen APIs ab
"""
import requests
from datetime import datetime, timedelta
import pandas as pd
from typing import Dict, List, Optional
import time
class BitcoinDataFetcher:
"""Fetches Bitcoin price data from various sources"""
def __init__(self):
self.base_url_coingecko = "https://api.coingecko.com/api/v3"
self.base_url_binance = "https://api.binance.com/api/v3"
def get_current_price(self) -> Optional[float]:
"""
Holt den aktuellen Bitcoin-Preis in USD
Returns:
float: Aktueller BTC/USD Preis oder None bei Fehler
"""
try:
# Versuche zuerst Binance (schneller und zuverlässiger)
url = f"{self.base_url_binance}/ticker/price"
params = {"symbol": "BTCUSDT"}
response = requests.get(url, params=params, timeout=10)
if response.status_code == 200:
data = response.json()
return float(data['price'])
except Exception as e:
print(f"Fehler beim Abrufen von Binance: {e}")
try:
# Fallback zu CoinGecko
url = f"{self.base_url_coingecko}/simple/price"
params = {
"ids": "bitcoin",
"vs_currencies": "usd"
}
response = requests.get(url, params=params, timeout=10)
if response.status_code == 200:
data = response.json()
return float(data['bitcoin']['usd'])
except Exception as e:
print(f"Fehler beim Abrufen von CoinGecko: {e}")
return None
def get_historical_data(self, days: int = 30) -> pd.DataFrame:
"""
Holt historische Bitcoin-Preisdaten
Args:
days: Anzahl der Tage zurück
Returns:
DataFrame mit Spalten: timestamp, price, volume
"""
try:
# Binance Klines (Candlestick-Daten)
url = f"{self.base_url_binance}/klines"
# Berechne Zeitstempel
end_time = int(datetime.now().timestamp() * 1000)
start_time = int((datetime.now() - timedelta(days=days)).timestamp() * 1000)
params = {
"symbol": "BTCUSDT",
"interval": "1h", # Stündliche Daten
"startTime": start_time,
"endTime": end_time,
"limit": 1000
}
response = requests.get(url, params=params, timeout=30)
if response.status_code == 200:
data = response.json()
# Konvertiere zu DataFrame
df = pd.DataFrame(data, columns=[
'timestamp', 'open', 'high', 'low', 'close',
'volume', 'close_time', 'quote_volume', 'trades',
'taker_buy_base', 'taker_buy_quote', 'ignore'
])
# Behalte nur relevante Spalten
df = df[['timestamp', 'close', 'volume']]
df.columns = ['timestamp', 'price', 'volume']
# Konvertiere Datentypen
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
df['price'] = df['price'].astype(float)
df['volume'] = df['volume'].astype(float)
return df
except Exception as e:
print(f"Fehler beim Abrufen historischer Daten: {e}")
# Fallback: Leeres DataFrame
return pd.DataFrame(columns=['timestamp', 'price', 'volume'])
def get_market_data(self) -> Dict:
"""
Holt erweiterte Marktdaten für Bitcoin
Returns:
Dict mit Marktdaten (Volumen, Marktkapitalisierung, etc.)
"""
try:
url = f"{self.base_url_coingecko}/coins/bitcoin"
params = {
"localization": "false",
"tickers": "false",
"market_data": "true",
"community_data": "false",
"developer_data": "false"
}
response = requests.get(url, params=params, timeout=15)
if response.status_code == 200:
data = response.json()
market_data = data.get('market_data', {})
return {
'current_price': market_data.get('current_price', {}).get('usd'),
'market_cap': market_data.get('market_cap', {}).get('usd'),
'total_volume': market_data.get('total_volume', {}).get('usd'),
'price_change_24h': market_data.get('price_change_percentage_24h'),
'price_change_7d': market_data.get('price_change_percentage_7d'),
'price_change_30d': market_data.get('price_change_percentage_30d'),
'high_24h': market_data.get('high_24h', {}).get('usd'),
'low_24h': market_data.get('low_24h', {}).get('usd'),
}
except Exception as e:
print(f"Fehler beim Abrufen von Marktdaten: {e}")
return {}
if __name__ == "__main__":
# Test
fetcher = BitcoinDataFetcher()
print("=== Bitcoin Preis ===")
price = fetcher.get_current_price()
if price:
print(f"Aktueller BTC/USD Preis: ${price:,.2f}")
print("\n=== Marktdaten ===")
market = fetcher.get_market_data()
for key, value in market.items():
if value is not None:
if 'price' in key or 'cap' in key or 'volume' in key or 'high' in key or 'low' in key:
print(f"{key}: ${value:,.2f}")
else:
print(f"{key}: {value:.2f}%")
print("\n=== Historische Daten (letzte 7 Tage) ===")
df = fetcher.get_historical_data(days=7)
if not df.empty:
print(f"Anzahl Datenpunkte: {len(df)}")
print(df.tail())
+254
View File
@@ -0,0 +1,254 @@
"""
MACD (Moving Average Convergence Divergence) Indicator
Berechnet MACD-Signale für Bitcoin Trading
"""
import pandas as pd
import numpy as np
from typing import Dict, Tuple, Optional
from enum import Enum
class MACDSignal(Enum):
"""MACD Signal-Typen"""
STRONG_BUY = "STARKER KAUF"
BUY = "KAUF"
NEUTRAL = "NEUTRAL"
SELL = "VERKAUF"
STRONG_SELL = "STARKER VERKAUF"
class MACDIndicator:
"""
MACD-Indikator für technische Analyse
Standard-Parameter:
- Fast EMA: 12 Perioden
- Slow EMA: 26 Perioden
- Signal: 9 Perioden
"""
def __init__(self, fast_period: int = 12, slow_period: int = 26, signal_period: int = 9):
"""
Args:
fast_period: Schnelle EMA-Periode (Standard: 12)
slow_period: Langsame EMA-Periode (Standard: 26)
signal_period: Signal-Linie-Periode (Standard: 9)
"""
self.fast_period = fast_period
self.slow_period = slow_period
self.signal_period = signal_period
def calculate_ema(self, data: pd.Series, period: int) -> pd.Series:
"""
Berechnet Exponential Moving Average (EMA)
Args:
data: Preisdaten
period: EMA-Periode
Returns:
EMA-Serie
"""
return data.ewm(span=period, adjust=False).mean()
def calculate_macd(self, prices: pd.Series) -> pd.DataFrame:
"""
Berechnet MACD-Indikator
Args:
prices: Preis-Serie (normalerweise Close-Preise)
Returns:
DataFrame mit MACD, Signal und Histogram
"""
# Berechne EMAs
ema_fast = self.calculate_ema(prices, self.fast_period)
ema_slow = self.calculate_ema(prices, self.slow_period)
# MACD-Linie
macd_line = ema_fast - ema_slow
# Signal-Linie (9-Tage EMA der MACD-Linie)
signal_line = self.calculate_ema(macd_line, self.signal_period)
# MACD-Histogramm (Differenz zwischen MACD und Signal)
histogram = macd_line - signal_line
# Erstelle DataFrame
df = pd.DataFrame({
'macd': macd_line,
'signal': signal_line,
'histogram': histogram
})
return df
def get_signal(self, df: pd.DataFrame) -> Tuple[MACDSignal, Dict]:
"""
Generiert Trading-Signal basierend auf MACD
Args:
df: DataFrame mit price-Spalte
Returns:
Tuple aus (Signal, Details-Dict)
"""
if df.empty or len(df) < self.slow_period + self.signal_period:
return MACDSignal.NEUTRAL, {
'reason': 'Nicht genug Daten für MACD-Berechnung',
'confidence': 0
}
# Berechne MACD
macd_df = self.calculate_macd(df['price'])
# Hole aktuelle und vorherige Werte
current_macd = macd_df['macd'].iloc[-1]
current_signal = macd_df['signal'].iloc[-1]
current_histogram = macd_df['histogram'].iloc[-1]
prev_macd = macd_df['macd'].iloc[-2]
prev_signal = macd_df['signal'].iloc[-2]
prev_histogram = macd_df['histogram'].iloc[-2]
# Bestimme Signal-Typ
signal = MACDSignal.NEUTRAL
confidence = 0
reasons = []
# 1. Bullish Crossover (MACD kreuzt Signal von unten)
if prev_macd <= prev_signal and current_macd > current_signal:
signal = MACDSignal.BUY
confidence = 70
reasons.append("Bullish Crossover: MACD kreuzt Signal-Linie von unten")
# Starkes Kaufsignal, wenn zusätzlich im negativen Bereich
if current_macd < 0:
signal = MACDSignal.STRONG_BUY
confidence = 85
reasons.append("MACD im negativen Bereich → Überkauft")
# 2. Bearish Crossover (MACD kreuzt Signal von oben)
elif prev_macd >= prev_signal and current_macd < current_signal:
signal = MACDSignal.SELL
confidence = 70
reasons.append("Bearish Crossover: MACD kreuzt Signal-Linie von oben")
# Starkes Verkaufssignal, wenn zusätzlich im positiven Bereich
if current_macd > 0:
signal = MACDSignal.STRONG_SELL
confidence = 85
reasons.append("MACD im positiven Bereich → Überverkauft")
# 3. Divergenz-Analyse (Histogramm)
else:
histogram_trend = current_histogram - prev_histogram
if histogram_trend > 0 and current_histogram > 0:
signal = MACDSignal.BUY
confidence = 55
reasons.append("Positives Momentum: Histogramm steigt")
elif histogram_trend < 0 and current_histogram < 0:
signal = MACDSignal.SELL
confidence = 55
reasons.append("Negatives Momentum: Histogramm fällt")
else:
signal = MACDSignal.NEUTRAL
confidence = 30
reasons.append("Kein klarer Trend erkennbar")
# Zusätzliche Analyse: Preis-Trend
recent_prices = df['price'].tail(10)
price_change = ((recent_prices.iloc[-1] - recent_prices.iloc[0]) / recent_prices.iloc[0]) * 100
if abs(price_change) > 5:
if price_change > 0:
reasons.append(f"Preis-Trend: +{price_change:.2f}% (aufwärts)")
else:
reasons.append(f"Preis-Trend: {price_change:.2f}% (abwärts)")
details = {
'macd': float(current_macd),
'signal': float(current_signal),
'histogram': float(current_histogram),
'prev_histogram': float(prev_histogram),
'crossover': current_macd > current_signal,
'confidence': confidence,
'reasons': reasons,
'price_change_10d': float(price_change)
}
return signal, details
def analyze_trend(self, df: pd.DataFrame, periods: int = 20) -> str:
"""
Analysiert den Trend der letzten Perioden
Args:
df: DataFrame mit MACD-Daten
periods: Anzahl Perioden zur Analyse
Returns:
Trend-Beschreibung
"""
macd_df = self.calculate_macd(df['price'])
if len(macd_df) < periods:
return "Nicht genug Daten"
recent_histogram = macd_df['histogram'].tail(periods)
# Zähle positive/negative Balken
positive_bars = (recent_histogram > 0).sum()
negative_bars = (recent_histogram < 0).sum()
if positive_bars > negative_bars * 1.5:
return "Starker Aufwärtstrend"
elif positive_bars > negative_bars:
return "Leichter Aufwärtstrend"
elif negative_bars > positive_bars * 1.5:
return "Starker Abwärtstrend"
elif negative_bars > positive_bars:
return "Leichter Abwärtstrend"
else:
return "Seitwärtstrend"
if __name__ == "__main__":
# Test mit simulierten Daten
print("=== MACD Indicator Test ===\n")
# Erstelle Test-Daten
dates = pd.date_range(start='2024-01-01', periods=100, freq='D')
prices = 40000 + np.cumsum(np.random.randn(100) * 500) # Random Walk
df = pd.DataFrame({
'timestamp': dates,
'price': prices
})
# Initialisiere MACD
macd = MACDIndicator()
# Berechne MACD
macd_df = macd.calculate_macd(df['price'])
print("Letzte 5 MACD-Werte:")
print(macd_df.tail())
print("\n=== Trading Signal ===")
signal, details = macd.get_signal(df)
print(f"Signal: {signal.value}")
print(f"Konfidenz: {details['confidence']}%")
print(f"\nMACD: {details['macd']:.2f}")
print(f"Signal: {details['signal']:.2f}")
print(f"Histogram: {details['histogram']:.2f}")
print(f"\nGründe:")
for reason in details['reasons']:
print(f" - {reason}")
print(f"\nTrend-Analyse: {macd.analyze_trend(df)}")
+300
View File
@@ -0,0 +1,300 @@
"""
News Sentiment Analyzer für Bitcoin
Analysiert Nachrichten und bestimmt das Markt-Sentiment
"""
import requests
from datetime import datetime, timedelta
from typing import List, Dict, Optional, Tuple
from enum import Enum
import re
class SentimentScore(Enum):
"""Sentiment-Score-Typen"""
VERY_POSITIVE = "SEHR POSITIV"
POSITIVE = "POSITIV"
NEUTRAL = "NEUTRAL"
NEGATIVE = "NEGATIV"
VERY_NEGATIVE = "SEHR NEGATIV"
class NewsSentimentAnalyzer:
"""
Analysiert Bitcoin-bezogene Nachrichten und bestimmt das Sentiment
"""
def __init__(self, api_key: Optional[str] = None):
"""
Args:
api_key: NewsAPI-Schlüssel (optional, verwendet Free Tier wenn None)
"""
self.api_key = api_key
self.newsapi_url = "https://newsapi.org/v2/everything"
# Sentiment-Keyword-Listen
self.positive_keywords = [
'bullish', 'surge', 'rally', 'gain', 'rise', 'soar', 'jump',
'breakthrough', 'adoption', 'institutional', 'buy', 'investment',
'growth', 'profit', 'support', 'upgrade', 'positive', 'optimistic',
'breakout', 'moon', 'accumulation', 'bull run', 'all-time high',
'ath', 'recovery', 'uptrend', 'momentum', 'strong'
]
self.negative_keywords = [
'bearish', 'crash', 'plunge', 'fall', 'drop', 'decline', 'sell',
'regulation', 'ban', 'warning', 'risk', 'fear', 'panic', 'loss',
'hack', 'fraud', 'scam', 'bubble', 'concern', 'volatile',
'downtrend', 'resistance', 'bear market', 'dump', 'correction',
'selling pressure', 'oversold', 'weak', 'uncertainty'
]
# Crypto News Sources (kostenlos zugänglich)
self.crypto_news_sources = [
'https://cryptopanic.com/api/v1/posts/',
'https://min-api.cryptocompare.com/data/v2/news/',
]
def fetch_news_newsapi(self, days: int = 1) -> List[Dict]:
"""
Holt Bitcoin-News von NewsAPI
Args:
days: Anzahl Tage zurück
Returns:
Liste von News-Artikeln
"""
if not self.api_key:
return []
try:
from_date = (datetime.now() - timedelta(days=days)).strftime('%Y-%m-%d')
params = {
'q': 'bitcoin OR BTC OR cryptocurrency',
'from': from_date,
'sortBy': 'publishedAt',
'language': 'en',
'apiKey': self.api_key
}
response = requests.get(self.newsapi_url, params=params, timeout=15)
if response.status_code == 200:
data = response.json()
return data.get('articles', [])
except Exception as e:
print(f"Fehler beim Abrufen von NewsAPI: {e}")
return []
def fetch_news_cryptocompare(self, limit: int = 50) -> List[Dict]:
"""
Holt Bitcoin-News von CryptoCompare (kostenlos)
Args:
limit: Anzahl News-Artikel
Returns:
Liste von News-Artikeln
"""
try:
url = "https://min-api.cryptocompare.com/data/v2/news/"
params = {
'categories': 'BTC',
'lang': 'EN'
}
response = requests.get(url, params=params, timeout=15)
if response.status_code == 200:
data = response.json()
news_list = data.get('Data', [])
# Formatiere zu einheitlichem Format
formatted_news = []
for item in news_list[:limit]:
formatted_news.append({
'title': item.get('title', ''),
'description': item.get('body', ''),
'publishedAt': datetime.fromtimestamp(item.get('published_on', 0)),
'source': item.get('source', ''),
'url': item.get('url', '')
})
return formatted_news
except Exception as e:
print(f"Fehler beim Abrufen von CryptoCompare: {e}")
return []
def analyze_text_sentiment(self, text: str) -> Tuple[float, Dict]:
"""
Analysiert Sentiment eines Textes
Args:
text: Zu analysierender Text
Returns:
Tuple aus (Score -1 bis +1, Details)
"""
if not text:
return 0.0, {'positive': 0, 'negative': 0}
text_lower = text.lower()
# Zähle positive und negative Keywords
positive_count = sum(1 for keyword in self.positive_keywords if keyword in text_lower)
negative_count = sum(1 for keyword in self.negative_keywords if keyword in text_lower)
# Berechne Score (-1 bis +1)
total_keywords = positive_count + negative_count
if total_keywords == 0:
score = 0.0
else:
score = (positive_count - negative_count) / total_keywords
details = {
'positive': positive_count,
'negative': negative_count,
'total': total_keywords
}
return score, details
def analyze_news_sentiment(self, days: int = 1, limit: int = 50) -> Tuple[SentimentScore, Dict]:
"""
Analysiert Gesamt-Sentiment der aktuellen Bitcoin-Nachrichten
Args:
days: Anzahl Tage zurück
limit: Max. Anzahl Artikel
Returns:
Tuple aus (Sentiment, Details)
"""
# Hole News von verschiedenen Quellen
news_articles = []
# Versuche NewsAPI (falls API-Key vorhanden)
if self.api_key:
news_articles.extend(self.fetch_news_newsapi(days))
# Hole von CryptoCompare (kostenlos)
crypto_news = self.fetch_news_cryptocompare(limit)
news_articles.extend(crypto_news)
if not news_articles:
return SentimentScore.NEUTRAL, {
'reason': 'Keine News gefunden',
'confidence': 0,
'articles_analyzed': 0
}
# Analysiere jeden Artikel
sentiment_scores = []
positive_articles = 0
negative_articles = 0
neutral_articles = 0
for article in news_articles[:limit]:
title = article.get('title', '')
description = article.get('description', '')
combined_text = f"{title} {description}"
score, details = self.analyze_text_sentiment(combined_text)
sentiment_scores.append(score)
if score > 0.2:
positive_articles += 1
elif score < -0.2:
negative_articles += 1
else:
neutral_articles += 1
# Berechne Durchschnitts-Sentiment
avg_sentiment = sum(sentiment_scores) / len(sentiment_scores) if sentiment_scores else 0
# Bestimme Gesamt-Sentiment
if avg_sentiment > 0.4:
sentiment = SentimentScore.VERY_POSITIVE
confidence = min(95, int(70 + abs(avg_sentiment) * 50))
elif avg_sentiment > 0.15:
sentiment = SentimentScore.POSITIVE
confidence = min(85, int(60 + abs(avg_sentiment) * 50))
elif avg_sentiment < -0.4:
sentiment = SentimentScore.VERY_NEGATIVE
confidence = min(95, int(70 + abs(avg_sentiment) * 50))
elif avg_sentiment < -0.15:
sentiment = SentimentScore.NEGATIVE
confidence = min(85, int(60 + abs(avg_sentiment) * 50))
else:
sentiment = SentimentScore.NEUTRAL
confidence = 50
details = {
'average_sentiment': float(avg_sentiment),
'confidence': confidence,
'articles_analyzed': len(news_articles),
'positive_articles': positive_articles,
'negative_articles': negative_articles,
'neutral_articles': neutral_articles,
'top_articles': news_articles[:5] # Top 5 für Details
}
return sentiment, details
def get_trending_topics(self, news_articles: List[Dict]) -> List[str]:
"""
Extrahiert Trend-Topics aus News
Args:
news_articles: Liste von News-Artikeln
Returns:
Liste der häufigsten Topics
"""
topics = []
keywords = [
'regulation', 'etf', 'institutional', 'mining',
'halving', 'adoption', 'sec', 'fed', 'inflation',
'blockchain', 'defi', 'nft', 'altcoin'
]
for article in news_articles:
text = f"{article.get('title', '')} {article.get('description', '')}".lower()
for keyword in keywords:
if keyword in text:
topics.append(keyword)
# Zähle Häufigkeit
from collections import Counter
topic_counts = Counter(topics)
return [topic for topic, count in topic_counts.most_common(5)]
if __name__ == "__main__":
# Test
print("=== Bitcoin News Sentiment Analyzer ===\n")
analyzer = NewsSentimentAnalyzer()
print("Lade Bitcoin-Nachrichten...")
sentiment, details = analyzer.analyze_news_sentiment(days=1, limit=30)
print(f"\n=== Sentiment-Analyse ===")
print(f"Gesamt-Sentiment: {sentiment.value}")
print(f"Konfidenz: {details['confidence']}%")
print(f"Durchschnitts-Score: {details['average_sentiment']:.3f}")
print(f"\nAnalysierte Artikel: {details['articles_analyzed']}")
print(f" Positiv: {details['positive_articles']}")
print(f" Neutral: {details['neutral_articles']}")
print(f" Negativ: {details['negative_articles']}")
if details.get('top_articles'):
print(f"\n=== Top 3 Schlagzeilen ===")
for i, article in enumerate(details['top_articles'][:3], 1):
print(f"{i}. {article.get('title', 'N/A')}")
+20
View File
@@ -0,0 +1,20 @@
# Bitcoin Trading Signal System - Python Dependencies
# Data Processing
pandas>=2.0.0
numpy>=1.24.0
# HTTP Requests
requests>=2.31.0
# Optional: Enhanced Sentiment Analysis
# textblob>=0.17.0
# vaderSentiment>=3.3.2
# Optional: Advanced Technical Analysis
# ta>=0.11.0
# pandas-ta>=0.3.14b0
# Development/Testing (optional)
# pytest>=7.4.0
# pytest-cov>=4.1.0
+295
View File
@@ -0,0 +1,295 @@
"""
Trading Signal Generator
Kombiniert MACD-Indikatoren und News-Sentiment für Trading-Empfehlungen
"""
from typing import Dict, Tuple
from enum import Enum
from dataclasses import dataclass
from datetime import datetime
from macd_indicator import MACDIndicator, MACDSignal
from news_sentiment import NewsSentimentAnalyzer, SentimentScore
class TradingAction(Enum):
"""Trading-Empfehlungs-Typen"""
STRONG_BUY = "🟢 STARKER KAUF"
BUY = "🟢 KAUF"
HOLD = "🟡 HALTEN"
SELL = "🔴 VERKAUF"
STRONG_SELL = "🔴 STARKER VERKAUF"
@dataclass
class TradingSignal:
"""Datenklasse für Trading-Signale"""
action: TradingAction
confidence: int # 0-100
price: float
timestamp: datetime
macd_signal: MACDSignal
sentiment: SentimentScore
reasons: list
technical_details: dict
sentiment_details: dict
def __str__(self):
return f"""
╔══════════════════════════════════════════════════════════════════╗
║ BITCOIN TRADING SIGNAL - {self.timestamp.strftime('%Y-%m-%d %H:%M')}
╚══════════════════════════════════════════════════════════════════╝
📊 EMPFEHLUNG: {self.action.value}
💯 KONFIDENZ: {self.confidence}%
💰 AKTUELLER PREIS: ${self.price:,.2f}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📈 TECHNISCHE ANALYSE (MACD)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Signal: {self.macd_signal.value}
MACD: {self.technical_details.get('macd', 0):.2f}
Signal Line: {self.technical_details.get('signal', 0):.2f}
Histogram: {self.technical_details.get('histogram', 0):.2f}
Preis-Änderung (10 Tage): {self.technical_details.get('price_change_10d', 0):.2f}%
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📰 SENTIMENT-ANALYSE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Markt-Sentiment: {self.sentiment.value}
Sentiment-Score: {self.sentiment_details.get('average_sentiment', 0):.3f}
Analysierte Artikel: {self.sentiment_details.get('articles_analyzed', 0)}
├─ Positiv: {self.sentiment_details.get('positive_articles', 0)}
├─ Neutral: {self.sentiment_details.get('neutral_articles', 0)}
└─ Negativ: {self.sentiment_details.get('negative_articles', 0)}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📋 BEGRÜNDUNG
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
"""
def format_reasons(self):
"""Formatiert die Gründe"""
output = ""
for i, reason in enumerate(self.reasons, 1):
output += f" {i}. {reason}\n"
return output
class SignalGenerator:
"""
Generiert Trading-Signale durch Kombination von MACD und Sentiment
"""
def __init__(self, newsapi_key: str = None):
"""
Args:
newsapi_key: Optional NewsAPI-Schlüssel für erweiterte News
"""
self.macd_indicator = MACDIndicator()
self.sentiment_analyzer = NewsSentimentAnalyzer(api_key=newsapi_key)
# Gewichtungen für Signal-Berechnung
self.macd_weight = 0.6 # 60% Gewichtung für technische Analyse
self.sentiment_weight = 0.4 # 40% Gewichtung für Sentiment
def calculate_combined_score(self, macd_signal: MACDSignal,
sentiment: SentimentScore,
macd_confidence: int,
sentiment_confidence: int) -> Tuple[float, int]:
"""
Berechnet kombinierten Score aus MACD und Sentiment
Returns:
Tuple aus (Score -1 bis +1, Gesamt-Konfidenz)
"""
# Konvertiere Signale zu Scores (-1 bis +1)
macd_score_map = {
MACDSignal.STRONG_BUY: 1.0,
MACDSignal.BUY: 0.5,
MACDSignal.NEUTRAL: 0.0,
MACDSignal.SELL: -0.5,
MACDSignal.STRONG_SELL: -1.0
}
sentiment_score_map = {
SentimentScore.VERY_POSITIVE: 1.0,
SentimentScore.POSITIVE: 0.5,
SentimentScore.NEUTRAL: 0.0,
SentimentScore.NEGATIVE: -0.5,
SentimentScore.VERY_NEGATIVE: -1.0
}
macd_score = macd_score_map.get(macd_signal, 0)
sentiment_score = sentiment_score_map.get(sentiment, 0)
# Gewichteter kombinierter Score
combined_score = (macd_score * self.macd_weight +
sentiment_score * self.sentiment_weight)
# Gewichtete kombinierte Konfidenz
combined_confidence = int(
macd_confidence * self.macd_weight +
sentiment_confidence * self.sentiment_weight
)
# Bonus für übereinstimmende Signale
if (macd_score > 0 and sentiment_score > 0) or \
(macd_score < 0 and sentiment_score < 0):
combined_confidence = min(100, combined_confidence + 10)
return combined_score, combined_confidence
def generate_signal(self, price_df, current_price: float) -> TradingSignal:
"""
Generiert Trading-Signal
Args:
price_df: DataFrame mit historischen Preisen
current_price: Aktueller Bitcoin-Preis
Returns:
TradingSignal mit Empfehlung
"""
# Hole MACD-Signal
macd_signal, macd_details = self.macd_indicator.get_signal(price_df)
# Hole Sentiment
sentiment, sentiment_details = self.sentiment_analyzer.analyze_news_sentiment(
days=1, limit=30
)
# Berechne kombinierten Score
combined_score, confidence = self.calculate_combined_score(
macd_signal,
sentiment,
macd_details['confidence'],
sentiment_details['confidence']
)
# Bestimme Trading-Action
if combined_score >= 0.6:
action = TradingAction.STRONG_BUY
elif combined_score >= 0.2:
action = TradingAction.BUY
elif combined_score <= -0.6:
action = TradingAction.STRONG_SELL
elif combined_score <= -0.2:
action = TradingAction.SELL
else:
action = TradingAction.HOLD
# Sammle Gründe
reasons = []
# MACD-Gründe
reasons.append(f"MACD-Signal: {macd_signal.value} (Konfidenz: {macd_details['confidence']}%)")
reasons.extend(macd_details.get('reasons', []))
# Sentiment-Gründe
reasons.append(
f"Markt-Sentiment: {sentiment.value} "
f"(Konfidenz: {sentiment_details['confidence']}%, "
f"Score: {sentiment_details['average_sentiment']:.3f})"
)
# Zusätzliche Hinweise
if macd_signal in [MACDSignal.STRONG_BUY, MACDSignal.BUY] and \
sentiment in [SentimentScore.VERY_POSITIVE, SentimentScore.POSITIVE]:
reasons.append("✅ MACD und Sentiment stimmen überein → Starkes Signal")
elif macd_signal in [MACDSignal.STRONG_SELL, MACDSignal.SELL] and \
sentiment in [SentimentScore.VERY_NEGATIVE, SentimentScore.NEGATIVE]:
reasons.append("✅ MACD und Sentiment stimmen überein → Starkes Signal")
elif (macd_signal in [MACDSignal.STRONG_BUY, MACDSignal.BUY] and
sentiment in [SentimentScore.NEGATIVE, SentimentScore.VERY_NEGATIVE]) or \
(macd_signal in [MACDSignal.STRONG_SELL, MACDSignal.SELL] and
sentiment in [SentimentScore.POSITIVE, SentimentScore.VERY_POSITIVE]):
reasons.append("⚠️ MACD und Sentiment widersprechen sich → Vorsicht geboten")
confidence = max(30, confidence - 20) # Reduziere Konfidenz
# Erstelle Trading-Signal
signal = TradingSignal(
action=action,
confidence=confidence,
price=current_price,
timestamp=datetime.now(),
macd_signal=macd_signal,
sentiment=sentiment,
reasons=reasons,
technical_details=macd_details,
sentiment_details=sentiment_details
)
return signal
def get_recommendation_text(self, signal: TradingSignal) -> str:
"""
Generiert Empfehlungstext
Args:
signal: Trading-Signal
Returns:
Formatierter Empfehlungstext
"""
recommendation = str(signal)
recommendation += signal.format_reasons()
# Füge Handlungsempfehlung hinzu
recommendation += "\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"
recommendation += "💡 HANDLUNGSEMPFEHLUNG\n"
recommendation += "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
if signal.action == TradingAction.STRONG_BUY:
recommendation += " 🟢 STARKE KAUFGELEGENHEIT\n"
recommendation += " → Erwäge einen Einstieg oder Aufstockung der Position\n"
recommendation += " → Setze Stop-Loss ca. 5-7% unter Einstiegspreis\n"
elif signal.action == TradingAction.BUY:
recommendation += " 🟢 KAUFGELEGENHEIT\n"
recommendation += " → Erwäge einen Einstieg mit kleiner Position\n"
recommendation += " → Warte ggf. auf Bestätigung durch weitere Signale\n"
elif signal.action == TradingAction.HOLD:
recommendation += " 🟡 ABWARTEN\n"
recommendation += " → Keine klare Richtung erkennbar\n"
recommendation += " → Behalte den Markt im Auge für klarere Signale\n"
elif signal.action == TradingAction.SELL:
recommendation += " 🔴 VERKAUFSSIGNAL\n"
recommendation += " → Erwäge Teilverkauf oder Gewinnmitnahme\n"
recommendation += " → Ziehe Stop-Loss nach, um Gewinne zu sichern\n"
elif signal.action == TradingAction.STRONG_SELL:
recommendation += " 🔴 STARKES VERKAUFSSIGNAL\n"
recommendation += " → Erwäge Ausstieg aus Position\n"
recommendation += " → Sichere Gewinne oder begrenze Verluste\n"
recommendation += f"\n ⚠️ Risiko-Hinweis: Diese Analyse hat eine Konfidenz von {signal.confidence}%\n"
recommendation += " ⚠️ Keine Anlageberatung - Trading auf eigenes Risiko!\n"
recommendation += "\n╚══════════════════════════════════════════════════════════════════╝\n"
return recommendation
if __name__ == "__main__":
# Test
from data_fetcher import BitcoinDataFetcher
print("=== Bitcoin Trading Signal Generator ===\n")
print("Lade Daten...\n")
# Hole Preisdaten
fetcher = BitcoinDataFetcher()
price_df = fetcher.get_historical_data(days=30)
current_price = fetcher.get_current_price()
if price_df.empty or not current_price:
print("Fehler beim Laden der Daten!")
else:
# Generiere Signal
generator = SignalGenerator()
signal = generator.generate_signal(price_df, current_price)
# Zeige Empfehlung
recommendation = generator.get_recommendation_text(signal)
print(recommendation)