forked from kodorvan/stcs
Fixed check auto trading
This commit is contained in:
@@ -123,6 +123,7 @@ async def start_trading_cycle(
|
|||||||
"Order does not meet minimum order value",
|
"Order does not meet minimum order value",
|
||||||
"position idx not match position mode",
|
"position idx not match position mode",
|
||||||
"Qty invalid",
|
"Qty invalid",
|
||||||
|
"The number of contracts exceeds maximum limit allowed"
|
||||||
}
|
}
|
||||||
else None
|
else None
|
||||||
)
|
)
|
||||||
@@ -132,7 +133,9 @@ async def start_trading_cycle(
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
async def trading_cycle(tg_id: int, symbol: str, reverse_side: str, size: str) -> str | None:
|
async def trading_cycle(
|
||||||
|
tg_id: int, symbol: str, reverse_side: str, size: str
|
||||||
|
) -> str | None:
|
||||||
try:
|
try:
|
||||||
user_deals_data = await rq.get_user_deal_by_symbol(tg_id=tg_id, symbol=symbol)
|
user_deals_data = await rq.get_user_deal_by_symbol(tg_id=tg_id, symbol=symbol)
|
||||||
trade_mode = user_deals_data.trade_mode
|
trade_mode = user_deals_data.trade_mode
|
||||||
@@ -169,7 +172,6 @@ async def trading_cycle(tg_id: int, symbol: str, reverse_side: str, size: str) -
|
|||||||
leverage=leverage,
|
leverage=leverage,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if reverse_side == "Buy":
|
if reverse_side == "Buy":
|
||||||
real_side = "Sell"
|
real_side = "Sell"
|
||||||
else:
|
else:
|
||||||
@@ -239,6 +241,7 @@ async def trading_cycle(tg_id: int, symbol: str, reverse_side: str, size: str) -
|
|||||||
"Risk is too high for this trade",
|
"Risk is too high for this trade",
|
||||||
"ab not enough for new order",
|
"ab not enough for new order",
|
||||||
"InvalidRequestError",
|
"InvalidRequestError",
|
||||||
|
"The number of contracts exceeds maximum limit allowed"
|
||||||
}
|
}
|
||||||
else None
|
else None
|
||||||
)
|
)
|
||||||
@@ -320,8 +323,8 @@ async def open_positions(
|
|||||||
po_position_idx = 1 if side == "Buy" else 2
|
po_position_idx = 1 if side == "Buy" else 2
|
||||||
if margin_type == "ISOLATED_MARGIN":
|
if margin_type == "ISOLATED_MARGIN":
|
||||||
get_leverage = safe_float(
|
get_leverage = safe_float(
|
||||||
leverage_to_buy if side == "Buy" else leverage_to_sell
|
leverage_to_buy if side == "Buy" else leverage_to_sell
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
get_leverage = safe_float(leverage)
|
get_leverage = safe_float(leverage)
|
||||||
else:
|
else:
|
||||||
@@ -359,7 +362,6 @@ async def open_positions(
|
|||||||
tg_id=tg_id,
|
tg_id=tg_id,
|
||||||
entry_price=price_for_calc,
|
entry_price=price_for_calc,
|
||||||
symbol=symbol,
|
symbol=symbol,
|
||||||
order_quantity=order_quantity,
|
|
||||||
leverage=get_leverage,
|
leverage=get_leverage,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -388,7 +390,6 @@ async def open_positions(
|
|||||||
take_profit_price = max(take_profit_price, 0)
|
take_profit_price = max(take_profit_price, 0)
|
||||||
stop_loss_price = max(stop_loss_price, 0)
|
stop_loss_price = max(stop_loss_price, 0)
|
||||||
|
|
||||||
|
|
||||||
# Place order
|
# Place order
|
||||||
order_params = {
|
order_params = {
|
||||||
"category": "linear",
|
"category": "linear",
|
||||||
|
@@ -5,7 +5,6 @@ from aiogram.fsm.context import FSMContext
|
|||||||
from aiogram.types import CallbackQuery
|
from aiogram.types import CallbackQuery
|
||||||
|
|
||||||
import app.telegram.keyboards.inline as kbi
|
import app.telegram.keyboards.inline as kbi
|
||||||
|
|
||||||
from app.bybit.get_functions.get_positions import (
|
from app.bybit.get_functions.get_positions import (
|
||||||
get_active_orders,
|
get_active_orders,
|
||||||
get_active_orders_by_symbol,
|
get_active_orders_by_symbol,
|
||||||
@@ -22,7 +21,7 @@ router_get_positions_handlers = Router(name="get_positions_handlers")
|
|||||||
|
|
||||||
@router_get_positions_handlers.callback_query(F.data == "my_deals")
|
@router_get_positions_handlers.callback_query(F.data == "my_deals")
|
||||||
async def get_positions_handlers(
|
async def get_positions_handlers(
|
||||||
callback_query: CallbackQuery, state: FSMContext
|
callback_query: CallbackQuery, state: FSMContext
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Gets the user's active positions.
|
Gets the user's active positions.
|
||||||
@@ -43,7 +42,7 @@ async def get_positions_handlers(
|
|||||||
|
|
||||||
@router_get_positions_handlers.callback_query(F.data == "change_position")
|
@router_get_positions_handlers.callback_query(F.data == "change_position")
|
||||||
async def get_positions_handler(
|
async def get_positions_handler(
|
||||||
callback_query: CallbackQuery, state: FSMContext
|
callback_query: CallbackQuery, state: FSMContext
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Gets the user's active positions.
|
Gets the user's active positions.
|
||||||
@@ -70,11 +69,15 @@ async def get_positions_handler(
|
|||||||
await callback_query.answer(text="Нет активных позиций.")
|
await callback_query.answer(text="Нет активных позиций.")
|
||||||
return
|
return
|
||||||
|
|
||||||
active_symbols_sides = [(pos.get("symbol"), pos.get("side")) for pos in active_positions]
|
active_symbols_sides = [
|
||||||
|
(pos.get("symbol"), pos.get("side")) for pos in active_positions
|
||||||
|
]
|
||||||
|
|
||||||
await callback_query.message.edit_text(
|
await callback_query.message.edit_text(
|
||||||
text="Ваши активные позиции:",
|
text="Ваши активные позиции:",
|
||||||
reply_markup=kbi.create_active_positions_keyboard(symbols=active_symbols_sides),
|
reply_markup=kbi.create_active_positions_keyboard(
|
||||||
|
symbols=active_symbols_sides
|
||||||
|
),
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Error in get_positions_handler: %s", e)
|
logger.error("Error in get_positions_handler: %s", e)
|
||||||
@@ -113,7 +116,8 @@ async def get_position_handler(callback_query: CallbackQuery, state: FSMContext)
|
|||||||
size = position.get("size") or "Нет данных"
|
size = position.get("size") or "Нет данных"
|
||||||
take_profit = position.get("takeProfit") or "Нет данных"
|
take_profit = position.get("takeProfit") or "Нет данных"
|
||||||
stop_loss = position.get("stopLoss") or "Нет данных"
|
stop_loss = position.get("stopLoss") or "Нет данных"
|
||||||
position_idx = position.get("positionIdx")
|
position_idx = position.get("positionIdx") or "Нет данных"
|
||||||
|
liq_price = position.get("liqPrice") or "Нет данных"
|
||||||
else:
|
else:
|
||||||
side = "Нет данных"
|
side = "Нет данных"
|
||||||
symbol = "Нет данных"
|
symbol = "Нет данных"
|
||||||
@@ -122,6 +126,7 @@ async def get_position_handler(callback_query: CallbackQuery, state: FSMContext)
|
|||||||
take_profit = "Нет данных"
|
take_profit = "Нет данных"
|
||||||
stop_loss = "Нет данных"
|
stop_loss = "Нет данных"
|
||||||
position_idx = "Нет данных"
|
position_idx = "Нет данных"
|
||||||
|
liq_price = "Нет данных"
|
||||||
|
|
||||||
side_rus = (
|
side_rus = (
|
||||||
"Покупка"
|
"Покупка"
|
||||||
@@ -129,23 +134,42 @@ async def get_position_handler(callback_query: CallbackQuery, state: FSMContext)
|
|||||||
else "Продажа" if side == "Sell" else "Нет данных"
|
else "Продажа" if side == "Sell" else "Нет данных"
|
||||||
)
|
)
|
||||||
|
|
||||||
position_idx_rus = ("Односторонний" if position_idx == 0
|
position_idx_rus = (
|
||||||
else "Покупка в режиме хеджирования" if position_idx == 1
|
"Односторонний"
|
||||||
else "Продажа в режиме хеджирования" if position_idx == 2
|
if position_idx == 0
|
||||||
else "Нет данных")
|
else (
|
||||||
|
"Покупка в режиме хеджирования"
|
||||||
|
if position_idx == 1
|
||||||
|
else (
|
||||||
|
"Продажа в режиме хеджирования"
|
||||||
|
if position_idx == 2
|
||||||
|
else "Нет данных"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
text_lines = [
|
||||||
|
f"Торговая пара: {symbol}",
|
||||||
|
f"Режим позиции: {position_idx_rus}",
|
||||||
|
f"Цена входа: {avg_price}",
|
||||||
|
f"Количество: {size}",
|
||||||
|
f"Движение: {side_rus}",
|
||||||
|
]
|
||||||
|
|
||||||
|
if take_profit and take_profit != "Нет данных":
|
||||||
|
text_lines.append(f"Тейк-профит: {take_profit}")
|
||||||
|
if stop_loss and stop_loss != "Нет данных":
|
||||||
|
text_lines.append(f"Стоп-лосс: {stop_loss}")
|
||||||
|
if liq_price and liq_price != "Нет данных":
|
||||||
|
text_lines.append(f"Цена ликвидации: {liq_price}")
|
||||||
|
|
||||||
|
text = "\n".join(text_lines)
|
||||||
|
|
||||||
await callback_query.message.edit_text(
|
await callback_query.message.edit_text(
|
||||||
text=f"Торговая пара: {symbol}\n"
|
text=text,
|
||||||
f"Режим позиции: {position_idx_rus}\n"
|
reply_markup=kbi.make_close_position_keyboard(
|
||||||
f"Цена входа: {avg_price}\n"
|
symbol_pos=symbol, side=side, position_idx=position_idx, qty=size
|
||||||
f"Количество: {size}\n"
|
),
|
||||||
f"Движение: {side_rus}\n"
|
|
||||||
f"Тейк-профит: {take_profit}\n"
|
|
||||||
f"Стоп-лосс: {stop_loss}\n",
|
|
||||||
reply_markup=kbi.make_close_position_keyboard(symbol_pos=symbol,
|
|
||||||
side=side,
|
|
||||||
position_idx=position_idx,
|
|
||||||
qty=size),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -159,7 +183,7 @@ async def get_position_handler(callback_query: CallbackQuery, state: FSMContext)
|
|||||||
|
|
||||||
@router_get_positions_handlers.callback_query(F.data == "open_orders")
|
@router_get_positions_handlers.callback_query(F.data == "open_orders")
|
||||||
async def get_open_orders_handler(
|
async def get_open_orders_handler(
|
||||||
callback_query: CallbackQuery, state: FSMContext
|
callback_query: CallbackQuery, state: FSMContext
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Gets the user's open orders.
|
Gets the user's open orders.
|
||||||
@@ -186,7 +210,9 @@ async def get_open_orders_handler(
|
|||||||
await callback_query.answer(text="Нет активных ордеров.")
|
await callback_query.answer(text="Нет активных ордеров.")
|
||||||
return
|
return
|
||||||
|
|
||||||
active_orders_sides = [(pos.get("symbol"), pos.get("side")) for pos in active_positions]
|
active_orders_sides = [
|
||||||
|
(pos.get("symbol"), pos.get("side")) for pos in active_positions
|
||||||
|
]
|
||||||
|
|
||||||
await callback_query.message.edit_text(
|
await callback_query.message.edit_text(
|
||||||
text="Ваши активные ордера:",
|
text="Ваши активные ордера:",
|
||||||
@@ -222,13 +248,13 @@ async def get_order_handler(callback_query: CallbackQuery, state: FSMContext):
|
|||||||
|
|
||||||
if orders:
|
if orders:
|
||||||
side = orders.get("side")
|
side = orders.get("side")
|
||||||
symbol = orders.get("symbol") or "Нет данных"
|
symbol = orders.get("symbol")
|
||||||
price = orders.get("price") or "Нет данных"
|
price = orders.get("price")
|
||||||
qty = orders.get("qty") or "Нет данных"
|
qty = orders.get("qty")
|
||||||
order_type = orders.get("orderType") or ""
|
order_type = orders.get("orderType")
|
||||||
trigger_price = orders.get("triggerPrice") or "Нет данных"
|
trigger_price = orders.get("triggerPrice")
|
||||||
take_profit = orders.get("takeProfit") or "Нет данных"
|
take_profit = orders.get("takeProfit")
|
||||||
stop_loss = orders.get("stopLoss") or "Нет данных"
|
stop_loss = orders.get("stopLoss")
|
||||||
order_id = orders.get("orderId")
|
order_id = orders.get("orderId")
|
||||||
else:
|
else:
|
||||||
side = "Нет данных"
|
side = "Нет данных"
|
||||||
@@ -253,16 +279,31 @@ async def get_order_handler(callback_query: CallbackQuery, state: FSMContext):
|
|||||||
else "Лимитный" if order_type == "Limit" else "Нет данных"
|
else "Лимитный" if order_type == "Limit" else "Нет данных"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
text_lines = [
|
||||||
|
f"Торговая пара: {symbol}",
|
||||||
|
f"Количество: {qty}",
|
||||||
|
f"Движение: {side_rus}",
|
||||||
|
f"Тип ордера: {order_type_rus}",
|
||||||
|
]
|
||||||
|
if price:
|
||||||
|
text_lines.append(f"Цена: {price}")
|
||||||
|
|
||||||
|
if trigger_price and trigger_price != "Нет данных":
|
||||||
|
text_lines.append(f"Триггер цена: {trigger_price}")
|
||||||
|
|
||||||
|
if take_profit and take_profit != "Нет данных":
|
||||||
|
text_lines.append(f"Тейк-профит: {take_profit}")
|
||||||
|
|
||||||
|
if stop_loss and stop_loss != "Нет данных":
|
||||||
|
text_lines.append(f"Стоп-лосс: {stop_loss}")
|
||||||
|
|
||||||
|
text = "\n".join(text_lines)
|
||||||
|
|
||||||
await callback_query.message.edit_text(
|
await callback_query.message.edit_text(
|
||||||
text=f"Торговая пара: {symbol}\n"
|
text=text,
|
||||||
f"Цена: {price}\n"
|
reply_markup=kbi.make_close_orders_keyboard(
|
||||||
f"Количество: {qty}\n"
|
symbol_order=symbol, order_id=order_id
|
||||||
f"Движение: {side_rus}\n"
|
),
|
||||||
f"Тип ордера: {order_type_rus}\n"
|
|
||||||
f"Триггер цена: {trigger_price}\n"
|
|
||||||
f"Тейк-профит: {take_profit}\n"
|
|
||||||
f"Стоп-лосс: {stop_loss}\n",
|
|
||||||
reply_markup=kbi.make_close_orders_keyboard(symbol_order=symbol, order_id=order_id),
|
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Error in get_order_handler: %s", e)
|
logger.error("Error in get_order_handler: %s", e)
|
||||||
|
@@ -162,17 +162,18 @@ async def start_trading_long(callback_query: CallbackQuery, state: FSMContext) -
|
|||||||
"Order does not meet minimum order value": "Сумма ордера не достаточна для запуска торговли",
|
"Order does not meet minimum order value": "Сумма ордера не достаточна для запуска торговли",
|
||||||
"position idx not match position mode": "Торговля уже запущена в режиме хеджирования на продажу для данного инструмента",
|
"position idx not match position mode": "Торговля уже запущена в режиме хеджирования на продажу для данного инструмента",
|
||||||
"Qty invalid": "Некорректное значение ордера для данного инструмента",
|
"Qty invalid": "Некорректное значение ордера для данного инструмента",
|
||||||
|
"The number of contracts exceeds maximum limit allowed": "️️Количество контрактов превышает допустимое максимальное количество контрактов",
|
||||||
}
|
}
|
||||||
|
|
||||||
if res == "OK":
|
if res == "OK":
|
||||||
await callback_query.answer(text="Торговля запущена")
|
await callback_query.message.edit_text(text="Торговля запущена")
|
||||||
await state.clear()
|
await state.clear()
|
||||||
else:
|
else:
|
||||||
await rq.set_auto_trading(
|
await rq.set_auto_trading(
|
||||||
tg_id=callback_query.from_user.id, symbol=symbol, auto_trading=False, side=side
|
tg_id=callback_query.from_user.id, symbol=symbol, auto_trading=False, side=side
|
||||||
)
|
)
|
||||||
text = error_messages.get(res, "Произошла ошибка при запуске торговли")
|
text = error_messages.get(res, "Произошла ошибка при запуске торговли")
|
||||||
await callback_query.answer(text=text)
|
await callback_query.message.edit_text(text=text, reply_markup=kbi.profile_bybit)
|
||||||
|
|
||||||
await callback_query.message.edit_text("Запуск торговли...")
|
await callback_query.message.edit_text("Запуск торговли...")
|
||||||
task = asyncio.create_task(delay_start())
|
task = asyncio.create_task(delay_start())
|
||||||
@@ -299,6 +300,11 @@ async def start_switch(callback_query: CallbackQuery, state: FSMContext) -> None
|
|||||||
await rq.set_auto_trading(
|
await rq.set_auto_trading(
|
||||||
tg_id=callback_query.from_user.id, symbol=symbol, auto_trading=True, side=side
|
tg_id=callback_query.from_user.id, symbol=symbol, auto_trading=True, side=side
|
||||||
)
|
)
|
||||||
|
if side == "Buy":
|
||||||
|
r_side = "Sell"
|
||||||
|
else:
|
||||||
|
r_side = "Buy"
|
||||||
|
await rq.set_auto_trading(tg_id=callback_query.from_user.id, symbol=symbol, auto_trading=True, side=r_side)
|
||||||
res = await start_trading_cycle(
|
res = await start_trading_cycle(
|
||||||
tg_id=callback_query.from_user.id,
|
tg_id=callback_query.from_user.id,
|
||||||
side=side,
|
side=side,
|
||||||
@@ -315,17 +321,24 @@ async def start_switch(callback_query: CallbackQuery, state: FSMContext) -> None
|
|||||||
"Order does not meet minimum order value": "Сумма ордера не достаточна для запуска торговли",
|
"Order does not meet minimum order value": "Сумма ордера не достаточна для запуска торговли",
|
||||||
"position idx not match position mode": "Торговля уже запущена в режиме хеджирования на продажу для данного инструмента",
|
"position idx not match position mode": "Торговля уже запущена в режиме хеджирования на продажу для данного инструмента",
|
||||||
"Qty invalid": "Некорректное значение ордера для данного инструмента",
|
"Qty invalid": "Некорректное значение ордера для данного инструмента",
|
||||||
|
"The number of contracts exceeds maximum limit allowed": "️ ️️Количество контрактов превышает допустимое максимальное количество контрактов",
|
||||||
}
|
}
|
||||||
|
|
||||||
if res == "OK":
|
if res == "OK":
|
||||||
await callback_query.answer(text="Торговля запущена")
|
await callback_query.message.edit_text(text="Торговля запущена")
|
||||||
await state.clear()
|
await state.clear()
|
||||||
else:
|
else:
|
||||||
await rq.set_auto_trading(
|
await rq.set_auto_trading(
|
||||||
tg_id=callback_query.from_user.id, symbol=symbol, auto_trading=False, side=side
|
tg_id=callback_query.from_user.id, symbol=symbol, auto_trading=False, side=side
|
||||||
)
|
)
|
||||||
|
if side == "Buy":
|
||||||
|
r_side = "Sell"
|
||||||
|
else:
|
||||||
|
r_side = "Buy"
|
||||||
|
await rq.set_auto_trading(tg_id=callback_query.from_user.id, symbol=symbol, auto_trading=False,
|
||||||
|
side=r_side)
|
||||||
text = error_messages.get(res, "Произошла ошибка при запуске торговли")
|
text = error_messages.get(res, "Произошла ошибка при запуске торговли")
|
||||||
await callback_query.answer(text=text)
|
await callback_query.message.edit_text(text=text, reply_markup=kbi.profile_bybit)
|
||||||
|
|
||||||
await callback_query.message.edit_text("Запуск торговли...")
|
await callback_query.message.edit_text("Запуск торговли...")
|
||||||
task = asyncio.create_task(delay_start())
|
task = asyncio.create_task(delay_start())
|
||||||
|
@@ -37,21 +37,32 @@ async def stop_all_trading(callback_query: CallbackQuery, state: FSMContext):
|
|||||||
await rq.set_stop_timer(tg_id=callback_query.from_user.id, timer_end=0)
|
await rq.set_stop_timer(tg_id=callback_query.from_user.id, timer_end=0)
|
||||||
await asyncio.sleep(timer_end * 60)
|
await asyncio.sleep(timer_end * 60)
|
||||||
|
|
||||||
user_auto_trading_list = await rq.get_all_user_auto_trading(tg_id=callback_query.from_user.id)
|
user_auto_trading_list = await rq.get_all_user_auto_trading(
|
||||||
|
tg_id=callback_query.from_user.id
|
||||||
|
)
|
||||||
|
|
||||||
for active_auto_trading in user_auto_trading_list:
|
if any(item.auto_trading for item in user_auto_trading_list):
|
||||||
if active_auto_trading.auto_trading:
|
for active_auto_trading in user_auto_trading_list:
|
||||||
symbol = active_auto_trading.symbol
|
if active_auto_trading.auto_trading:
|
||||||
get_side = active_auto_trading.side
|
symbol = active_auto_trading.symbol
|
||||||
req = await rq.set_auto_trading(
|
get_side = active_auto_trading.side
|
||||||
tg_id=callback_query.from_user.id, symbol=symbol, auto_trading=False, side=get_side
|
req = await rq.set_auto_trading(
|
||||||
)
|
tg_id=callback_query.from_user.id,
|
||||||
if not req:
|
symbol=symbol,
|
||||||
await callback_query.edit_text(text="Произошла ошибка при остановке торговли",
|
auto_trading=False,
|
||||||
reply_markup=kbi.profile_bybit)
|
side=get_side,
|
||||||
return
|
)
|
||||||
|
if not req:
|
||||||
await callback_query.message.edit_text(text="Торговля остановлена", reply_markup=kbi.profile_bybit)
|
await callback_query.message.edit_text(
|
||||||
|
text="Произошла ошибка при остановке торговли",
|
||||||
|
reply_markup=kbi.profile_bybit,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
await callback_query.message.edit_text(
|
||||||
|
text="Торговля остановлена", reply_markup=kbi.profile_bybit
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await callback_query.message.edit_text(text="Нет активной торговли")
|
||||||
|
|
||||||
task = asyncio.create_task(delay_start())
|
task = asyncio.create_task(delay_start())
|
||||||
await add_stop_task(user_id=callback_query.from_user.id, task=task)
|
await add_stop_task(user_id=callback_query.from_user.id, task=task)
|
||||||
@@ -74,11 +85,15 @@ async def cancel_stop_trading(callback_query: CallbackQuery, state: FSMContext):
|
|||||||
try:
|
try:
|
||||||
await state.clear()
|
await state.clear()
|
||||||
cancel_stop_task(callback_query.from_user.id)
|
cancel_stop_task(callback_query.from_user.id)
|
||||||
await callback_query.message.edit_text(text="Таймер отменён.", reply_markup=kbi.profile_bybit)
|
await callback_query.message.edit_text(
|
||||||
|
text="Таймер отменён.", reply_markup=kbi.profile_bybit
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await callback_query.answer(text="Произошла ошибка при отмене остановки торговли")
|
await callback_query.answer(
|
||||||
|
text="Произошла ошибка при отмене остановки торговли"
|
||||||
|
)
|
||||||
logger.error(
|
logger.error(
|
||||||
"Error processing command cancel_timer_stop for user %s: %s",
|
"Error processing command cancel_timer_stop for user %s: %s",
|
||||||
callback_query.from_user.id,
|
callback_query.from_user.id,
|
||||||
e,
|
e,
|
||||||
)
|
)
|
||||||
|
Reference in New Issue
Block a user