From 29c168e31ddfa452eaca03dc05d06807e4fcd5ec Mon Sep 17 00:00:00 2001 From: algizn97 Date: Thu, 30 Oct 2025 12:45:22 +0500 Subject: [PATCH] Added error information output --- app/bybit/open_positions.py | 8 +- app/bybit/telegram_message_handler.py | 414 +++++++++++++------------ app/telegram/handlers/start_trading.py | 8 +- 3 files changed, 221 insertions(+), 209 deletions(-) diff --git a/app/bybit/open_positions.py b/app/bybit/open_positions.py index 9ccb188..5fe98b2 100644 --- a/app/bybit/open_positions.py +++ b/app/bybit/open_positions.py @@ -30,7 +30,7 @@ async def start_trading_cycle( risk_management_data = await rq.get_user_risk_management(tg_id=tg_id) trade_mode = additional_data.trade_mode switch_side = additional_data.switch_side - side= additional_data.side + side = additional_data.side margin_type = additional_data.margin_type leverage = additional_data.leverage order_quantity = additional_data.order_quantity @@ -107,7 +107,8 @@ async def start_trading_cycle( "position idx not match position mode", "Qty invalid", "The number of contracts exceeds maximum limit allowed", - "The number of contracts exceeds minimum limit allowed" + "The number of contracts exceeds minimum limit allowed", + "Order placement failed as your position may exceed the max", } else None ) @@ -193,6 +194,7 @@ async def trading_cycle_profit( "ab not enough for new order", "InvalidRequestError", "The number of contracts exceeds maximum limit allowed", + "Order placement failed as your position may exceed the max", } else None ) @@ -293,6 +295,7 @@ async def trading_cycle( "ab not enough for new order", "InvalidRequestError", "The number of contracts exceeds maximum limit allowed", + "Order placement failed as your position may exceed the max", } else None ) @@ -363,6 +366,7 @@ async def open_positions( "Qty invalid": "Qty invalid", "The number of contracts exceeds maximum limit allowed": "The number of contracts exceeds maximum limit allowed", "The number of contracts exceeds minimum limit allowed": "The number of contracts exceeds minimum limit allowed", + "Order placement failed as your position may exceed the max": "Order placement failed as your position may exceed the max", } for key, msg in known_errors.items(): if key in error_text: diff --git a/app/bybit/telegram_message_handler.py b/app/bybit/telegram_message_handler.py index b5d874b..db92bcb 100644 --- a/app/bybit/telegram_message_handler.py +++ b/app/bybit/telegram_message_handler.py @@ -64,244 +64,248 @@ class TelegramMessageHandler: exec_fees = format_value(execution.get("execFee")) fee_rate = format_value(execution.get("feeRate")) side = format_value(execution.get("side")) - side_rus = ( - "Покупка" - if side == "Buy" - else "Продажа" if side == "Sell" else "Нет данных" - ) - if safe_float(exec_fees) == 0: - exec_fee = safe_float(exec_price) * safe_float(exec_qty) * safe_float( - fee_rate - ) - else: - exec_fee = safe_float(exec_fees) - - if safe_float(closed_size) == 0: - await rq.set_fee_user_auto_trading( - tg_id=tg_id, symbol=symbol, fee=safe_float(exec_fee) - ) user_auto_trading = await rq.get_user_auto_trading( tg_id=tg_id, symbol=symbol ) - - get_total_fee = user_auto_trading.total_fee - total_fee = safe_float(exec_fee) + safe_float(get_total_fee) - - exec_pnl = format_value(execution.get("execPnl")) - ex_pnl = safe_float(exec_pnl) - pnl = safe_float(exec_pnl) - - header = ( - "Сделка закрыта:" if safe_float(closed_size) > 0 else "Сделка открыта:" - ) - text = f"{header}\n" f"Торговая пара: {symbol}\n" - auto_trading = ( user_auto_trading.auto_trading if user_auto_trading else False ) - user_deals_data = await rq.get_user_deal_by_symbol( - tg_id=tg_id, symbol=symbol - ) - commission_fee = user_deals_data.commission_fee - commission_place = user_deals_data.commission_place - current_series = user_deals_data.current_series - current_step = user_deals_data.current_step - order_quantity = user_deals_data.order_quantity - pnl_series = user_deals_data.pnl_series - margin_type = user_deals_data.margin_type - take_profit_percent = user_deals_data.take_profit_percent - stop_loss_percent = user_deals_data.stop_loss_percent - fee = safe_float(user_auto_trading.fee) - total_pnl = safe_float(exec_pnl) - safe_float(exec_fee) - fee - leverage = safe_float(user_deals_data.leverage) - - if commission_fee == "Yes_commission_fee": - if commission_place == "Commission_for_qty": - total_quantity = safe_float(order_quantity) + safe_float( - total_fee - ) * 2 - else: - total_quantity = safe_float(order_quantity) - else: - total_quantity = safe_float(order_quantity) - - if user_deals_data is not None and auto_trading and safe_float(closed_size) == 0: - await rq.set_total_fee_user_auto_trading( - tg_id=tg_id, symbol=symbol, total_fee=total_fee + if auto_trading: + side_rus = ( + "Покупка" + if side == "Buy" + else "Продажа" if side == "Sell" else "Нет данных" ) - text += f"Текущая ставка: {total_quantity:.2f} USDT\n" - text += f"Серия №: {current_series}\n" - text += f"Сделка №: {current_step}\n" + if safe_float(exec_fees) == 0: + exec_fee = safe_float(exec_price) * safe_float(exec_qty) * safe_float( + fee_rate + ) + else: + exec_fee = safe_float(exec_fees) - text += ( - f"Цена исполнения: {exec_price}\n" - f"Комиссия: {exec_fee:.8f}\n" - ) + if safe_float(closed_size) == 0: + await rq.set_fee_user_auto_trading( + tg_id=tg_id, symbol=symbol, fee=safe_float(exec_fee) + ) - if safe_float(closed_size) == 0: - instruments_info = await get_instruments_info(tg_id=tg_id, symbol=symbol) - qty_step_str = instruments_info.get("lotSizeFilter").get("qtyStep") - qty_step = safe_float(qty_step_str) - qty = (safe_float(order_quantity) * safe_float(leverage)) / safe_float(exec_price) - decimals = abs(int(round(math.log10(qty_step)))) - qty_format = math.floor(qty / qty_step) * qty_step - qty_formatted = round(qty_format, decimals) - total_commission = 0 + + + get_total_fee = user_auto_trading.total_fee + total_fee = safe_float(exec_fee) + safe_float(get_total_fee) + + exec_pnl = format_value(execution.get("execPnl")) + ex_pnl = safe_float(exec_pnl) + pnl = safe_float(exec_pnl) + + header = ( + "Сделка закрыта:" if safe_float(closed_size) > 0 else "Сделка открыта:" + ) + text = f"{header}\n" f"Торговая пара: {symbol}\n" + user_deals_data = await rq.get_user_deal_by_symbol( + tg_id=tg_id, symbol=symbol + ) + commission_fee = user_deals_data.commission_fee or "Yes_commission_fee" + commission_place = user_deals_data.commission_place or "Commission_for_qty" + current_series = user_deals_data.current_series + current_step = user_deals_data.current_step + order_quantity = user_deals_data.order_quantity + pnl_series = user_deals_data.pnl_series + margin_type = user_deals_data.margin_type + take_profit_percent = user_deals_data.take_profit_percent + stop_loss_percent = user_deals_data.stop_loss_percent + fee = safe_float(user_auto_trading.fee) + total_pnl = safe_float(exec_pnl) - safe_float(exec_fee) - fee + leverage = safe_float(user_deals_data.leverage) if commission_fee == "Yes_commission_fee": - if commission_place == "Commission_for_tp": - total_commission = safe_float(total_fee) / qty_formatted - - if margin_type == "ISOLATED_MARGIN": - if side == "Buy": - take_profit_price = safe_float(exec_price) * ( - 1 + take_profit_percent / 100) + total_commission - stop_loss_price = None + if commission_place == "Commission_for_qty": + total_quantity = safe_float(order_quantity) + safe_float( + total_fee + ) * 2 else: - take_profit_price = safe_float(exec_price) * ( - 1 - take_profit_percent / 100) - total_commission - stop_loss_price = None + total_quantity = safe_float(order_quantity) else: - if side == "Buy": - take_profit_price = safe_float(exec_price) * ( - 1 + take_profit_percent / 100) + total_commission - stop_loss_price = safe_float(exec_price) * (1 - stop_loss_percent / 100) - else: - take_profit_price = safe_float(exec_price) * ( - 1 - take_profit_percent / 100) - total_commission - stop_loss_price = safe_float(exec_price) * (1 + stop_loss_percent / 100) + total_quantity = safe_float(order_quantity) - take_profit_price = max(take_profit_price, 0) - stop_loss_price = max(stop_loss_price, 0) - - await set_tp_sl_for_position(tg_id=tg_id, - symbol=symbol, - take_profit_price=take_profit_price, - stop_loss_price=stop_loss_price, - position_idx=0) - - take_profit_truncated = await truncate_float(take_profit_price, 4) - stop_loss_truncated = await truncate_float(stop_loss_price, 4) - - text += (f"Движение: {side_rus}\n" - f"Тейк-профит: {take_profit_truncated}\n" - f"Стоп-лосс: {stop_loss_truncated}\n" - ) - else: - new_pnl = safe_float(pnl_series) + total_pnl - await rq.set_pnl_series_by_symbol( - tg_id=tg_id, symbol=symbol, pnl_series=new_pnl) - text += f"\nДоход: {ex_pnl:.4f}\n" - text += f"Реализованный PNL: {total_pnl:.4f}\n" - text += f"Прибыль серии: {safe_float(new_pnl):.4f}\n" - - await self.telegram_bot.send_message( - chat_id=tg_id, text=text, reply_markup=kbi.profile_bybit - ) - - user_symbols = user_auto_trading.symbol if user_auto_trading else None - - if ( - auto_trading - and safe_float(closed_size) > 0 - and user_symbols is not None - ): - if safe_float(pnl) > 0: - profit_text = "📈 Начинаю новую серию с базовой ставки\n" - await self.telegram_bot.send_message( - chat_id=tg_id, text=profit_text, reply_markup=kbi.profile_bybit - ) - - if side == "Buy": - r_side = "Sell" - else: - r_side = "Buy" - - await rq.set_last_side_by_symbol( - tg_id=tg_id, symbol=symbol, last_side=r_side) + if user_deals_data is not None and auto_trading and safe_float(closed_size) == 0: await rq.set_total_fee_user_auto_trading( - tg_id=tg_id, symbol=symbol, total_fee=0 + tg_id=tg_id, symbol=symbol, total_fee=total_fee ) - await rq.set_fee_user_auto_trading( - tg_id=tg_id, symbol=symbol, fee=0 - ) - await rq.set_pnl_series_by_symbol(tg_id=tg_id, symbol=symbol, pnl_series=0) + text += f"Текущая ставка: {total_quantity:.2f} USDT\n" + text += f"Серия №: {current_series}\n" + text += f"Сделка №: {current_step}\n" - res = await trading_cycle_profit( - tg_id=tg_id, symbol=symbol, side=r_side - ) - if res == "OK": - pass + text += ( + f"Цена исполнения: {exec_price}\n" + f"Комиссия: {exec_fee:.8f}\n" + ) + + if safe_float(closed_size) == 0: + instruments_info = await get_instruments_info(tg_id=tg_id, symbol=symbol) + qty_step_str = instruments_info.get("lotSizeFilter").get("qtyStep") + qty_step = safe_float(qty_step_str) + qty = (safe_float(order_quantity) * safe_float(leverage)) / safe_float(exec_price) + decimals = abs(int(round(math.log10(qty_step)))) + qty_format = math.floor(qty / qty_step) * qty_step + qty_formatted = round(qty_format, decimals) + total_commission = 0 + + if commission_fee == "Yes_commission_fee": + if commission_place == "Commission_for_tp": + total_commission = safe_float(total_fee) / qty_formatted + + if margin_type == "ISOLATED_MARGIN": + if side == "Buy": + take_profit_price = safe_float(exec_price) * ( + 1 + take_profit_percent / 100) + total_commission + stop_loss_price = None + else: + take_profit_price = safe_float(exec_price) * ( + 1 - take_profit_percent / 100) - total_commission + stop_loss_price = None else: - errors = { - "Max bets in series": "❗️ Максимальное количество сделок в серии достигнуто", - "Risk is too high for this trade": "❗️ Риск сделки слишком высок для продолжения", - "ab not enough for new order": "❗️ Недостаточно средств для продолжения торговли", - "InvalidRequestError": "❗️ Недостаточно средств для размещения нового ордера с заданным количеством и плечом.", - "The number of contracts exceeds maximum limit allowed": "❗️ Превышен максимальный лимит ставки", - } - error_text = errors.get( - res, "❗️ Не удалось открыть новую сделку" - ) - await rq.set_auto_trading( - tg_id=tg_id, symbol=symbol, auto_trading=False - ) + if side == "Buy": + take_profit_price = safe_float(exec_price) * ( + 1 + take_profit_percent / 100) + total_commission + stop_loss_price = safe_float(exec_price) * (1 - stop_loss_percent / 100) + else: + take_profit_price = safe_float(exec_price) * ( + 1 - take_profit_percent / 100) - total_commission + stop_loss_price = safe_float(exec_price) * (1 + stop_loss_percent / 100) - await rq.set_total_fee_user_auto_trading( - tg_id=tg_id, symbol=symbol, total_fee=0 - ) - await rq.set_fee_user_auto_trading( - tg_id=tg_id, symbol=symbol, fee=0 - ) - await self.telegram_bot.send_message( - chat_id=tg_id, - text=error_text, - reply_markup=kbi.profile_bybit, - ) + take_profit_price = max(take_profit_price, 0) + stop_loss_price = max(stop_loss_price, 0) + + await set_tp_sl_for_position(tg_id=tg_id, + symbol=symbol, + take_profit_price=take_profit_price, + stop_loss_price=stop_loss_price, + position_idx=0) + + take_profit_truncated = await truncate_float(take_profit_price, 6) + stop_loss_truncated = await truncate_float(stop_loss_price, 6) + + text += (f"Движение: {side_rus}\n" + f"Тейк-профит: {take_profit_truncated}\n" + f"Стоп-лосс: {stop_loss_truncated}\n" + ) else: - open_order_text = "\n❗️ Открываю новую сделку с увеличенной ставкой.\n" - await self.telegram_bot.send_message( - chat_id=tg_id, text=open_order_text - ) + new_pnl = safe_float(pnl_series) + total_pnl + await rq.set_pnl_series_by_symbol( + tg_id=tg_id, symbol=symbol, pnl_series=new_pnl) + text += f"\nПрибыль без комиссии: {ex_pnl:.4f}\n" + text += f"Реализованная прибыль: {total_pnl:.4f}\n" + text += f"Прибыль серии: {safe_float(new_pnl):.4f}\n" - if side == "Buy": - r_side = "Sell" - else: - r_side = "Buy" + await self.telegram_bot.send_message( + chat_id=tg_id, text=text, reply_markup=kbi.profile_bybit + ) - res = await trading_cycle( - tg_id=tg_id, symbol=symbol, side=r_side - ) + user_symbols = user_auto_trading.symbol if user_auto_trading else None - if res == "OK": - pass - else: - errors = { - "Max bets in series": "❗️ Максимальное количество сделок в серии достигнуто", - "Risk is too high for this trade": "❗️ Риск сделки слишком высок для продолжения", - "ab not enough for new order": "❗️ Недостаточно средств для продолжения торговли", - "InvalidRequestError": "❗️ Недостаточно средств для размещения нового ордера с заданным количеством и плечом.", - "The number of contracts exceeds maximum limit allowed": "❗️ Превышен максимальный лимит ставки", - } - error_text = errors.get( - res, "❗️ Не удалось открыть новую сделку" - ) - await rq.set_auto_trading( - tg_id=tg_id, symbol=symbol, auto_trading=False + if ( + auto_trading + and safe_float(closed_size) > 0 + and user_symbols is not None + ): + if safe_float(pnl) > 0: + profit_text = "📈 Начинаю новую серию с базовой ставки\n" + await self.telegram_bot.send_message( + chat_id=tg_id, text=profit_text, reply_markup=kbi.profile_bybit ) + if side == "Buy": + r_side = "Sell" + else: + r_side = "Buy" + + await rq.set_last_side_by_symbol( + tg_id=tg_id, symbol=symbol, last_side=r_side) await rq.set_total_fee_user_auto_trading( tg_id=tg_id, symbol=symbol, total_fee=0 ) await rq.set_fee_user_auto_trading( tg_id=tg_id, symbol=symbol, fee=0 ) - await self.telegram_bot.send_message( - chat_id=tg_id, - text=error_text, - reply_markup=kbi.profile_bybit, + await rq.set_pnl_series_by_symbol(tg_id=tg_id, symbol=symbol, pnl_series=0) + + res = await trading_cycle_profit( + tg_id=tg_id, symbol=symbol, side=r_side ) + if res == "OK": + pass + else: + errors = { + "Max bets in series": "❗️ Максимальное количество сделок в серии достигнуто", + "Risk is too high for this trade": "❗️ Риск сделки слишком высок для продолжения", + "ab not enough for new order": "❗️ Недостаточно средств для продолжения торговли", + "InvalidRequestError": "❗️ Недостаточно средств для размещения нового ордера с заданным количеством и плечом.", + "The number of contracts exceeds maximum limit allowed": "❗️ Превышен максимальный лимит ставки", + "Order placement failed as your position may exceed the max": "❗️ Превышен максимальный лимит ставки", + } + error_text = errors.get( + res, "❗️ Не удалось открыть новую сделку" + ) + await rq.set_auto_trading( + tg_id=tg_id, symbol=symbol, auto_trading=False + ) + + await rq.set_total_fee_user_auto_trading( + tg_id=tg_id, symbol=symbol, total_fee=0 + ) + await rq.set_fee_user_auto_trading( + tg_id=tg_id, symbol=symbol, fee=0 + ) + await self.telegram_bot.send_message( + chat_id=tg_id, + text=error_text, + reply_markup=kbi.profile_bybit, + ) + else: + open_order_text = "\n❗️ Открываю новую сделку с увеличенной ставкой.\n" + await self.telegram_bot.send_message( + chat_id=tg_id, text=open_order_text + ) + + if side == "Buy": + r_side = "Sell" + else: + r_side = "Buy" + + res = await trading_cycle( + tg_id=tg_id, symbol=symbol, side=r_side + ) + + if res == "OK": + pass + else: + errors = { + "Max bets in series": "❗️ Максимальное количество сделок в серии достигнуто", + "Risk is too high for this trade": "❗️ Риск сделки слишком высок для продолжения", + "ab not enough for new order": "❗️ Недостаточно средств для продолжения торговли", + "InvalidRequestError": "❗️ Недостаточно средств для размещения нового ордера с заданным количеством и плечом.", + "The number of contracts exceeds maximum limit allowed": "❗️ Превышен максимальный лимит ставки", + "Order placement failed as your position may exceed the max": "❗️ Превышен максимальный лимит ставки", + } + error_text = errors.get( + res, "❗️ Не удалось открыть новую сделку" + ) + await rq.set_auto_trading( + tg_id=tg_id, symbol=symbol, auto_trading=False + ) + + await rq.set_total_fee_user_auto_trading( + tg_id=tg_id, symbol=symbol, total_fee=0 + ) + await rq.set_fee_user_auto_trading( + tg_id=tg_id, symbol=symbol, fee=0 + ) + await self.telegram_bot.send_message( + chat_id=tg_id, + text=error_text, + reply_markup=kbi.profile_bybit, + ) except Exception as e: logger.error("Error in telegram_message_handler: %s", e, exc_info=True) diff --git a/app/telegram/handlers/start_trading.py b/app/telegram/handlers/start_trading.py index 440f35c..e410d61 100644 --- a/app/telegram/handlers/start_trading.py +++ b/app/telegram/handlers/start_trading.py @@ -97,7 +97,8 @@ async def start_trading(callback_query: CallbackQuery, state: FSMContext) -> Non "Limit price is out min price": "Цена лимитного ордера меньше допустимого", "Limit price is out max price": "Цена лимитного ордера больше допустимого", "Risk is too high for this trade": "Риск сделки превышает допустимый убыток", - "estimated will trigger liq": "Лимитный ордер может вызвать мгновенную ликвидацию. Проверьте параметры ордера.", + "estimated will trigger liq": "Лимитный ордер может вызвать мгновенную ликвидацию. " + "Проверьте параметры ордера.", "ab not enough for new order": "Недостаточно средств для создания нового ордера", "InvalidRequestError": "Произошла ошибка при запуске торговли.", "Order does not meet minimum order value": "Сумма ставки меньше допустимого для запуска торговли. " @@ -106,6 +107,9 @@ async def start_trading(callback_query: CallbackQuery, state: FSMContext) -> Non "Qty invalid": "Некорректное значение ставки для данного инструмента", "The number of contracts exceeds maximum limit allowed": "️️Превышен максимальный лимит ставки", "The number of contracts exceeds minimum limit allowed": "️️Лимит ставки меньше минимально допустимого", + "Order placement failed as your position may exceed the max": + "Не удалось разместить ордер, так как ваша позиция может превышать максимальный лимит." + "Пожалуйста, уменьшите кредитное плечо, чтобы увеличить максимальное значение" } if res == "OK": @@ -141,7 +145,7 @@ async def start_trading(callback_query: CallbackQuery, state: FSMContext) -> Non lambda c: c.data == "cancel_timer_merged" ) async def cancel_start_trading( - callback_query: CallbackQuery, state: FSMContext + callback_query: CallbackQuery, state: FSMContext ) -> None: """ Handles the "cancel_timer" callback query.