2
0
forked from kodorvan/stcs

Fixed close position

This commit is contained in:
algizn97
2025-10-03 14:18:53 +05:00
parent 6705bf4492
commit 4adbd70948
2 changed files with 51 additions and 78 deletions

View File

@@ -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

View File

@@ -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()