150 lines
6.6 KiB
Python
150 lines
6.6 KiB
Python
import asyncio
|
||
import logging.config
|
||
|
||
from aiogram import F, Router
|
||
from aiogram.fsm.context import FSMContext
|
||
from aiogram.types import CallbackQuery
|
||
|
||
import app.telegram.keyboards.inline as kbi
|
||
import database.request as rq
|
||
from app.bybit.get_functions.get_positions import get_active_positions_by_symbol
|
||
from app.bybit.open_positions import start_trading_cycle
|
||
from app.helper_functions import safe_float
|
||
from app.telegram.tasks.tasks import (
|
||
add_start_task_merged,
|
||
cancel_start_task_merged
|
||
)
|
||
from logger_helper.logger_helper import LOGGING_CONFIG
|
||
|
||
logging.config.dictConfig(LOGGING_CONFIG)
|
||
logger = logging.getLogger("start_trading")
|
||
|
||
router_start_trading = Router(name="start_trading")
|
||
|
||
|
||
@router_start_trading.callback_query(F.data == "start_trading")
|
||
async def start_trading(callback_query: CallbackQuery, state: FSMContext) -> None:
|
||
"""
|
||
Handles the "start_trading" callback query.
|
||
Clears the FSM state and sends a message to the user to select the trading mode.
|
||
:param callback_query: Message
|
||
:param state: FSMContext
|
||
:return: None
|
||
"""
|
||
try:
|
||
await state.clear()
|
||
symbol = await rq.get_user_symbol(tg_id=callback_query.from_user.id)
|
||
deals = await get_active_positions_by_symbol(
|
||
tg_id=callback_query.from_user.id, symbol=symbol
|
||
)
|
||
position = next((d for d in deals if d.get("symbol") == symbol), None)
|
||
|
||
if position:
|
||
size = position.get("size", 0)
|
||
else:
|
||
size = 0
|
||
|
||
if safe_float(size) > 0:
|
||
await callback_query.answer(
|
||
text="У вас есть активная позиция",
|
||
)
|
||
return
|
||
|
||
conditional_data = await rq.get_user_conditional_settings(
|
||
tg_id=callback_query.from_user.id
|
||
)
|
||
timer_start = conditional_data.timer_start
|
||
|
||
cancel_start_task_merged(user_id=callback_query.from_user.id)
|
||
|
||
async def delay_start():
|
||
if timer_start > 0:
|
||
await callback_query.message.edit_text(
|
||
text=f"Торговля будет запущена с задержкой {timer_start} мин.",
|
||
reply_markup=kbi.cancel_timer_merged,
|
||
)
|
||
await rq.set_start_timer(
|
||
tg_id=callback_query.from_user.id, timer_start=0
|
||
)
|
||
await asyncio.sleep(timer_start * 60)
|
||
|
||
await rq.set_auto_trading(
|
||
tg_id=callback_query.from_user.id,
|
||
symbol=symbol,
|
||
auto_trading=True,
|
||
)
|
||
res = await start_trading_cycle(
|
||
tg_id=callback_query.from_user.id,
|
||
)
|
||
|
||
error_messages = {
|
||
"Limit price is out min price": "Цена лимитного ордера меньше минимального",
|
||
"Limit price is out max price": "Цена лимитного ордера больше максимального",
|
||
"Risk is too high for this trade": "Риск сделки превышает допустимый убыток",
|
||
"estimated will trigger liq": "Лимитный ордер может вызвать мгновенную ликвидацию. Проверьте параметры ордера.",
|
||
"ab not enough for new order": "Недостаточно средств для создания нового ордера",
|
||
"InvalidRequestError": "Произошла ошибка при запуске торговли.",
|
||
"Order does not meet minimum order value": "Сумма ордера не достаточна для запуска торговли",
|
||
"position idx not match position mode": "Ошибка режима позиции для данного инструмента",
|
||
"Qty invalid": "Некорректное значение ордера для данного инструмента",
|
||
"The number of contracts exceeds maximum limit allowed": "️️Количество контрактов превышает допустимое максимальное количество контрактов",
|
||
"The number of contracts exceeds minimum limit allowed": "️️Количество контрактов превышает допустимое минимальное количество контрактов",
|
||
}
|
||
|
||
if res == "OK":
|
||
await callback_query.message.edit_text(text="Торговля запущена")
|
||
await state.clear()
|
||
else:
|
||
await rq.set_auto_trading(
|
||
tg_id=callback_query.from_user.id,
|
||
symbol=symbol,
|
||
auto_trading=False,
|
||
)
|
||
text = error_messages.get(res, "Произошла ошибка при запуске торговли")
|
||
await callback_query.message.edit_text(
|
||
text=text, reply_markup=kbi.profile_bybit
|
||
)
|
||
|
||
await callback_query.message.edit_text("Запуск торговли...")
|
||
task = asyncio.create_task(delay_start())
|
||
await add_start_task_merged(user_id=callback_query.from_user.id, task=task)
|
||
|
||
except Exception as e:
|
||
await callback_query.answer(text="Произошла ошибка при запуске торговли")
|
||
logger.error(
|
||
"Error processing command long for user %s: %s",
|
||
callback_query.from_user.id,
|
||
e,
|
||
)
|
||
except asyncio.CancelledError:
|
||
logger.error("Cancelled timer for user %s", callback_query.from_user.id)
|
||
|
||
|
||
@router_start_trading.callback_query(
|
||
lambda c: c.data == "cancel_timer_merged"
|
||
)
|
||
async def cancel_start_trading(
|
||
callback_query: CallbackQuery, state: FSMContext
|
||
) -> None:
|
||
"""
|
||
Handles the "cancel_timer" callback query.
|
||
Clears the FSM state and sends a message to the user to cancel the start trading process.
|
||
:param callback_query: Message
|
||
:param state: FSMContext
|
||
:return: None
|
||
"""
|
||
try:
|
||
await state.clear()
|
||
if callback_query.data == "cancel_timer_merged":
|
||
cancel_start_task_merged(user_id=callback_query.from_user.id)
|
||
await callback_query.message.edit_text(
|
||
text="Запуск торговли отменен", reply_markup=kbi.profile_bybit
|
||
)
|
||
except Exception as e:
|
||
await callback_query.answer("Произошла ошибка при отмене запуска торговли")
|
||
logger.error(
|
||
"Error processing command cancel_timer for user %s: %s",
|
||
callback_query.from_user.id,
|
||
e,
|
||
)
|