forked from kodorvan/stcs
version 1 STCS
This commit is contained in:
9
app/services/Bybit/config.py
Normal file
9
app/services/Bybit/config.py
Normal file
@@ -0,0 +1,9 @@
|
||||
API_KEY=''
|
||||
API_SECRET=''
|
||||
SYMBOL=''
|
||||
|
||||
'''
|
||||
API_KEY = 'o5854uk3qBD4lySnjv'
|
||||
SECRET_KEY = 'aMFPbs0AKyOSLTgXyrqCfREDi7byjnsOd0Kj'
|
||||
SYMBOL = "SHIB1000USDT"
|
||||
'''
|
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('Данные добавлены, нажмите на профиль и начните торговлю!')
|
||||
|
||||
|
348
app/services/Bybit/functions/Futures.py
Normal file
348
app/services/Bybit/functions/Futures.py
Normal file
@@ -0,0 +1,348 @@
|
||||
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:
|
||||
print(f'''
|
||||
=====================
|
||||
=====Сделка=========
|
||||
===уСПЕШНЕАЯ================
|
||||
===================
|
||||
=================
|
||||
|
||||
{realised_pnl}
|
||||
|
||||
===============
|
||||
===============
|
||||
=============
|
||||
===============
|
||||
==============
|
||||
''')
|
||||
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
|
||||
|
||||
print(f'''
|
||||
======СДЕЛКА===============
|
||||
=====УБЫТОЧНАЯ==============
|
||||
===================
|
||||
===================
|
||||
=================
|
||||
|
||||
{realised_pnl}
|
||||
|
||||
===============
|
||||
===============
|
||||
=============
|
||||
===============
|
||||
==============
|
||||
''')
|
||||
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)
|
||||
|
||||
print(f'''
|
||||
=====================
|
||||
===================
|
||||
===================
|
||||
===================
|
||||
=================
|
||||
|
||||
{r}
|
||||
|
||||
===============
|
||||
===============
|
||||
=============
|
||||
===============
|
||||
==============
|
||||
''')
|
||||
|
||||
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:
|
||||
print(f'''
|
||||
=====================
|
||||
=====Сделка=========
|
||||
===уСПЕШНЕАЯ================
|
||||
===================
|
||||
=================
|
||||
|
||||
{realised_pnl}
|
||||
|
||||
===============
|
||||
===============
|
||||
=============
|
||||
===============
|
||||
==============
|
||||
''')
|
||||
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
|
||||
|
||||
print(f'''
|
||||
======СДЕЛКА===============
|
||||
=====УБЫТОЧНАЯ==============
|
||||
===================
|
||||
===================
|
||||
=================
|
||||
|
||||
{realised_pnl}
|
||||
|
||||
===============
|
||||
===============
|
||||
=============
|
||||
===============
|
||||
==============
|
||||
''')
|
||||
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)
|
||||
|
||||
print(f'''
|
||||
=====================
|
||||
===================
|
||||
===================
|
||||
===================
|
||||
=================
|
||||
|
||||
{r}
|
||||
|
||||
===============
|
||||
===============
|
||||
=============
|
||||
===============
|
||||
==============
|
||||
''')
|
||||
|
||||
except exceptions.InvalidRequestError as e:
|
||||
await message.answer('Недостаточно баланса')
|
||||
except Exception as e:
|
||||
await message.answer('Непредвиденная оишбка')
|
38
app/services/Bybit/functions/balance.py
Normal file
38
app/services/Bybit/functions/balance.py
Normal file
@@ -0,0 +1,38 @@
|
||||
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
|
||||
)
|
||||
|
||||
try:
|
||||
balance = client.get_wallet_balance(accountType='UNIFIED', coin='USDT')['result']['list'][0]['coin'][0]['walletBalance']
|
||||
|
||||
print(f'''
|
||||
=====================
|
||||
=====BALANCE=========
|
||||
======USDT=============
|
||||
===================
|
||||
=================
|
||||
|
||||
{balance}
|
||||
|
||||
===============
|
||||
===============
|
||||
=============
|
||||
===============
|
||||
==============
|
||||
''')
|
||||
|
||||
return balance
|
||||
except Exception as e:
|
||||
await message.answer('Баланс не был получен')
|
||||
return 0
|
37
app/services/Bybit/functions/func_min_qty.py
Normal file
37
app/services/Bybit/functions/func_min_qty.py
Normal file
@@ -0,0 +1,37 @@
|
||||
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)
|
||||
|
||||
print(f'''
|
||||
=====================
|
||||
=====MIN=========
|
||||
=====QTY==============
|
||||
===================
|
||||
=================
|
||||
|
||||
{min_qty}
|
||||
|
||||
===============
|
||||
===============
|
||||
=============
|
||||
===============
|
||||
==============
|
||||
''')
|
||||
|
||||
return min_qty
|
105
app/services/Bybit/functions/functions.py
Normal file
105
app/services/Bybit/functions/functions.py
Normal file
@@ -0,0 +1,105 @@
|
||||
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)
|
||||
|
||||
if api and secret:
|
||||
balance = await get_balance(callback.from_user.id, callback.message)
|
||||
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)
|
||||
else:
|
||||
callback.message.answer('Перед началом работы, в настройках подключите bybit')
|
||||
|
||||
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)
|
||||
|
||||
if api and secret:
|
||||
balance = await get_balance(message.from_user.id, message)
|
||||
symbol = await rq.get_symbol(message.from_user.id)
|
||||
|
||||
text = f'''Торговля на Bybit
|
||||
|
||||
<b>ваш баланс (USDT):</b> {balance}
|
||||
<b>Текущая торговая пара: </b> {symbol}
|
||||
|
||||
Как начать торговлю?
|
||||
1. Внимательно проверьте и настройте все параметры в вашем профиле
|
||||
2. Ниже нажмите 'Указать торговую пару' и отправьте торговую пару заглавными буквами, указав два актива без всяких лишних символов! (Пример: BTCUSDT)
|
||||
'''
|
||||
|
||||
await message.answer(text=text, parse_mode='html', reply_markup=inline_markup.trading_markup)
|
||||
else:
|
||||
await message.answer('Перед началом работы, в настройках подключите bybit')
|
||||
|
||||
@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 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':
|
||||
print('====================================LONG=========================================')
|
||||
await Futures.contract_long(callback.from_user.id, callback.message, margin_mode)
|
||||
case 'Short':
|
||||
print('====================================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
|
40
app/services/Bybit/functions/price_symbol.py
Normal file
40
app/services/Bybit/functions/price_symbol.py
Normal file
@@ -0,0 +1,40 @@
|
||||
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'))
|
||||
|
||||
print(f'''
|
||||
=====================
|
||||
=====PRICE=========
|
||||
===================
|
||||
===================
|
||||
=================
|
||||
|
||||
{price}
|
||||
|
||||
===============
|
||||
===============
|
||||
=============
|
||||
===============
|
||||
==============
|
||||
''')
|
||||
|
||||
return price
|
||||
except exceptions.InvalidRequestError as e:
|
||||
await message.answer('Неверно указана торговая пара')
|
||||
return 1.0
|
Reference in New Issue
Block a user