forked from kodorvan/stcs
193 lines
8.6 KiB
Python
193 lines
8.6 KiB
Python
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"Цена: {price}\n"
|
||
f"Режим позиции: {position_idx_rus}\n"
|
||
f"Количество: {qty}\n"
|
||
f"Тип ордера: {order_type_rus}\n"
|
||
f"Движение: {side_rus}\n"
|
||
f"Триггер цена: {trigger_price}\n"
|
||
f"Тейк-профит: {take_profit}\n"
|
||
f"Стоп-лосс: {stop_loss}\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 "Нет данных"
|
||
)
|
||
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)
|
||
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:.4f}\n"
|
||
)
|
||
|
||
if safe_float(closed_size) > 0:
|
||
text += f"\nРеализованная прибыль: {total_pnl:.4f}\n"
|
||
|
||
await self.telegram_bot.send_message(
|
||
chat_id=tg_id, text=text, reply_markup=kbi.profile_bybit
|
||
)
|
||
|
||
user_auto_trading = await rq.get_user_auto_trading(
|
||
tg_id=tg_id, symbol=symbol
|
||
)
|
||
auto_trading = (
|
||
user_auto_trading.auto_trading if user_auto_trading else False
|
||
)
|
||
user_symbols = await rq.get_user_deal_by_symbol(tg_id=tg_id, symbol=symbol)
|
||
|
||
if (
|
||
auto_trading
|
||
and safe_float(closed_size) > 0
|
||
and user_symbols is not None
|
||
):
|
||
if safe_float(total_pnl) > 0:
|
||
await rq.set_auto_trading(
|
||
tg_id=tg_id, symbol=symbol, auto_trading=False
|
||
)
|
||
profit_text = "📈 Прибыль достигнута\n"
|
||
await self.telegram_bot.send_message(
|
||
chat_id=tg_id, text=profit_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
|
||
)
|
||
res = await trading_cycle(
|
||
tg_id=tg_id, symbol=symbol, reverse_side=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": "❗️ Недостаточно средств для размещения нового ордера с заданным количеством и плечом.",
|
||
}
|
||
error_text = errors.get(
|
||
res, "❗️ Не удалось открыть новую сделку"
|
||
)
|
||
await rq.set_auto_trading(
|
||
tg_id=tg_id, symbol=symbol, auto_trading=False
|
||
)
|
||
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)
|