2
0
forked from kodorvan/stcs
Files
stcs/app/bybit/telegram_message_handler.py
algizn97 220c45d54c Fixed
2025-10-04 09:34:11 +05:00

229 lines
10 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import logging.config
import app.telegram.keyboards.inline as kbi
import database.request as rq
from app.bybit.logger_bybit.logger_bybit import LOGGING_CONFIG
from app.bybit.open_positions import trading_cycle
from app.helper_functions import format_value, safe_float, safe_int
logging.config.dictConfig(LOGGING_CONFIG)
logger = logging.getLogger("telegram_message_handler")
class TelegramMessageHandler:
def __init__(self, telegram_bot):
self.telegram_bot = telegram_bot
async def format_position_update(self, message):
pass
async def format_order_update(self, message, tg_id):
try:
order_data = message.get("data", [{}])[0]
symbol = format_value(order_data.get("symbol"))
qty = format_value(order_data.get("qty"))
order_type = format_value(order_data.get("orderType"))
order_type_rus = (
"Рыночный"
if order_type == "Market"
else "Лимитный" if order_type == "Limit" else "Нет данных"
)
side = format_value(order_data.get("side"))
side_rus = (
"Покупка"
if side == "Buy"
else "Продажа" if side == "Sell" else "Нет данных"
)
order_status = format_value(order_data.get("orderStatus"))
price = format_value(order_data.get("price"))
trigger_price = format_value(order_data.get("triggerPrice"))
take_profit = format_value(order_data.get("takeProfit"))
stop_loss = format_value(order_data.get("stopLoss"))
position_idx = safe_int(order_data.get("positionIdx"))
position_idx_rus = (
"Односторонний"
if position_idx == 0
else (
"Покупка в режиме хеджирования"
if position_idx == 1
else (
"Продажа в режиме хеджирования"
if position_idx == 2
else "Нет данных"
)
)
)
status_map = {
"New": "Ордер создан",
"Cancelled": "Ордер отменен",
"Deactivated": "Ордер деактивирован",
"Untriggered": "Условный ордер выставлен",
}
if order_status == "Filled" or order_status not in status_map:
return None
status_text = status_map[order_status]
text = (
f"{status_text}:\n"
f"Торговая пара: {symbol}\n"
f"Режим позиции: {position_idx_rus}\n"
f"Количество: {qty}\n"
f"Тип ордера: {order_type_rus}\n"
f"Движение: {side_rus}\n"
)
if price and price != "0":
text += f"Цена: {price}\n"
if take_profit and take_profit != "Нет данных":
text += f"Тейк-профит: {take_profit}\n"
if stop_loss and stop_loss != "Нет данных":
text += f"Стоп-лосс: {stop_loss}\n"
if trigger_price and trigger_price != "Нет данных":
text += f"Триггер цена: {trigger_price}\n"
await self.telegram_bot.send_message(
chat_id=tg_id, text=text, reply_markup=kbi.profile_bybit
)
except Exception as e:
logger.error("Error in format_order_update: %s", e)
async def format_execution_update(self, message, tg_id):
try:
execution = message.get("data", [{}])[0]
closed_size = format_value(execution.get("closedSize"))
symbol = format_value(execution.get("symbol"))
exec_price = format_value(execution.get("execPrice"))
exec_fee = format_value(execution.get("execFee"))
exec_qty = format_value(execution.get("execQty"))
order_type = format_value(execution.get("orderType"))
order_type_rus = (
"Рыночный"
if order_type == "Market"
else "Лимитный" if order_type == "Limit" else "Нет данных"
)
side = format_value(execution.get("side"))
side_rus = (
"Покупка"
if side == "Buy"
else "Продажа" if side == "Sell" else "Нет данных"
)
if safe_float(closed_size) == 0:
await rq.set_fee_user_auto_trading(
tg_id=tg_id, symbol=symbol, side=side, fee=safe_float(exec_fee)
)
if side == "Buy":
res_side = "Sell"
else:
res_side = "Buy"
user_auto_trading = await rq.get_user_auto_trading(
tg_id=tg_id, symbol=symbol, side=res_side
)
if user_auto_trading is not None and user_auto_trading.fee is not None:
fee = user_auto_trading.fee
else:
fee = 0
exec_pnl = format_value(execution.get("execPnl"))
risk_management_data = await rq.get_user_risk_management(tg_id=tg_id)
commission_fee = risk_management_data.commission_fee
if commission_fee == "Yes_commission_fee":
total_pnl = safe_float(exec_pnl) - safe_float(exec_fee) - fee
else:
total_pnl = safe_float(exec_pnl)
header = (
"Сделка закрыта:" if safe_float(closed_size) > 0 else "Сделка открыта:"
)
text = f"{header}\n" f"Торговая пара: {symbol}\n"
if safe_float(closed_size) > 0:
text += f"Количество закрытых сделок: {closed_size}\n"
text += (
f"Цена исполнения: {exec_price}\n"
f"Количество исполненных сделок: {exec_qty}\n"
f"Тип ордера: {order_type_rus}\n"
f"Движение: {side_rus}\n"
f"Комиссия за сделку: {exec_fee}\n"
)
if safe_float(closed_size) > 0:
text += f"\nРеализованная прибыль: {total_pnl:.7f}\n"
await self.telegram_bot.send_message(
chat_id=tg_id, text=text, reply_markup=kbi.profile_bybit
)
auto_trading = (
user_auto_trading.auto_trading if user_auto_trading else False
)
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(total_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_auto_trading(tg_id=tg_id, symbol=symbol, auto_trading=False, side=r_side)
user_deals_data = await rq.get_user_deal_by_symbol(tg_id=tg_id, symbol=symbol)
if user_deals_data and user_deals_data.switch_side_mode:
await rq.set_auto_trading(tg_id=tg_id, symbol=symbol, auto_trading=False, side=side)
else:
open_order_text = "\n❗️ Сделка закрылась в минус, открываю новую сделку с увеличенной ставкой.\n"
await self.telegram_bot.send_message(
chat_id=tg_id, text=open_order_text
)
res = await trading_cycle(
tg_id=tg_id, symbol=symbol, reverse_side=side, size=closed_size
)
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, "❗️ Не удалось открыть новую сделку"
)
if side == "Buy":
r_side = "Sell"
else:
r_side = "Buy"
await rq.set_auto_trading(
tg_id=tg_id, symbol=symbol, auto_trading=False, side=r_side
)
user_deals_data = await rq.get_user_deal_by_symbol(tg_id=tg_id, symbol=symbol)
if user_deals_data and user_deals_data.switch_side_mode:
await rq.set_auto_trading(
tg_id=tg_id, symbol=symbol, auto_trading=False, side=side
)
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)