1
0
forked from kodorvan/stcs

Compare commits

...

2 Commits

Author SHA1 Message Date
algizn97
704249d0af Fixed and updated tasks 2025-08-27 14:28:53 +05:00
algizn97
bf44b481e9 Added new handlers for tasks 2025-08-27 14:28:23 +05:00
4 changed files with 120 additions and 21 deletions

View File

@@ -98,7 +98,7 @@ async def handle_execution_message(message, msg: dict) -> None:
Обработчик сообщений об исполнении сделки. Обработчик сообщений об исполнении сделки.
Логирует событие и проверяет условия для мартингейла и TP. Логирует событие и проверяет условия для мартингейла и TP.
""" """
logger.info(f"Исполнена сделка:\n{json.dumps(msg, indent=4, ensure_ascii=False)}") # logger.info(f"Исполнена сделка:\n{json.dumps(msg, indent=4, ensure_ascii=False)}")
pnl = parse_pnl_from_msg(msg) pnl = parse_pnl_from_msg(msg)
tg_id = message.from_user.id tg_id = message.from_user.id

View File

@@ -1,4 +1,5 @@
import logging.config import asyncio
import logging.config
from aiogram import F, Router from aiogram import F, Router
from app.tasks.tasks import handle_stop_close_trade, handle_start_close_trade, handle_stop_trading, handle_start_trading from app.tasks.tasks import handle_stop_close_trade, handle_start_close_trade, handle_stop_trading, handle_start_trading
@@ -246,12 +247,12 @@ async def start_trading_process(callback: CallbackQuery) -> None:
timer_minute = timer_data or 0 timer_minute = timer_data or 0
if timer_minute > 0: if timer_minute > 0:
await handle_start_trading(tg_id, message) await handle_start_trading(tg_id, message, side=side, margin_mode=margin_mode, use_timer=True)
await message.answer(f"Торговля начнётся через {timer_minute} мин. Для отмены нажмите кнопку ниже.", await message.answer(f"Торговля начнётся через {timer_minute} мин. Для отмены нажмите кнопку ниже.",
reply_markup=inline_markup.cancel_start_markup) reply_markup=inline_markup.cancel_start_markup)
await rq.update_user_timer(tg_id, minutes=0) await rq.update_user_timer(tg_id, minutes=0)
else: else:
await open_position(tg_id, message, side=side, margin_mode=margin_mode) await handle_start_trading(tg_id, message, side=side, margin_mode=margin_mode, use_timer=False)
await callback.answer() await callback.answer()
@@ -443,6 +444,67 @@ async def reset_martingale(callback: CallbackQuery) -> None:
await callback.answer("Сброс шагов выполнен.") await callback.answer("Сброс шагов выполнен.")
@router_functions_bybit_trade.callback_query(F.data == "clb_stop_trading")
async def confirm_stop_trading(callback: CallbackQuery):
"""
Предлагает пользователю выбрать вариант подтверждение остановки торговли.
"""
await callback.message.answer(
"Выберите вариант остановки торговли:", reply_markup=inline_markup.stop_choice_markup
)
await callback.answer()
@router_functions_bybit_trade.callback_query(F.data == "stop_immediately")
async def stop_immediately(callback: CallbackQuery):
"""
Останавливает торговлю немедленно.
"""
tg_id = callback.from_user.id
await handle_stop_trading(tg_id, use_timer=False)
await callback.message.answer("Торговля остановлена.", reply_markup=inline_markup.back_to_main)
await callback.answer()
@router_functions_bybit_trade.callback_query(F.data == "stop_with_timer")
async def stop_with_timer_start(callback: CallbackQuery, state: FSMContext):
"""
Запускает диалог с пользователем для задания задержки перед остановкой торговли.
"""
await state.set_state(CloseTradeTimerState.waiting_for_delay)
await callback.message.answer("Введите задержку в минутах перед остановкой торговли:", reply_markup=inline_markup.cancel)
await callback.answer()
@router_functions_bybit_trade.message(CloseTradeTimerState.waiting_for_delay)
async def process_stop_delay(message: Message, state: FSMContext):
"""
Обрабатывает ввод задержки и запускает задачу остановки торговли с задержкой.
"""
try:
delay_minutes = int(message.text.strip())
if delay_minutes <= 0:
await message.answer("Введите положительное число минут.")
return
except ValueError:
await message.answer("Некорректный формат. Введите число в минутах.")
return
tg_id = message.from_user.id
delay_seconds = delay_minutes * 60
# Остановка задачи с таймером через заданную задержку
# Можно реализовать через запуск отдельной асинхронной задачи, которая через delay_seconds отменит торговый цикл
async def delayed_stop():
await asyncio.sleep(delay_seconds)
await handle_stop_trading(tg_id, use_timer=True)
await message.answer("Торговля по таймеру остановлена.")
asyncio.create_task(delayed_stop())
await message.answer(f"Торговля будет остановлена через {delay_minutes} минут.", reply_markup=inline_markup.back_to_main)
await state.clear()
@router_functions_bybit_trade.callback_query(F.data == "clb_cancel") @router_functions_bybit_trade.callback_query(F.data == "clb_cancel")
async def cancel(callback: CallbackQuery, state: FSMContext) -> None: async def cancel(callback: CallbackQuery, state: FSMContext) -> None:
""" """

View File

@@ -1,7 +1,7 @@
import asyncio import asyncio
import logging.config import logging.config
from typing import Optional from typing import Optional
from app.services.Bybit.functions.Futures import close_trade_after_delay, trading_cycle from app.services.Bybit.functions.Futures import close_trade_after_delay, trading_cycle, open_position
from logger_helper.logger_helper import LOGGING_CONFIG from logger_helper.logger_helper import LOGGING_CONFIG
logging.config.dictConfig(LOGGING_CONFIG) logging.config.dictConfig(LOGGING_CONFIG)
@@ -9,16 +9,17 @@ logger = logging.getLogger("tasks")
active_start_tasks = {} active_start_tasks = {}
active_close_tasks = {} active_close_tasks = {}
active_start_tasks_timer = {}
lock_start_tasks = asyncio.Lock() lock_start_tasks = asyncio.Lock()
lock_close_tasks = asyncio.Lock() lock_close_tasks = asyncio.Lock()
def start_trading_cycle(tg_id, message) -> None: def start_trading_cycle(tg_id, message, side: str, margin_mode: str, tpsl_mode='Full') -> None:
""" """
Запускает асинхронную задачу торгового цикла для пользователя с указанным tg_id. Запускает асинхронную задачу торгового цикла для пользователя с указанным tg_id.
""" """
task = asyncio.create_task(trading_cycle(tg_id, message)) task = asyncio.create_task(open_position(tg_id, message, side, margin_mode, tpsl_mode))
active_start_tasks[tg_id] = task active_start_tasks[tg_id] = task
@@ -31,6 +32,17 @@ def stop_trading_cycle(tg_id) -> None:
task.cancel() task.cancel()
def start_trading_for_timer(tg_id, message, side: str, margin_mode: str, tpsl_mode='Full') -> None:
# Старт с задержкой (trading_cycle)
task = asyncio.create_task(trading_cycle(tg_id, message))
active_start_tasks_timer[tg_id] = task
def stop_trading_for_timer(tg_id) -> None:
task: Optional[asyncio.Task] = active_start_tasks_timer.pop(tg_id, None)
if task:
task.cancel()
def start_close_trade_task(tg_id, message, symbol, delay_sec) -> None: def start_close_trade_task(tg_id, message, symbol, delay_sec) -> None:
""" """
Запускает асинхронную задачу автоматического закрытия сделки после задержки. Запускает асинхронную задачу автоматического закрытия сделки после задержки.
@@ -48,11 +60,22 @@ def stop_close_trade_task(tg_id) -> None:
task.cancel() task.cancel()
async def handle_start_trading(tg_id: int, message): async def handle_start_trading(tg_id: int, message, side: str, margin_mode: str, tpsl_mode='Full', use_timer=False):
""" """
Запускает торговый цикл. Если уже есть запущенная задача, отменяет её. Запускает торговый цикл. Если уже есть запущенная задача, отменяет её.
""" """
async with lock_start_tasks: async with lock_start_tasks:
if use_timer:
old_task = active_start_tasks_timer.get(tg_id)
if old_task and not old_task.done():
old_task.cancel()
try:
await old_task
except asyncio.CancelledError:
logger.info(f"Старая задача торговли с таймером для пользователя {tg_id} отменена")
start_trading_for_timer(tg_id, message, side, margin_mode, tpsl_mode)
logger.info(f"Новая задача торговли с таймером запущена для пользователя {tg_id}")
else:
old_task = active_start_tasks.get(tg_id) old_task = active_start_tasks.get(tg_id)
if old_task and not old_task.done(): if old_task and not old_task.done():
old_task.cancel() old_task.cancel()
@@ -60,15 +83,19 @@ async def handle_start_trading(tg_id: int, message):
await old_task await old_task
except asyncio.CancelledError: except asyncio.CancelledError:
logger.info(f"Старая задача торговли для пользователя {tg_id} отменена") logger.info(f"Старая задача торговли для пользователя {tg_id} отменена")
start_trading_cycle(tg_id, message) start_trading_cycle(tg_id, message, side, margin_mode, tpsl_mode)
logger.info(f"Новая задача торговли запущена для пользователя {tg_id}") logger.info(f"Новая задача торговли запущена для пользователя {tg_id}")
async def handle_stop_trading(tg_id: int): async def handle_stop_trading(tg_id: int, use_timer=False):
""" """
Останавливает торговую задачу пользователя, если она активна. Останавливает торговую задачу пользователя, если она активна.
""" """
async with lock_start_tasks: async with lock_start_tasks:
if use_timer:
stop_trading_for_timer(tg_id)
logger.info(f"Задача торговли с таймером остановлена для пользователя {tg_id}")
else:
stop_trading_cycle(tg_id) stop_trading_cycle(tg_id)
logger.info(f"Задача торговли остановлена для пользователя {tg_id}") logger.info(f"Задача торговли остановлена для пользователя {tg_id}")

View File

@@ -32,7 +32,8 @@ trading_markup = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text="Настройки", callback_data='clb_settings_message')], [InlineKeyboardButton(text="Настройки", callback_data='clb_settings_message')],
[InlineKeyboardButton(text="Мои сделки", callback_data='clb_my_deals')], [InlineKeyboardButton(text="Мои сделки", callback_data='clb_my_deals')],
[InlineKeyboardButton(text="Указать торговую пару", callback_data='clb_update_trading_pair')], [InlineKeyboardButton(text="Указать торговую пару", callback_data='clb_update_trading_pair')],
[InlineKeyboardButton(text="Выбрать тип входа", callback_data='clb_update_entry_type')], [InlineKeyboardButton(text="Начать торговлю", callback_data='clb_update_entry_type')],
[InlineKeyboardButton(text="Остановить торговлю", callback_data='clb_stop_trading')],
]) ])
start_trading_markup = InlineKeyboardMarkup(inline_keyboard=[ start_trading_markup = InlineKeyboardMarkup(inline_keyboard=[
@@ -184,3 +185,12 @@ timer_markup = InlineKeyboardMarkup(inline_keyboard=[
cancel_start_markup = InlineKeyboardMarkup(inline_keyboard=[ cancel_start_markup = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text="Отменить таймер", callback_data="clb_stop_timer")] [InlineKeyboardButton(text="Отменить таймер", callback_data="clb_stop_timer")]
]) ])
stop_choice_markup = InlineKeyboardMarkup(
inline_keyboard=[
[
InlineKeyboardButton(text="Остановить сразу", callback_data="stop_immediately"),
InlineKeyboardButton(text="Остановить по таймеру", callback_data="stop_with_timer"),
]
]
)