import ccxt
import time
import pandas as pd
from ta.momentum import RSIIndicator
from ta.trend import MACD, SMAIndicator
from ta.volatility import BollingerBands
from threading import Timer

# Initialize the CCXT Binance Futures client
exchange = ccxt.binance({
    'apiKey': 'your_api_key',  # Replace with your actual API key
    'secret': 'your_api_secret',  # Replace with your actual API secret
    'options': {'defaultType': 'future'}
})

# Get leverage settings
def set_leverage(pair, leverage):
    try:
        exchange.fapiPrivate_post_leverage({'symbol': pair, 'leverage': leverage})
        print(f"Set leverage for {pair} to {leverage}")
    except Exception as e:
        print(f"Error setting leverage: {e}")

# Function to fetch historical data for a given pair
def collect_data(coin_pair, interval='1h', limit=500):
    try:
        klines = exchange.fetch_ohlcv(coin_pair, timeframe=interval, limit=limit)
        data = pd.DataFrame(klines, columns=[
            'timestamp', 'open', 'high', 'low', 'close', 'volume'
        ])
        data['timestamp'] = pd.to_datetime(data['timestamp'], unit='ms')
        data.set_index('timestamp', inplace=True)
        data = data.astype(float)
        return data
    except Exception as e:
        print(f"Error fetching data for {coin_pair}: {e}")
        return pd.DataFrame()

# Function to analyze data with indicators
def analyze_data(df):
    try:
        df['SMA50'] = SMAIndicator(df['close'], window=50).sma_indicator()
        df['RSI'] = RSIIndicator(df['close']).rsi()
        macd = MACD(df['close'])
        df['MACD'] = macd.macd()
        df['MACD_Signal'] = macd.macd_signal()
        bollinger = BollingerBands(df['close'])
        df['BB_High'] = bollinger.bollinger_hband()
        df['BB_Low'] = bollinger.bollinger_lband()
        return df
    except Exception as e:
        print(f"Error analyzing data: {e}")
        return df

# Function to generate trading signals
def trading_logic(df):
    try:
        signals = []
        for i in range(1, len(df)):
            if df['MACD'][i] > df['MACD_Signal'][i] and df['RSI'][i] < 70 and df['close'][i] > df['BB_Low'][i]:
                signals.append('BUY')
            elif df['MACD'][i] < df['MACD_Signal'][i] and df['RSI'][i] > 30 and df['close'][i] < df['BB_High'][i]:
                signals.append('SELL')
            else:
                signals.append('HOLD')
        return signals
    except Exception as e:
        print(f"Error generating trading signals: {e}")
        return []

# Function to simulate trading and track profit/loss
def simulate_trading(df, signals, balance, leverage):
    try:
        initial_balance = balance  # Starting with the user-defined balance
        position = None
        position_price = 0
        leverage_amount = 1  # Default leverage amount

        for i in range(len(signals)):
            if signals[i] == 'BUY' and position is None:
                position = 'LONG'
                position_price = df['close'][i]
                leverage_amount = balance * leverage
                print(f"Opening LONG position at {position_price} with leverage {leverage_amount}")
                exchange.create_market_order(symbol=pair, side='buy', amount=leverage_amount)  # Buy
            elif signals[i] == 'SELL' and position == 'LONG':
                balance += (df['close'][i] - position_price) * leverage
                position = None
                position_price = 0
                print(f"Closing LONG position at {df['close'][i]} with profit/loss")
                exchange.create_market_order(symbol=pair, side='sell', amount=leverage_amount)  # Sell
                break  # Exit after closing trade
            elif signals[i] == 'SELL' and position is None:
                position = 'SHORT'
                position_price = df['close'][i]
                leverage_amount = balance * leverage
                print(f"Opening SHORT position at {position_price} with leverage {leverage_amount}")
                exchange.create_market_order(symbol=pair, side='sell', amount=leverage_amount)  # Sell
            elif signals[i] == 'BUY' and position == 'SHORT':
                balance += (position_price - df['close'][i]) * leverage
                position = None
                position_price = 0
                print(f"Closing SHORT position at {df['close'][i]} with profit/loss")
                exchange.create_market_order(symbol=pair, side='buy', amount=leverage_amount)  # Buy
                break  # Exit after closing trade

        profit_loss = balance - initial_balance
        return profit_loss
    except Exception as e:
        print(f"Error simulating trading: {e}")
        return 0

# Function to find the best trading pair based on profitability
def find_best_pair():
    try:
        markets = exchange.load_markets()
        all_pairs = [pair for pair in markets.keys() if 'USDT' in pair and markets[pair]['type'] == 'future']
        best_pair = None
        best_profit_loss = -float('inf')

        for pair in all_pairs:
            print(f"Analyzing {pair}...")
            df = collect_data(pair, interval='1h', limit=500)
            if df.empty:
                continue
            df = analyze_data(df)
            signals = trading_logic(df)
            profit_loss = simulate_trading(df, signals, balance, leverage)
            print(f"{pair} Profit/Loss: {profit_loss}")

            if profit_loss > best_profit_loss:
                best_profit_loss = profit_loss
                best_pair = pair

        if best_pair:
            print(f"Best pair to trade: {best_pair} with Profit/Loss: {best_profit_loss}")
            return best_pair
        else:
            print("No suitable trading pair found.")
            return None
    except Exception as e:
        print(f"Error finding the best trading pair: {e}")
        return None

# Function to trade the best pair
def trade_best_pair(pair):
    try:
        df = collect_data(pair, interval='1h', limit=500)
        if df.empty:
            return
        df = analyze_data(df)
        signals = trading_logic(df)

        # Setting leverage
        set_leverage(pair, leverage)

        for i in range(1, len(signals)):
            if signals[i] == 'BUY':
                print(f"Executing BUY order for {pair}")
                exchange.create_market_order(symbol=pair, side='buy', amount=leverage * balance)  # Adjust amount as needed
            elif signals[i] == 'SELL':
                print(f"Executing SELL order for {pair}")
                exchange.create_market_order(symbol=pair, side='sell', amount=leverage * balance)  # Adjust amount as needed
        
        print(f"Trade executed for {pair}.")
        # Setting a timer for 20 minutes for user to decide on further actions
        global timer
        timer = Timer(1200, find_best_pair)
        timer.start()

        ask_user()

        # Cancel the timer if the user responds in time
        timer.cancel()
    except Exception as e:
        print(f"Error trading the best pair: {e}")

# CLI for user interaction
def main():
    global balance, leverage, timer

    # Ask user if they want to start the AI bot for automatic trading
    auto_trade = input("Do you want to start the AI bot for automatic trading? (yes/no): ").strip().lower()
    if auto_trade == 'yes':
        # Collect user input for initial balance and leverage
        while True:
            try:
                balance = float(input("Enter your initial balance for trading: "))
                leverage = int(input("Enter the leverage you want to use (e.g., 1 for no leverage): "))
                if balance <= 0 or leverage <= 0:
                    raise ValueError("Balance and leverage must be positive numbers.")
                break
            except ValueError as e:
                print(f"Invalid input: {e}. Please try again.")

        # Find the best trading pair and set leverage
        best_pair = find_best_pair()
        if best_pair:
            trade_best_pair(best_pair)

    else:
        print("AI bot trading is not started. Manual trading options will be provided.")

    def ask_user():
        response = input("Do you want to open a new trade? (yes/no): ").strip().lower()
        if response == 'yes':
            best_pair = find_best_pair()
            if best_pair:
                trade_best_pair(best_pair)
        elif response == 'no':
            print("