import logging.config from aiogram import F, Router from aiogram.fsm.context import FSMContext from aiogram.types import CallbackQuery import app.telegram.keyboards.inline as kbi import database.request as rq from app.bybit import get_bybit_client from app.bybit.get_functions.get_tickers import get_tickers from app.helper_functions import calculate_total_budget, get_base_currency, safe_float from logger_helper.logger_helper import LOGGING_CONFIG logging.config.dictConfig(LOGGING_CONFIG) logger = logging.getLogger("settings") router_settings = Router(name="settings") @router_settings.callback_query(F.data == "additional_settings") async def additional_settings(callback_query: CallbackQuery, state: FSMContext) -> None: """ Handler for the "additional_settings" command. Sends a message with additional settings options. """ try: await state.clear() tg_id = callback_query.from_user.id symbol = await rq.get_user_symbol(tg_id=tg_id) additional_data = await rq.get_user_additional_settings(tg_id=tg_id) if not additional_data: await rq.create_user( tg_id=tg_id, username=callback_query.from_user.username ) await rq.create_user_additional_settings(tg_id=tg_id) await rq.create_user_risk_management(tg_id=tg_id) await rq.create_user_conditional_settings(tg_id=tg_id) await additional_settings(callback_query=callback_query, state=state) return trade_mode_map = { "Merged_Single": "Односторонний режим", "Both_Sides": "Хеджирование", } margin_type_map = { "ISOLATED_MARGIN": "Изолированная", "REGULAR_MARGIN": "Кросс", } order_type_map = {"Market": "Рыночный", "Limit": "Лимитный"} trade_mode = additional_data.trade_mode or "" margin_type = additional_data.margin_type or "" order_type = additional_data.order_type or "" trade_mode_rus = trade_mode_map.get(trade_mode, trade_mode) margin_type_rus = margin_type_map.get(margin_type, margin_type) order_type_rus = order_type_map.get(order_type, "Условный") def f(x): return safe_float(x) leverage = f(additional_data.leverage) leverage_to_buy = f(additional_data.leverage_to_buy) leverage_to_sell = f(additional_data.leverage_to_sell) martingale = f(additional_data.martingale_factor) max_bets = additional_data.max_bets_in_series quantity = f(additional_data.order_quantity) limit_price = f(additional_data.limit_price) trigger_price = f(additional_data.trigger_price) or 0 tickers = await get_tickers(tg_id=tg_id, symbol=symbol) price_symbol = safe_float(tickers.get("lastPrice")) or 0 bid = f(tickers.get("bid1Price")) or 0 ask = f(tickers.get("ask1Price")) or 0 sym = get_base_currency(symbol) if trade_mode == "Merged_Single": leverage_str = f"{leverage:.2f}x" else: if margin_type == "ISOLATED_MARGIN": leverage_str = f"{leverage_to_buy:.2f}x:{leverage_to_sell:.2f}x" else: leverage_str = f"{leverage:.2f}x" conditional_order_type = additional_data.conditional_order_type or "" conditional_order_type_rus = ( "Лимитный" if conditional_order_type == "Limit" else ( "Рыночный" if conditional_order_type == "Market" else conditional_order_type ) ) conditional_order_type_text = ( f"- Тип условного ордера: {conditional_order_type_rus}\n" if order_type == "Conditional" else "" ) limit_price_text = "" trigger_price_text = "" if order_type == "Limit": limit_price_text = f"- Цена лимитного ордера: {limit_price:.4f} USDT\n" elif order_type == "Conditional": if conditional_order_type == "Limit": limit_price_text = f"- Цена лимитного ордера: {limit_price:.4f} USDT\n" trigger_price_text = f"- Триггер цена: {trigger_price:.4f} USDT\n" risk_management_data = await rq.get_user_risk_management(tg_id=tg_id) commission_fee = risk_management_data.commission_fee client = await get_bybit_client(tg_id=tg_id) fee_info = client.get_fee_rates(category="linear", symbol=symbol) if commission_fee == "Yes_commission_fee": commission_fee_percent = safe_float( fee_info["result"]["list"][0]["takerFeeRate"] ) else: commission_fee_percent = 0.0 if order_type == "Conditional": if conditional_order_type == "Limit": entry_price = limit_price ask_price = limit_price bid_price = limit_price else: ask_price = trigger_price bid_price = trigger_price entry_price = trigger_price else: if order_type == "Limit": entry_price = limit_price ask_price = limit_price bid_price = limit_price else: entry_price = price_symbol ask_price = ask bid_price = bid durability_buy = quantity * bid_price durability_sell = quantity * ask_price quantity_price = quantity * entry_price total_commission = quantity_price * commission_fee_percent total_budget = await calculate_total_budget( quantity=durability_buy, martingale_factor=martingale, max_steps=max_bets, commission_fee_percent=total_commission, ) text = ( f"Основные настройки:\n\n" f"- Режим позиции: {trade_mode_rus}\n" f"- Тип маржи: {margin_type_rus}\n" f"- Размер кредитного плеча: {leverage_str}\n" f"- Тип ордера: {order_type_rus}\n" f"- Количество ордера: {quantity} {sym}\n" f"- Коэффициент мартингейла: {martingale:.2f}\n" f"{conditional_order_type_text}" f"{trigger_price_text}" f"{limit_price_text}" f"- Максимальное кол-во ставок в серии: {max_bets}\n\n" f"- Стоимость: {durability_buy:.2f}/{durability_sell:.2f} USDT\n" f"- Рекомендуемый бюджет: {total_budget:.4f} USDT\n" ) keyboard = kbi.get_additional_settings_keyboard( current_order_type=order_type, conditional_order=conditional_order_type ) await callback_query.message.edit_text(text=text, reply_markup=keyboard) logger.debug( "Command additional_settings processed successfully for user: %s", tg_id ) except Exception as e: await callback_query.message.edit_text( text="Произошла ошибка. Пожалуйста, попробуйте ещё раз.", reply_markup=kbi.profile_bybit, ) logger.error( "Error processing command additional_settings for user %s: %s", callback_query.from_user.id, e, ) @router_settings.callback_query(F.data == "risk_management") async def risk_management(callback_query: CallbackQuery, state: FSMContext) -> None: """ Handler for the "risk_management" command. Sends a message with risk management options. """ try: await state.clear() risk_management_data = await rq.get_user_risk_management( tg_id=callback_query.from_user.id ) if risk_management_data: take_profit_percent = risk_management_data.take_profit_percent or "" stop_loss_percent = risk_management_data.stop_loss_percent or "" max_risk_percent = risk_management_data.max_risk_percent or "" commission_fee = risk_management_data.commission_fee or "" commission_fee_rus = ( "Да" if commission_fee == "Yes_commission_fee" else "Нет" ) await callback_query.message.edit_text( text=f"Риск-менеджмент:\n\n" f"- Процент изменения цены для фиксации прибыли: {take_profit_percent}%\n" f"- Процент изменения цены для фиксации убытка: {stop_loss_percent}%\n\n" f"- Максимальный риск на сделку (в % от баланса): {max_risk_percent}%\n\n" f"- Комиссия биржи для расчета прибыли: {commission_fee_rus}\n\n", reply_markup=kbi.risk_management, ) logger.debug( "Command main_settings processed successfully for user: %s", callback_query.from_user.id, ) else: await rq.create_user( tg_id=callback_query.from_user.id, username=callback_query.from_user.username, ) await rq.create_user_additional_settings(tg_id=callback_query.from_user.id) await rq.create_user_risk_management(tg_id=callback_query.from_user.id) await rq.create_user_conditional_settings(tg_id=callback_query.from_user.id) await risk_management(callback_query=callback_query, state=state) except Exception as e: logger.error( "Error processing command main_settings for user %s: %s", callback_query.from_user.id, e, ) @router_settings.callback_query(F.data == "conditional_settings") async def conditions(callback_query: CallbackQuery, state: FSMContext) -> None: """ Handler for the "conditions" command. Sends a message with trading conditions options. """ try: await state.clear() conditional_settings_data = await rq.get_user_conditional_settings( tg_id=callback_query.from_user.id ) if conditional_settings_data: start_timer = conditional_settings_data.timer_start or 0 stop_timer = conditional_settings_data.timer_end or 0 await callback_query.message.edit_text( text="Условия торговли:\n\n" f"- Таймер для старта: {start_timer} мин.\n" f"- Таймер для остановки: {stop_timer} мин.\n", reply_markup=kbi.conditions, ) logger.debug( "Command main_settings processed successfully for user: %s", callback_query.from_user.id, ) else: await rq.create_user( tg_id=callback_query.from_user.id, username=callback_query.from_user.username, ) await rq.create_user_additional_settings(tg_id=callback_query.from_user.id) await rq.create_user_risk_management(tg_id=callback_query.from_user.id) await rq.create_user_conditional_settings(tg_id=callback_query.from_user.id) await conditions(callback_query=callback_query, state=state) except Exception as e: logger.error( "Error processing command main_settings for user %s: %s", callback_query.from_user.id, e, )