import os
import django
from concurrent.futures import ProcessPoolExecutor
import ccxt
import pandas as pd
import numpy as np
import talib as ta
from django.utils import timezone
from .models import Signal
import logging

# Set the environment variable to point to your project’s settings
os.environ.setdefault(‘DJANGO_SETTINGS_MODULE’, ‘binancebot.settings’)
django.setup()

# Configure logging
logging.basicConfig(level=logging.DEBUG)

class SignalGenerator:
    def init(self, symbol=‘BTC/USDT’, timeframe=‘1m’):
        self.symbol = symbol
        self.timeframe = timeframe
        self.exchange = ccxt.binance({
            ‘options’: {‘defaultType’: ‘future’}  # Configure for futures markets
        })

    def fetch_market_data(self):
        try:
            latest_bar = self.exchange.fetch_ohlcv(self.symbol, self.timeframe, limit=1)
            if latest_bar:
                latest_bar = latest_bar[0]
                df = pd.DataFrame([latest_bar], columns=[‘timestamp’, ‘open’, ‘high’, ‘low’, ‘close’, ‘volume’])
                df[‘timestamp’] = pd.to_datetime(df[‘timestamp’], unit=‘ms’)
                return df
            else:
                logging.error(f"No market data fetched for {self.symbol}.“)
                return pd.DataFrame()
        except Exception as e:
            logging.error(f"Error fetching market data for {self.symbol}: {e}”)
            return pd.DataFrame()

    def generate_signals(self, df):
        try:
            # Example: Simple moving average crossover
            df[‘SMA10’] = ta.SMA(df[‘close’], timeperiod=10)
            df[‘SMA20’] = ta.SMA(df[‘close’], timeperiod=20)
            df[‘Signal’] = np.where(df[‘SMA10’] > df[‘SMA20’], ‘BUY’, ‘SELL’)
            return df
        except Exception as e:
            logging.error(f"Error generating signals for {self.symbol}: {e}“)
            return df

    def save_signals(self, df):
        try:
            last_signal = df.iloc[-1]
            Signal.objects.update_or_create(
                timestamp=timezone.make_aware(last_signal[‘timestamp’]),
                symbol=self.symbol,
                defaults={
                    ‘price’: last_signal[‘close’],
                    ‘signal_type’: last_signal[‘Signal’],
                }
            )
            logging.info(f"Signal saved for {self.symbol}: {last_signal[‘Signal’]}”)
        except Exception as e:
            logging.error(f"Error saving signals for {self.symbol} to database: {e}“)

    def run(self):
        df = self.fetch_market_data()
        if not df.empty:
            df = self.generate_signals(df)
            self.save_signals(df)
        else:
            logging.error(f"No data fetched for {self.symbol}, cannot proceed with signal generation.”)

def process_symbol(symbol):
    signal_generator = SignalGenerator(symbol=symbol)
    signal_generator.run()

def main():
    try:
        exchange = ccxt.binance({‘options’: {‘defaultType’: ‘future’}})
        markets = exchange.load_markets()

        usdt_pairs = [symbol for symbol in markets if symbol.endswith(‘/USDT’)]

        with ProcessPoolExecutor() as executor:
            executor.map(process_symbol, usdt_pairs)

    except KeyboardInterrupt:
        logging.info(“KeyboardInterrupt caught. Exiting gracefully.”)
    except Exception as e:
        logging.error(f"An error occurred: {e}")

if name == “main”:
    main()


Why is this code not recognize KeyboardInterrupt. It continues to run wen I click ctrl c