diff --git a/app/bybit/close_positions.py b/app/bybit/close_positions.py index 6b2fbc3..3750bef 100644 --- a/app/bybit/close_positions.py +++ b/app/bybit/close_positions.py @@ -1,77 +1,69 @@ import logging.config from app.bybit import get_bybit_client -from app.bybit.get_functions.get_positions import get_active_positions_by_symbol from app.bybit.logger_bybit.logger_bybit import LOGGING_CONFIG logging.config.dictConfig(LOGGING_CONFIG) logger = logging.getLogger("close_positions") -async def close_position(tg_id: int, symbol: str) -> bool: +async def close_position(tg_id: int, symbol: str, side: str, position_idx: int, qty: float) -> bool: """ - Closes position + Closes all positions :param tg_id: Telegram user ID :param symbol: symbol + :param side: side + :param position_idx: position index + :param qty: quantity :return: bool """ try: client = await get_bybit_client(tg_id) - active_positions = await get_active_positions_by_symbol(tg_id, symbol) - side = active_positions.get("side") - size = active_positions.get("size") - position_idx = active_positions.get("positionIdx") if side == "Buy": - side = "Sell" - elif side == "Sell": - side = "Buy" + r_side = "Sell" + else: + r_side = "Buy" response = client.place_order( category="linear", symbol=symbol, - side=side, + side=r_side, orderType="Market", - qty=size, + qty=qty, timeInForce="GTC", positionIdx=position_idx, ) if response["retCode"] == 0: - logger.info("Position closed for %s for user %s", symbol, tg_id) + logger.info("All positions closed for %s for user %s", symbol, tg_id) return True else: - logger.error("Error closing position for %s for user %s", symbol, tg_id) + logger.error("Error closing all positions for %s for user %s", symbol, tg_id) return False except Exception as e: - logger.error("Error closing position for %s for user %s: %s", symbol, tg_id, e) + logger.error("Error closing all positions for %s for user %s: %s", symbol, tg_id, e) return False - -async def cancel_order(tg_id, symbol) -> bool: +async def cancel_order(tg_id: int, symbol: str, order_id: str) -> bool: """ Cancel order by order id """ try: client = await get_bybit_client(tg_id) - orders_resp = client.get_open_orders(category="linear", symbol=symbol) - orders = orders_resp.get("result", {}).get("list", []) - for order in orders: - order_id = order.get("orderId") - cancel_resp = client.cancel_order( - category="linear", symbol=symbol, orderId=order_id + cancel_resp = client.cancel_order( + category="linear", symbol=symbol, orderId=order_id + ) + + if cancel_resp.get("retCode") == 0: + return True + else: + logger.error( + "Error canceling order for user %s: %s", + tg_id, + cancel_resp.get("retMsg"), ) - - if cancel_resp.get("retCode") == 0: - return True - else: - logger.error( - "Error canceling order for user %s: %s", - tg_id, - cancel_resp.get("retMsg"), - ) - return False - return False + return False except Exception as e: logger.error("Error canceling order for user %s: %s", tg_id, e) return False diff --git a/app/telegram/handlers/close_orders.py b/app/telegram/handlers/close_orders.py index 7d103bf..0b99461 100644 --- a/app/telegram/handlers/close_orders.py +++ b/app/telegram/handlers/close_orders.py @@ -1,12 +1,15 @@ import logging.config -from aiogram import F, Router +from aiogram import Router from aiogram.fsm.context import FSMContext from aiogram.types import CallbackQuery -from app.bybit.close_positions import cancel_all_orders, cancel_order, close_position +from app.bybit.close_positions import cancel_order, close_position +from app.helper_functions import safe_float from logger_helper.logger_helper import LOGGING_CONFIG +import database.request as rq + logging.config.dictConfig(LOGGING_CONFIG) logger = logging.getLogger("close_orders") @@ -17,7 +20,7 @@ router_close_orders = Router(name="close_orders") lambda c: c.data and c.data.startswith("close_position_") ) async def close_position_handler( - callback_query: CallbackQuery, state: FSMContext + callback_query: CallbackQuery, state: FSMContext ) -> None: """ Close a position. @@ -26,13 +29,23 @@ async def close_position_handler( :return: None """ try: - symbol = callback_query.data.split("_", 2)[2] - res = await close_position(tg_id=callback_query.from_user.id, symbol=symbol) + data = callback_query.data + parts = data.split("_") + symbol = parts[2] + side = parts[3] + position_idx = int(parts[4]) + qty = safe_float(parts[5]) + res = await close_position(tg_id=callback_query.from_user.id, + symbol=symbol, + side=side, + position_idx=position_idx, + qty=qty) if not res: await callback_query.answer(text="Произошла ошибка при закрытии позиции.") return + await rq.set_auto_trading(tg_id=callback_query.from_user.id, symbol=symbol, auto_trading=False, side=side) await callback_query.answer(text="Позиция успешно закрыта.") logger.debug( "Command close_position processed successfully for user: %s", @@ -53,7 +66,7 @@ async def close_position_handler( lambda c: c.data and c.data.startswith("close_order_") ) async def cancel_order_handler( - callback_query: CallbackQuery, state: FSMContext + callback_query: CallbackQuery, state: FSMContext ) -> None: """ Cancel an order. @@ -62,8 +75,11 @@ async def cancel_order_handler( :return: None """ try: - symbol = callback_query.data.split("_", 2)[2] - res = await cancel_order(tg_id=callback_query.from_user.id, symbol=symbol) + data = callback_query.data + parts = data.split("_") + symbol = parts[2] + order_id = parts[3] + res = await cancel_order(tg_id=callback_query.from_user.id, symbol=symbol, order_id=order_id) if not res: await callback_query.answer(text="Произошла ошибка при закрытии ордера.") @@ -82,39 +98,4 @@ async def cancel_order_handler( e, ) finally: - await state.clear() - - -@router_close_orders.callback_query(F.data == "cancel_all_orders") -async def cancel_all_orders_handler( - callback_query: CallbackQuery, state: FSMContext -) -> None: - """ - Close all open positions and orders. - :param callback_query: Incoming callback query from Telegram inline keyboard. - :param state: Finite State Machine context for the current user session. - :return: None - """ - try: - res = await cancel_all_orders(tg_id=callback_query.from_user.id) - - if not res: - await callback_query.answer( - text="Произошла ошибка при закрытии всех ордеров." - ) - return - - await callback_query.answer(text="Все ордера успешно закрыты.") - logger.debug( - "Command close_all_orders processed successfully for user: %s", - callback_query.from_user.id, - ) - except Exception as e: - await callback_query.answer(text="Произошла ошибка при закрытии всех ордеров.") - logger.error( - "Error processing command close_all_orders for user %s: %s", - callback_query.from_user.id, - e, - ) - finally: - await state.clear() + await state.clear() \ No newline at end of file