9 Commits

Author SHA1 Message Date
f26df3b1a4 Merge pull request 'Merge pull STCS' (#2) from Pixe1lz/stcs:stable into stable
Reviewed-on: kodorvan/stcs#2
2025-07-30 14:32:49 +07:00
Kirill Strelnikov
1997b9d1c0 The message about the Bybit profile output has been corrected when clicking the "Start" button, and messages regarding the requirement to connect the platform and incorrect API entries have been added. Messages about successful and erroneous changes to user settings have been added. 2025-07-22 16:08:23 +07:00
Kirill Strelnikov
e555bfa8fb The text of the welcome message has been changed, the text of the risk management settings has been changed, the default value for "maximum_trade_risk" in the database has been changed from 1 to 100. The message upon re-clicking the "Start Trading" button has been removed. 2025-07-22 12:54:23 +07:00
Kirill Strelnikov
0fecb5dab7 Merge branch 'stable' of https://git.svoboda.works/Pixe1lz/stcs into stable 2025-07-21 16:58:38 +07:00
Kirill Strelnikov
242be34a97 fix app/telegram/handlers/handlers.py, fix app/telegram/functions/functions.py || change two buttons "Начать торговлю" || fix text registration message, fix text profile || delete app/services/Bybit/config.py || delete comments 2025-07-21 16:55:30 +07:00
Бездельник бездельников
2da3c282d1 merge upstream 2025-07-21 15:33:27 +07:00
Kirill Strelnikov
fb0c14aba1 Update Readme.md 2025-07-21 15:05:50 +07:00
Kirill Strelnikov
ed67ed78c0 version 1 STCS 2025-07-21 13:40:33 +07:00
127003ebe1 Merge pull request 'add files project' (#1) from Pixe1lz/stcs:stable into stable
Reviewed-on: kodorvan/stcs#1
2025-07-10 18:26:34 +07:00
20 changed files with 916 additions and 134 deletions

View File

@@ -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)

View File

@@ -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\" />

View File

@@ -1 +1,20 @@
abobus
# Чат-робот STCS
__
**Функционал:**
+ **Настройки**
+ Основные параметры *(Настроен, работает)*
+ Режим торговли Лонг/Шорт *(настроены)*, Switch/Smart *(не настроены)*
+ Тип маржи: Изолированная / Кросс *(настроено)*
+ Размер кредитного плеча: от x1 до x100 *(настроено)*
+ Начальная ставка: числовое значение *(настроено)*
+ Коэффициент мартингейла: число *(настроено)*
+ Максимальное количество ставок в серии: число *(настроено)*
+ Риск-менеджмент (Настроен, работает)
+ Процент изменения цены для фиксации прибыли (TP%): число *(настроено)*
+ Процент изменения цены для фиксации убытков (SL%): число (пример: 1%) *(настроено)*
+ Максимальный риск на сделку (в % от баланса): число (опционально) *(настроено)*
+ Условия запуска *(Не настроен)*
+ Дополнительные параметры *(Не настроен)*
+ Подключение Bybit *(настроено)*
+ Информация о правильном получении и сохранении Bybit-API keys *(настроено)*

View 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('Данные добавлены, нажмите на профиль и начните торговлю!')

View 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('Непредвиденная оишбка')

View 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

View 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

View 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 пока недоступен')

View 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

View 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

View File

@@ -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")]
])

View File

@@ -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)

View File

@@ -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():

View File

@@ -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()

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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")