from aiogram import F, Router from app.services.Bybit.functions import Futures, func_min_qty from app.services.Bybit.functions.Futures import open_market_order, open_limit_order from app.services.Bybit.functions.balance import get_balance import app.telegram.Keyboards.inline_keyboards as inline_markup import app.telegram.database.requests as rq from aiogram.types import Message, CallbackQuery # FSM - Механизм состояния from aiogram.fsm.state import State, StatesGroup from aiogram.fsm.context import FSMContext router_functions_bybit_trade = Router() class state_update_symbol(StatesGroup): symbol = State() class state_update_entry_type(StatesGroup): entry_type = State() @router_functions_bybit_trade.callback_query(F.data.in_(['clb_start_trading', 'clb_back_to_main'])) async def clb_start_bybit_trade_message(callback: CallbackQuery, state: FSMContext): api = await rq.get_bybit_api_key(callback.from_user.id) secret = await rq.get_bybit_secret_key(callback.from_user.id) balance = await get_balance(callback.from_user.id, callback.message) if balance: symbol = await rq.get_symbol(callback.from_user.id) text = f'''💎 Торговля на Bybit ⚖️ Ваш баланс (USDT): {balance} 📊 Текущая торговая пара: {symbol} Как начать торговлю? 1️⃣ Проверьте и тщательно настройте все параметры в вашем профиле. 2️⃣ Нажмите ниже кнопку 'Указать торговую пару' и введите торговую пару заглавными буквами, без лишних символов (например: BTCUSDT). ''' await callback.message.edit_text(text=text, parse_mode='html', reply_markup=inline_markup.trading_markup) async def start_bybit_trade_message(message, state): api = await rq.get_bybit_api_key(message.from_user.id) secret = await rq.get_bybit_secret_key(message.from_user.id) balance = await get_balance(message.from_user.id, message) if balance: symbol = await rq.get_symbol(message.from_user.id) text = f'''💎 Торговля на Bybit ⚖️ Ваш баланс (USDT): {balance} 📊 Текущая торговая пара: {symbol} Как начать торговлю? 1️⃣ Проверьте и тщательно настройте все параметры в вашем профиле. 2️⃣ Нажмите ниже кнопку 'Указать торговую пару' и введите торговую пару заглавными буквами, без лишних символов (например: BTCUSDT). ''' await message.answer(text=text, parse_mode='html', reply_markup=inline_markup.trading_markup) @router_functions_bybit_trade.callback_query(F.data == 'clb_update_trading_pair') async def update_symbol_for_trade_message(callback: CallbackQuery, state: FSMContext): await state.set_state(state_update_symbol.symbol) await callback.message.answer(text='Укажите торговую пару заглавными буквами без пробелов и лишних символов (пример: BTCUSDT): ') @router_functions_bybit_trade.message(state_update_symbol.symbol) async def update_symbol_for_trade(message: Message, state: FSMContext): await state.update_data(symbol = message.text) data = await state.get_data() await message.answer('Пара была успешно обновлена') await rq.update_symbol(message.from_user.id, data['symbol']) await start_bybit_trade_message(message, state) await state.clear() @router_functions_bybit_trade.callback_query(F.data == 'clb_update_entry_type') async def update_entry_type_message(callback: CallbackQuery, state: FSMContext): await state.set_state(state_update_entry_type.entry_type) await callback.message.answer("Выберите тип входа в позицию:", reply_markup=inline_markup.entry_order_type_markup) await callback.answer() @router_functions_bybit_trade.callback_query(lambda c: c.data and c.data.startswith('entry_order_type:')) async def entry_order_type_callback(callback: CallbackQuery, state: FSMContext): order_type = callback.data.split(':')[1] if order_type not in ['Market', 'Limit']: await callback.answer("Ошибка выбора", show_alert=True) return await state.update_data(entry_order_type=order_type) await rq.update_entry_order_type(callback.from_user.id, order_type) if order_type == 'Limit': await callback.answer("Вы выбрали Limit. Введите цену для лимитного ордера.") await callback.message.answer("Введите цену лимитного ордера:") await state.update_data(awaiting_limit_price=True) else: await callback.answer("Вы выбрали Market. Нажмите кнопку ниже, чтобы открыть сделку.") await callback.message.answer("Нажмите кнопку, чтобы открыть сделку.", reply_markup=inline_markup.open_deal_markup) await callback.message.delete() @router_functions_bybit_trade.message() async def process_limit_price_message(message: Message, state: FSMContext): data = await state.get_data() if not data.get('awaiting_limit_price'): return try: price = float(message.text) if price <= 0: raise ValueError() except ValueError: await message.answer("Ошибка: введите корректное положительное число для цены.") return await state.update_data(limit_price=price, awaiting_limit_price=False) await message.answer(f"Цена лимитного ордера установлена: {price}. Нажмите кнопку ниже, чтобы открыть сделку.", reply_markup=inline_markup.open_deal_markup) @router_functions_bybit_trade.callback_query(F.data == "clb_open_deal") async def open_deal(callback: CallbackQuery, state: FSMContext): data_main_stgs = await rq.get_user_main_settings(callback.from_user.id) data = await state.get_data() order_type = await rq.get_entry_order_type(callback.from_user.id) api = await rq.get_bybit_api_key(callback.from_user.id) secret = await rq.get_bybit_secret_key(callback.from_user.id) qty = data_main_stgs['starting_quantity'] qty_min = await func_min_qty.get_min_qty(callback.from_user.id, callback.message) if qty < qty_min: await callback.message.edit_text(f"Количество вашей ставки ({qty}) меньше минимального количества ({qty_min}) для данной торговой пары") await callback.answer() return if order_type == 'Market': await open_market_order(callback.from_user.id, callback.message, api_key=api, secret_key=secret) await rq.update_user_trades(callback.from_user.id, symbol=data.get('symbol'), side=order_type) elif order_type == 'Limit': price = data.get('limit_price') if not price: await callback.answer("Цена для лимитного ордера не задана. Введите сначала цену.") return await open_limit_order(callback.from_user.id, callback.message, price, api_key=api, secret_key=secret) else: await callback.answer("Неизвестный тип ордера.") await callback.message.edit_reply_markup() await state.clear() @router_functions_bybit_trade.callback_query(F.data == "clb_my_deals") async def show_my_trades_callback(callback: CallbackQuery): tg_id = callback.from_user.id trades = await rq.get_user_trades(tg_id) if not trades: await callback.message.answer("У вас ещё нет сделок.") await callback.answer() return grouped = {} for trade in trades: symbol = trade['symbol'] if isinstance(trade, dict) else trade.symbol grouped.setdefault(symbol, []).append(trade) text_response = "Ваши сделки по валютным парам:\n\n" for symbol, trade_list in grouped.items(): text_response += f"{symbol}\n" for t in trade_list: side = t['side'] if isinstance(t, dict) else t.side text_response += f" - {side}\n" text_response += "\n" await callback.message.answer(text_response, parse_mode='html') await callback.answer() # @router_functions_bybit_trade.callback_query(F.data == 'clb_open_deal') # async def make_deal_bybit (callback: CallbackQuery): # data_main_stgs = await rq.get_user_main_settings(callback.from_user.id) # # trade_mode = data_main_stgs['trading_mode'] # qty = data_main_stgs['starting_quantity'] # margin_mode = data_main_stgs['margin_type'] qty_min = await func_min_qty.get_min_qty(callback.from_user.id, callback.message) # # if qty < qty_min: # await callback.message.edit_text(f"Количество вашей ставки ({qty}) меньше минимального количества ({qty_min}) для данной торговой пары") # else: # match trade_mode: # case 'Long': # await Futures.contract_long(callback.from_user.id, callback.message, margin_mode) # case 'Short': # await Futures.contract_short(callback.from_user.id, callback.message, margin_mode) # case 'Switch': # await callback.message.edit_text('Режим Switch пока недоступен') # case 'Smart': # await callback.message.edit_text('Режим Smart пока недоступен')