Compare commits
	
		
			8 Commits
		
	
	
		
			127003ebe1
			...
			f26df3b1a4
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| f26df3b1a4 | |||
| 
						 | 
					1997b9d1c0 | ||
| 
						 | 
					e555bfa8fb | ||
| 
						 | 
					0fecb5dab7 | ||
| 
						 | 
					242be34a97 | ||
| 
						 | 
					2da3c282d1 | ||
| 
						 | 
					fb0c14aba1 | ||
| 
						 | 
					ed67ed78c0 | 
@@ -6,8 +6,11 @@ from aiogram.types import Message
 | 
			
		||||
 | 
			
		||||
from app.telegram.database.models import async_main
 | 
			
		||||
 | 
			
		||||
from app.telegram.handlers.handlers import router # Для вызова событий
 | 
			
		||||
from app.telegram.functions.main_settings.settings import router_main_settings # Для вызова событий
 | 
			
		||||
from app.telegram.handlers.handlers import router 
 | 
			
		||||
from app.telegram.functions.main_settings.settings import router_main_settings 
 | 
			
		||||
from app.telegram.functions.risk_management_settings.settings import router_risk_management_settings
 | 
			
		||||
from app.services.Bybit.functions.Add_Bybit_API import router_register_bybit_api
 | 
			
		||||
from app.services.Bybit.functions.functions import router_functions_bybit_trade
 | 
			
		||||
 | 
			
		||||
from config import TOKEN_TG_BOT
 | 
			
		||||
 | 
			
		||||
@@ -21,6 +24,9 @@ async def main():
 | 
			
		||||
 | 
			
		||||
    dp.include_router(router)
 | 
			
		||||
    dp.include_router(router_main_settings)
 | 
			
		||||
    dp.include_router(router_risk_management_settings)
 | 
			
		||||
    dp.include_router(router_register_bybit_api)
 | 
			
		||||
    dp.include_router(router_functions_bybit_trade)
 | 
			
		||||
 | 
			
		||||
    await dp.start_polling(bot)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,12 @@
 | 
			
		||||
    <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Compile Include="app\services\Bybit\functions\Add_Bybit_API.py" />
 | 
			
		||||
    <Compile Include="app\services\Bybit\functions\balance.py" />
 | 
			
		||||
    <Compile Include="app\services\Bybit\functions\functions.py" />
 | 
			
		||||
    <Compile Include="app\services\Bybit\functions\func_min_qty.py" />
 | 
			
		||||
    <Compile Include="app\services\Bybit\functions\Futures.py" />
 | 
			
		||||
    <Compile Include="app\services\Bybit\functions\price_symbol.py" />
 | 
			
		||||
    <Compile Include="app\telegram\functions\additional_settings\settings.py" />
 | 
			
		||||
    <Compile Include="app\telegram\functions\condition_settings\settings.py" />
 | 
			
		||||
    <Compile Include="app\telegram\functions\functions.py" />
 | 
			
		||||
@@ -37,6 +43,9 @@
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Folder Include="app\" />
 | 
			
		||||
    <Folder Include="app\services\Bybit\" />
 | 
			
		||||
    <Folder Include="app\services\" />
 | 
			
		||||
    <Folder Include="app\services\Bybit\functions\" />
 | 
			
		||||
    <Folder Include="app\telegram\database\" />
 | 
			
		||||
    <Folder Include="app\telegram\functions\condition_settings\" />
 | 
			
		||||
    <Folder Include="app\telegram\functions\additional_settings\" />
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								README.md
									
									
									
									
									
								
							@@ -1 +1,20 @@
 | 
			
		||||
abobus
 | 
			
		||||
# Чат-робот STCS
 | 
			
		||||
__
 | 
			
		||||
 | 
			
		||||
**Функционал:**
 | 
			
		||||
+ **Настройки**
 | 
			
		||||
  + Основные параметры *(Настроен, работает)*
 | 
			
		||||
    + Режим торговли Лонг/Шорт *(настроены)*, Switch/Smart *(не настроены)*
 | 
			
		||||
    + Тип маржи: Изолированная / Кросс *(настроено)*
 | 
			
		||||
    + Размер кредитного плеча: от x1 до x100 *(настроено)*
 | 
			
		||||
    + Начальная ставка: числовое значение *(настроено)*
 | 
			
		||||
    + Коэффициент мартингейла: число *(настроено)*
 | 
			
		||||
    + Максимальное количество ставок в серии: число *(настроено)*
 | 
			
		||||
  + Риск-менеджмент (Настроен, работает)
 | 
			
		||||
    + Процент изменения цены для фиксации прибыли (TP%): число *(настроено)*
 | 
			
		||||
    + Процент изменения цены для фиксации убытков (SL%): число (пример: 1%) *(настроено)*
 | 
			
		||||
    + Максимальный риск на сделку (в % от баланса): число (опционально) *(настроено)*
 | 
			
		||||
   + Условия запуска *(Не настроен)*
 | 
			
		||||
   + Дополнительные параметры *(Не настроен)*
 | 
			
		||||
   + Подключение Bybit *(настроено)*
 | 
			
		||||
    + Информация о правильном получении и сохранении Bybit-API keys *(настроено)*
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										73
									
								
								app/services/Bybit/functions/Add_Bybit_API.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								app/services/Bybit/functions/Add_Bybit_API.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
			
		||||
from aiogram import F, Router
 | 
			
		||||
 | 
			
		||||
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_register_bybit_api = Router()
 | 
			
		||||
 | 
			
		||||
class state_reg_bybit_api(StatesGroup):
 | 
			
		||||
    api_key = State()
 | 
			
		||||
    secret_key = State()
 | 
			
		||||
 | 
			
		||||
@router_register_bybit_api.callback_query(F.data == 'clb_new_user_connect_bybit_api_message')
 | 
			
		||||
async def info_for_bybit_api_message(callback: CallbackQuery):
 | 
			
		||||
    text = '''<b>Подключение Bybit аккаунта</b>
 | 
			
		||||
    
 | 
			
		||||
<b>1. Зарегистрируйтесь или войдите в свой аккаунт на Bybit (https://www.bybit.com/).</b>
 | 
			
		||||
<b>2. В личном кабинете выберите раздел API. </b>  
 | 
			
		||||
<b>3. Создание нового API ключа</b>  
 | 
			
		||||
   - Нажмите кнопку Create New Key (Создать новый ключ).
 | 
			
		||||
   - Выберите системно-сгенерированный ключ.
 | 
			
		||||
   - Укажите название API ключа (любое).  
 | 
			
		||||
   - Выберите права доступа для торговли (Trade).  
 | 
			
		||||
   - Можно ограничить доступ по IP для безопасности.
 | 
			
		||||
<b>4. Подтверждение создания</b>  
 | 
			
		||||
   - Подтвердите создание ключа.
 | 
			
		||||
   - Отправьте чат-роботу.
 | 
			
		||||
 | 
			
		||||
<b>Важно: сохраните отдельно API Key и Secret Key в надежном месте. Secret ключ отображается только один раз. </b>            
 | 
			
		||||
    '''
 | 
			
		||||
 | 
			
		||||
    await callback.message.answer(text=text, parse_mode='html', reply_markup=inline_markup.connect_bybit_api_markup)
 | 
			
		||||
 | 
			
		||||
    await callback.answer()
 | 
			
		||||
 | 
			
		||||
@router_register_bybit_api.callback_query(F.data == 'clb_new_user_connect_bybit_api')
 | 
			
		||||
async def add_api_key_message(callback: CallbackQuery, state: FSMContext):   
 | 
			
		||||
    await state.set_state(state_reg_bybit_api.api_key)
 | 
			
		||||
 | 
			
		||||
    text = 'Отправьте KEY_API ниже: '
 | 
			
		||||
 | 
			
		||||
    await callback.message.answer(text=text)
 | 
			
		||||
 | 
			
		||||
@router_register_bybit_api.message(state_reg_bybit_api.api_key)
 | 
			
		||||
async def add_api_key_and_message_for_secret_key(message: Message, state: FSMContext):
 | 
			
		||||
    await state.update_data(api_key = message.text)
 | 
			
		||||
    
 | 
			
		||||
    text = 'Отправьте SECRET_KEY ниже'
 | 
			
		||||
 | 
			
		||||
    await message.answer(text=text)
 | 
			
		||||
 | 
			
		||||
    await state.set_state(state_reg_bybit_api.secret_key)
 | 
			
		||||
 | 
			
		||||
@router_register_bybit_api.message(state_reg_bybit_api.secret_key)
 | 
			
		||||
async def add_secret_key(message: Message, state: FSMContext):
 | 
			
		||||
    await state.update_data(secret_key = message.text)
 | 
			
		||||
 | 
			
		||||
    data = await state.get_data()
 | 
			
		||||
 | 
			
		||||
    await rq.update_api_key(message.from_user.id, data['api_key'])
 | 
			
		||||
    await rq.update_secret_key(message.from_user.id, data['secret_key'])
 | 
			
		||||
    await rq.set_new_user_symbol(message.from_user.id)
 | 
			
		||||
    
 | 
			
		||||
    await state.clear()
 | 
			
		||||
 | 
			
		||||
    await message.answer('Данные добавлены, нажмите на профиль и начните торговлю!')
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
							
								
								
									
										254
									
								
								app/services/Bybit/functions/Futures.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								app/services/Bybit/functions/Futures.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,254 @@
 | 
			
		||||
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'])
 | 
			
		||||
        
 | 
			
		||||
        # Инициализация переменных
 | 
			
		||||
        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:
 | 
			
		||||
        await message.answer('Недостаточно баланса')
 | 
			
		||||
    except Exception as 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'])
 | 
			
		||||
        
 | 
			
		||||
        # Инициализация переменных
 | 
			
		||||
        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:
 | 
			
		||||
        await message.answer('Недостаточно баланса')
 | 
			
		||||
    except Exception as e:
 | 
			
		||||
        await message.answer('Непредвиденная оишбка')
 | 
			
		||||
							
								
								
									
										33
									
								
								app/services/Bybit/functions/balance.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								app/services/Bybit/functions/balance.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
import app.telegram.database.requests as rq
 | 
			
		||||
 | 
			
		||||
from pybit.unified_trading import HTTP
 | 
			
		||||
 | 
			
		||||
client = HTTP()
 | 
			
		||||
 | 
			
		||||
async def get_balance(tg_id, message):
 | 
			
		||||
    api_key = await rq.get_bybit_api_key(tg_id)
 | 
			
		||||
    secret_key = await rq.get_bybit_secret_key(tg_id)
 | 
			
		||||
 | 
			
		||||
    client = HTTP(
 | 
			
		||||
        api_key=api_key,
 | 
			
		||||
        api_secret=secret_key
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    if api_key == 'None' or secret_key == 'None':
 | 
			
		||||
        await message.answer('⚠️ Подключите платформу для торговли')
 | 
			
		||||
        return 0      
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        check_user = client.get_wallet_balance()
 | 
			
		||||
 | 
			
		||||
        if check_user:
 | 
			
		||||
            try:
 | 
			
		||||
                balance = client.get_wallet_balance(accountType='UNIFIED', coin='USDT')['result']['list'][0]['coin'][0]['walletBalance']
 | 
			
		||||
 | 
			
		||||
                return balance
 | 
			
		||||
            except Exception as e:
 | 
			
		||||
                await message.answer('⚠️ Ошибка при получении баланса пользователя') 
 | 
			
		||||
                return 0
 | 
			
		||||
    except Exception as e:
 | 
			
		||||
        await message.answer('⚠️ Неверные данные API, перепроверьте их')
 | 
			
		||||
        return 0
 | 
			
		||||
							
								
								
									
										21
									
								
								app/services/Bybit/functions/func_min_qty.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								app/services/Bybit/functions/func_min_qty.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
import app.telegram.database.requests as rq
 | 
			
		||||
import app.services.Bybit.functions.price_symbol as price_s
 | 
			
		||||
 | 
			
		||||
from pybit.unified_trading import HTTP
 | 
			
		||||
 | 
			
		||||
client = HTTP()
 | 
			
		||||
 | 
			
		||||
async def get_min_qty(tg_id, message):
 | 
			
		||||
    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)
 | 
			
		||||
 | 
			
		||||
    client = HTTP(
 | 
			
		||||
        api_key=api_key,
 | 
			
		||||
        api_secret=secret_key
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    price = await price_s.get_price(tg_id, message)
 | 
			
		||||
    min_qty = int(5 / price * 1.1)
 | 
			
		||||
 | 
			
		||||
    return min_qty
 | 
			
		||||
							
								
								
									
										99
									
								
								app/services/Bybit/functions/functions.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								app/services/Bybit/functions/functions.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
			
		||||
from aiogram import F, Router
 | 
			
		||||
 | 
			
		||||
from app.services.Bybit.functions import Futures, func_min_qty
 | 
			
		||||
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()
 | 
			
		||||
    
 | 
			
		||||
@router_functions_bybit_trade.callback_query(F.data == 'clb_start_trading')
 | 
			
		||||
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_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 пока недоступен')
 | 
			
		||||
							
								
								
									
										23
									
								
								app/services/Bybit/functions/min_qty.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								app/services/Bybit/functions/min_qty.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
from app.services.Bybit.functions import price_symbol
 | 
			
		||||
import app.telegram.database.requests as rq
 | 
			
		||||
 | 
			
		||||
from pybit.unified_trading import HTTP
 | 
			
		||||
 | 
			
		||||
client = HTTP()
 | 
			
		||||
 | 
			
		||||
async def get_min_qty(tg_id):
 | 
			
		||||
    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)
 | 
			
		||||
 | 
			
		||||
    client = HTTP(
 | 
			
		||||
        api_key=api_key,
 | 
			
		||||
        api_secret=secret_key
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    price = await price_symbol(tg_id)
 | 
			
		||||
    json_data = client.get_instruments_info(symbol=SYMBOL, category='linear')
 | 
			
		||||
 | 
			
		||||
    min_qty = int(5 / price * 1.1) # <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1% <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 5 USDT
 | 
			
		||||
    
 | 
			
		||||
    return min_qty
 | 
			
		||||
							
								
								
									
										24
									
								
								app/services/Bybit/functions/price_symbol.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								app/services/Bybit/functions/price_symbol.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
import app.telegram.database.requests as rq
 | 
			
		||||
 | 
			
		||||
from pybit import exceptions
 | 
			
		||||
from pybit.unified_trading import HTTP
 | 
			
		||||
 | 
			
		||||
client = HTTP()
 | 
			
		||||
 | 
			
		||||
async def get_price(tg_id, message):
 | 
			
		||||
    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)
 | 
			
		||||
 | 
			
		||||
    client = HTTP(
 | 
			
		||||
        api_key=api_key,
 | 
			
		||||
        api_secret=secret_key
 | 
			
		||||
    )
 | 
			
		||||
    
 | 
			
		||||
    try:
 | 
			
		||||
        price = float(client.get_tickers(category='linear', symbol=SYMBOL).get('result').get('list')[0].get('ask1Price'))
 | 
			
		||||
 | 
			
		||||
        return price
 | 
			
		||||
    except exceptions.InvalidRequestError as e:
 | 
			
		||||
        await message.answer('Неверно указана торговая пара')
 | 
			
		||||
        return 1.0
 | 
			
		||||
@@ -1,15 +1,15 @@
 | 
			
		||||
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
 | 
			
		||||
 | 
			
		||||
start_markup = InlineKeyboardMarkup(inline_keyboard=[
 | 
			
		||||
    [InlineKeyboardButton(text="Зарегистрироваться", callback_data="callback_registration")],    
 | 
			
		||||
    [InlineKeyboardButton(text="Авторизоваться", callback_data="callback_autorisation")]   
 | 
			
		||||
start_markup = InlineKeyboardMarkup(inline_keyboard=[    
 | 
			
		||||
    [InlineKeyboardButton(text="🔥 Начать торговлю", callback_data="clb_start_chatbot_message")]   
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
settings_markup = InlineKeyboardMarkup(inline_keyboard=[
 | 
			
		||||
    [InlineKeyboardButton(text="Настройки", callback_data='clb_settings_message')]
 | 
			
		||||
    [InlineKeyboardButton(text="Настройки", callback_data='clb_settings_message')],
 | 
			
		||||
    [InlineKeyboardButton(text="Запуск", callback_data='clb_start_trading')]
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
back_btn_profile = [InlineKeyboardButton(text="Назад", callback_data='callback_autorisation')]
 | 
			
		||||
back_btn_profile = [InlineKeyboardButton(text="Назад", callback_data='clb_start_chatbot_message')]
 | 
			
		||||
 | 
			
		||||
special_settings_markup = InlineKeyboardMarkup(inline_keyboard=[
 | 
			
		||||
    [InlineKeyboardButton(text="Основные настройки", callback_data='clb_change_main_settings'), 
 | 
			
		||||
@@ -18,9 +18,20 @@ special_settings_markup = InlineKeyboardMarkup(inline_keyboard=[
 | 
			
		||||
    [InlineKeyboardButton(text="Условия запуска", callback_data='clb_change_condition_settings'), 
 | 
			
		||||
     InlineKeyboardButton(text="Дополнительные параметры", callback_data='clb_change_additional_settings')],
 | 
			
		||||
 | 
			
		||||
    [InlineKeyboardButton(text="Подключить Bybit", callback_data='clb_new_user_connect_bybit_api_message')],
 | 
			
		||||
 | 
			
		||||
     back_btn_profile
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
connect_bybit_api_markup = InlineKeyboardMarkup(inline_keyboard=[
 | 
			
		||||
    [InlineKeyboardButton(text="Подключить Bybit", callback_data='clb_new_user_connect_bybit_api')]
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
trading_markup = InlineKeyboardMarkup(inline_keyboard=[
 | 
			
		||||
    [InlineKeyboardButton(text="Указать торговую пару", callback_data='clb_update_trading_pair')],        
 | 
			
		||||
    [InlineKeyboardButton(text="Совершить сделку", callback_data='clb_open_deal')]        
 | 
			
		||||
]) 
 | 
			
		||||
 | 
			
		||||
back_btn_list_settings = [InlineKeyboardButton(text="Назад", callback_data='clb_back_to_special_settings_message')] # Кнопка для возврата к списку каталога настроек
 | 
			
		||||
back_btn_list_settings_markup = InlineKeyboardMarkup(inline_keyboard=[[InlineKeyboardButton(text="Назад", callback_data='clb_back_to_special_settings_message')]]) # Клавиатура для возврата к списку каталога настроек
 | 
			
		||||
 | 
			
		||||
@@ -85,4 +96,17 @@ margin_type_markup = InlineKeyboardMarkup(inline_keyboard=[
 | 
			
		||||
    InlineKeyboardButton(text="Кросс", callback_data="margin_type_cross")],
 | 
			
		||||
 | 
			
		||||
    back_btn_list_settings
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
trigger_markup = InlineKeyboardMarkup(inline_keyboard=[ # ИЗМЕНИТЬ НА INLINE
 | 
			
		||||
    [InlineKeyboardButton(text='Ручной', callback_data="clb_trigger_ruchnoy"), InlineKeyboardButton(text='TradingView', callback_data="clb_trigger_tradingview")],    
 | 
			
		||||
    [InlineKeyboardButton(text="Автоматический", callback_data="clb_trigger_auto")]    
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
buttons_yes_no_markup = InlineKeyboardMarkup(inline_keyboard=[  # ИЗМЕНИТЬ НА INLINE
 | 
			
		||||
    [InlineKeyboardButton(text='Да', callback_data="clb_yes"), InlineKeyboardButton(text='Нет', callback_data="clb_yes")]         
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
buttons_on_off_markup = InlineKeyboardMarkup(inline_keyboard=[  # ИЗМЕНИТЬ НА INLINE
 | 
			
		||||
    [InlineKeyboardButton(text='Включить', callback_data="clb_on"), InlineKeyboardButton(text='Выключить', callback_data="clb_off")]        
 | 
			
		||||
])
 | 
			
		||||
@@ -3,17 +3,4 @@
 | 
			
		||||
base_buttons_markup = ReplyKeyboardMarkup(keyboard=[
 | 
			
		||||
    [KeyboardButton(text="👤 Профиль")],    
 | 
			
		||||
    # [KeyboardButton(text="Настройки")]         
 | 
			
		||||
], resize_keyboard=True)
 | 
			
		||||
 | 
			
		||||
trigger_markup = ReplyKeyboardMarkup(keyboard=[ # ИЗМЕНИТЬ НА INLINE
 | 
			
		||||
    [KeyboardButton(text='Ручной'), KeyboardButton(text='TradingView')],    
 | 
			
		||||
    [KeyboardButton(text="Автоматический")]    
 | 
			
		||||
], resize_keyboard=True)
 | 
			
		||||
 | 
			
		||||
buttons_yes_no_markup = ReplyKeyboardMarkup(keyboard=[  # ИЗМЕНИТЬ НА INLINE
 | 
			
		||||
    [KeyboardButton(text='Да'), KeyboardButton(text='Нет')]         
 | 
			
		||||
], resize_keyboard=True)
 | 
			
		||||
 | 
			
		||||
buttons_on_off_markup = ReplyKeyboardMarkup(keyboard=[  # ИЗМЕНИТЬ НА INLINE
 | 
			
		||||
    [KeyboardButton(text='Включить'), KeyboardButton(text='Выключить')]        
 | 
			
		||||
], resize_keyboard=True)
 | 
			
		||||
@@ -21,6 +21,25 @@ class User_Telegram_Id(Base):
 | 
			
		||||
 | 
			
		||||
    tg_id = mapped_column(BigInteger)
 | 
			
		||||
 | 
			
		||||
class User_Bybit_API(Base):
 | 
			
		||||
    __tablename__ = 'user_bybit_api'
 | 
			
		||||
 | 
			
		||||
    id: Mapped[int] = mapped_column(primary_key=True)
 | 
			
		||||
 | 
			
		||||
    tg_id = mapped_column(ForeignKey("user_telegram_id.tg_id"))
 | 
			
		||||
 | 
			
		||||
    api_key = mapped_column(String(18), default='None')
 | 
			
		||||
    secret_key = mapped_column(String(36), default='None')
 | 
			
		||||
 | 
			
		||||
class User_Symbol(Base):
 | 
			
		||||
    __tablename__ = 'user_symbols'
 | 
			
		||||
 | 
			
		||||
    id: Mapped[int] = mapped_column(primary_key=True)
 | 
			
		||||
 | 
			
		||||
    tg_id = mapped_column(ForeignKey("user_telegram_id.tg_id"))
 | 
			
		||||
 | 
			
		||||
    symbol = mapped_column(String(18), default='PENGUUSDT')
 | 
			
		||||
 | 
			
		||||
class Trading_Mode(Base):
 | 
			
		||||
    __tablename__ = 'trading_modes'
 | 
			
		||||
 | 
			
		||||
@@ -65,7 +84,7 @@ class User_Risk_Management_Settings(Base):
 | 
			
		||||
 | 
			
		||||
    price_profit = mapped_column(Integer(), default=1)
 | 
			
		||||
    price_loss = mapped_column(Integer(), default=1)
 | 
			
		||||
    max_risk_deal = mapped_column(Integer(), default=1)
 | 
			
		||||
    max_risk_deal = mapped_column(Integer(), default=100)
 | 
			
		||||
 | 
			
		||||
class User_Condition_Settings(Base):
 | 
			
		||||
    __tablename__ = 'user_condition_settings'
 | 
			
		||||
@@ -105,7 +124,7 @@ async def async_main():
 | 
			
		||||
                logger.info("Заполение таблицы режима торговли")
 | 
			
		||||
                await conn.execute(Trading_Mode.__table__.insert().values(mode=mode))
 | 
			
		||||
 | 
			
		||||
        types = ['Изолированный', 'Кросс']
 | 
			
		||||
        types = ['Isolated', 'Cross']
 | 
			
		||||
        for type in types:
 | 
			
		||||
            result = await conn.execute(select(Margin_type).where(Margin_type.type == type))           
 | 
			
		||||
            if not result.first():
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,8 @@ logger = logging.getLogger(__name__)
 | 
			
		||||
from app.telegram.database.models import async_session
 | 
			
		||||
from app.telegram.database.models import User_Telegram_Id as UTi
 | 
			
		||||
from app.telegram.database.models import User_Main_Settings as UMS
 | 
			
		||||
from app.telegram.database.models import User_Bybit_API as UBA
 | 
			
		||||
from app.telegram.database.models import User_Symbol
 | 
			
		||||
from app.telegram.database.models import User_Risk_Management_Settings as URMS
 | 
			
		||||
from app.telegram.database.models import User_Condition_Settings as UCS 
 | 
			
		||||
from app.telegram.database.models import User_Additional_Settings as UAS 
 | 
			
		||||
@@ -27,6 +29,32 @@ async def save_tg_id_new_user(tg_id):
 | 
			
		||||
 | 
			
		||||
        await session.commit()
 | 
			
		||||
 | 
			
		||||
async def set_new_user_bybit_api(tg_id):
 | 
			
		||||
    async with async_session() as session:
 | 
			
		||||
        user = await session.scalar(select(UBA).where(UBA.tg_id == tg_id))
 | 
			
		||||
 | 
			
		||||
        if not user:
 | 
			
		||||
            session.add(UBA(
 | 
			
		||||
                tg_id=tg_id,
 | 
			
		||||
            ))
 | 
			
		||||
 | 
			
		||||
            logger.info(f"Bybit был успешно подключен")
 | 
			
		||||
 | 
			
		||||
        await session.commit()
 | 
			
		||||
 | 
			
		||||
async def set_new_user_symbol(tg_id):
 | 
			
		||||
    async with async_session() as session:
 | 
			
		||||
        user = await session.scalar(select(User_Symbol).where(User_Symbol.tg_id == tg_id))
 | 
			
		||||
 | 
			
		||||
        if not user:
 | 
			
		||||
            session.add(User_Symbol(
 | 
			
		||||
                tg_id=tg_id              
 | 
			
		||||
            ))
 | 
			
		||||
 | 
			
		||||
            logger.info(f"Symbol был успешно добавлен")
 | 
			
		||||
 | 
			
		||||
        await session.commit()
 | 
			
		||||
 | 
			
		||||
async def set_new_user_default_main_settings(tg_id, trading_mode, margin_type) -> None:
 | 
			
		||||
    async with async_session() as session:
 | 
			
		||||
        settings = await session.scalar(select(UMS).where(UMS.tg_id == tg_id))
 | 
			
		||||
@@ -86,7 +114,22 @@ async def set_new_user_default_additional_settings(tg_id) -> None:
 | 
			
		||||
async def check_user(tg_id):
 | 
			
		||||
    async with async_session() as session:
 | 
			
		||||
        user = await session.scalar(select(UTi).where(UTi.tg_id == tg_id))
 | 
			
		||||
        return user            
 | 
			
		||||
        return user 
 | 
			
		||||
    
 | 
			
		||||
async def get_bybit_api_key(tg_id):
 | 
			
		||||
    async with async_session() as session:
 | 
			
		||||
        api_key = await session.scalar(select(UBA.api_key).where(UBA.tg_id == tg_id))
 | 
			
		||||
        return api_key
 | 
			
		||||
    
 | 
			
		||||
async def get_bybit_secret_key(tg_id):
 | 
			
		||||
    async with async_session() as session:
 | 
			
		||||
        secret_key = await session.scalar(select(UBA.secret_key).where(UBA.tg_id == tg_id))
 | 
			
		||||
        return secret_key
 | 
			
		||||
    
 | 
			
		||||
async def get_symbol(tg_id):
 | 
			
		||||
    async with async_session() as session:
 | 
			
		||||
        symbol = await session.scalar(select(User_Symbol.symbol).where(User_Symbol.tg_id == tg_id))
 | 
			
		||||
        return symbol 
 | 
			
		||||
 | 
			
		||||
async def get_for_registration_trading_mode():
 | 
			
		||||
    async with async_session() as session:
 | 
			
		||||
@@ -128,7 +171,45 @@ async def get_user_main_settings(tg_id):
 | 
			
		||||
 | 
			
		||||
            return data
 | 
			
		||||
 | 
			
		||||
# UPDATE_DB
 | 
			
		||||
async def get_user_risk_management_settings(tg_id):
 | 
			
		||||
    async with async_session() as session:
 | 
			
		||||
        user = await session.scalar(select(URMS).where(URMS.tg_id == tg_id))
 | 
			
		||||
 | 
			
		||||
        if user:
 | 
			
		||||
            logger.info("Получение риск-менеджмента настроек пользователя")
 | 
			
		||||
 | 
			
		||||
            price_profit = await session.scalar(select(URMS.price_profit).where(URMS.tg_id == tg_id))
 | 
			
		||||
            price_loss = await session.scalar(select(URMS.price_loss).where(URMS.tg_id == tg_id))
 | 
			
		||||
            max_risk_deal = await session.scalar(select(URMS.max_risk_deal).where(URMS.tg_id == tg_id))
 | 
			
		||||
 | 
			
		||||
            data = {
 | 
			
		||||
                'price_profit': price_profit,
 | 
			
		||||
                'price_loss': price_loss,
 | 
			
		||||
                'max_risk_deal': max_risk_deal                        
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return data
 | 
			
		||||
 | 
			
		||||
#UPDATE_SYMBOL
 | 
			
		||||
async def update_symbol(tg_id, symbol) -> None:
 | 
			
		||||
    async with async_session() as session:
 | 
			
		||||
        await session.execute(update(User_Symbol).where(User_Symbol.tg_id == tg_id).values(symbol = symbol))
 | 
			
		||||
        
 | 
			
		||||
        await session.commit()
 | 
			
		||||
 | 
			
		||||
async def update_api_key(tg_id, api):
 | 
			
		||||
    async with async_session() as session:
 | 
			
		||||
        api_key = await session.execute(update(UBA).where(UBA.tg_id == tg_id).values(api_key = api))
 | 
			
		||||
 | 
			
		||||
        await session.commit()
 | 
			
		||||
 | 
			
		||||
async def update_secret_key(tg_id, api):
 | 
			
		||||
    async with async_session() as session:
 | 
			
		||||
        secret_key = await session.execute(update(UBA).where(UBA.tg_id == tg_id).values(secret_key = api))
 | 
			
		||||
 | 
			
		||||
        await session.commit()
 | 
			
		||||
 | 
			
		||||
# UPDATE_MAIN_SETTINGS_DB
 | 
			
		||||
async def update_trade_mode_user(tg_id, trading_mode) -> None:
 | 
			
		||||
    async with async_session() as session:
 | 
			
		||||
        mode = await session.scalar(select(Trading_Mode.mode).where(Trading_Mode.mode == trading_mode))
 | 
			
		||||
@@ -171,4 +252,24 @@ async def update_maximal_quantity(tg_id, num):
 | 
			
		||||
    async with async_session() as session:
 | 
			
		||||
        await session.execute(update(UMS).where(UMS.tg_id == tg_id).values(maximal_quantity = num))
 | 
			
		||||
        
 | 
			
		||||
        await session.commit()
 | 
			
		||||
 | 
			
		||||
# UPDATE_RISK_MANAGEMENT_SETTINGS_DB
 | 
			
		||||
 | 
			
		||||
async def update_price_profit(tg_id, num):
 | 
			
		||||
    async with async_session() as session:
 | 
			
		||||
        await session.execute(update(URMS).where(URMS.tg_id == tg_id).values(price_profit = num))
 | 
			
		||||
        
 | 
			
		||||
        await session.commit()
 | 
			
		||||
 | 
			
		||||
async def update_price_loss(tg_id, num):
 | 
			
		||||
    async with async_session() as session:
 | 
			
		||||
        await session.execute(update(URMS).where(URMS.tg_id == tg_id).values(price_loss = num))
 | 
			
		||||
        
 | 
			
		||||
        await session.commit()
 | 
			
		||||
 | 
			
		||||
async def update_max_risk_deal(tg_id, num):
 | 
			
		||||
    async with async_session() as session:
 | 
			
		||||
        await session.execute(update(URMS).where(URMS.tg_id == tg_id).values(max_risk_deal = num))
 | 
			
		||||
        
 | 
			
		||||
        await session.commit()
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
import app.telegram.Keyboards.inline_keyboards as inline_markup
 | 
			
		||||
import app.telegram.Keyboards.reply_keyboards as reply_markup
 | 
			
		||||
 | 
			
		||||
import app.telegram.database.requests as rq
 | 
			
		||||
 | 
			
		||||
@@ -8,34 +7,32 @@ async def reg_new_user_default_additional_settings(id, message):
 | 
			
		||||
 | 
			
		||||
    await rq.set_new_user_default_additional_settings(tg_id)
 | 
			
		||||
 | 
			
		||||
async def main_settings_message(message):
 | 
			
		||||
async def main_settings_message(id, message, state):
 | 
			
		||||
    text = '''<b>Дополнительные параметры</b>
 | 
			
		||||
 | 
			
		||||
Сохранить как шаблон стратегии: да / нет
 | 
			
		||||
<b>- Сохранить как шаблон стратегии:</b> да / нет  
 | 
			
		||||
<b>- Автозапуск после сохранения:</b> да / нет  
 | 
			
		||||
<b>- Уведомления в Telegram:</b> включено / отключено '''
 | 
			
		||||
 | 
			
		||||
Автозапуск после сохранения: да / нет
 | 
			
		||||
 | 
			
		||||
Уведомления в Telegram: включено / отключено '''
 | 
			
		||||
 | 
			
		||||
    await message.answer(text=text, parse_mode='html', reply_markup=inline_markup.additional_settings_markup)
 | 
			
		||||
    await message.edit_text(text=text, parse_mode='html', reply_markup=inline_markup.additional_settings_markup)
 | 
			
		||||
 | 
			
		||||
async def save_pattern_message(message, state):
 | 
			
		||||
    text = '''<b>Сохранение шаблона</b>
 | 
			
		||||
 | 
			
		||||
                                                                                          
 | 
			
		||||
    Описание... '''
 | 
			
		||||
 | 
			
		||||
    await message.answer(text=text, parse_mode='html', reply_markup=reply_markup.buttons_yes_no_markup)
 | 
			
		||||
    await message.answer(text=text, parse_mode='html', reply_markup=inline_markup.buttons_yes_no_markup)
 | 
			
		||||
 | 
			
		||||
async def auto_start_message(message, state):
 | 
			
		||||
    text = '''<b>Автозапуск</b>
 | 
			
		||||
 | 
			
		||||
    Описание... '''
 | 
			
		||||
 | 
			
		||||
    await message.answer(text=text, parse_mode='html', reply_markup=reply_markup.buttons_yes_no_markup)
 | 
			
		||||
    await message.answer(text=text, parse_mode='html', reply_markup=inline_markup.buttons_yes_no_markup)
 | 
			
		||||
 | 
			
		||||
async def notifications_message(message, state):
 | 
			
		||||
    text = '''<b>Уведомления</b>
 | 
			
		||||
    text = '''<b>Уведомления</b>                                                                
 | 
			
		||||
 | 
			
		||||
    Описание... '''
 | 
			
		||||
 | 
			
		||||
    await message.answer(text=text, parse_mode='html', reply_markup=reply_markup.buttons_on_off_markup)
 | 
			
		||||
    await message.answer(text=text, parse_mode='html', reply_markup=inline_markup.buttons_on_off_markup)                                                                                                                                
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
import app.telegram.Keyboards.inline_keyboards as inline_markup
 | 
			
		||||
import app.telegram.Keyboards.reply_keyboards as reply_markup
 | 
			
		||||
 | 
			
		||||
import app.telegram.database.requests as rq
 | 
			
		||||
 | 
			
		||||
@@ -10,25 +9,17 @@ async def reg_new_user_default_condition_settings(id, message):
 | 
			
		||||
 | 
			
		||||
    await rq.set_new_user_default_condition_settings(tg_id, trigger)
 | 
			
		||||
 | 
			
		||||
async def main_settings_message(message):
 | 
			
		||||
async def main_settings_message(id, message, state):
 | 
			
		||||
    text = """ <b>Условия запуска</b>
 | 
			
		||||
 | 
			
		||||
Триггер: Ручной запуск / Сигнал TradingView / Полностью автоматический
 | 
			
		||||
 | 
			
		||||
Фильтр времени: диапазон по дням недели и времени суток
 | 
			
		||||
 | 
			
		||||
Фильтр волатильности / объёма: включить/отключить
 | 
			
		||||
 | 
			
		||||
Интеграции и внешние сигналы:
 | 
			
		||||
 | 
			
		||||
Использовать сигналы TradingView: да / нет
 | 
			
		||||
 | 
			
		||||
Использовать AI-аналитику от ChatGPT: да / нет
 | 
			
		||||
 | 
			
		||||
Webhook URL для сигналов (если используется TradingView).
 | 
			
		||||
 | 
			
		||||
<b>- Триггер:</b> Ручной запуск / Сигнал TradingView / Полностью автоматический 
 | 
			
		||||
<b>- Фильтр времени: </b> диапазон по дням недели и времени суток  
 | 
			
		||||
<b>- Фильтр волатильности / объёма: </b> включить/отключить  
 | 
			
		||||
<b>- Интеграции и внешние сигналы: </b>
 | 
			
		||||
<b>- Использовать сигналы TradingView:</b> да / нет
 | 
			
		||||
<b>- Использовать AI-аналитику от ChatGPT:</b> да / не
 | 
			
		||||
<b>- Webhook URL для сигналов (если используется TradingView): </b>
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
    await message.answer(text=text, parse_mode='html', reply_markup=inline_markup.condition_settings_markup)
 | 
			
		||||
   
 | 
			
		||||
async def trigger_message(message, state):
 | 
			
		||||
@@ -36,7 +27,7 @@ async def trigger_message(message, state):
 | 
			
		||||
 | 
			
		||||
    Описание ручного запуска, сигналов, автоматического режима '''
 | 
			
		||||
 | 
			
		||||
    await message.answer(text=text, parse_mode='html', reply_markup=reply_markup.trigger_markup)
 | 
			
		||||
    await message.answer(text=text, parse_mode='html', reply_markup=inline_markup.trigger_markup)
 | 
			
		||||
 | 
			
		||||
async def filter_time_message(message, state):
 | 
			
		||||
    text = '''Фильтр времени
 | 
			
		||||
@@ -51,7 +42,7 @@ async def filter_volatility_message(message, state):
 | 
			
		||||
 | 
			
		||||
    Описание... '''
 | 
			
		||||
 | 
			
		||||
    await message.answer(text=text, parse_mode='html', reply_markup=reply_markup.buttons_on_off_markup)
 | 
			
		||||
    await message.answer(text=text, parse_mode='html', reply_markup=inline_markup.buttons_on_off_markup)
 | 
			
		||||
 | 
			
		||||
async def external_cues_message(message, state):
 | 
			
		||||
    text = '''<b>Внешние сигналы</b>
 | 
			
		||||
@@ -65,7 +56,7 @@ async def trading_cues_message(message, state):
 | 
			
		||||
 | 
			
		||||
    Описание... '''
 | 
			
		||||
 | 
			
		||||
    await message.answer(text=text, parse_mode='html', reply_markup=reply_markup.buttons_yes_no_markup)
 | 
			
		||||
    await message.answer(text=text, parse_mode='html', reply_markup=inline_markup.buttons_yes_no_markup)
 | 
			
		||||
 | 
			
		||||
async def webhook_message(message, state):
 | 
			
		||||
    text = '''Скиньте ссылку на <b>webhook</b> (если есть trading view): '''
 | 
			
		||||
@@ -77,6 +68,6 @@ async def ai_analytics_message(message, state):
 | 
			
		||||
 | 
			
		||||
    Описание... '''
 | 
			
		||||
 | 
			
		||||
    await message.answer(text=text, parse_mode='html', reply_markup=reply_markup.buttons_yes_no_markup)
 | 
			
		||||
    await message.answer(text=text, parse_mode='html', reply_markup=inline_markup.buttons_yes_no_markup)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,33 +2,29 @@
 | 
			
		||||
import app.telegram.Keyboards.reply_keyboards as reply_markup
 | 
			
		||||
 | 
			
		||||
async def start_message(message):
 | 
			
		||||
    await message.answer(f""" Привет <b>{message.from_user.username}</b>! 👋
 | 
			
		||||
 | 
			
		||||
Добро пожаловать в бот по трейдингу на Bibyt — вашего надежного помощника для анализа рынка и принятия взвешенных решений. Здесь вы получите:
 | 
			
		||||
<b>
 | 
			
		||||
📊 Анализ текущих трендов  
 | 
			
		||||
📈 Инструменты для прогнозирования и оценки рисков  
 | 
			
		||||
⚡️ Сигналы и рекомендации по сделкам  
 | 
			
		||||
🔔 Уведомления о важных изменениях и новостях
 | 
			
		||||
</b>
 | 
			
		||||
Просто отправляйте интересующий вас инструмент или команду, и бот быстро предоставит актуальную информацию и аналитику.
 | 
			
		||||
 | 
			
		||||
Начнем торговать умно и эффективно вместе! 🚀 
 | 
			
		||||
    username = ''
 | 
			
		||||
    
 | 
			
		||||
    if message.from_user.first_name == None:
 | 
			
		||||
        username = message.from_user.last_name
 | 
			
		||||
    elif message.from_user.last_name == None:
 | 
			
		||||
        username = message.from_user.first_name
 | 
			
		||||
    else:
 | 
			
		||||
        username = f'{message.from_user.first_name} {message.from_user.last_name}'
 | 
			
		||||
    await message.answer(f""" Привет <b>{username}</b>! 👋
 | 
			
		||||
 | 
			
		||||
Добро пожаловать в чат-робот для автоматизации трейдинга — вашего надежного помощника для анализа рынка и принятия взвешенных решений. 
 | 
			
		||||
""", parse_mode='html', reply_markup=inline_markup.start_markup)
 | 
			
		||||
 | 
			
		||||
async def profile_message(username, message):
 | 
			
		||||
    await message.answer(f""" <b>{username}</b>
 | 
			
		||||
    await message.answer(f""" <b>@{username}</b>
 | 
			
		||||
 | 
			
		||||
Баланс:  
 | 
			
		||||
Баланс  
 | 
			
		||||
⭐️ 0
 | 
			
		||||
 | 
			
		||||
Описание:  
 | 
			
		||||
Активный трейдер на платформе Bibyt с индивидуальной стратегией и аналитикой в реальном времени. Постоянно улучшает навыки и следит за рыночными тенденциями для максимальной прибыли.
 | 
			
		||||
""", parse_mode='html', reply_markup=inline_markup.settings_markup)
 | 
			
		||||
 | 
			
		||||
async def check_profile_message(message):
 | 
			
		||||
    await message.answer(f'Добро пожаловать {message.from_user.username}!', reply_markup=reply_markup.base_buttons_markup)
 | 
			
		||||
async def check_profile_message(message, username):
 | 
			
		||||
    await message.answer(f'С возвращением, {username}!', reply_markup=reply_markup.base_buttons_markup)
 | 
			
		||||
    
 | 
			
		||||
async def settings_message(message):
 | 
			
		||||
    await message.edit_text("Выберите что настроить", reply_markup=inline_markup.special_settings_markup)
 | 
			
		||||
@@ -12,12 +12,12 @@ from aiogram.fsm.state import State, StatesGroup
 | 
			
		||||
router_main_settings = Router()
 | 
			
		||||
 | 
			
		||||
class update_main_settings(StatesGroup):
 | 
			
		||||
    trading_mode = State() # +
 | 
			
		||||
    size_leverage = State() #
 | 
			
		||||
    margin_type = State() #
 | 
			
		||||
    martingale_factor = State() #
 | 
			
		||||
    starting_quantity = State() #
 | 
			
		||||
    maximal_quantity = State() #
 | 
			
		||||
    trading_mode = State() 
 | 
			
		||||
    size_leverage = State() 
 | 
			
		||||
    margin_type = State() 
 | 
			
		||||
    martingale_factor = State() 
 | 
			
		||||
    starting_quantity = State() 
 | 
			
		||||
    maximal_quantity = State() 
 | 
			
		||||
 | 
			
		||||
async def reg_new_user_default_main_settings(id, message):
 | 
			
		||||
    tg_id = id
 | 
			
		||||
@@ -31,18 +31,14 @@ async def reg_new_user_default_main_settings(id, message):
 | 
			
		||||
async def main_settings_message(id, message, state):
 | 
			
		||||
     data = await rq.get_user_main_settings(id)
 | 
			
		||||
 | 
			
		||||
     await message.answer(f"""<b>Основные настройки</b>   
 | 
			
		||||
Режим торговли: <b>{data['trading_mode']}</b>
 | 
			
		||||
 | 
			
		||||
Тип маржи: <b>{data['margin_type']}</b>
 | 
			
		||||
 | 
			
		||||
Размер кредитного плеча: <b>х{data['size_leverage']}</b>
 | 
			
		||||
 | 
			
		||||
Начальная ставка: <b>{data['starting_quantity']}</b>
 | 
			
		||||
 | 
			
		||||
Коэффициент мартингейла: <b>{data['martingale_factor']}</b>
 | 
			
		||||
 | 
			
		||||
Максимальное количесиво ставок в серии: <b>{data['maximal_quantity']}</b>    
 | 
			
		||||
     await message.answer(f"""<b>Основные настройки</b>
 | 
			
		||||
     
 | 
			
		||||
<b>- Режим торговли:</b> {data['trading_mode']}
 | 
			
		||||
<b>- Тип маржи:</b> {data['margin_type']}
 | 
			
		||||
<b>- Размер кредитного плеча:</b> х{data['size_leverage']}
 | 
			
		||||
<b>- Начальная ставка:</b> {data['starting_quantity']}
 | 
			
		||||
<b>- Коэффициент мартингейла:</b> {data['martingale_factor']}
 | 
			
		||||
<b>- Максимальное количесиво ставок в серии:</b> {data['maximal_quantity']}    
 | 
			
		||||
""", parse_mode='html', reply_markup=inline_markup.main_settings_markup)
 | 
			
		||||
 | 
			
		||||
async def trading_mode_message(message, state):
 | 
			
		||||
@@ -66,30 +62,34 @@ async def state_trading_mode(callback: CallbackQuery, state):
 | 
			
		||||
   await callback.answer()
 | 
			
		||||
 | 
			
		||||
   id = callback.from_user.id
 | 
			
		||||
   print(f"sdljfngdjklfg ## {callback.data}")
 | 
			
		||||
   data_settings = await rq.get_user_main_settings(id)
 | 
			
		||||
 | 
			
		||||
   try:
 | 
			
		||||
       match callback.data:
 | 
			
		||||
           case 'trade_mode_long':
 | 
			
		||||
                await callback.message.answer(f"✅ Изменено: {data_settings['trading_mode']} → Long")
 | 
			
		||||
                await rq.update_trade_mode_user(id, 'Long')
 | 
			
		||||
                await main_settings_message(id, callback.message, state)
 | 
			
		||||
 | 
			
		||||
                await state.clear()
 | 
			
		||||
           case 'trade_mode_short':
 | 
			
		||||
                await callback.message.answer(f"✅ Изменено: {data_settings['trading_mode']} → Short")
 | 
			
		||||
                await rq.update_trade_mode_user(id, 'Short')
 | 
			
		||||
                await main_settings_message(id, callback.message, state)
 | 
			
		||||
 | 
			
		||||
                await state.clear()
 | 
			
		||||
           case 'trade_mode_switch':
 | 
			
		||||
                await callback.message.answer(f"✅ Изменено: {data_settings['trading_mode']} → Switch")
 | 
			
		||||
                await rq.update_trade_mode_user(id, 'Switch')
 | 
			
		||||
                await main_settings_message(id, callback.message, state)
 | 
			
		||||
 | 
			
		||||
                await state.clear()
 | 
			
		||||
           case 'trade_mode_smart':
 | 
			
		||||
               await rq.update_trade_mode_user(id, 'Smart')
 | 
			
		||||
               await main_settings_message(id, callback.message, state)
 | 
			
		||||
                await callback.message.answer(f"✅ Изменено: {data_settings['trading_mode']} → Smart")
 | 
			
		||||
                await rq.update_trade_mode_user(id, 'Smart')
 | 
			
		||||
                await main_settings_message(id, callback.message, state)
 | 
			
		||||
 | 
			
		||||
               await state.clear()
 | 
			
		||||
       await state.clear()
 | 
			
		||||
   except Exception as e:
 | 
			
		||||
        print(f"error: {e}")
 | 
			
		||||
 | 
			
		||||
@@ -103,32 +103,42 @@ async def state_size_leverage(message: Message, state):
 | 
			
		||||
    await state.update_data(size_leverage = message.text)
 | 
			
		||||
 | 
			
		||||
    data = await state.get_data()
 | 
			
		||||
    data_settings = await rq.get_user_main_settings(message.from_user.id)
 | 
			
		||||
 | 
			
		||||
    if data['size_leverage'].isdigit() and int(data['size_leverage']) <= 100:
 | 
			
		||||
        await message.answer(f"✅ Изменено: {data_settings['size_leverage']} → {data['size_leverage']}")
 | 
			
		||||
 | 
			
		||||
        await rq.update_size_leverange(message.from_user.id, data['size_leverage'])
 | 
			
		||||
        await main_settings_message(message.from_user.id, message, state)
 | 
			
		||||
 | 
			
		||||
        await state.clear()
 | 
			
		||||
    else:
 | 
			
		||||
        await message.answer(f'⛔️ Ошибка: ваше значение ({data['size_leverage']}) или выше лимита (100) или вы вводите неверные символы')
 | 
			
		||||
 | 
			
		||||
        await main_settings_message(message.from_user.id, message, state)        
 | 
			
		||||
 | 
			
		||||
async def martingale_factor_message(message, state):
 | 
			
		||||
    await state.set_state(update_main_settings.martingale_factor)
 | 
			
		||||
 | 
			
		||||
    await message.edit_text("Введите <b>коэффициент Мартингейла:</b>", parse_mode='html', reply_markup=inline_markup.back_btn_list_settings_markup)
 | 
			
		||||
 | 
			
		||||
                                                                                                           
 | 
			
		||||
@router_main_settings.message(update_main_settings.martingale_factor)
 | 
			
		||||
async def state_martingale_factor(message: Message, state):
 | 
			
		||||
    await state.update_data(martingale_factor = message.text)
 | 
			
		||||
 | 
			
		||||
    data = await state.get_data()
 | 
			
		||||
    data_settings = await rq.get_user_main_settings(message.from_user.id)
 | 
			
		||||
 | 
			
		||||
    if data['martingale_factor'].isdigit() and int(data['martingale_factor']) <= 100:
 | 
			
		||||
        await message.answer(f"✅ Изменено: {data_settings['martingale_factor']} → {data['martingale_factor']}")
 | 
			
		||||
 | 
			
		||||
        await rq.update_martingale_factor(message.from_user.id, data['martingale_factor'])
 | 
			
		||||
        await main_settings_message(message.from_user.id, message, state)
 | 
			
		||||
 | 
			
		||||
        await state.clear()
 | 
			
		||||
    else:
 | 
			
		||||
        await message.answer(f'⛔️ Ошибка: ваше значение ({data['martingale_factor']}) или выше лимита (100) или вы вводите неверные символы')
 | 
			
		||||
 | 
			
		||||
        await main_settings_message(message.from_user.id, message, state)
 | 
			
		||||
    
 | 
			
		||||
async def margin_type_message(message, state):
 | 
			
		||||
@@ -155,17 +165,21 @@ async def state_margin_type(callback: CallbackQuery, state):
 | 
			
		||||
   await callback.answer()
 | 
			
		||||
 | 
			
		||||
   id = callback.from_user.id
 | 
			
		||||
   print(f"sdljfngdjklfg ## {callback.data}")
 | 
			
		||||
   data_settings = await rq.get_user_main_settings(id)
 | 
			
		||||
 | 
			
		||||
   try:
 | 
			
		||||
       match callback.data:
 | 
			
		||||
           case 'margin_type_isolated':
 | 
			
		||||
                await rq.update_margin_type(id, 'Изолированный')
 | 
			
		||||
                await callback.message.answer(f"✅ Изменено: {data_settings['margin_type']} → Isolated")
 | 
			
		||||
 | 
			
		||||
                await rq.update_margin_type(id, 'Isolated')
 | 
			
		||||
                await main_settings_message(id, callback.message, state)
 | 
			
		||||
 | 
			
		||||
                await state.clear()
 | 
			
		||||
           case 'margin_type_cross':
 | 
			
		||||
                await rq.update_margin_type(id, 'Кросс')
 | 
			
		||||
                await callback.message.answer(f"✅ Изменено: {data_settings['margin_type']} → Cross")
 | 
			
		||||
 | 
			
		||||
                await rq.update_margin_type(id, 'Cross')
 | 
			
		||||
                await main_settings_message(id, callback.message, state)
 | 
			
		||||
 | 
			
		||||
                await state.clear()
 | 
			
		||||
@@ -182,30 +196,40 @@ async def state_starting_quantity(message: Message, state):
 | 
			
		||||
    await state.update_data(starting_quantity = message.text)
 | 
			
		||||
 | 
			
		||||
    data = await state.get_data()
 | 
			
		||||
    data_settings = await rq.get_user_main_settings(message.from_user.id)
 | 
			
		||||
 | 
			
		||||
    if data['starting_quantity'].isdigit():
 | 
			
		||||
        await message.answer(f"✅ Изменено: {data_settings['starting_quantity']} → {data['starting_quantity']}")
 | 
			
		||||
 | 
			
		||||
    if data['starting_quantity'].isdigit() and int(data['starting_quantity']) <= 100:
 | 
			
		||||
        await rq.update_starting_quantity(message.from_user.id, data['starting_quantity'])
 | 
			
		||||
        await main_settings_message(message.from_user.id, message, state)
 | 
			
		||||
 | 
			
		||||
        await state.clear()
 | 
			
		||||
    else:
 | 
			
		||||
        await message.answer(f'⛔️ Ошибка: вы вводите неверные символы')
 | 
			
		||||
 | 
			
		||||
        await main_settings_message(message.from_user.id, message, state)
 | 
			
		||||
 | 
			
		||||
async def maximum_quantity_message(message, state):
 | 
			
		||||
    await state.set_state(update_main_settings.maximal_quantity)
 | 
			
		||||
 | 
			
		||||
    await message.edit_text("Введите <b>максимальное количество ставок:</b>", parse_mode='html', reply_markup=inline_markup.back_btn_list_settings_markup)
 | 
			
		||||
    await message.edit_text("Введите <b>максимальное количество серии ставок:</b>", parse_mode='html', reply_markup=inline_markup.back_btn_list_settings_markup)
 | 
			
		||||
 | 
			
		||||
@router_main_settings.message(update_main_settings.maximal_quantity)
 | 
			
		||||
async def state_maximal_quantity(message: Message, state):
 | 
			
		||||
    await state.update_data(maximal_quantity = message.text)
 | 
			
		||||
 | 
			
		||||
    data = await state.get_data()
 | 
			
		||||
    data_settings = await rq.get_user_main_settings(message.from_user.id)
 | 
			
		||||
 | 
			
		||||
    if data['maximal_quantity'].isdigit() and int(data['maximal_quantity']) <= 100:
 | 
			
		||||
        await message.answer(f"✅ Изменено: {data_settings['maximal_quantity']} → {data['maximal_quantity']}")
 | 
			
		||||
 | 
			
		||||
        await rq.update_maximal_quantity(message.from_user.id, data['maximal_quantity'])
 | 
			
		||||
        await main_settings_message(message.from_user.id, message, state)
 | 
			
		||||
 | 
			
		||||
        await state.clear()
 | 
			
		||||
    else:
 | 
			
		||||
        await message.answer(f'⛔️ Ошибка: ваше значение ({data['maximal_quantity']}) или выше лимита (100) или вы вводите неверные символы')
 | 
			
		||||
        
 | 
			
		||||
        await main_settings_message(message.from_user.id, message, state)
 | 
			
		||||
@@ -1,37 +1,110 @@
 | 
			
		||||
import app.telegram.Keyboards.inline_keyboards as inline_markup
 | 
			
		||||
from aiogram import Router
 | 
			
		||||
import app.telegram.Keyboards.inline_keyboards as inline_markup
 | 
			
		||||
import app.telegram.Keyboards.reply_keyboards as reply_markup
 | 
			
		||||
 | 
			
		||||
import app.telegram.database.requests as rq
 | 
			
		||||
from aiogram.types import Message, CallbackQuery
 | 
			
		||||
 | 
			
		||||
# FSM - Механизм состояния
 | 
			
		||||
from aiogram.fsm.state import State, StatesGroup
 | 
			
		||||
 | 
			
		||||
router_risk_management_settings = Router()
 | 
			
		||||
 | 
			
		||||
class update_risk_management_settings(StatesGroup):
 | 
			
		||||
    price_profit = State()
 | 
			
		||||
    price_loss = State()
 | 
			
		||||
    max_risk_deal = State()
 | 
			
		||||
 | 
			
		||||
async def reg_new_user_default_risk_management_settings(id, message):
 | 
			
		||||
    tg_id = id
 | 
			
		||||
 | 
			
		||||
    await rq.set_new_user_default_risk_management_settings(tg_id)    
 | 
			
		||||
    await rq.set_new_user_default_risk_management_settings(tg_id)
 | 
			
		||||
 | 
			
		||||
async def main_settings_message(id, message, state):
 | 
			
		||||
    data = await rq.get_user_risk_management_settings(id)
 | 
			
		||||
 | 
			
		||||
async def main_settings_message(message):
 | 
			
		||||
    text = f"""<b>Риск менеджмент</b>,
 | 
			
		||||
 | 
			
		||||
    Процент изменения цены для фиксации прибыли: 0
 | 
			
		||||
 | 
			
		||||
    Процент изменения цены для фиксации убытков: 0
 | 
			
		||||
 | 
			
		||||
    Максимальный риск на сделку (в % от баланса): 0 
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    await message.edit_text(text=text, parse_mode='html', reply_markup=inline_markup.risk_management_settings_markup)
 | 
			
		||||
<b>- Процент изменения цены для фиксации прибыли:</b> {data['price_profit']}%
 | 
			
		||||
<b>- Процент изменения цены для фиксации убытков:</b> {data['price_loss']}%
 | 
			
		||||
<b>- Максимальный риск на сделку (в % от баланса):</b> {data['max_risk_deal']}% 
 | 
			
		||||
"""
 | 
			
		||||
    await message.answer(text=text, parse_mode='html', reply_markup=inline_markup.risk_management_settings_markup)
 | 
			
		||||
 | 
			
		||||
async def price_profit_message(message, state):
 | 
			
		||||
    await state.set_state(update_risk_management_settings.price_profit)
 | 
			
		||||
 | 
			
		||||
    text =  'Введите число изменения цены для фиксации прибыли: '
 | 
			
		||||
 | 
			
		||||
    await message.answer(text=text, parse_mode='html', reply_markup=None)
 | 
			
		||||
 | 
			
		||||
@router_risk_management_settings.message(update_risk_management_settings.price_profit)
 | 
			
		||||
async def state_price_profit(message: Message, state):
 | 
			
		||||
    await state.update_data(price_profit = message.text)
 | 
			
		||||
 | 
			
		||||
    data = await state.get_data()
 | 
			
		||||
    data_settings = await rq.get_user_risk_management_settings(message.from_user.id)
 | 
			
		||||
 | 
			
		||||
    if data['price_profit'].isdigit() and int(data['price_profit']) <= 100:
 | 
			
		||||
        await message.answer(f"✅ Изменено: {data_settings['price_profit']}% → {data['price_profit']}%")
 | 
			
		||||
 | 
			
		||||
        await rq.update_price_profit(message.from_user.id, data['price_profit'])
 | 
			
		||||
        await main_settings_message(message.from_user.id, message, state)
 | 
			
		||||
 | 
			
		||||
        await state.clear()
 | 
			
		||||
    else:
 | 
			
		||||
        await message.answer(f'⛔️ Ошибка: ваше значение ({data['price_profit']}%) или выше лимита (100) или вы вводите неверные символы')
 | 
			
		||||
 | 
			
		||||
        await main_settings_message(message.from_user.id, message, state) 
 | 
			
		||||
 | 
			
		||||
async def price_loss_message(message, state):
 | 
			
		||||
    await state.set_state(update_risk_management_settings.price_loss)
 | 
			
		||||
 | 
			
		||||
    text =  'Введите число изменения цены для фиксации убытков: '
 | 
			
		||||
 | 
			
		||||
    await message.answer(text=text, parse_mode='html', reply_markup=None)
 | 
			
		||||
 | 
			
		||||
@router_risk_management_settings.message(update_risk_management_settings.price_loss)
 | 
			
		||||
async def state_price_loss(message: Message, state):
 | 
			
		||||
    await state.update_data(price_loss = message.text)
 | 
			
		||||
 | 
			
		||||
    data = await state.get_data()
 | 
			
		||||
    data_settings = await rq.get_user_risk_management_settings(message.from_user.id)
 | 
			
		||||
 | 
			
		||||
    if data['price_loss'].isdigit() and int(data['price_loss']) <= 100:
 | 
			
		||||
        await message.answer(f"✅ Изменено: {data_settings['price_loss']}% → {data['price_loss']}%")
 | 
			
		||||
 | 
			
		||||
        await rq.update_price_loss(message.from_user.id, data['price_loss'])
 | 
			
		||||
        await main_settings_message(message.from_user.id, message, state)
 | 
			
		||||
 | 
			
		||||
        await state.clear()
 | 
			
		||||
    else:
 | 
			
		||||
        await message.answer(f'⛔️ Ошибка: ваше значение ({data['price_loss']}%) или выше лимита (100) или вы вводите неверные символы')
 | 
			
		||||
 | 
			
		||||
        await main_settings_message(message.from_user.id, message, state) 
 | 
			
		||||
 | 
			
		||||
async def max_risk_deal_message(message, state):
 | 
			
		||||
    await state.set_state(update_risk_management_settings.max_risk_deal)
 | 
			
		||||
 | 
			
		||||
    text =  'Введите число (процент от баланса) для изменения максимального риска на сделку: '
 | 
			
		||||
 | 
			
		||||
    await message.answer(text=text, parse_mode='html', reply_markup=None)
 | 
			
		||||
    await message.answer(text=text, parse_mode='html', reply_markup=None)
 | 
			
		||||
 | 
			
		||||
@router_risk_management_settings.message(update_risk_management_settings.max_risk_deal)
 | 
			
		||||
async def state_max_risk_deal(message: Message, state):
 | 
			
		||||
    await state.update_data(max_risk_deal = message.text)
 | 
			
		||||
 | 
			
		||||
    data = await state.get_data()
 | 
			
		||||
    data_settings = await rq.get_user_risk_management_settings(message.from_user.id)
 | 
			
		||||
 | 
			
		||||
    if data['max_risk_deal'].isdigit() and int(data['max_risk_deal']) <= 100:
 | 
			
		||||
        await message.answer(f"✅ Изменено: {data_settings['max_risk_deal']}% → {data['max_risk_deal']}%")
 | 
			
		||||
 | 
			
		||||
        await rq.update_max_risk_deal(message.from_user.id, data['max_risk_deal'])
 | 
			
		||||
        await main_settings_message(message.from_user.id, message, state)
 | 
			
		||||
 | 
			
		||||
        await state.clear()
 | 
			
		||||
    else:
 | 
			
		||||
        await message.answer(f'⛔️ Ошибка: ваше значение ({data['max_risk_deal']}%) или выше лимита (100) или вы вводите неверные символы')
 | 
			
		||||
 | 
			
		||||
        await main_settings_message(message.from_user.id, message, state) 
 | 
			
		||||
@@ -19,6 +19,7 @@ router = Router()
 | 
			
		||||
 | 
			
		||||
@router.message(CommandStart())
 | 
			
		||||
async def start_message(message: Message):
 | 
			
		||||
    await rq.set_new_user_bybit_api(message.from_user.id)
 | 
			
		||||
    await func.start_message(message)
 | 
			
		||||
 | 
			
		||||
@router.message(F.text == "👤 Профиль")
 | 
			
		||||
@@ -35,26 +36,34 @@ async def settings_msg(message: Message):
 | 
			
		||||
    if user:
 | 
			
		||||
        await func.settings_message(message)
 | 
			
		||||
 | 
			
		||||
@router.callback_query(F.data == "callback_registration")
 | 
			
		||||
async def clb_func_reg (callback: CallbackQuery):
 | 
			
		||||
    await rq.save_tg_id_new_user(callback.from_user.id)
 | 
			
		||||
    print(callback.from_user.id)
 | 
			
		||||
 | 
			
		||||
    await func_main_settings.reg_new_user_default_main_settings(callback.from_user.id, callback.message)
 | 
			
		||||
    await func_rmanagement_settings.reg_new_user_default_risk_management_settings(callback.from_user.id, callback.message)
 | 
			
		||||
    await func_condition_settings.reg_new_user_default_condition_settings(callback.from_user.id, callback.message) 
 | 
			
		||||
    await func_additional_settings.reg_new_user_default_additional_settings(callback.from_user.id, callback.message)
 | 
			
		||||
 | 
			
		||||
    await callback.message.answer(f'Регистрация прошла успешно, здравствуйте {callback.from_user.username}!', reply_markup=reply_markup.base_buttons_markup)
 | 
			
		||||
 | 
			
		||||
    await callback.answer()
 | 
			
		||||
 | 
			
		||||
@router.callback_query(F.data == "callback_autorisation")
 | 
			
		||||
async def clb_func_reg (callback: CallbackQuery):
 | 
			
		||||
@router.callback_query(F.data == "clb_start_chatbot_message")
 | 
			
		||||
async def clb_profile_msg (callback: CallbackQuery):
 | 
			
		||||
    user = await rq.check_user(callback.from_user.id)
 | 
			
		||||
 | 
			
		||||
    if user:
 | 
			
		||||
    username = ''
 | 
			
		||||
    
 | 
			
		||||
    if callback.from_user.first_name == None: 
 | 
			
		||||
        username = callback.from_user.last_name
 | 
			
		||||
    elif callback.from_user.last_name == None:
 | 
			
		||||
        username = callback.from_user.first_name
 | 
			
		||||
    else:
 | 
			
		||||
        username = f'{callback.from_user.first_name} {callback.from_user.last_name}'
 | 
			
		||||
 | 
			
		||||
    if user:      
 | 
			
		||||
        await func.profile_message(callback.from_user.username, callback.message)
 | 
			
		||||
    else:
 | 
			
		||||
        await rq.save_tg_id_new_user(callback.from_user.id)
 | 
			
		||||
 | 
			
		||||
        await func_main_settings.reg_new_user_default_main_settings(callback.from_user.id, callback.message)
 | 
			
		||||
        await func_rmanagement_settings.reg_new_user_default_risk_management_settings(callback.from_user.id, callback.message)
 | 
			
		||||
        await func_condition_settings.reg_new_user_default_condition_settings(callback.from_user.id, callback.message) 
 | 
			
		||||
        await func_additional_settings.reg_new_user_default_additional_settings(callback.from_user.id, callback.message)
 | 
			
		||||
 | 
			
		||||
        await callback.message.answer(f'Здравствуйте, {username}!', reply_markup=reply_markup.base_buttons_markup)
 | 
			
		||||
 | 
			
		||||
        await func.profile_message(username, callback.message)
 | 
			
		||||
 | 
			
		||||
    await callback.answer()
 | 
			
		||||
    
 | 
			
		||||
 # Настройки торговли
 | 
			
		||||
@router.callback_query(F.data == "clb_settings_message")
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user