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
This commit is contained in:
@@ -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())
|
||||
Reference in New Issue
Block a user