123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- import os
- from dotenv import load_dotenv
- from typing import Optional
- import logging
- load_dotenv()
- logger = logging.getLogger(__name__)
- class Config:
- """Configuration class for the Hyperliquid trading bot."""
-
-
- HYPERLIQUID_PRIVATE_KEY: Optional[str] = os.getenv('HYPERLIQUID_PRIVATE_KEY')
- HYPERLIQUID_SECRET_KEY: Optional[str] = os.getenv('HYPERLIQUID_SECRET_KEY')
- HYPERLIQUID_WALLET_ADDRESS: Optional[str] = os.getenv('HYPERLIQUID_WALLET_ADDRESS')
- HYPERLIQUID_TESTNET: bool = os.getenv('HYPERLIQUID_TESTNET', 'true').lower() == 'true'
-
-
- DEFAULT_TRADING_TOKEN: str = os.getenv('DEFAULT_TRADING_TOKEN', 'BTC')
- RISK_MANAGEMENT_ENABLED: bool = os.getenv('RISK_MANAGEMENT_ENABLED', 'true').lower() == 'true'
- STOP_LOSS_PERCENTAGE: float = float(os.getenv('STOP_LOSS_PERCENTAGE', '10.0'))
-
-
- TELEGRAM_BOT_TOKEN: Optional[str] = os.getenv('TELEGRAM_BOT_TOKEN')
- TELEGRAM_CHAT_ID: Optional[str] = os.getenv('TELEGRAM_CHAT_ID')
- TELEGRAM_ENABLED: bool = os.getenv('TELEGRAM_ENABLED', 'true').lower() == 'true'
-
-
- BOT_HEARTBEAT_SECONDS = int(os.getenv('BOT_HEARTBEAT_SECONDS', '30'))
-
-
- LOG_LEVEL: str = os.getenv('LOG_LEVEL', 'INFO')
-
-
- LOG_TO_FILE: bool = os.getenv('LOG_TO_FILE', 'true').lower() == 'true'
- LOG_FILE_PATH: str = os.getenv('LOG_FILE_PATH', 'logs/trading_bot.log')
- LOG_MAX_SIZE_MB: int = int(os.getenv('LOG_MAX_SIZE_MB', '10'))
- LOG_BACKUP_COUNT: int = int(os.getenv('LOG_BACKUP_COUNT', '5'))
- LOG_ROTATION_TYPE: str = os.getenv('LOG_ROTATION_TYPE', 'size')
- LOG_ROTATION_INTERVAL: str = os.getenv('LOG_ROTATION_INTERVAL', 'midnight')
-
- @classmethod
- def validate(cls) -> bool:
- """Validate all configuration settings."""
- is_valid = True
-
-
- if not cls.HYPERLIQUID_PRIVATE_KEY:
- logger.error("❌ HYPERLIQUID_PRIVATE_KEY is required")
- is_valid = False
-
-
- if not cls.HYPERLIQUID_WALLET_ADDRESS and cls.HYPERLIQUID_PRIVATE_KEY:
-
- if not cls.HYPERLIQUID_PRIVATE_KEY.startswith('0x') and len(cls.HYPERLIQUID_PRIVATE_KEY) < 40:
- logger.warning("⚠️ HYPERLIQUID_WALLET_ADDRESS not set - will attempt to use private key as address")
- elif len(cls.HYPERLIQUID_PRIVATE_KEY) < 64:
- logger.warning("⚠️ HYPERLIQUID_WALLET_ADDRESS not set and private key appears short - consider setting explicit wallet address")
-
-
- if cls.TELEGRAM_ENABLED:
- if not cls.TELEGRAM_BOT_TOKEN:
- logger.error("❌ TELEGRAM_BOT_TOKEN is required when Telegram is enabled")
- is_valid = False
-
- if not cls.TELEGRAM_CHAT_ID:
- logger.error("❌ TELEGRAM_CHAT_ID is required when Telegram is enabled")
- is_valid = False
-
-
- if cls.BOT_HEARTBEAT_SECONDS < 5:
- logger.error("❌ BOT_HEARTBEAT_SECONDS must be at least 5 seconds to avoid rate limiting")
- is_valid = False
- elif cls.BOT_HEARTBEAT_SECONDS > 600:
- logger.warning("⚠️ BOT_HEARTBEAT_SECONDS is very high (>10 minutes), monitoring may be slow")
-
-
- if cls.DEFAULT_TRADING_TOKEN == '':
- logger.error("❌ DEFAULT_TRADING_TOKEN must be set")
- is_valid = False
-
-
- if cls.LOG_MAX_SIZE_MB <= 0:
- logger.error("❌ LOG_MAX_SIZE_MB must be positive")
- is_valid = False
-
- if cls.LOG_BACKUP_COUNT < 0:
- logger.error("❌ LOG_BACKUP_COUNT must be non-negative")
- is_valid = False
-
- if cls.LOG_ROTATION_TYPE not in ['size', 'time']:
- logger.error("❌ LOG_ROTATION_TYPE must be 'size' or 'time'")
- is_valid = False
-
- return is_valid
-
- @classmethod
- def get_hyperliquid_config(cls) -> dict:
- """Get Hyperliquid configuration in CCXT format."""
- config = {
- 'testnet': cls.HYPERLIQUID_TESTNET,
- 'sandbox': cls.HYPERLIQUID_TESTNET,
- }
-
-
-
- if cls.HYPERLIQUID_PRIVATE_KEY:
- config['privateKey'] = cls.HYPERLIQUID_PRIVATE_KEY
- config['apiKey'] = cls.HYPERLIQUID_PRIVATE_KEY
-
- if cls.HYPERLIQUID_WALLET_ADDRESS:
- config['walletAddress'] = cls.HYPERLIQUID_WALLET_ADDRESS
- elif cls.HYPERLIQUID_PRIVATE_KEY:
-
-
- wallet_addr = cls.HYPERLIQUID_PRIVATE_KEY
- if not wallet_addr.startswith('0x'):
- wallet_addr = f"0x{wallet_addr}"
- config['walletAddress'] = wallet_addr
-
- if cls.HYPERLIQUID_SECRET_KEY:
- config['secret'] = cls.HYPERLIQUID_SECRET_KEY
-
- return config
-
- @classmethod
- def print_config(cls):
- """Print current configuration (hiding sensitive data)."""
- logger.info("🔧 Configuration:")
- logger.info(f" 📡 Hyperliquid Testnet: {cls.HYPERLIQUID_TESTNET}")
- logger.info(f" 🔑 Private Key: {'✅ Set' if cls.HYPERLIQUID_PRIVATE_KEY else '❌ Missing'}")
- logger.info(f" 🏠 Wallet Address: {'✅ Set' if cls.HYPERLIQUID_WALLET_ADDRESS else '⚠️ Will derive from private key'}")
- logger.info(f" 🔐 Secret Key: {'✅ Set' if cls.HYPERLIQUID_SECRET_KEY else '⚠️ Missing (may be optional)'}")
- logger.info(f" 📱 Telegram: {'✅ Enabled' if cls.TELEGRAM_ENABLED else '❌ Disabled'}")
- logger.info(f" 🔍 Log Level: {cls.LOG_LEVEL}")
- logger.info(f" 💾 Log to File: {cls.LOG_TO_FILE}")
- logger.info(f" ⏱️ Heartbeat: {cls.BOT_HEARTBEAT_SECONDS}s")
- logger.info(f" 💰 DEFAULT_TRADING_TOKEN: {cls.DEFAULT_TRADING_TOKEN}")
- logger.info(f" 🧮 RISK_MANAGEMENT_ENABLED: {cls.RISK_MANAGEMENT_ENABLED}")
- logger.info(f" 🔄 STOP_LOSS_PERCENTAGE: {cls.STOP_LOSS_PERCENTAGE}%")
- logger.info(f" 🤖 TELEGRAM_BOT_TOKEN: {'✅ Set' if cls.TELEGRAM_BOT_TOKEN else '❌ Not Set'}")
- logger.info(f" 💬 TELEGRAM_CHAT_ID: {'✅ Set' if cls.TELEGRAM_CHAT_ID else '❌ Not Set'}")
- logger.info(f" 🔍 LOG_FILE_PATH: {cls.LOG_FILE_PATH}")
- logger.info(f" 🔄 LOG_MAX_SIZE_MB: {cls.LOG_MAX_SIZE_MB} MB")
- logger.info(f" 🔄 LOG_BACKUP_COUNT: {cls.LOG_BACKUP_COUNT}")
- logger.info(f" 🔄 LOG_ROTATION_TYPE: {cls.LOG_ROTATION_TYPE}")
- logger.info(f" 🔄 LOG_ROTATION_INTERVAL: {cls.LOG_ROTATION_INTERVAL}")
|