Compare commits

...

8 Commits

5 changed files with 276 additions and 240 deletions

View File

@@ -30,7 +30,7 @@ async def start_trading_cycle(
risk_management_data = await rq.get_user_risk_management(tg_id=tg_id) risk_management_data = await rq.get_user_risk_management(tg_id=tg_id)
trade_mode = additional_data.trade_mode trade_mode = additional_data.trade_mode
switch_side = additional_data.switch_side switch_side = additional_data.switch_side
side= additional_data.side side = additional_data.side
margin_type = additional_data.margin_type margin_type = additional_data.margin_type
leverage = additional_data.leverage leverage = additional_data.leverage
order_quantity = additional_data.order_quantity order_quantity = additional_data.order_quantity
@@ -54,12 +54,6 @@ async def start_trading_cycle(
tg_id=tg_id, tg_id=tg_id,
symbol=symbol, symbol=symbol,
mode=0) mode=0)
await set_margin_mode(tg_id=tg_id, margin_mode=margin_type)
await set_leverage(
tg_id=tg_id,
symbol=symbol,
leverage=leverage,
)
await rq.set_user_deal( await rq.set_user_deal(
tg_id=tg_id, tg_id=tg_id,
@@ -107,7 +101,8 @@ async def start_trading_cycle(
"position idx not match position mode", "position idx not match position mode",
"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",
} }
else None else None
) )
@@ -193,6 +188,7 @@ async def trading_cycle_profit(
"ab not enough for new order", "ab not enough for new order",
"InvalidRequestError", "InvalidRequestError",
"The number of contracts exceeds maximum limit allowed", "The number of contracts exceeds maximum limit allowed",
"Order placement failed as your position may exceed the max",
} }
else None else None
) )
@@ -293,6 +289,7 @@ async def trading_cycle(
"ab not enough for new order", "ab not enough for new order",
"InvalidRequestError", "InvalidRequestError",
"The number of contracts exceeds maximum limit allowed", "The number of contracts exceeds maximum limit allowed",
"Order placement failed as your position may exceed the max",
} }
else None else None
) )
@@ -313,7 +310,12 @@ async def open_positions(
try: try:
client = await get_bybit_client(tg_id=tg_id) client = await get_bybit_client(tg_id=tg_id)
get_ticker = await get_tickers(tg_id, symbol=symbol) get_ticker = await get_tickers(tg_id, symbol=symbol)
price_symbol = safe_float(get_ticker.get("lastPrice")) or 0
if get_ticker is None:
price_symbol = 0
else:
price_symbol = safe_float(get_ticker.get("lastPrice"))
instruments_info = await get_instruments_info(tg_id=tg_id, symbol=symbol) instruments_info = await get_instruments_info(tg_id=tg_id, symbol=symbol)
qty_step_str = instruments_info.get("lotSizeFilter").get("qtyStep") qty_step_str = instruments_info.get("lotSizeFilter").get("qtyStep")
qty_step = safe_float(qty_step_str) qty_step = safe_float(qty_step_str)
@@ -363,6 +365,7 @@ async def open_positions(
"Qty invalid": "Qty invalid", "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 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", "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(): for key, msg in known_errors.items():
if key in error_text: if key in error_text:

View File

@@ -25,11 +25,13 @@ async def set_tp_sl_for_position(
""" """
try: try:
client = await get_bybit_client(tg_id) client = await get_bybit_client(tg_id)
take_profit = round(take_profit_price, 6) if take_profit_price is not None else None
stop_loss = round(stop_loss_price, 6) if stop_loss_price is not None else None
resp = client.set_trading_stop( resp = client.set_trading_stop(
category="linear", category="linear",
symbol=symbol, symbol=symbol,
takeProfit=str(round(take_profit_price, 5)), takeProfit=str(take_profit) if take_profit is not None else None,
stopLoss=str(round(stop_loss_price, 5)), stopLoss=str(stop_loss) if stop_loss is not None else None,
positionIdx=position_idx, positionIdx=position_idx,
tpslMode="Full", tpslMode="Full",
) )

View File

@@ -1,9 +1,10 @@
import logging.config import logging.config
import math import math
# import json
import app.telegram.keyboards.inline as kbi import app.telegram.keyboards.inline as kbi
import database.request as rq import database.request as rq
from app.bybit.get_functions.get_instruments_info import get_instruments_info from app.bybit.get_functions.get_instruments_info import get_instruments_info
from app.bybit.get_functions.get_positions import get_active_positions_by_symbol
from app.bybit.logger_bybit.logger_bybit import LOGGING_CONFIG from app.bybit.logger_bybit.logger_bybit import LOGGING_CONFIG
from app.bybit.open_positions import trading_cycle, trading_cycle_profit from app.bybit.open_positions import trading_cycle, trading_cycle_profit
from app.bybit.set_functions.set_tp_sl import set_tp_sl_for_position from app.bybit.set_functions.set_tp_sl import set_tp_sl_for_position
@@ -56,252 +57,289 @@ class TelegramMessageHandler:
async def format_execution_update(self, message, tg_id): async def format_execution_update(self, message, tg_id):
try: try:
# logger.info("Execution update: %s", json.dumps(message))
execution = message.get("data", [{}])[0] execution = message.get("data", [{}])[0]
closed_size = format_value(execution.get("closedSize")) exec_type = format_value(execution.get("execType"))
symbol = format_value(execution.get("symbol")) if exec_type == "Trade" or exec_type == "BustTrade":
exec_price = format_value(execution.get("execPrice")) closed_size = format_value(execution.get("closedSize"))
exec_qty = format_value(execution.get("execQty")) symbol = format_value(execution.get("symbol"))
exec_fees = format_value(execution.get("execFee")) exec_price = format_value(execution.get("execPrice"))
fee_rate = format_value(execution.get("feeRate")) exec_qty = format_value(execution.get("execQty"))
side = format_value(execution.get("side")) exec_fees = format_value(execution.get("execFee"))
side_rus = ( fee_rate = format_value(execution.get("feeRate"))
"Покупка" side = format_value(execution.get("side"))
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: user_auto_trading = await rq.get_user_auto_trading(
await rq.set_fee_user_auto_trading( tg_id=tg_id, symbol=symbol
tg_id=tg_id, symbol=symbol, fee=safe_float(exec_fee) )
auto_trading = (
user_auto_trading.auto_trading if user_auto_trading else False
) )
user_auto_trading = await rq.get_user_auto_trading( side_rus = (
tg_id=tg_id, symbol=symbol "Покупка"
) if side == "Buy"
else "Продажа" if side == "Sell" else "Нет данных"
get_total_fee = user_auto_trading.total_fee )
total_fee = safe_float(exec_fee) + safe_float(get_total_fee) if safe_float(exec_fees) == 0:
exec_fee = safe_float(exec_price) * safe_float(exec_qty) * safe_float(
exec_pnl = format_value(execution.get("execPnl")) fee_rate
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: else:
total_quantity = safe_float(order_quantity) exec_fee = safe_float(exec_fees)
else:
total_quantity = safe_float(order_quantity)
if user_deals_data is not None and auto_trading and safe_float(closed_size) == 0: if safe_float(closed_size) == 0:
await rq.set_total_fee_user_auto_trading( await rq.set_fee_user_auto_trading(
tg_id=tg_id, symbol=symbol, total_fee=total_fee tg_id=tg_id, symbol=symbol, fee=safe_float(exec_fee)
)
get_total_fee = 0
if user_auto_trading is not None:
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"Текущая ставка: {total_quantity:.2f} USDT\n" text = f"{header}\n" f"Торговая пара: {symbol}\n"
text += f"Серия №: {current_series}\n" user_deals_data = await rq.get_user_deal_by_symbol(
text += f"Сделка №: {current_step}\n" tg_id=tg_id, symbol=symbol
)
if user_deals_data is None:
commission_fee = "Yes_commission_fee"
commission_place = "Commission_for_qty"
text += ( else:
f"Цена исполнения: {exec_price}\n" commission_fee = user_deals_data.commission_fee or "Yes_commission_fee"
f"Комиссия: {exec_fee:.8f}\n" commission_place = user_deals_data.commission_place or "Commission_for_qty"
)
if safe_float(closed_size) == 0: current_series = user_deals_data.current_series
instruments_info = await get_instruments_info(tg_id=tg_id, symbol=symbol) current_step = user_deals_data.current_step
qty_step_str = instruments_info.get("lotSizeFilter").get("qtyStep") order_quantity = user_deals_data.order_quantity
qty_step = safe_float(qty_step_str) pnl_series = user_deals_data.pnl_series
qty = (safe_float(order_quantity) * safe_float(leverage)) / safe_float(exec_price) margin_type = user_deals_data.margin_type
decimals = abs(int(round(math.log10(qty_step)))) take_profit_percent = user_deals_data.take_profit_percent
qty_format = math.floor(qty / qty_step) * qty_step stop_loss_percent = user_deals_data.stop_loss_percent
qty_formatted = round(qty_format, decimals) fee = safe_float(user_auto_trading.fee)
total_commission = 0 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_fee == "Yes_commission_fee":
if commission_place == "Commission_for_tp": if commission_place == "Commission_for_qty":
total_commission = safe_float(total_fee) / qty_formatted total_quantity = safe_float(order_quantity) + safe_float(
total_fee
if margin_type == "ISOLATED_MARGIN": ) * 2
if side == "Buy":
take_profit_price = safe_float(exec_price) * (
1 + take_profit_percent / 100) + total_commission
stop_loss_price = None
else: else:
take_profit_price = safe_float(exec_price) * ( total_quantity = safe_float(order_quantity)
1 - take_profit_percent / 100) - total_commission
stop_loss_price = None
else: else:
if side == "Buy": total_quantity = safe_float(order_quantity)
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)
take_profit_price = max(take_profit_price, 0) if user_deals_data is not None and auto_trading and safe_float(closed_size) == 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)
await rq.set_total_fee_user_auto_trading( 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( text += f"Текущая ставка: {total_quantity:.2f} USDT\n"
tg_id=tg_id, symbol=symbol, fee=0 text += f"Серия №: {current_series}\n"
) text += f"Сделка №: {current_step}\n"
await rq.set_pnl_series_by_symbol(tg_id=tg_id, symbol=symbol, pnl_series=0)
res = await trading_cycle_profit( text += (
tg_id=tg_id, symbol=symbol, side=r_side f"Цена исполнения: {exec_price}\n"
) f"Комиссия: {exec_fee:.8f}\n"
if res == "OK": )
pass
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: else:
errors = { if side == "Buy":
"Max bets in series": "❗️ Максимальное количество сделок в серии достигнуто", take_profit_price = safe_float(exec_price) * (
"Risk is too high for this trade": "❗️ Риск сделки слишком высок для продолжения", 1 + take_profit_percent / 100) + total_commission
"ab not enough for new order": "❗️ Недостаточно средств для продолжения торговли", stop_loss_price = safe_float(exec_price) * (1 - stop_loss_percent / 100)
"InvalidRequestError": "❗️ Недостаточно средств для размещения нового ордера с заданным количеством и плечом.", else:
"The number of contracts exceeds maximum limit allowed": "❗️ Превышен максимальный лимит ставки", take_profit_price = safe_float(exec_price) * (
} 1 - take_profit_percent / 100) - total_commission
error_text = errors.get( stop_loss_price = safe_float(exec_price) * (1 + stop_loss_percent / 100)
res, "❗️ Не удалось открыть новую сделку"
) take_profit_price = max(take_profit_price, 0)
await rq.set_auto_trading( stop_loss_price = max(stop_loss_price, 0)
tg_id=tg_id, symbol=symbol, auto_trading=False
) ress = 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)
if ress:
take_profit_truncated = await truncate_float(take_profit_price, 6)
text += (f"Движение: {side_rus}\n"
f"Тейк-профит: {take_profit_truncated}\n"
)
if stop_loss_price is not None:
stop_loss_truncated = await truncate_float(stop_loss_price, 6)
else:
stop_loss_truncated = None
if stop_loss_truncated is not None:
text += f"Стоп-лосс: {stop_loss_truncated}\n"
else:
deals = await get_active_positions_by_symbol(
tg_id=tg_id, symbol=symbol
)
position = next((d for d in deals if d.get("symbol") == symbol), None)
if position:
liq_price = position.get("liqPrice", 0)
text += f"Цена ликвидации: {liq_price}\n"
else:
text += (f"Движение: {side_rus}\n"
"Не удалось установить ТП и СЛ\n")
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: else:
open_order_text = "\n❗️ Открываю новую сделку с увеличенной ставкой.\n" if auto_trading:
await self.telegram_bot.send_message( new_pnl = safe_float(pnl_series) + total_pnl
chat_id=tg_id, text=open_order_text await rq.set_pnl_series_by_symbol(
) tg_id=tg_id, symbol=symbol, pnl_series=new_pnl)
text += f"\nПрибыль без комиссии: {ex_pnl:.4f}\n"
if side == "Buy": text += f"Реализованная прибыль: {total_pnl:.4f}\n"
r_side = "Sell" text += f"Прибыль серии: {safe_float(new_pnl):.4f}\n"
else: else:
r_side = "Buy" text += f"\nПрибыль без комиссии: {ex_pnl:.4f}\n"
text += f"Реализованная прибыль: {total_pnl:.4f}\n"
res = await trading_cycle( await self.telegram_bot.send_message(
tg_id=tg_id, symbol=symbol, side=r_side chat_id=tg_id, text=text, reply_markup=kbi.profile_bybit
) )
if res == "OK": user_symbols = user_auto_trading.symbol if user_auto_trading else None
pass
else: if (
errors = { auto_trading
"Max bets in series": "❗️ Максимальное количество сделок в серии достигнуто", and safe_float(closed_size) > 0
"Risk is too high for this trade": "❗️ Риск сделки слишком высок для продолжения", and user_symbols is not None
"ab not enough for new order": "❗️ Недостаточно средств для продолжения торговли", ):
"InvalidRequestError": "❗️ Недостаточно средств для размещения нового ордера с заданным количеством и плечом.", if safe_float(pnl) > 0:
"The number of contracts exceeds maximum limit allowed": "❗️ Превышен максимальный лимит ставки", profit_text = "📈 Начинаю новую серию с базовой ставки\n"
} await self.telegram_bot.send_message(
error_text = errors.get( chat_id=tg_id, text=profit_text, reply_markup=kbi.profile_bybit
res, "❗️ Не удалось открыть новую сделку"
)
await rq.set_auto_trading(
tg_id=tg_id, symbol=symbol, auto_trading=False
) )
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( 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=0
) )
await rq.set_fee_user_auto_trading( await rq.set_fee_user_auto_trading(
tg_id=tg_id, symbol=symbol, fee=0 tg_id=tg_id, symbol=symbol, fee=0
) )
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( await self.telegram_bot.send_message(
chat_id=tg_id, chat_id=tg_id, text=open_order_text
text=error_text,
reply_markup=kbi.profile_bybit,
) )
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: except Exception as e:
logger.error("Error in telegram_message_handler: %s", e, exc_info=True) logger.error("Error in telegram_message_handler: %s", e, exc_info=True)

View File

@@ -25,7 +25,6 @@ class WebSocketBot:
self.user_keys = {} self.user_keys = {}
self.loop = None self.loop = None
self.message_handler = TelegramMessageHandler(telegram_bot) self.message_handler = TelegramMessageHandler(telegram_bot)
self.last_execution_seq = {}
async def run_user_check_loop(self): async def run_user_check_loop(self):
"""Run a loop to check for users and connect them to the WebSocket.""" """Run a loop to check for users and connect them to the WebSocket."""
@@ -106,18 +105,8 @@ class WebSocketBot:
await self.message_handler.format_order_update(message, tg_id) await self.message_handler.format_order_update(message, tg_id)
async def handle_execution_update(self, message, tg_id): async def handle_execution_update(self, message, tg_id):
"""Handle execution updates.""" """Handle execution updates without duplicate processing."""
data_items = message.get('data', []) await self.message_handler.format_execution_update(message, tg_id)
if not data_items:
return
for exec_data in data_items:
seq = exec_data.get('seq')
if tg_id not in self.last_execution_seq:
self.last_execution_seq[tg_id] = -1
if seq <= self.last_execution_seq[tg_id]:
continue
self.last_execution_seq[tg_id] = seq
await self.message_handler.format_execution_update(message, tg_id)
@staticmethod @staticmethod
async def get_users_from_db(): async def get_users_from_db():

View File

@@ -97,7 +97,8 @@ async def start_trading(callback_query: CallbackQuery, state: FSMContext) -> Non
"Limit price is out min price": "Цена лимитного ордера меньше допустимого", "Limit price is out min price": "Цена лимитного ордера меньше допустимого",
"Limit price is out max price": "Цена лимитного ордера больше допустимого", "Limit price is out max price": "Цена лимитного ордера больше допустимого",
"Risk is too high for this trade": "Риск сделки превышает допустимый убыток", "Risk is too high for this trade": "Риск сделки превышает допустимый убыток",
"estimated will trigger liq": "Лимитный ордер может вызвать мгновенную ликвидацию. Проверьте параметры ордера.", "estimated will trigger liq": "Лимитный ордер может вызвать мгновенную ликвидацию. "
"Проверьте параметры ордера.",
"ab not enough for new order": "Недостаточно средств для создания нового ордера", "ab not enough for new order": "Недостаточно средств для создания нового ордера",
"InvalidRequestError": "Произошла ошибка при запуске торговли.", "InvalidRequestError": "Произошла ошибка при запуске торговли.",
"Order does not meet minimum order value": "Сумма ставки меньше допустимого для запуска торговли. " "Order does not meet minimum order value": "Сумма ставки меньше допустимого для запуска торговли. "
@@ -106,6 +107,9 @@ async def start_trading(callback_query: CallbackQuery, state: FSMContext) -> Non
"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":
"Не удалось разместить ордер, так как ваша позиция может превышать максимальный лимит."
"Пожалуйста, уменьшите кредитное плечо, чтобы увеличить максимальное значение"
} }
if res == "OK": if res == "OK":
@@ -141,7 +145,7 @@ async def start_trading(callback_query: CallbackQuery, state: FSMContext) -> Non
lambda c: c.data == "cancel_timer_merged" lambda c: c.data == "cancel_timer_merged"
) )
async def cancel_start_trading( async def cancel_start_trading(
callback_query: CallbackQuery, state: FSMContext callback_query: CallbackQuery, state: FSMContext
) -> None: ) -> None:
""" """
Handles the "cancel_timer" callback query. Handles the "cancel_timer" callback query.