# vumanchu_fixed_v2.py - MIT MFI (VuManChu-Formel) UND 15m KORREKTUR
from config import BINGX_CONFIG
import requests
import time
import hmac
import hashlib
from datetime import datetime
import os
import pandas as pd
import numpy as np
from typing import Dict, List, Tuple, Optional

class FixedVuManChuAnalysis:
    def __init__(self, api_key: str, secret: str):
        self.api_key = api_key
        self.secret = secret
        self.base_url = "https://open-api.bingx.com"
        self.timeframes = {
            '3m': '3m',
            '5m': '5m',
            '15m': '15m',
            '1h': '1h'
        }
        self.log_file = "vumanchu_fixed_log.csv"
        
        # VuManChu Parameter
        self.wt_channel_len = 9
        self.wt_average_len = 12
        self.wt_ma_len = 3
        self.rsi_period = 14
        self.mfi_period = 60
        self.mfi_multiplier = 150
        
        # Levels
        self.wt_ob_level = 53
        self.wt_os_level = -53
        
        self.setup_logging()
        
    def setup_logging(self):
        """Initialisiert die Log-Datei (mit MFI und 15m Spalten)"""
        if not os.path.exists(self.log_file):
            with open(self.log_file, 'w', encoding='utf-8') as f:
                f.write("Timestamp,Price,Signal,Score,"
                        "3m_WT1,3m_WT2,3m_MFI,"
                        "5m_WT1,5m_WT2,5m_MFI,"
                        "15m_WT1,15m_WT2,15m_MFI,"
                        "1h_WT1,1h_WT2,1h_MFI\n")
    
    def log_data(self, data):
        """Schreibt Daten in Log-Datei (angepasst an neue Spalten)"""
        try:
            timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            
            log_entry = (
                f"{timestamp},"
                f"{data['price']:.2f},"
                f"{data['signal']},{data['score']:.1f},"
                f"{data['3m_wt1']:.2f},{data['3m_wt2']:.2f},{data['3m_mfi']:.2f},"
                f"{data['5m_wt1']:.2f},{data['5m_wt2']:.2f},{data['5m_mfi']:.2f},"
                f"{data['15m_wt1']:.2f},{data['15m_wt2']:.2f},{data['15m_mfi']:.2f},"
                f"{data['1h_wt1']:.2f},{data['1h_wt2']:.2f},{data['1h_mfi']:.2f}\n"
            )
            
            with open(self.log_file, 'a', encoding='utf-8') as f:
                f.write(log_entry)
            
            print(f"📝 Daten geloggt: {timestamp}")
            
        except Exception as e:
            print(f"❌ Logging Fehler: {e}")
    
    def get_klines_data_fixed(self, symbol='BTC-USDT', interval='5m', limit=100):
        """Holt Kline-Daten - KORRIGIERT für 8 Spalten"""
        try:
            timestamp = int(time.time() * 1000)
            params = f'symbol={symbol}&interval={interval}&limit={limit}&timestamp={timestamp}'
            signature = hmac.new(self.secret.encode(), params.encode(), hashlib.sha256).hexdigest()
            
            url = f'{self.base_url}/openApi/spot/v1/market/kline?{params}&signature={signature}'
            headers = {'X-BX-APIKEY': self.api_key}
            
            response = requests.get(url, headers=headers, timeout=10)
            data = response.json()
            
            # print(f"📡 {interval} API Response: {len(data['data']) if data['code'] == 0 else 0} candles") # Debug
            
            if data['code'] == 0 and data['data']:
                df = pd.DataFrame(data['data'], columns=[
                    'timestamp', 'open', 'high', 'low', 'close', 'volume',
                    'close_time', 'quote_volume'
                ])
                
                df = df.astype({
                    'timestamp': 'int64',
                    'open': 'float64',
                    'high': 'float64',
                    'low': 'float64',
                    'close': 'float64',
                    'volume': 'float64'
                })
                df['datetime'] = pd.to_datetime(df['timestamp'], unit='ms')
                return df.sort_values('datetime').reset_index(drop=True)
            else:
                print(f"❌ API Error {interval}: {data.get('msg', 'Unknown')}")
                return pd.DataFrame()
                
        except Exception as e:
            print(f"❌ Kline Fehler ({interval}): {e}")
            return pd.DataFrame()
    
    def calculate_wavetrend_simple(self, df):
        """Vereinfachte WaveTrend Berechnung"""
        if len(df) < self.wt_channel_len:
            return pd.Series([0] * len(df)), pd.Series([0] * len(df))
        
        src = df['close']
        
        esa = src.ewm(span=self.wt_channel_len, adjust=False).mean()
        de = abs(src - esa).ewm(span=self.wt_channel_len, adjust=False).mean()
        
        # Division durch 0 vermeiden
        de_safe = de.replace(0, 0.0001)
        ci = (src - esa) / (0.015 * de_safe)
        
        wt1 = ci.ewm(span=self.wt_average_len, adjust=False).mean()
        wt2 = wt1.rolling(window=self.wt_ma_len).mean()
        
        return wt1, wt2
    
    def calculate_rsi_simple(self, df):
        """Vereinfachte RSI Berechnung"""
        if len(df) < self.rsi_period:
            return pd.Series([50] * len(df))
        
        delta = df['close'].diff()
        gain = (delta.where(delta > 0, 0)).rolling(window=self.rsi_period).mean()
        loss = (-delta.where(delta < 0, 0)).rolling(window=self.rsi_period).mean()
        
        rs = gain / loss.replace(0, 0.0001)
        rsi = 100 - (100 / (1 + rs))
        return rsi

    def calculate_rsimfi(self, df):
        """
        NEU: Berechnet den 'RSI+MFI' Oszillator aus dem VuManChu Skript.
        f_rsimfi(_period, _multiplier, _tf) => 
            security(syminfo.tickerid, _tf, sma(((close - open) / (high - low)) * _multiplier, _period) - rsiMFIPosY)
        Wir lassen rsiMFIPosY (ein reiner Anzeige-Offset) weg und nutzen 0 als Zentrum.
        """
        if len(df) < self.mfi_period:
            return pd.Series([0] * len(df))
        
        # (high - low) -> Division durch 0 vermeiden
        high_low_diff = (df['high'] - df['low']).replace(0, 0.0001)
        close_open_diff = df['close'] - df['open']
        
        # VuManChu-spezifische Formel: ((close - open) / (high - low)) * multiplier
        rsimfi_val = (close_open_diff / high_low_diff) * self.mfi_multiplier
        
        # sma(...)
        rsimfi_sma = rsimfi_val.rolling(window=self.mfi_period).mean()
        
        return rsimfi_sma

    def analyze_simple_vumanchu(self, symbol='BTC-USDT'):
        """Vereinfachte VuManChu Analyse INKLUSIVE MFI"""
        analysis_data = {}
        
        for tf_name, tf_value in self.timeframes.items():
            print(f"🔄 Analysiere {tf_name}...")
            df = self.get_klines_data_fixed(symbol=symbol, interval=tf_value, limit=100)
            
            if not df.empty and len(df) > 20:
                current_price = df['close'].iloc[-1]
                
                # Indikatoren berechnen
                wt1, wt2 = self.calculate_wavetrend_simple(df)
                rsi = self.calculate_rsi_simple(df)
                mfi = self.calculate_rsimfi(df) # NEU
                
                # Einfache Signal-Erkennung
                wt_oversold = wt2.iloc[-1] <= self.wt_os_level if not wt2.empty else False
                wt_overbought = wt2.iloc[-1] >= self.wt_ob_level if not wt2.empty else False
                
                wt_cross_up = False
                wt_cross_down = False
                if len(wt1) > 1 and len(wt2) > 1:
                    wt_cross_up = wt1.iloc[-1] > wt2.iloc[-1] and wt1.iloc[-2] <= wt2.iloc[-2]
                    wt_cross_down = wt1.iloc[-1] < wt2.iloc[-1] and wt1.iloc[-2] >= wt2.iloc[-2]
                
                # Einfache Divergence-Erkennung (unverändert)
                bullish_div = False
                bearish_div = False
                if len(df) > 10:
                    price_slope = (df['close'].iloc[-1] - df['close'].iloc[-5]) / 5
                    wt_slope = (wt2.iloc[-1] - wt2.iloc[-5]) / 5 if not wt2.empty else 0
                    
                    bullish_div = price_slope < 0 and wt_slope > 0 and wt_oversold
                    bearish_div = price_slope > 0 and wt_slope < 0 and wt_overbought
                
                analysis_data[tf_name] = {
                    'price': current_price,
                    'wt1': wt1.iloc[-1] if not wt1.empty else 0,
                    'wt2': wt2.iloc[-1] if not wt2.empty else 0,
                    'rsi': rsi.iloc[-1] if not rsi.empty else 50,
                    'mfi': mfi.iloc[-1] if not mfi.empty else 0, # NEU
                    'wt_oversold': wt_oversold,
                    'wt_overbought': wt_overbought,
                    'wt_cross_up': wt_cross_up,
                    'wt_cross_down': wt_cross_down,
                    'bullish_div': bullish_div,
                    'bearish_div': bearish_div,
                    'rsi_oversold': rsi.iloc[-1] < 30 if not rsi.empty else False,
                    'rsi_overbought': rsi.iloc[-1] > 70 if not rsi.empty else False
                }
                print(f"✅ {tf_name} analysiert - Preis: ${current_price:.2f}")
            else:
                analysis_data[tf_name] = None
                print(f"❌ {tf_name} keine Daten")
        
        return analysis_data
    
    def generate_simple_signals(self, analysis):
        """Generiert Signale (JETZT MIT MFI-FILTER)"""
        signals = []
        
        for tf_name, data in analysis.items():
            if data:
                # 1. WaveTrend Buy Signal (KORRIGIERT: mit MFI-Filter)
                if data['wt_cross_up'] and data['wt_oversold'] and data['mfi'] > 0:
                    signals.append(f"🟢 {tf_name} WT BUY - Oversold Cross (MFI Bestätigt)")
                
                # 2. WaveTrend Sell Signal (KORRIGIERT: mit MFI-Filter)
                if data['wt_cross_down'] and data['wt_overbought'] and data['mfi'] < 0:
                    signals.append(f"🔴 {tf_name} WT SELL - Overbought Cross (MFI Bestätigt)")
                
                # 3. Bullish Divergence
                if data['bullish_div']:
                    signals.append(f"🟢 {tf_name} BULLISH DIV")
                
                # 4. Bearish Divergence
                if data['bearish_div']:
                    signals.append(f"🔴 {tf_name} BEARISH DIV")
                
                # 5. RSI Bestätigung
                if data['rsi_oversold'] and data['wt_oversold']:
                    signals.append(f"🟡 {tf_name} RSI OVERSOLD")
                if data['rsi_overbought'] and data['wt_overbought']:
                    signals.append(f"🟡 {tf_name} RSI OVERBOUGHT")
        
        return signals
    
    def get_simple_consensus(self, analysis, signals):
        """Einfache Konsens-Bestimmung"""
        if not signals:
            return "NEUTRAL", 0
        
        bull_signals = sum(1 for s in signals if '🟢' in s)
        bear_signals = sum(1 for s in signals if '🔴' in s)
        
        score = bull_signals - bear_signals
        
        if score >= 3:
            return "STRONG BULLISH", score
        elif score >= 1:
            return "BULLISH", score
        elif score <= -3:
            return "STRONG BEARISH", score
        elif score <= -1:
            return "BEARISH", score
        else:
            return "NEUTRAL", score

def main():
    print("🚀 VuManChu Fixed Trading Bot (v2 - mit MFI)")
    print("=" * 60)
    
    analyzer = FixedVuManChuAnalysis(
        api_key=BINGX_CONFIG['API_KEY'],
        secret=BINGX_CONFIG['SECRET_KEY']
    )
    
    try:
        while True:
            # Für Windows: 'cls', für Linux/Mac: 'clear'
            os.system('cls' if os.name == 'nt' else 'clear')
            print("📊 VUMANCHU FIXED ANALYSIS (v2 - mit MFI)")
            print("=" * 60)
            print(f"🕐 {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
            print()
            
            # Analyse durchführen
            analysis = analyzer.analyze_simple_vumanchu()
            signals = analyzer.generate_simple_signals(analysis)
            consensus, score = analyzer.get_simple_consensus(analysis, signals)
            
            # Preisanzeige (5m als Referenz)
            if analysis['5m']:
                current_price = analysis['5m']['price']
                print(f"💰 BTC-USDT: ${current_price:,.2f}")
            
            print(f"\n🎯 KONSENS-SIGNAL: {consensus} (Score: {score})")
            
            # Signal-Anzeige
            if "STRONG BULLISH" in consensus:
                print("🟢🟢🟢 STARK BULLISH - KAUFEMPFEHLUNG")
            elif "BULLISH" in consensus:
                print("🟢🟢 BULLISH - Leichte Kaufempfehlung")
            elif "STRONG BEARISH" in consensus:
                print("🔴🔴🔴 STARK BEARISH - VERKAUFSEMPFEHLUNG")
            elif "BEARISH" in consensus:
                print("🔴🔴 BEARISH - Leichte Verkaufsempfehlung")
            else:
                print("🟡 NEUTRAL - Abwarten")
            
            print(f"\n📈 AKTIVE SIGNALE:")
            print("-" * 40)
            
            for signal in signals:
                print(f"• {signal}")
            
            if not signals:
                print("• 🟡 Keine aktiven Signale")
            
            print(f"\n📊 INDIKATOREN-ÜBERSICHT (KORRIGIERT):")
            print("-" * 60)
            
            # KORRIGIERT: Loop über alle definierten Timeframes
            for tf_name in analyzer.timeframes.keys():
                if analysis[tf_name]:
                    data = analysis[tf_name]
                    status = ""
                    if data['wt_oversold']:
                        status = "OVERSOLD"
                    elif data['wt_overbought']:
                        status = "OVERBOUGHT"
                    else:
                        status = "NEUTRAL"
                    
                    # KORRIGIERT: MFI hinzugefügt
                    print(f"  {tf_name.upper():<4}: WT1={data['wt1']:6.1f}, WT2={data['wt2']:6.1f} [MFI: {data['mfi']:6.1f}] [{status}]")
            
            # Logging (KORRIGIERT: Prüft alle TFs)
            if all(tf in analysis and analysis[tf] for tf in analyzer.timeframes.keys()):
                log_data = {
                    'price': analysis['5m']['price'],
                    'signal': consensus,
                    'score': score,
                    '3m_wt1': analysis['3m']['wt1'], '3m_wt2': analysis['3m']['wt2'], '3m_mfi': analysis['3m']['mfi'],
                    '5m_wt1': analysis['5m']['wt1'], '5m_wt2': analysis['5m']['wt2'], '5m_mfi': analysis['5m']['mfi'],
                    '15m_wt1': analysis['15m']['wt1'], '15m_wt2': analysis['15m']['wt2'], '15m_mfi': analysis['15m']['mfi'],
                    '1h_wt1': analysis['1h']['wt1'], '1h_wt2': analysis['1h']['wt2'], '1h_mfi': analysis['1h']['mfi']
                }
                analyzer.log_data(log_data)
            
            print(f"\n📝 LOGGING: Daten werden gespeichert")
            print(f"🔄 Nächste Aktualisierung in 60s...")
            print("Drücke Ctrl+C zum Beenden")
            time.sleep(60)
            
    except KeyboardInterrupt:
        print("\n👋 VuManChu Bot gestoppt")

if __name__ == "__main__":
    main()