/
fgtmenow
/
tb
Обзор
Документация
Войти
/
fgtmenow
/
tb
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
dev
_common/config/settings.py
235 строк
8 KB
Azarev Artem
Добавлена база знаний по стратегии Smart Money Trading, включая архитектуру, терминологию и торговые стратегии. Реализованы интерфейсы для типизации компонентов торгового бота и шаблон для торговых стратегий.
17 янв 2026, 03:39
17 янв 2026, 03:39
ab5fefa
Код
Авторство
О чём код?
""" Модуль загрузки конфигурации из переменных окружения. Использует python-dotenv для загрузки .env файла. Предоставляет валидацию и значения по умолчанию для всех параметров. Пример использования: from _common.config.settings import settings print(settings.LEVERAGE) print(settings.api_key) # Текущий API ключ (test или prod) """ import os from dataclasses import dataclass, field from pathlib import Path from typing import Literal # Попытка импорта dotenv try: from dotenv import load_dotenv DOTENV_AVAILABLE = True except ImportError: DOTENV_AVAILABLE = False def _load_env(): """Загружает переменные окружения из .env файла.""" if not DOTENV_AVAILABLE: return # Ищем .env файл в корне проекта current_dir = Path(__file__).parent project_root = current_dir.parent.parent # _common/config -> _common -> project root env_file = project_root / '.env' if env_file.exists(): load_dotenv(env_file) def _get_bool(key: str, default: bool = False) -> bool: """Получает булево значение из переменной окружения.""" value = os.getenv(key, str(default)).lower() return value in ('true', '1', 'yes', 'on') def _get_int(key: str, default: int) -> int: """Получает целочисленное значение из переменной окружения.""" try: return int(os.getenv(key, str(default))) except ValueError: return default def _get_float(key: str, default: float) -> float: """Получает вещественное значение из переменной окружения.""" try: return float(os.getenv(key, str(default))) except ValueError: return default def _get_list(key: str, default: list[str]) -> list[str]: """Получает список строк из переменной окружения (через запятую).""" value = os.getenv(key) if value is None: return default return [item.strip() for item in value.split(',') if item.strip()] @dataclass class Settings: """ Конфигурация торгового бота. Загружает настройки из переменных окружения с валидацией и значениями по умолчанию. Атрибуты: TRADING_MODE: Режим торговли (TEST/PROD) SYMBOL_TARGET: Список торговых пар TIME_FRAME: Таймфрейм торговли LEVERAGE: Торговое плечо ... """ # API Credentials BYBIT_TESTNET_API_KEY: str = field(default='') BYBIT_TESTNET_API_SECRET: str = field(default='') BYBIT_API_KEY: str = field(default='') BYBIT_API_SECRET: str = field(default='') # Trading Mode TRADING_MODE: Literal['TEST', 'PROD'] = field(default='TEST') # Trading Configuration SYMBOL_TARGET: list[str] = field(default_factory=lambda: ['BTCUSDT']) TIME_FRAME: str = field(default='1') BACKTEST_PERIOD: Literal['DAY', 'WEEK', 'MONTH'] = field(default='DAY') # Risk Management LEVERAGE: int = field(default=10) TRADE_AMOUNT: float = field(default=100.0) MIN_MARGIN_AMOUNT: float = field(default=30.0) CROSS_MARGIN: bool = field(default=False) # Backtest Settings SKIP_FRAMES: int = field(default=5) SHOW_PLOT: bool = field(default=True) # Logging LOG_LEVEL: Literal['DEBUG', 'INFO', 'WARNING', 'ERROR'] = field(default='INFO') LOG_TO_FILE: bool = field(default=False) LOG_FILE_PATH: str = field(default='logs/trading_bot.log') def __post_init__(self): """Валидация параметров после инициализации.""" # Валидация плеча if not 1 <= self.LEVERAGE <= 100: raise ValueError(f"LEVERAGE must be between 1 and 100, got {self.LEVERAGE}") # Валидация торговой суммы if self.TRADE_AMOUNT <= 0: raise ValueError(f"TRADE_AMOUNT must be positive, got {self.TRADE_AMOUNT}") # Валидация минимальной маржи if self.MIN_MARGIN_AMOUNT < 0: raise ValueError(f"MIN_MARGIN_AMOUNT cannot be negative, got {self.MIN_MARGIN_AMOUNT}") @property def is_testnet(self) -> bool: """Возвращает True если используется testnet.""" return self.TRADING_MODE == 'TEST' @property def api_key(self) -> str: """Возвращает API ключ для текущего режима.""" if self.is_testnet: return self.BYBIT_TESTNET_API_KEY return self.BYBIT_API_KEY @property def api_secret(self) -> str: """Возвращает API секрет для текущего режима.""" if self.is_testnet: return self.BYBIT_TESTNET_API_SECRET return self.BYBIT_API_SECRET def validate_api_credentials(self) -> bool: """ Проверяет наличие API ключей для текущего режима. Возвращает: True если ключи заданы """ return bool(self.api_key and self.api_secret) def load_settings() -> Settings: """ Загружает настройки из переменных окружения. Возвращает: Settings: Объект с конфигурацией """ _load_env() # Получаем режим торговли mode = os.getenv('TRADING_MODE', 'TEST').upper() if mode not in ('TEST', 'PROD'): mode = 'TEST' # Получаем период бэктеста period = os.getenv('BACKTEST_PERIOD', 'DAY').upper() if period not in ('DAY', 'WEEK', 'MONTH'): period = 'DAY' # Получаем уровень логирования log_level = os.getenv('LOG_LEVEL', 'INFO').upper() if log_level not in ('DEBUG', 'INFO', 'WARNING', 'ERROR'): log_level = 'INFO' return Settings( # API Credentials BYBIT_TESTNET_API_KEY=os.getenv('BYBIT_TESTNET_API_KEY', ''), BYBIT_TESTNET_API_SECRET=os.getenv('BYBIT_TESTNET_API_SECRET', ''), BYBIT_API_KEY=os.getenv('BYBIT_API_KEY', ''), BYBIT_API_SECRET=os.getenv('BYBIT_API_SECRET', ''), # Trading Mode TRADING_MODE=mode, # Trading Configuration SYMBOL_TARGET=_get_list('SYMBOL_TARGET', ['BTCUSDT']), TIME_FRAME=os.getenv('TIME_FRAME', '1'), BACKTEST_PERIOD=period, # Risk Management LEVERAGE=_get_int('LEVERAGE', 10), TRADE_AMOUNT=_get_float('TRADE_AMOUNT', 100.0), MIN_MARGIN_AMOUNT=_get_float('MIN_MARGIN_AMOUNT', 30.0), CROSS_MARGIN=_get_bool('CROSS_MARGIN', False), # Backtest Settings SKIP_FRAMES=_get_int('SKIP_FRAMES', 5), SHOW_PLOT=_get_bool('SHOW_PLOT', True), # Logging LOG_LEVEL=log_level, LOG_TO_FILE=_get_bool('LOG_TO_FILE', False), LOG_FILE_PATH=os.getenv('LOG_FILE_PATH', 'logs/trading_bot.log'), ) # Глобальный экземпляр настроек (ленивая загрузка) _settings: Settings | None = None def get_settings() -> Settings: """ Возвращает глобальный экземпляр настроек. Использует ленивую загрузку — настройки загружаются при первом вызове. Возвращает: Settings: Объект с конфигурацией """ global _settings if _settings is None: _settings = load_settings() return _settings # Удобный алиас для импорта settings = get_settings()