From fd279f05625f962191c6fd0b99f2de0eed75ed55 Mon Sep 17 00:00:00 2001 From: algizn97 Date: Tue, 26 Aug 2025 19:34:47 +0500 Subject: [PATCH] Added loggers for models --- app/telegram/database/models.py | 214 +++++++++++++++++++++++++++----- logger_helper/logger_helper.py | 5 + 2 files changed, 185 insertions(+), 34 deletions(-) diff --git a/app/telegram/database/models.py b/app/telegram/database/models.py index 789a1a9..6b6ab01 100644 --- a/app/telegram/database/models.py +++ b/app/telegram/database/models.py @@ -1,31 +1,55 @@ -import logging -from datetime import datetime - +from datetime import datetime +import logging.config from sqlalchemy.sql.sqltypes import DateTime -logger = logging.getLogger(__name__) - from sqlalchemy import BigInteger, Boolean, Integer, String, ForeignKey from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column from sqlalchemy.ext.asyncio import AsyncAttrs, async_sessionmaker, create_async_engine - +from logger_helper.logger_helper import LOGGING_CONFIG from sqlalchemy import select, insert +logging.config.dictConfig(LOGGING_CONFIG) +logger = logging.getLogger("models") + engine = create_async_engine(url='sqlite+aiosqlite:///db.sqlite3') async_session = async_sessionmaker(engine) + class Base(AsyncAttrs, DeclarativeBase): + """Базовый класс для declarative моделей SQLAlchemy с поддержкой async.""" pass + class User_Telegram_Id(Base): + """ + Модель таблицы user_telegram_id. + + Хранит идентификаторы Telegram пользователей. + + Атрибуты: + id (int): Внутренний первичный ключ записи. + tg_id (int): Уникальный идентификатор пользователя Telegram. + """ __tablename__ = 'user_telegram_id' id: Mapped[int] = mapped_column(primary_key=True) tg_id = mapped_column(BigInteger) + class User_Bybit_API(Base): + """ + Модель таблицы user_bybit_api. + + Хранит API ключи и секреты Bybit для каждого Telegram пользователя. + + Атрибуты: + id (int): Внутренний первичный ключ записи. + tg_id (int): Внешний ключ на Telegram пользователя (user_telegram_id.tg_id). + api_key (str): API ключ Bybit (уникальный для пользователя). + secret_key (str): Секретный ключ Bybit (уникальный для пользователя). + """ __tablename__ = 'user_bybit_api' id: Mapped[int] = mapped_column(primary_key=True) @@ -35,7 +59,26 @@ class User_Bybit_API(Base): api_key = mapped_column(String(18), default='None') secret_key = mapped_column(String(36), default='None') + class User_Symbol(Base): + """ + Модель таблицы user_main_settings. + + Хранит основные настройки торговли для пользователя. + + Атрибуты: + id (int): Внутренний первичный ключ записи. + tg_id (int): Внешний ключ на Telegram пользователя. + trading_mode (str): Режим торговли (ForeignKey на trading_modes.mode). + margin_type (str): Тип маржи (ForeignKey на margin_types.type). + size_leverage (int): Кредитное плечо. + starting_quantity (int): Начальный объём позиции. + martingale_factor (int): Коэффициент мартингейла. + martingale_step (int): Текущий шаг мартингейла. + maximal_quantity (int): Максимальное количество шагов мартингейла. + entry_order_type (str): Тип входа (Market или Limit). + limit_order_price (str, optional): Цена лимитного ордера, если используется. + """ __tablename__ = 'user_symbols' id: Mapped[int] = mapped_column(primary_key=True) @@ -44,28 +87,69 @@ class User_Symbol(Base): symbol = mapped_column(String(18), default='PENGUUSDT') + class Trading_Mode(Base): + """ + Справочник доступных режимов торговли. + + Атрибуты: + id (int): Первичный ключ. + mode (str): Уникальный режим (например, 'Long', 'Short'). + """ __tablename__ = 'trading_modes' id: Mapped[int] = mapped_column(primary_key=True) mode = mapped_column(String(10), unique=True) + class Margin_type(Base): + """ + Справочник типов маржинальной торговли. + + Атрибуты: + id (int): Первичный ключ. + type (str): Тип маржи (например, 'Isolated', 'Cross'). + """ __tablename__ = 'margin_types' id: Mapped[int] = mapped_column(primary_key=True) type = mapped_column(String(15), unique=True) + class Trigger(Base): + """ + Справочник видов триггеров для сделок. + + Атрибуты: + id (int): Первичный ключ. + trigger (str): Название триггера (например, 'Ручной', 'Автоматический'). + """ __tablename__ = 'triggers' id: Mapped[int] = mapped_column(primary_key=True) trigger = mapped_column(String(15), unique=True) + class User_Main_Settings(Base): + """ + Основные настройки пользователя для торговли. + + Атрибуты: + id (int): Первичный ключ. + tg_id (int): Внешний ключ на Telegram пользователя. + trading_mode (str): Режим торговли, FK на trading_modes.mode. + margin_type (str): Тип маржи, FK на margin_types.type. + size_leverage (int): Кредитное плечо. + starting_quantity (int): Начальный объем позиции. + martingale_factor (int): Коэффициент мартингейла. + martingale_step (int): Текущий шаг мартингейла. + maximal_quantity (int): Максимальное число шагов мартингейла. + entry_order_type (str): Тип ордера входа (Market/Limit). + limit_order_price (Optional[str]): Цена лимитного ордера, если есть. + """ __tablename__ = 'user_main_settings' id: Mapped[int] = mapped_column(primary_key=True) @@ -84,6 +168,17 @@ class User_Main_Settings(Base): class User_Risk_Management_Settings(Base): + """ + Настройки управления рисками пользователя. + + Атрибуты: + id (int): Первичный ключ. + tg_id (int): Внешний ключ на Telegram пользователя. + price_profit (int): Процент прибыли для трейда. + price_loss (int): Процент убытка для трейда. + max_risk_deal (int): Максимально допустимый риск по сделке в процентах. + commission_fee (str): Учитывать ли комиссию в расчетах ("Да"/"Нет"). + """ __tablename__ = 'user_risk_management_settings' id: Mapped[int] = mapped_column(primary_key=True) @@ -93,9 +188,24 @@ class User_Risk_Management_Settings(Base): price_profit = mapped_column(Integer(), default=1) price_loss = mapped_column(Integer(), default=1) max_risk_deal = mapped_column(Integer(), default=100) - commission_fee = mapped_column(Integer(), default=0) + commission_fee = mapped_column(String(), default="Да") + class User_Condition_Settings(Base): + """ + Дополнительные пользовательские условия для торговли. + + Атрибуты: + id (int): Первичный ключ. + tg_id (int): Внешний ключ на Telegram пользователя. + trigger (str): Тип триггера, FK на triggers.trigger. + filter_time (str): Временной фильтр. + filter_volatility (bool): Фильтр по волатильности. + external_cues (bool): Внешние сигналы. + tradingview_cues (bool): Сигналы TradingView. + webhook (str): URL webhook. + ai_analytics (bool): Использование AI для аналитики. + """ __tablename__ = 'user_condition_settings' id: Mapped[int] = mapped_column(primary_key=True) @@ -110,7 +220,18 @@ class User_Condition_Settings(Base): webhook = mapped_column(String(40), default='') ai_analytics = mapped_column(Boolean, default=False) + class User_Additional_Settings(Base): + """ + Прочие дополнительные настройки пользователя. + + Атрибуты: + id (int): Первичный ключ. + tg_id (int): Внешний ключ на Telegram пользователя. + pattern_save (bool): Сохранять ли шаблоны. + autostart (bool): Автоматический запуск. + notifications (bool): Получение уведомлений. + """ __tablename__ = 'user_additional_settings' id: Mapped[int] = mapped_column(primary_key=True) @@ -121,34 +242,19 @@ class User_Additional_Settings(Base): autostart = mapped_column(Boolean, default=False) notifications = mapped_column(Boolean, default=False) -async def async_main(): - async with engine.begin() as conn: - await conn.run_sync(Base.metadata.create_all) - - # Заполнение таблиц - modes = ['Long', 'Short', 'Switch', 'Smart'] - for mode in modes: - result = await conn.execute(select(Trading_Mode).where(Trading_Mode.mode == mode)) - if not result.first(): - logger.info("Заполение таблицы режима торговли") - await conn.execute(Trading_Mode.__table__.insert().values(mode=mode)) - - types = ['Isolated', 'Cross'] - for type in types: - result = await conn.execute(select(Margin_type).where(Margin_type.type == type)) - if not result.first(): - logger.info("Заполение таблицы типов маржи") - await conn.execute(Margin_type.__table__.insert().values(type=type)) - - triggers = ['Ручной', 'Автоматический', 'TradingView'] - for trigger in triggers: - result = await conn.execute(select(Trigger).where(Trigger.trigger == trigger)) - if not result.first(): - logger.info("Заполение таблицы триггеров") - await conn.execute(Trigger.__table__.insert().values(trigger=trigger)) - class USER_DEALS(Base): + """ + Таблица сделок пользователя. + + Атрибуты: + id (int): Первичный ключ. + tg_id (int): Внешний ключ на Telegram пользователя. + symbol (str): Торговая пара. + side (str): Направление сделки (Buy/Sell). + open_price (int): Цена открытия. + positive_percent (int): Процент доходности. + """ __tablename__ = 'user_deals' id: Mapped[int] = mapped_column(primary_key=True) @@ -162,10 +268,50 @@ class USER_DEALS(Base): class UserTimer(Base): + """ + Таймер пользователя для отсроченного запуска сделок. + + Атрибуты: + id (int): Первичный ключ. + tg_id (int): Внешний ключ на Telegram пользователя. + timer_minutes (int): Количество минут таймера. + timer_start (datetime): Время начала таймера. + timer_end (Optional[datetime]): Время окончания таймера (если установлено). + """ __tablename__ = 'user_timers' id: Mapped[int] = mapped_column(primary_key=True) tg_id = mapped_column(ForeignKey("user_telegram_id.tg_id")) timer_minutes = mapped_column(Integer, nullable=False, default=0) timer_start = mapped_column(DateTime, default=datetime.utcnow) - timer_end = mapped_column(DateTime, nullable=True) \ No newline at end of file + timer_end = mapped_column(DateTime, nullable=True) + + +async def async_main(): + """ + Асинхронное создание всех таблиц и заполнение справочников начальными данными. + """ + async with engine.begin() as conn: + await conn.run_sync(Base.metadata.create_all) + + # Заполнение таблиц + modes = ['Long', 'Short', 'Switch', 'Smart'] + for mode in modes: + result = await conn.execute(select(Trading_Mode).where(Trading_Mode.mode == mode)) + if not result.first(): + logger.info("Заполение таблицы режима торговли") + await conn.execute(Trading_Mode.__table__.insert().values(mode=mode)) + + types = ['Isolated', 'Cross'] + for type in types: + result = await conn.execute(select(Margin_type).where(Margin_type.type == type)) + if not result.first(): + logger.info("Заполение таблицы типов маржи") + await conn.execute(Margin_type.__table__.insert().values(type=type)) + + triggers = ['Ручной', 'Автоматический', 'TradingView'] + for trigger in triggers: + result = await conn.execute(select(Trigger).where(Trigger.trigger == trigger)) + if not result.first(): + logger.info("Заполение таблицы триггеров") + await conn.execute(Trigger.__table__.insert().values(trigger=trigger)) diff --git a/logger_helper/logger_helper.py b/logger_helper/logger_helper.py index cde13eb..8123460 100644 --- a/logger_helper/logger_helper.py +++ b/logger_helper/logger_helper.py @@ -85,5 +85,10 @@ LOGGING_CONFIG = { "level": "DEBUG", "propagate": False, }, + "models": { + "handlers": ["console", "timed_rotating_file"], + "level": "DEBUG", + "propagate": False, + }, }, }