import time from typing import Optional from asyncio import Handle from annotated_types import T from pybit import exceptions from pybit.unified_trading import HTTP from pybit.unified_trading import WebSocket from app.services.Bybit.functions import price_symbol import app.services.Bybit.functions.balance as balance_g import app.telegram.database.requests as rq import logging logging.basicConfig(level=logging.DEBUG) def handle_message(message): print(message) async def info_access_open_deal(message, symbol, trade_mode, margin_mode, leverage, qty): match margin_mode: case 'ISOLATED_MARGIN': margin_mode = 'Isolated' case 'REGULAR_MARGIN': margin_mode = 'Cross' text = f'''Позиция была успешна открыта! Торговая пара: {symbol} Движение: {trade_mode} Тип-маржи: {margin_mode} Кредитное плечо: {leverage} Количество: {qty} ''' await message.answer(text=text, parse_mode='html') async def error_max_step(message): await message.answer('Сделка не была совершена, превышен лимит максимального количества ставок') async def error_max_risk(message): await message.answer('Сделка не была совершена, слишком высокий риск') async def contract_long(tg_id, message, margin_mode): api_key = await rq.get_bybit_api_key(tg_id) secret_key = await rq.get_bybit_secret_key(tg_id) SYMBOL = await rq.get_symbol(tg_id) data_main_stgs = await rq.get_user_main_settings(tg_id) data_risk_management_stgs = await rq.get_user_risk_management_settings(tg_id) match margin_mode: case 'Isolated': margin_mode = 'ISOLATED_MARGIN' case 'Cross': margin_mode = 'REGULAR_MARGIN' client = HTTP( api_key=api_key, api_secret=secret_key ) try: balance = 0 price = 0 balance = await balance_g.get_balance(tg_id) price = await price_symbol.get_price(tg_id, message) client.set_margin_mode( setMarginMode=margin_mode # margin_type ) martingale_factor = float(data_main_stgs['martingale_factor']) # Исправлено: было maximal_quantity max_martingale_steps = int(data_main_stgs['maximal_quantity']) starting_quantity = float(data_main_stgs['starting_quantity']) max_risk_percent = float(data_risk_management_stgs['max_risk_deal']) loss_profit = float(data_risk_management_stgs['price_loss']) takeprofit= float(data_risk_management_stgs['price_profit']) commission_fee = float(data_risk_management_stgs.get('commission_fee', 0)) takeProfit_raw = takeprofit takeProfit = takeProfit_raw - commission_fee # уменьшаем TP на комиссию if takeProfit < 0: takeProfit = 0 # Инициализация переменных next_quantity = starting_quantity last_quantity = starting_quantity realised_pnl = 0.0 current_martingale_step = 0 # Текущая ставка в серии next_quantity = 0 realised_pnl = 0 last_quantity = starting_quantity # Пример расчёта следующего размера позиции try: position_info = client.get_positions(category='linear', symbol=SYMBOL) position = position_info['result']['list'][0] # или другой нужный индекс realised_pnl = float(position['unrealisedPnl']) if realised_pnl > 0: starting_quantity = next_quantity current_martingale_step = 0 elif not realised_pnl: next_quantity = starting_quantity current_martingale_step += 1 else: current_martingale_step += 1 next_quantity = last_quantity * martingale_factor starting_quantity = next_quantity except Exception as e: print("Не получены позиции") next_quantity = starting_quantity potential_loss = (next_quantity * float(price)) * (loss_profit / 100) allowed_loss = float(balance) * (max_risk_percent / 100) if current_martingale_step >= max_martingale_steps: print("Достигнут максимум ставок в серии (8)!") print("Торговля не продолжится") await error_max_step(message) else: if potential_loss > allowed_loss: print(f"ОШИБКА: Риск превышен!") print(f"Ручной qty = {next_quantity} → Убыток = {potential_loss} USDT") print(f"Разрешено = {allowed_loss} USDT (1% от баланса)") await error_max_risk(message) else: print(f"Риск в допустимых пределах. Qty = {next_quantity}") r = client.place_order( category='linear', symbol=SYMBOL, side='Buy', orderType="Market", leverage=int(data_main_stgs['size_leverage']), qty=next_quantity, takeProfit=takeProfit, # TP - закрывает позицию, когда цена достигает нужного уровня stopProfit=float(data_risk_management_stgs['price_loss']), # SL - закрывает позицию, когда убыток достигает нужного уровня orderLinkId=f"deal_{SYMBOL}_{time.time()}" ) await info_access_open_deal(message, SYMBOL, data_main_stgs['trading_mode'], margin_mode, data_main_stgs['size_leverage'], next_quantity) except exceptions.InvalidRequestError as e: logging.error(f"Неверно указана торговая пара: {e}") await message.answer('Недостаточно баланса') except Exception as e: logging.error(f"Ошибка при совершении сделки: {e}") await message.answer('⚠️ Ошибка при совершении сделки') async def contract_short(tg_id, message, margin_mode): api_key = await rq.get_bybit_api_key(tg_id) secret_key = await rq.get_bybit_secret_key(tg_id) SYMBOL = await rq.get_symbol(tg_id) data_main_stgs = await rq.get_user_main_settings(tg_id) data_risk_management_stgs = await rq.get_user_risk_management_settings(tg_id) match margin_mode: case 'Isolated': margin_mode = 'ISOLATED_MARGIN' case 'Cross': margin_mode = 'REGULAR_MARGIN' client = HTTP( api_key=api_key, api_secret=secret_key ) try: balance = 0 price = 0 balance = await balance_g.get_balance(tg_id) price = await price_symbol.get_price(tg_id, message) client.set_margin_mode( setMarginMode=margin_mode # margin_type ) martingale_factor = float(data_main_stgs['martingale_factor']) # Исправлено: было maximal_quantity max_martingale_steps = int(data_main_stgs['maximal_quantity']) starting_quantity = float(data_main_stgs['starting_quantity']) max_risk_percent = float(data_risk_management_stgs['max_risk_deal']) loss_profit = float(data_risk_management_stgs['price_loss']) takeprofit = float(data_risk_management_stgs['price_profit']) commission_fee = float(data_risk_management_stgs.get('commission_fee', 0)) takeProfit_raw = takeprofit takeProfit = takeProfit_raw - commission_fee # уменьшаем TP на комиссию if takeProfit < 0: takeProfit = 0 # Инициализация переменных next_quantity = starting_quantity last_quantity = starting_quantity realised_pnl = 0.0 current_martingale_step = 0 # Текущая ставка в серии next_quantity = 0 realised_pnl = 0 last_quantity = starting_quantity # Пример расчёта следующего размера позиции try: position_info = client.get_positions(category='linear', symbol=SYMBOL) position = position_info['result']['list'][0] # или другой нужный индекс realised_pnl = float(position['unrealisedPnl']) if realised_pnl > 0: starting_quantity = next_quantity current_martingale_step = 0 elif not realised_pnl: next_quantity = starting_quantity current_martingale_step += 1 else: current_martingale_step += 1 next_quantity = last_quantity * martingale_factor starting_quantity = next_quantity except Exception as e: print("Не получены позиции") next_quantity = starting_quantity potential_loss = (next_quantity * float(price)) * (loss_profit / 100) allowed_loss = float(balance) * (max_risk_percent / 100) if current_martingale_step >= max_martingale_steps: print("Достигнут максимум ставок в серии (8)!") print("Торговля не продолжится") await error_max_step(message) else: if potential_loss > allowed_loss: print(f"ОШИБКА: Риск превышен!") print(f"Ручной qty = {next_quantity} → Убыток = {potential_loss} USDT") print(f"Разрешено = {allowed_loss} USDT (1% от баланса)") await error_max_risk(message) else: print(f"Риск в допустимых пределах. Qty = {next_quantity}") r = client.place_order( category='linear', symbol=SYMBOL, side='Sell', orderType="Market", leverage=int(data_main_stgs['size_leverage']), qty=next_quantity, orderLinkId=f"deal_{SYMBOL}_{time.time()}" ) await info_access_open_deal(message, SYMBOL, data_main_stgs['trading_mode'], margin_mode, data_main_stgs['size_leverage'], next_quantity) except exceptions.InvalidRequestError as e: logging.error(f"Error in open_deal: {e}") await message.answer('Недостаточно баланса') except Exception as e: logging.error(f"Error in open_deal: {e}") await message.answer('⚠️ Ошибка при совершении сделки') async def open_market_order(tg_id, message, api_key, secret_key): data_main_stgs = await rq.get_user_main_settings(tg_id) trading_mode = data_main_stgs['trading_mode'] margin_mode = data_main_stgs.get('margin_type') if trading_mode == 'Long': await contract_long(tg_id, message, margin_mode) elif trading_mode == 'Short': await contract_short(tg_id, message, margin_mode) else: await message.answer("Неизвестный режим торговли: выберите Long или Short.") async def open_limit_order(tg_id, message, price, api_key, secret_key): data_main_stgs = await rq.get_user_main_settings(tg_id) trading_mode = data_main_stgs['trading_mode'] margin_mode = data_main_stgs.get('margin_type') client = HTTP( api_key=api_key, api_secret=secret_key ) symbol = await rq.get_symbol(tg_id) qty = float(data_main_stgs['starting_quantity']) side = 'Buy' if trading_mode == 'Long' else 'Sell' try: response = client.place_order( category='linear', symbol=symbol, side=side, orderType='Limit', qty=qty, price=price, timeInForce='GTC', orderLinkId=f"order_{int(time.time())}" ) if response.get('retCode') == 0: await message.answer(f"Limit ордер открыт: {side} {qty} {symbol} по цене {price}") else: await message.answer(f"Ошибка открытия ордера: {response.get('retMsg')}") except Exception as e: logging.error(f"Ошибка при открытии лимитного ордера: {e}") await message.answer("Ошибка при открытии ордера")