| import os |
| import logging |
| import ccxt |
| from logging.handlers import RotatingFileHandler |
| from datetime import datetime |
| import json |
| from typing import List, Dict, Any |
|
|
| def setup_logger(): |
| """Configure and set up the logger""" |
| |
| os.makedirs("logs", exist_ok=True) |
| |
| |
| logger = logging.getLogger("crypto_data_source") |
| logger.setLevel(logging.INFO) |
| |
| |
| console_handler = logging.StreamHandler() |
| console_handler.setLevel(logging.INFO) |
| |
| |
| log_file = f"logs/crypto_data_source_{datetime.now().strftime('%Y%m%d')}.log" |
| file_handler = RotatingFileHandler( |
| log_file, maxBytes=10*1024*1024, backupCount=5 |
| ) |
| file_handler.setLevel(logging.INFO) |
| |
| |
| formatter = logging.Formatter( |
| '%(asctime)s - %(name)s - %(levelname)s - %(message)s' |
| ) |
| |
| |
| console_handler.setFormatter(formatter) |
| file_handler.setFormatter(formatter) |
| |
| |
| logger.addHandler(console_handler) |
| logger.addHandler(file_handler) |
| |
| return logger |
|
|
| def get_available_exchanges() -> List[str]: |
| """Get list of available exchanges with OHLCV support""" |
| exchanges = [] |
| |
| |
| preferred_exchanges = [ |
| 'binance', 'kucoin', 'coinbase', 'kraken', 'okx', 'bybit' |
| ] |
| |
| for exchange_id in preferred_exchanges: |
| try: |
| exchange_class = getattr(ccxt, exchange_id) |
| exchange = exchange_class() |
| |
| |
| if exchange.has['fetchOHLCV']: |
| exchanges.append(exchange_id) |
| except: |
| |
| continue |
| |
| return exchanges |
|
|
| def format_timestamp(timestamp_ms: int) -> str: |
| """Format timestamp to ISO string""" |
| return datetime.fromtimestamp(timestamp_ms / 1000).isoformat() |
|
|
| def safe_json_serialize(obj): |
| """Custom JSON serializer for handling non-serializable types""" |
| if isinstance(obj, (datetime)): |
| return obj.isoformat() |
| raise TypeError(f"Type {type(obj)} not serializable") |
|
|