forked from kodorvan/stcs
Added documentation
This commit is contained in:
40
app/services/Bybit/functions/get_valid_symbol.py
Normal file
40
app/services/Bybit/functions/get_valid_symbol.py
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import logging.config
|
||||||
|
from pybit.unified_trading import HTTP
|
||||||
|
import app.telegram.database.requests as rq
|
||||||
|
from logger_helper.logger_helper import LOGGING_CONFIG
|
||||||
|
|
||||||
|
logging.config.dictConfig(LOGGING_CONFIG)
|
||||||
|
logger = logging.getLogger("get_valid_symbol")
|
||||||
|
|
||||||
|
|
||||||
|
async def get_valid_symbols(user_id: int, symbol: str) -> bool:
|
||||||
|
"""
|
||||||
|
Проверяет существование торговой пары на Bybit в категории 'linear'.
|
||||||
|
|
||||||
|
Эта функция получает API-ключи пользователя из базы данных и
|
||||||
|
с помощью Bybit API проверяет наличие данного символа в списке
|
||||||
|
торговых инструментов категории 'linear'.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user_id (int): Идентификатор пользователя Telegram.
|
||||||
|
symbol (str): Торговый символ (валютная пара), например "BTCUSDT".
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: Возвращает True, если торговая пара существует, иначе False.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
Исключения подавляются и вызывается False, если произошла ошибка запроса к API.
|
||||||
|
"""
|
||||||
|
api_key = await rq.get_bybit_api_key(user_id)
|
||||||
|
secret_key = await rq.get_bybit_secret_key(user_id)
|
||||||
|
client = HTTP(api_key=api_key, api_secret=secret_key)
|
||||||
|
|
||||||
|
try:
|
||||||
|
resp = client.get_instruments_info(category='linear', symbol=symbol)
|
||||||
|
# Проверка наличия результата и непустого списка инструментов
|
||||||
|
if resp.get('retCode') == 0 and resp.get('result') and resp['result'].get('list'):
|
||||||
|
return len(resp['result']['list']) > 0
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Ошибка при получении списка инструментов: {e}")
|
||||||
|
return False
|
@@ -1,23 +1,52 @@
|
|||||||
from app.services.Bybit.functions import price_symbol
|
import math
|
||||||
|
import logging.config
|
||||||
|
from app.services.Bybit.functions.price_symbol import get_price
|
||||||
import app.telegram.database.requests as rq
|
import app.telegram.database.requests as rq
|
||||||
|
from logger_helper.logger_helper import LOGGING_CONFIG
|
||||||
from pybit.unified_trading import HTTP
|
from pybit.unified_trading import HTTP
|
||||||
|
|
||||||
client = HTTP()
|
logging.config.dictConfig(LOGGING_CONFIG)
|
||||||
|
logger = logging.getLogger("min_qty")
|
||||||
|
|
||||||
async def get_min_qty(tg_id):
|
def round_up_qty(value: float, step: float) -> float:
|
||||||
|
"""
|
||||||
|
Округление value вверх до ближайшего кратного step.
|
||||||
|
"""
|
||||||
|
return math.ceil(value / step) * step
|
||||||
|
|
||||||
|
async def get_min_qty(tg_id: int) -> float:
|
||||||
|
"""
|
||||||
|
Получает минимальный объем (количество) ордера для символа пользователя на Bybit,
|
||||||
|
округленное с учетом шага количества qtyStep.
|
||||||
|
|
||||||
|
:param tg_id: int - идентификатор пользователя Telegram
|
||||||
|
:return: float - минимальное количество лота для ордера
|
||||||
|
"""
|
||||||
api_key = await rq.get_bybit_api_key(tg_id)
|
api_key = await rq.get_bybit_api_key(tg_id)
|
||||||
secret_key = await rq.get_bybit_secret_key(tg_id)
|
secret_key = await rq.get_bybit_secret_key(tg_id)
|
||||||
SYMBOL = await rq.get_symbol(tg_id)
|
symbol = await rq.get_symbol(tg_id)
|
||||||
|
|
||||||
client = HTTP(
|
client = HTTP(api_key=api_key, api_secret=secret_key)
|
||||||
api_key=api_key,
|
|
||||||
api_secret=secret_key
|
|
||||||
)
|
|
||||||
|
|
||||||
price = await price_symbol(tg_id)
|
price = await get_price(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
|
response = client.get_instruments_info(symbol=symbol, category='linear')
|
||||||
|
|
||||||
return min_qty
|
instrument = response['result'][0]
|
||||||
|
lot_size_filter = instrument.get('lotSizeFilter', {})
|
||||||
|
|
||||||
|
min_order_qty = float(lot_size_filter.get('minOrderQty', 0))
|
||||||
|
min_notional_value = float(lot_size_filter.get('minNotionalValue', 0))
|
||||||
|
qty_step = float(lot_size_filter.get('qtyStep', 1))
|
||||||
|
|
||||||
|
calculated_qty = (5 / price) * 1.1
|
||||||
|
|
||||||
|
min_qty = max(min_order_qty, calculated_qty)
|
||||||
|
|
||||||
|
min_qty_rounded = round_up_qty(min_qty, qty_step)
|
||||||
|
|
||||||
|
logger.debug(f"tg_id={tg_id}: price={price}, min_order_qty={min_order_qty}, "
|
||||||
|
f"min_notional_value={min_notional_value}, qty_step={qty_step}, "
|
||||||
|
f"calculated_qty={calculated_qty}, min_qty_rounded={min_qty_rounded}")
|
||||||
|
|
||||||
|
return min_qty_rounded
|
||||||
|
@@ -1,24 +1,33 @@
|
|||||||
import app.telegram.database.requests as rq
|
import app.telegram.database.requests as rq
|
||||||
|
import logging.config
|
||||||
|
from logger_helper.logger_helper import LOGGING_CONFIG
|
||||||
from pybit import exceptions
|
from pybit import exceptions
|
||||||
from pybit.unified_trading import HTTP
|
from pybit.unified_trading import HTTP
|
||||||
|
|
||||||
client = HTTP()
|
logging.config.dictConfig(LOGGING_CONFIG)
|
||||||
|
logger = logging.getLogger("price_symbol")
|
||||||
|
|
||||||
async def get_price(tg_id, message):
|
|
||||||
|
async def get_price(tg_id: int) -> float:
|
||||||
|
"""
|
||||||
|
Асинхронно получает текущую цену символа пользователя на Bybit.
|
||||||
|
|
||||||
|
:param tg_id: int - ID пользователя Telegram
|
||||||
|
:return: float - текущая цена символа
|
||||||
|
"""
|
||||||
api_key = await rq.get_bybit_api_key(tg_id)
|
api_key = await rq.get_bybit_api_key(tg_id)
|
||||||
secret_key = await rq.get_bybit_secret_key(tg_id)
|
secret_key = await rq.get_bybit_secret_key(tg_id)
|
||||||
SYMBOL = await rq.get_symbol(tg_id)
|
symbol = await rq.get_symbol(tg_id)
|
||||||
|
|
||||||
client = HTTP(
|
client = HTTP(
|
||||||
api_key=api_key,
|
api_key=api_key,
|
||||||
api_secret=secret_key
|
api_secret=secret_key
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
|
||||||
price = float(client.get_tickers(category='linear', symbol=SYMBOL).get('result').get('list')[0].get('ask1Price'))
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
price = float(
|
||||||
|
client.get_tickers(category='linear', symbol=symbol).get('result').get('list')[0].get('ask1Price'))
|
||||||
return price
|
return price
|
||||||
except exceptions.InvalidRequestError as e:
|
except exceptions.InvalidRequestError as e:
|
||||||
await message.answer('Неверно указана торговая пара')
|
logger.error(f"Ошибка при получении цены: {e}")
|
||||||
return 1.0
|
return 1.0
|
||||||
|
Reference in New Issue
Block a user