Compare commits
	
		
			7 Commits
		
	
	
		
			aebcc9dff2
			...
			fec367cc1d
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| fec367cc1d | |||
| 
						 | 
					4bbff680aa | ||
| 
						 | 
					49d4bb26bf | ||
| 
						 | 
					29bb6bd0a8 | ||
| 
						 | 
					2fb8cb4acb | ||
| 
						 | 
					887b46c1d4 | ||
| 
						 | 
					b074d1d8a1 | 
@@ -106,6 +106,7 @@ def format_order_details_position(data):
 | 
				
			|||||||
    symbol = msg.get("symbol", "N/A")
 | 
					    symbol = msg.get("symbol", "N/A")
 | 
				
			||||||
    order_type = msg.get("orderType", "N/A")
 | 
					    order_type = msg.get("orderType", "N/A")
 | 
				
			||||||
    side = msg.get("side", "")
 | 
					    side = msg.get("side", "")
 | 
				
			||||||
 | 
					    trigger_price = msg.get("triggerPrice", "N/A")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    movement = ""
 | 
					    movement = ""
 | 
				
			||||||
    if side.lower() == "buy":
 | 
					    if side.lower() == "buy":
 | 
				
			||||||
@@ -149,6 +150,28 @@ def format_order_details_position(data):
 | 
				
			|||||||
            f"Движение: {movement}\n"
 | 
					            f"Движение: {movement}\n"
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        return text
 | 
					        return text
 | 
				
			||||||
 | 
					    elif order_status.lower() == "untriggered":
 | 
				
			||||||
 | 
					        text = (
 | 
				
			||||||
 | 
					            f"Условный ордер создан:\n"
 | 
				
			||||||
 | 
					            f"Торговая пара: {symbol}\n"
 | 
				
			||||||
 | 
					            f"Цена: {price:.6f}\n"
 | 
				
			||||||
 | 
					            f"Триггер цена: {trigger_price}\n"
 | 
				
			||||||
 | 
					            f"Количество: {qty}\n"
 | 
				
			||||||
 | 
					            f"Тип ордера: {order_type}\n"
 | 
				
			||||||
 | 
					            f"Движение: {movement}\n"
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        return text
 | 
				
			||||||
 | 
					    elif order_status.lower() == "deactivated":
 | 
				
			||||||
 | 
					        text = (
 | 
				
			||||||
 | 
					            f"Условный ордер отменен:\n"
 | 
				
			||||||
 | 
					            f"Торговая пара: {symbol}\n"
 | 
				
			||||||
 | 
					            f"Цена: {price:.6f}\n"
 | 
				
			||||||
 | 
					            f"Триггер цена: {trigger_price}\n"
 | 
				
			||||||
 | 
					            f"Количество: {qty}\n"
 | 
				
			||||||
 | 
					            f"Тип ордера: {order_type}\n"
 | 
				
			||||||
 | 
					            f"Движение: {movement}\n"
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        return text
 | 
				
			||||||
    return None
 | 
					    return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -224,6 +247,9 @@ async def handle_execution_message(message, msg):
 | 
				
			|||||||
    if trade_info:
 | 
					    if trade_info:
 | 
				
			||||||
        await message.answer(f"{trade_info}", reply_markup=inline_markup.back_to_main)
 | 
					        await message.answer(f"{trade_info}", reply_markup=inline_markup.back_to_main)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if data is not None:
 | 
				
			||||||
 | 
					        await rq.update_trigger_price(tg_id, 0.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if closed_size == 0:
 | 
					    if closed_size == 0:
 | 
				
			||||||
        side = data.get("side", "")
 | 
					        side = data.get("side", "")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -276,7 +302,10 @@ async def handle_order_message(message, msg: dict) -> None:
 | 
				
			|||||||
    Логирует событие и проверяет условия для мартингейла и TP.
 | 
					    Логирует событие и проверяет условия для мартингейла и TP.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    # logger.info(f"Исполнен ордер:\n{json.dumps(msg, indent=4, ensure_ascii=False)}")
 | 
					    # logger.info(f"Исполнен ордер:\n{json.dumps(msg, indent=4, ensure_ascii=False)}")
 | 
				
			||||||
 | 
					    data = msg.get("data", [{}])[0]
 | 
				
			||||||
 | 
					    tg_id = message.from_user.id
 | 
				
			||||||
 | 
					    if data is not None:
 | 
				
			||||||
 | 
					        await rq.update_trigger_price(tg_id, 0.0)
 | 
				
			||||||
    trade_info = format_order_details_position(msg)
 | 
					    trade_info = format_order_details_position(msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if trade_info:
 | 
					    if trade_info:
 | 
				
			||||||
@@ -322,7 +351,7 @@ async def open_position(
 | 
				
			|||||||
        bybit_margin_mode = (
 | 
					        bybit_margin_mode = (
 | 
				
			||||||
            "ISOLATED_MARGIN" if margin_mode == "Isolated" else "REGULAR_MARGIN"
 | 
					            "ISOLATED_MARGIN" if margin_mode == "Isolated" else "REGULAR_MARGIN"
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					        trigger_price = await rq.get_trigger_price(tg_id)
 | 
				
			||||||
        limit_price = None
 | 
					        limit_price = None
 | 
				
			||||||
        if order_type == "Limit":
 | 
					        if order_type == "Limit":
 | 
				
			||||||
            limit_price = await rq.get_limit_price(tg_id)
 | 
					            limit_price = await rq.get_limit_price(tg_id)
 | 
				
			||||||
@@ -426,18 +455,33 @@ async def open_position(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if bybit_margin_mode == "ISOLATED_MARGIN":
 | 
					        if bybit_margin_mode == "ISOLATED_MARGIN":
 | 
				
			||||||
            # Открываем позицию
 | 
					            # Открываем позицию
 | 
				
			||||||
 | 
					            if trigger_price and float(trigger_price) > 0:
 | 
				
			||||||
 | 
					                response = client.place_order(
 | 
				
			||||||
 | 
					                    category="linear",
 | 
				
			||||||
 | 
					                    symbol=symbol,
 | 
				
			||||||
 | 
					                    side=side,
 | 
				
			||||||
 | 
					                    orderType="Stop" if order_type == "Conditional" else order_type,
 | 
				
			||||||
 | 
					                    qty=str(quantity),
 | 
				
			||||||
 | 
					                    price=(str(limit_price) if order_type == "Limit" and limit_price else None),
 | 
				
			||||||
 | 
					                    triggerPrice=str(trigger_price),
 | 
				
			||||||
 | 
					                    triggerBy="LastPrice",
 | 
				
			||||||
 | 
					                    triggerDirection=2 if side == "Buy" else 1,
 | 
				
			||||||
 | 
					                    timeInForce="GTC",
 | 
				
			||||||
 | 
					                    orderLinkId=f"deal_{symbol}_{int(time.time())}",
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                # Обычный ордер, без триггера
 | 
				
			||||||
                response = client.place_order(
 | 
					                response = client.place_order(
 | 
				
			||||||
                    category="linear",
 | 
					                    category="linear",
 | 
				
			||||||
                    symbol=symbol,
 | 
					                    symbol=symbol,
 | 
				
			||||||
                    side=side,
 | 
					                    side=side,
 | 
				
			||||||
                    orderType=order_type,
 | 
					                    orderType=order_type,
 | 
				
			||||||
                    qty=str(quantity),
 | 
					                    qty=str(quantity),
 | 
				
			||||||
                price=(
 | 
					                    price=(str(limit_price) if order_type == "Limit" and limit_price else None),
 | 
				
			||||||
                    str(limit_price) if order_type == "Limit" and limit_price else None
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
                    timeInForce="GTC",
 | 
					                    timeInForce="GTC",
 | 
				
			||||||
                    orderLinkId=f"deal_{symbol}_{int(time.time())}",
 | 
					                    orderLinkId=f"deal_{symbol}_{int(time.time())}",
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if response.get("retCode", -1) == 0:
 | 
					            if response.get("retCode", -1) == 0:
 | 
				
			||||||
                return True
 | 
					                return True
 | 
				
			||||||
            if response.get("retCode", -1) != 0:
 | 
					            if response.get("retCode", -1) != 0:
 | 
				
			||||||
@@ -544,6 +588,9 @@ async def open_position(
 | 
				
			|||||||
                slOrderType=sl_order_type,
 | 
					                slOrderType=sl_order_type,
 | 
				
			||||||
                slLimitPrice=str(sl_limit_price) if sl_limit_price else None,
 | 
					                slLimitPrice=str(sl_limit_price) if sl_limit_price else None,
 | 
				
			||||||
                tpslMode=tpsl_mode,
 | 
					                tpslMode=tpsl_mode,
 | 
				
			||||||
 | 
					                triggerPrice=str(trigger_price) if trigger_price and float(trigger_price) > 0 else None,
 | 
				
			||||||
 | 
					                triggerBy="LastPrice" if trigger_price and float(trigger_price) > 0 else None,
 | 
				
			||||||
 | 
					                triggerDirection=2 if side == "Buy" else 1 if trigger_price and float(trigger_price) > 0 else None,
 | 
				
			||||||
                timeInForce="GTC",
 | 
					                timeInForce="GTC",
 | 
				
			||||||
                orderLinkId=f"deal_{symbol}_{int(time.time())}",
 | 
					                orderLinkId=f"deal_{symbol}_{int(time.time())}",
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
@@ -724,20 +771,20 @@ async def get_active_orders(tg_id, message):
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    client = await get_bybit_client(tg_id)
 | 
					    client = await get_bybit_client(tg_id)
 | 
				
			||||||
    response = client.get_open_orders(
 | 
					    response = client.get_open_orders(
 | 
				
			||||||
        category="linear", settleCoin="USDT", orderType="Limit"
 | 
					        category="linear", settleCoin="USDT", orderType="Limit" and "Market"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    orders = response.get("result", {}).get("list", [])
 | 
					    orders = response.get("result", {}).get("list", [])
 | 
				
			||||||
    limit_orders = [order for order in orders if order.get("orderType") == "Limit"]
 | 
					    limit_orders = [order for order in orders]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if limit_orders:
 | 
					    if limit_orders:
 | 
				
			||||||
        symbols = [order["symbol"] for order in limit_orders]
 | 
					        symbols = [order["symbol"] for order in limit_orders]
 | 
				
			||||||
        await message.answer(
 | 
					        await message.answer(
 | 
				
			||||||
            "📈 Ваши активные лимитные ордера:",
 | 
					            "📈 Ваши активные ордера:",
 | 
				
			||||||
            reply_markup=inline_markup.create_trades_inline_keyboard_limits(symbols),
 | 
					            reply_markup=inline_markup.create_trades_inline_keyboard_limits(symbols),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        await message.answer(
 | 
					        await message.answer(
 | 
				
			||||||
            "❗️ У вас нет активных лимитных ордеров.",
 | 
					            "❗️ У вас нет активных ордеров.",
 | 
				
			||||||
            reply_markup=inline_markup.back_to_main,
 | 
					            reply_markup=inline_markup.back_to_main,
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
@@ -752,12 +799,11 @@ async def get_active_orders_by_symbol(tg_id, symbol, message):
 | 
				
			|||||||
    limit_orders = [
 | 
					    limit_orders = [
 | 
				
			||||||
        order
 | 
					        order
 | 
				
			||||||
        for order in active_orders.get("result", {}).get("list", [])
 | 
					        for order in active_orders.get("result", {}).get("list", [])
 | 
				
			||||||
        if order.get("orderType") == "Limit"
 | 
					 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if not limit_orders:
 | 
					    if not limit_orders:
 | 
				
			||||||
        await message.answer(
 | 
					        await message.answer(
 | 
				
			||||||
            "Нет активных лимитных ордеров по данной торговой паре.",
 | 
					            "Нет активных ордеров по данной торговой паре.",
 | 
				
			||||||
            reply_markup=inline_markup.back_to_main,
 | 
					            reply_markup=inline_markup.back_to_main,
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
@@ -769,9 +815,8 @@ async def get_active_orders_by_symbol(tg_id, symbol, message):
 | 
				
			|||||||
            f"Тип ордера: {order.get('orderType')}\n"
 | 
					            f"Тип ордера: {order.get('orderType')}\n"
 | 
				
			||||||
            f"Сторона: {order.get('side')}\n"
 | 
					            f"Сторона: {order.get('side')}\n"
 | 
				
			||||||
            f"Цена: {order.get('price')}\n"
 | 
					            f"Цена: {order.get('price')}\n"
 | 
				
			||||||
 | 
					            f"Триггер цена: {order.get('triggerPrice')}\n"
 | 
				
			||||||
            f"Количество: {order.get('qty')}\n"
 | 
					            f"Количество: {order.get('qty')}\n"
 | 
				
			||||||
            f"Тейк-профит: {order.get('takeProfit')}\n"
 | 
					 | 
				
			||||||
            f"Стоп-лосс: {order.get('stopLoss')}\n"
 | 
					 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        texts.append(text)
 | 
					        texts.append(text)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,6 @@ from app.services.Bybit.functions.Futures import (close_user_trade, set_take_pro
 | 
				
			|||||||
                                                  get_active_positions_by_symbol, get_active_orders_by_symbol,
 | 
					                                                  get_active_positions_by_symbol, get_active_orders_by_symbol,
 | 
				
			||||||
                                                  get_active_positions, get_active_orders, cancel_all_tp_sl_orders,
 | 
					                                                  get_active_positions, get_active_orders, cancel_all_tp_sl_orders,
 | 
				
			||||||
                                                  open_position, close_trade_after_delay, safe_float,
 | 
					                                                  open_position, close_trade_after_delay, safe_float,
 | 
				
			||||||
                                                  calculate_total_budget, get_bybit_client,
 | 
					 | 
				
			||||||
                                                  )
 | 
					                                                  )
 | 
				
			||||||
from app.services.Bybit.functions.balance import get_balance
 | 
					from app.services.Bybit.functions.balance import get_balance
 | 
				
			||||||
import app.telegram.Keyboards.inline_keyboards as inline_markup
 | 
					import app.telegram.Keyboards.inline_keyboards as inline_markup
 | 
				
			||||||
@@ -18,9 +17,9 @@ import app.telegram.Keyboards.inline_keyboards as inline_markup
 | 
				
			|||||||
import app.telegram.database.requests as rq
 | 
					import app.telegram.database.requests as rq
 | 
				
			||||||
from aiogram.types import Message, CallbackQuery
 | 
					from aiogram.types import Message, CallbackQuery
 | 
				
			||||||
from app.services.Bybit.functions.price_symbol import get_price
 | 
					from app.services.Bybit.functions.price_symbol import get_price
 | 
				
			||||||
import app.services.Bybit.functions.balance as balance_g
 | 
					# import app.services.Bybit.functions.balance as balance_g
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from app.states.States import (state_update_entry_type, state_update_symbol, state_limit_price,
 | 
					from app.states.States import (state_update_symbol,
 | 
				
			||||||
                               SetTP_SL_State, CloseTradeTimerState)
 | 
					                               SetTP_SL_State, CloseTradeTimerState)
 | 
				
			||||||
from aiogram.fsm.context import FSMContext
 | 
					from aiogram.fsm.context import FSMContext
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -121,72 +120,6 @@ async def update_symbol_for_trade(message: Message, state: FSMContext) -> None:
 | 
				
			|||||||
    await state.clear()
 | 
					    await state.clear()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@router_functions_bybit_trade.callback_query(F.data == 'clb_update_entry_type')
 | 
					 | 
				
			||||||
async def update_entry_type_message(callback: CallbackQuery, state: FSMContext) -> None:
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    Запрашивает у пользователя тип входа в позицию (Market или Limit).
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    await state.set_state(state_update_entry_type.entry_type)
 | 
					 | 
				
			||||||
    await callback.message.answer("Выберите тип входа в позицию:", reply_markup=inline_markup.entry_order_type_markup)
 | 
					 | 
				
			||||||
    await callback.answer()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@router_functions_bybit_trade.callback_query(lambda c: c.data and c.data.startswith('entry_order_type:'))
 | 
					 | 
				
			||||||
async def entry_order_type_callback(callback: CallbackQuery, state: FSMContext) -> None:
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    Обработка выбора типа входа в позицию.
 | 
					 | 
				
			||||||
    Если Limit, запрашивает цену лимитного ордера.
 | 
					 | 
				
			||||||
    Если Market — обновляет настройки.
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    order_type = callback.data.split(':')[1]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if order_type not in ['Market', 'Limit']:
 | 
					 | 
				
			||||||
        await callback.answer("Ошибка выбора", show_alert=True)
 | 
					 | 
				
			||||||
        return
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if order_type == 'Limit':
 | 
					 | 
				
			||||||
        await state.set_state(state_limit_price.price)
 | 
					 | 
				
			||||||
        await callback.message.answer("Введите цену:", reply_markup=inline_markup.cancel)
 | 
					 | 
				
			||||||
        await callback.answer()
 | 
					 | 
				
			||||||
        return
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    try:
 | 
					 | 
				
			||||||
        await state.update_data(entry_order_type=order_type)
 | 
					 | 
				
			||||||
        await rq.update_entry_order_type(callback.from_user.id, order_type)
 | 
					 | 
				
			||||||
        await callback.message.answer("Выбран тип входа в позицию по текущей цене:",
 | 
					 | 
				
			||||||
                                      reply_markup=inline_markup.start_trading_markup)
 | 
					 | 
				
			||||||
        await callback.answer()
 | 
					 | 
				
			||||||
    except Exception as e:
 | 
					 | 
				
			||||||
        logger.error("Произошла ошибка при обновлении типа входа в позицию: %s", e)
 | 
					 | 
				
			||||||
        await callback.message.answer("Произошла ошибка при обновлении типа входа в позицию",
 | 
					 | 
				
			||||||
                                      reply_markup=inline_markup.back_to_main)
 | 
					 | 
				
			||||||
    await state.clear()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@router_functions_bybit_trade.message(state_limit_price.price)
 | 
					 | 
				
			||||||
async def set_limit_price(message: Message, state: FSMContext) -> None:
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    Обрабатывает ввод цены лимитного ордера, проверяет формат и сохраняет настройки.
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    try:
 | 
					 | 
				
			||||||
        price = float(message.text)
 | 
					 | 
				
			||||||
        if price <= 0:
 | 
					 | 
				
			||||||
            await message.answer("Цена должна быть положительным числом. Попробуйте снова.",
 | 
					 | 
				
			||||||
                                 reply_markup=inline_markup.cancel)
 | 
					 | 
				
			||||||
            return
 | 
					 | 
				
			||||||
    except ValueError:
 | 
					 | 
				
			||||||
        await message.answer("Некорректный формат цены. Введите число.", reply_markup=inline_markup.cancel)
 | 
					 | 
				
			||||||
        return
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    await state.update_data(entry_order_type='Limit', limit_price=price)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    await rq.update_entry_order_type(message.from_user.id, 'Limit')
 | 
					 | 
				
			||||||
    await rq.update_limit_price(message.from_user.id, price)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    await message.answer(f"Триггер цена установлена: {price}", reply_markup=inline_markup.start_trading_markup)
 | 
					 | 
				
			||||||
    await state.clear()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@router_functions_bybit_trade.callback_query(F.data == "clb_start_chatbot_trading")
 | 
					@router_functions_bybit_trade.callback_query(F.data == "clb_start_chatbot_trading")
 | 
				
			||||||
async def start_trading_process(callback: CallbackQuery) -> None:
 | 
					async def start_trading_process(callback: CallbackQuery) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,6 +21,9 @@ class state_limit_price(StatesGroup):
 | 
				
			|||||||
    """FSM состояние для установки лимита."""
 | 
					    """FSM состояние для установки лимита."""
 | 
				
			||||||
    price = State()
 | 
					    price = State()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class state_trigger_price(StatesGroup):
 | 
				
			||||||
 | 
					    """FSM состояние для установки лимита."""
 | 
				
			||||||
 | 
					    price = State()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CloseTradeTimerState(StatesGroup):
 | 
					class CloseTradeTimerState(StatesGroup):
 | 
				
			||||||
    """FSM состояние ожидания задержки перед закрытием сделки."""
 | 
					    """FSM состояние ожидания задержки перед закрытием сделки."""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,8 +35,6 @@ special_settings_markup = InlineKeyboardMarkup(inline_keyboard=[
 | 
				
			|||||||
    back_btn_to_main
 | 
					    back_btn_to_main
 | 
				
			||||||
])
 | 
					])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
connect_bybit_api_markup = InlineKeyboardMarkup(inline_keyboard=[
 | 
					connect_bybit_api_markup = InlineKeyboardMarkup(inline_keyboard=[
 | 
				
			||||||
    [InlineKeyboardButton(text="Подключить Bybit", callback_data='clb_new_user_connect_bybit_api')]
 | 
					    [InlineKeyboardButton(text="Подключить Bybit", callback_data='clb_new_user_connect_bybit_api')]
 | 
				
			||||||
])
 | 
					])
 | 
				
			||||||
@@ -45,7 +43,7 @@ trading_markup = InlineKeyboardMarkup(inline_keyboard=[
 | 
				
			|||||||
    [InlineKeyboardButton(text="Настройки", callback_data='clb_settings_message')],
 | 
					    [InlineKeyboardButton(text="Настройки", callback_data='clb_settings_message')],
 | 
				
			||||||
    [InlineKeyboardButton(text="Мои сделки", callback_data='clb_my_deals')],
 | 
					    [InlineKeyboardButton(text="Мои сделки", callback_data='clb_my_deals')],
 | 
				
			||||||
    [InlineKeyboardButton(text="Указать торговую пару", callback_data='clb_update_trading_pair')],
 | 
					    [InlineKeyboardButton(text="Указать торговую пару", callback_data='clb_update_trading_pair')],
 | 
				
			||||||
    [InlineKeyboardButton(text="Начать торговать", callback_data='clb_update_entry_type')],
 | 
					    [InlineKeyboardButton(text="Начать торговать", callback_data='clb_start_chatbot_trading')],
 | 
				
			||||||
    [InlineKeyboardButton(text="Остановить торговлю", callback_data='clb_stop_trading')],
 | 
					    [InlineKeyboardButton(text="Остановить торговлю", callback_data='clb_stop_trading')],
 | 
				
			||||||
])
 | 
					])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -61,14 +59,12 @@ cancel = InlineKeyboardMarkup(inline_keyboard=[
 | 
				
			|||||||
entry_order_type_markup = InlineKeyboardMarkup(
 | 
					entry_order_type_markup = InlineKeyboardMarkup(
 | 
				
			||||||
    inline_keyboard=[
 | 
					    inline_keyboard=[
 | 
				
			||||||
        [
 | 
					        [
 | 
				
			||||||
            InlineKeyboardButton(text="Текущая цена", callback_data="entry_order_type:Market"),
 | 
					            InlineKeyboardButton(text="Маркет", callback_data="entry_order_type:Market"),
 | 
				
			||||||
            InlineKeyboardButton(text="Триггер цена", callback_data="entry_order_type:Limit"),
 | 
					            InlineKeyboardButton(text="Лимит", callback_data="entry_order_type:Limit"),
 | 
				
			||||||
        ], back_btn_to_main
 | 
					        ], back_btn_to_main
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
back_to_main = InlineKeyboardMarkup(inline_keyboard=[
 | 
					back_to_main = InlineKeyboardMarkup(inline_keyboard=[
 | 
				
			||||||
    [InlineKeyboardButton(text="На главную", callback_data='back_to_main')],
 | 
					    [InlineKeyboardButton(text="На главную", callback_data='back_to_main')],
 | 
				
			||||||
])
 | 
					])
 | 
				
			||||||
@@ -101,8 +97,10 @@ risk_management_settings_markup = InlineKeyboardMarkup(inline_keyboard=[
 | 
				
			|||||||
])
 | 
					])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
condition_settings_markup = InlineKeyboardMarkup(inline_keyboard=[
 | 
					condition_settings_markup = InlineKeyboardMarkup(inline_keyboard=[
 | 
				
			||||||
    [InlineKeyboardButton(text='Режим торговли', callback_data='clb_change_mode'),
 | 
					    [InlineKeyboardButton(text='Таймер', callback_data='clb_change_timer'),
 | 
				
			||||||
     InlineKeyboardButton(text='Таймер', callback_data='clb_change_timer')],
 | 
					     InlineKeyboardButton(text='Тип позиции', callback_data='clb_update_entry_type')],
 | 
				
			||||||
 | 
					    [InlineKeyboardButton(text='Триггер цена', callback_data='clb_change_trigger_price'),
 | 
				
			||||||
 | 
					     InlineKeyboardButton(text='Лимит цена', callback_data='clb_change_limit_price')],
 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
    # [InlineKeyboardButton(text='Фильтр волатильности', callback_data='clb_change_filter_volatility'),
 | 
					    # [InlineKeyboardButton(text='Фильтр волатильности', callback_data='clb_change_filter_volatility'),
 | 
				
			||||||
    #  InlineKeyboardButton(text='Внешние сигналы', callback_data='clb_change_external_cues')],
 | 
					    #  InlineKeyboardButton(text='Внешние сигналы', callback_data='clb_change_external_cues')],
 | 
				
			||||||
@@ -116,6 +114,11 @@ condition_settings_markup = InlineKeyboardMarkup(inline_keyboard=[
 | 
				
			|||||||
    back_btn_to_main
 | 
					    back_btn_to_main
 | 
				
			||||||
])
 | 
					])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					back_to_condition_settings = InlineKeyboardMarkup(inline_keyboard=[
 | 
				
			||||||
 | 
					    [InlineKeyboardButton(text='Назад', callback_data='clb_change_condition_settings')],
 | 
				
			||||||
 | 
					    back_btn_to_main
 | 
				
			||||||
 | 
					])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
additional_settings_markup = InlineKeyboardMarkup(inline_keyboard=[
 | 
					additional_settings_markup = InlineKeyboardMarkup(inline_keyboard=[
 | 
				
			||||||
    [InlineKeyboardButton(text='Сохранить шаблон', callback_data='clb_change_save_pattern'),
 | 
					    [InlineKeyboardButton(text='Сохранить шаблон', callback_data='clb_change_save_pattern'),
 | 
				
			||||||
     InlineKeyboardButton(text='Автозапуск', callback_data='clb_change_auto_start')],
 | 
					     InlineKeyboardButton(text='Автозапуск', callback_data='clb_change_auto_start')],
 | 
				
			||||||
@@ -162,11 +165,12 @@ buttons_on_off_markup = InlineKeyboardMarkup(inline_keyboard=[  # ИЗМЕНИТ
 | 
				
			|||||||
])
 | 
					])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
my_deals_select_markup = InlineKeyboardMarkup(inline_keyboard=[
 | 
					my_deals_select_markup = InlineKeyboardMarkup(inline_keyboard=[
 | 
				
			||||||
    [InlineKeyboardButton(text='Открытые сделки', callback_data="clb_open_deals"),
 | 
					    [InlineKeyboardButton(text='Позиции', callback_data="clb_open_deals"),
 | 
				
			||||||
     InlineKeyboardButton(text='Лимитные ордера', callback_data="clb_open_orders")],
 | 
					     InlineKeyboardButton(text='Ордера', callback_data="clb_open_orders")],
 | 
				
			||||||
    back_btn_to_main
 | 
					    back_btn_to_main
 | 
				
			||||||
])
 | 
					])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def create_trades_inline_keyboard(trades):
 | 
					def create_trades_inline_keyboard(trades):
 | 
				
			||||||
    builder = InlineKeyboardBuilder()
 | 
					    builder = InlineKeyboardBuilder()
 | 
				
			||||||
    for trade in trades:
 | 
					    for trade in trades:
 | 
				
			||||||
@@ -174,6 +178,7 @@ def create_trades_inline_keyboard(trades):
 | 
				
			|||||||
    builder.adjust(2)
 | 
					    builder.adjust(2)
 | 
				
			||||||
    return builder.as_markup()
 | 
					    return builder.as_markup()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def create_trades_inline_keyboard_limits(trades):
 | 
					def create_trades_inline_keyboard_limits(trades):
 | 
				
			||||||
    builder = InlineKeyboardBuilder()
 | 
					    builder = InlineKeyboardBuilder()
 | 
				
			||||||
    for trade in trades:
 | 
					    for trade in trades:
 | 
				
			||||||
@@ -190,12 +195,14 @@ def create_close_deal_markup(symbol: str) -> InlineKeyboardMarkup:
 | 
				
			|||||||
        back_btn_to_main
 | 
					        back_btn_to_main
 | 
				
			||||||
    ])
 | 
					    ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def create_close_limit_markup(symbol: str) -> InlineKeyboardMarkup:
 | 
					def create_close_limit_markup(symbol: str) -> InlineKeyboardMarkup:
 | 
				
			||||||
    return InlineKeyboardMarkup(inline_keyboard=[
 | 
					    return InlineKeyboardMarkup(inline_keyboard=[
 | 
				
			||||||
        [InlineKeyboardButton(text="Закрыть лимитный ордер", callback_data=f"close_limit:{symbol}")],
 | 
					        [InlineKeyboardButton(text="Закрыть ордер", callback_data=f"close_limit:{symbol}")],
 | 
				
			||||||
        back_btn_to_main
 | 
					        back_btn_to_main
 | 
				
			||||||
    ])
 | 
					    ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
timer_markup = InlineKeyboardMarkup(inline_keyboard=[
 | 
					timer_markup = InlineKeyboardMarkup(inline_keyboard=[
 | 
				
			||||||
    [InlineKeyboardButton(text="Установить таймер", callback_data="clb_set_timer")],
 | 
					    [InlineKeyboardButton(text="Установить таймер", callback_data="clb_set_timer")],
 | 
				
			||||||
    [InlineKeyboardButton(text="Удалить таймер", callback_data="clb_delete_timer")],
 | 
					    [InlineKeyboardButton(text="Удалить таймер", callback_data="clb_delete_timer")],
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -153,7 +153,8 @@ class User_Main_Settings(Base):
 | 
				
			|||||||
    martingale_step = mapped_column(Integer(), default=1)
 | 
					    martingale_step = mapped_column(Integer(), default=1)
 | 
				
			||||||
    maximal_quantity = mapped_column(Integer(), default=10)
 | 
					    maximal_quantity = mapped_column(Integer(), default=10)
 | 
				
			||||||
    entry_order_type = mapped_column(String(10), default='Market')
 | 
					    entry_order_type = mapped_column(String(10), default='Market')
 | 
				
			||||||
    limit_order_price = mapped_column(Numeric(18, 15), nullable=True)
 | 
					    limit_order_price = mapped_column(Numeric(18, 15), nullable=True, default=0)
 | 
				
			||||||
 | 
					    trigger_price = mapped_column(Numeric(18, 15), nullable=True, default=0)
 | 
				
			||||||
    last_side = mapped_column(String(10), default='Buy')
 | 
					    last_side = mapped_column(String(10), default='Buy')
 | 
				
			||||||
    trading_start_stop = mapped_column(Integer(), default=0)
 | 
					    trading_start_stop = mapped_column(Integer(), default=0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -306,3 +307,10 @@ async def async_main():
 | 
				
			|||||||
            if not result.first():
 | 
					            if not result.first():
 | 
				
			||||||
                logger.info("Заполение таблицы последнего направления")
 | 
					                logger.info("Заполение таблицы последнего направления")
 | 
				
			||||||
                await conn.execute(User_Main_Settings.__table__.insert().values(last_side=side))
 | 
					                await conn.execute(User_Main_Settings.__table__.insert().values(last_side=side))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        order_type = ['Limit', 'Market']
 | 
				
			||||||
 | 
					        for typ in order_type:
 | 
				
			||||||
 | 
					            result = await conn.execute(select(User_Main_Settings).where(User_Main_Settings.entry_order_type == typ))
 | 
				
			||||||
 | 
					            if not result.first():
 | 
				
			||||||
 | 
					                logger.info("Заполение таблицы типов ордеров")
 | 
				
			||||||
 | 
					                await conn.execute(User_Main_Settings.__table__.insert().values(entry_order_type=typ))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,6 +318,7 @@ async def get_user_main_settings(tg_id):
 | 
				
			|||||||
                'maximal_quantity': user.maximal_quantity,
 | 
					                'maximal_quantity': user.maximal_quantity,
 | 
				
			||||||
                'entry_order_type': user.entry_order_type,
 | 
					                'entry_order_type': user.entry_order_type,
 | 
				
			||||||
                'limit_order_price': user.limit_order_price,
 | 
					                'limit_order_price': user.limit_order_price,
 | 
				
			||||||
 | 
					                'trigger_price': user.trigger_price,
 | 
				
			||||||
                'martingale_step': user.martingale_step,
 | 
					                'martingale_step': user.martingale_step,
 | 
				
			||||||
                'last_side': user.last_side,
 | 
					                'last_side': user.last_side,
 | 
				
			||||||
                'trading_start_stop': user.trading_start_stop,
 | 
					                'trading_start_stop': user.trading_start_stop,
 | 
				
			||||||
@@ -438,6 +439,31 @@ async def update_entry_order_type(tg_id, order_type):
 | 
				
			|||||||
        await session.commit()
 | 
					        await session.commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def update_trigger_price(tg_id, price):
 | 
				
			||||||
 | 
					    """Обновить условную цену пользователя."""
 | 
				
			||||||
 | 
					    async with async_session() as session:
 | 
				
			||||||
 | 
					        await session.execute(
 | 
				
			||||||
 | 
					            update(UMS)
 | 
				
			||||||
 | 
					            .where(UMS.tg_id == tg_id)
 | 
				
			||||||
 | 
					            .values(trigger_price=str(price))
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        await session.commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def get_trigger_price(tg_id):
 | 
				
			||||||
 | 
					    """Получить условную цену пользователя как float, либо None."""
 | 
				
			||||||
 | 
					    async with async_session() as session:
 | 
				
			||||||
 | 
					        result = await session.execute(
 | 
				
			||||||
 | 
					            select(UMS.trigger_price)
 | 
				
			||||||
 | 
					            .where(UMS.tg_id == tg_id)
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        price = result.scalar_one_or_none()
 | 
				
			||||||
 | 
					        if price:
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                return float(price)
 | 
				
			||||||
 | 
					            except ValueError:
 | 
				
			||||||
 | 
					                return None
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async def get_limit_price(tg_id):
 | 
					async def get_limit_price(tg_id):
 | 
				
			||||||
    """Получить лимитную цену пользователя как float, либо None."""
 | 
					    """Получить лимитную цену пользователя как float, либо None."""
 | 
				
			||||||
    async with async_session() as session:
 | 
					    async with async_session() as session:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@ from aiogram.types import Message, CallbackQuery
 | 
				
			|||||||
from aiogram.fsm.context import FSMContext
 | 
					from aiogram.fsm.context import FSMContext
 | 
				
			||||||
import app.telegram.database.requests as rq
 | 
					import app.telegram.database.requests as rq
 | 
				
			||||||
from app.states.States import condition_settings
 | 
					from app.states.States import condition_settings
 | 
				
			||||||
 | 
					from app.states.States import state_limit_price, state_update_entry_type, state_trigger_price
 | 
				
			||||||
from logger_helper.logger_helper import LOGGING_CONFIG
 | 
					from logger_helper.logger_helper import LOGGING_CONFIG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
logging.config.dictConfig(LOGGING_CONFIG)
 | 
					logging.config.dictConfig(LOGGING_CONFIG)
 | 
				
			||||||
@@ -23,8 +23,24 @@ async def reg_new_user_default_condition_settings(id):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async def main_settings_message(id, message):
 | 
					async def main_settings_message(id, message):
 | 
				
			||||||
 | 
					    data = await rq.get_user_main_settings(id)
 | 
				
			||||||
 | 
					    entry_order_type = data['entry_order_type']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if entry_order_type == "Market":
 | 
				
			||||||
 | 
					        entry_order_type_rus = "Маркет"
 | 
				
			||||||
 | 
					    elif entry_order_type == "Limit":
 | 
				
			||||||
 | 
					        entry_order_type_rus = "Лимит"
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        entry_order_type_rus = "Условный"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    trigger_price = data['trigger_price'] or 0.0
 | 
				
			||||||
 | 
					    limit_price = data['limit_order_price'] or 0.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    text = f""" <b>Условия запуска</b>
 | 
					    text = f""" <b>Условия запуска</b>
 | 
				
			||||||
<b>- Таймер: </b> установить таймер / удалить таймер
 | 
					<b>- Таймер: </b> установить таймер / удалить таймер
 | 
				
			||||||
 | 
					<b>- Тип позиции:</b> {entry_order_type_rus}
 | 
				
			||||||
 | 
					<b>- Триггер цена: </b> {trigger_price:,.4f}
 | 
				
			||||||
 | 
					<b>- Лимит цена: </b> {limit_price:,.4f}
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
    await message.answer(text=text, parse_mode='html', reply_markup=inline_markup.condition_settings_markup)
 | 
					    await message.answer(text=text, parse_mode='html', reply_markup=inline_markup.condition_settings_markup)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -75,6 +91,85 @@ async def delete_timer_callback(callback: CallbackQuery, state: FSMContext):
 | 
				
			|||||||
    await callback.answer()
 | 
					    await callback.answer()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@condition_settings_router.callback_query(F.data == 'clb_update_entry_type')
 | 
				
			||||||
 | 
					async def update_entry_type_message(callback: CallbackQuery, state: FSMContext) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Запрашивает у пользователя тип входа в позицию (Market или Limit).
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    await state.set_state(state_update_entry_type.entry_type)
 | 
				
			||||||
 | 
					    await callback.message.answer("Выберите тип входа в позицию:", reply_markup=inline_markup.entry_order_type_markup)
 | 
				
			||||||
 | 
					    await callback.answer()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@condition_settings_router.callback_query(lambda c: c.data and c.data.startswith('entry_order_type:'))
 | 
				
			||||||
 | 
					async def entry_order_type_callback(callback: CallbackQuery, state: FSMContext) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Обработка выбора типа входа в позицию.
 | 
				
			||||||
 | 
					    Если Limit, запрашивает цену лимитного ордера.
 | 
				
			||||||
 | 
					    Если Market — обновляет настройки.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    order_type = callback.data.split(':')[1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if order_type not in ['Market', 'Limit']:
 | 
				
			||||||
 | 
					        await callback.answer("Ошибка выбора", show_alert=True)
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if order_type == 'Limit':
 | 
				
			||||||
 | 
					        order_type_rus = 'Лимит'
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        order_type_rus = 'Маркет'
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        await state.update_data(entry_order_type=order_type)
 | 
				
			||||||
 | 
					        await rq.update_entry_order_type(callback.from_user.id, order_type)
 | 
				
			||||||
 | 
					        await callback.message.answer(f"Выбран тип входа {order_type_rus}",
 | 
				
			||||||
 | 
					                                      reply_markup=inline_markup.back_to_condition_settings)
 | 
				
			||||||
 | 
					        await callback.answer()
 | 
				
			||||||
 | 
					    except Exception as e:
 | 
				
			||||||
 | 
					        logger.error("Произошла ошибка при обновлении типа входа в позицию: %s", e)
 | 
				
			||||||
 | 
					        await callback.message.answer("Произошла ошибка при обновлении типа входа в позицию",
 | 
				
			||||||
 | 
					                                      reply_markup=inline_markup.back_to_condition_settings)
 | 
				
			||||||
 | 
					    await state.clear()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@condition_settings_router.callback_query(F.data == 'clb_change_limit_price')
 | 
				
			||||||
 | 
					async def set_limit_price_callback(callback: CallbackQuery, state: FSMContext) -> None:
 | 
				
			||||||
 | 
					    await state.set_state(state_limit_price.price)
 | 
				
			||||||
 | 
					    await callback.message.answer("Введите цену лимитного ордера:", reply_markup=inline_markup.cancel)
 | 
				
			||||||
 | 
					    await callback.answer()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@condition_settings_router.message(state_limit_price.price)
 | 
				
			||||||
 | 
					async def process_limit_price_input(message: Message, state: FSMContext) -> None:
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        price = float(message.text)
 | 
				
			||||||
 | 
					        await state.update_data(price=price)
 | 
				
			||||||
 | 
					        await rq.update_limit_price(tg_id=message.from_user.id, price=price)
 | 
				
			||||||
 | 
					        await message.answer(f"Цена лимитного ордера установлена: {price}", reply_markup=inline_markup.back_to_condition_settings)
 | 
				
			||||||
 | 
					        await state.clear()
 | 
				
			||||||
 | 
					    except ValueError:
 | 
				
			||||||
 | 
					        await message.reply("Пожалуйста, введите корректную цену.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@condition_settings_router.callback_query(F.data == 'clb_change_trigger_price')
 | 
				
			||||||
 | 
					async def change_trigger_price_callback(callback: CallbackQuery, state: FSMContext) -> None:
 | 
				
			||||||
 | 
					    await state.set_state(state_trigger_price.price)
 | 
				
			||||||
 | 
					    await callback.message.answer("Введите цену триггера:", reply_markup=inline_markup.cancel)
 | 
				
			||||||
 | 
					    await callback.answer()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@condition_settings_router.message(state_trigger_price.price)
 | 
				
			||||||
 | 
					async def process_trigger_price_input(message: Message, state: FSMContext) -> None:
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        price = float(message.text)
 | 
				
			||||||
 | 
					        await state.update_data(price=price)
 | 
				
			||||||
 | 
					        await rq.update_trigger_price(tg_id=message.from_user.id, price=price)
 | 
				
			||||||
 | 
					        await message.answer(f"Цена триггера установлена: {price}", reply_markup=inline_markup.back_to_condition_settings)
 | 
				
			||||||
 | 
					        await state.clear()
 | 
				
			||||||
 | 
					    except ValueError:
 | 
				
			||||||
 | 
					        await message.reply("Пожалуйста, введите корректную цену.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async def filter_volatility_message(message, state):
 | 
					async def filter_volatility_message(message, state):
 | 
				
			||||||
    text = '''Фильтр волатильности
 | 
					    text = '''Фильтр волатильности
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,6 @@
 | 
				
			|||||||
import logging.config
 | 
					import logging.config
 | 
				
			||||||
import app.telegram.Keyboards.inline_keyboards as inline_markup
 | 
					import app.telegram.Keyboards.inline_keyboards as inline_markup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from pybit.unified_trading import HTTP
 | 
					 | 
				
			||||||
import app.telegram.database.requests as rq
 | 
					import app.telegram.database.requests as rq
 | 
				
			||||||
from aiogram.types import Message, CallbackQuery
 | 
					from aiogram.types import Message, CallbackQuery
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -125,6 +124,7 @@ async def state_trading_mode(callback: CallbackQuery, state):
 | 
				
			|||||||
        logger.error("Ошибка при обновлении режима торговли: %s", e)
 | 
					        logger.error("Ошибка при обновлении режима торговли: %s", e)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async def switch_mode_enabled_message(message, state):
 | 
					async def switch_mode_enabled_message(message, state):
 | 
				
			||||||
    await state.set_state(update_main_settings.switch_mode_enabled)
 | 
					    await state.set_state(update_main_settings.switch_mode_enabled)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user