Python

Получение данных Bybit при помощи Python

Если у вас еще не установлена библиотека Pybit, нужно выполнить следующую команду:

pip install pybit

После успешной установки пакета, в самом начале мы импортируем библиотеку Pybit, как показано ниже:

from pybit.unified_trading import HTTP
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import datetime as dt
import time 
import json

with open('authcreds.json') as j:
        creds = json.load(j)
        
key = creds['KEY_NAME']['key']
secret = creds['KEY_NAME']['secret']
  
session = HTTP(api_key=key, api_secret=secret, testnet=False)

Для того чтобы получать исторические данные от Bybit, необходимо определиться с рядом параметров перед вызовом API. Для целей этой статьи мы будем собирать данные бессрочного фьючерсного контракта USDT. Поэтому мы будем использовать категорию “linear”, как показано ниже.

categorytruestringТип продукта: spot,linear,inverse,option
symbolfalsestringОбозначение
baseCoinfalsestringБазовая монета. Только для опций
expDatefalsestringExpiry date. e.g., 25DEC22. For option only

Получение списка доступных бессрочных контрактов USDT Bybit 

Тикер криптовалюты – это символ или аббревиатура, обозначающая конкретную криптовалюту, подобно тому, как символы акций обозначают публично торгуемые компании.

Тикер криптовалют представляет собой комбинацию букв и цифр, которые используются для уникальной идентификации конкретной криптовалюты. Например для Биткойна тикер это “BTC”, тикер Ethereum это “ETH”.

Тикеры криптовалют используются для отслеживания производительности конкретной криптовалюты и обеспечения удобства получения справочной информаций или торговле этой криптовалютой. Когда вы ищете криптовалюту на торговой платформе или в системе отслеживания цен, вы обычно видите ее тикер, отображаемый рядом с текущей ценой и другой информацией.

result = session.get_tickers(
                category="linear").get('result')['list']

tickers = [asset['symbol'] for asset in result if asset['symbol'].endswith('USDT')]
print(tickers)

Будет выведен общий список продуктов USDT, которые Bybit в настоящее время предлагает. Затем пользователи могут выбрать актив для загрузки исторических данных в следующем разделе.

['10000NFTUSDT', '1000BONKUSDT', '1000BTTUSDT', '1000FLOKIUSDT', '1000LUNCUSDT', '1000XECUSDT', '1INCHUSDT', 'AAVEUSDT', 'ACHUSDT', 'ADAUSDT', 'AGIXUSDT', 'AGLDUSDT', 'AKROUSDT', 'ALGOUSDT', 'ALICEUSDT', 'ALPHAUSDT', 'ANKRUSDT', 'ANTUSDT', 'APEUSDT', 'API3USDT', 'APTUSDT', 'ARBUSDT', 'ARPAUSDT', 'ARUSDT', 'ASTRUSDT', 'ATOMUSDT', 'AUDIOUSDT', 'AVAXUSDT', 'AXSUSDT', 'BAKEUSDT', 'BALUSDT', 'BANDUSDT', 'BATUSDT', 'BCHUSDT', 'BELUSDT', 'BICOUSDT', 'BITUSDT', 'BLURUSDT', 'BLZUSDT', 'BNBUSDT', 'BNXUSDT', 'BOBAUSDT', 'BSVUSDT', 'BSWUSDT', 'BTCUSDT', 'BUSDUSDT', 'C98USDT', 'CEEKUSDT', 'CELOUSDT', 'CELRUSDT', 'CFXUSDT', 'CHRUSDT', 'CHZUSDT', 'CKBUSDT', 'COCOSUSDT', 'COMPUSDT', 'COREUSDT', 'COTIUSDT', 'CREAMUSDT', 'CROUSDT', 'CRVUSDT', 'CTCUSDT', 'CTKUSDT', 'CTSIUSDT', 'CVCUSDT', 'CVXUSDT', 'DARUSDT', 'DASHUSDT', 'DENTUSDT', 'DGBUSDT', 'DODOUSDT', 'DOGEUSDT', 'DOTUSDT', 'DUSKUSDT', 'DYDXUSDT', 'EGLDUSDT', 'ENJUSDT', 'ENSUSDT', 'EOSUSDT', 'ETCUSDT', 'ETHUSDT', 'ETHWUSDT', 'FETUSDT', 'FILUSDT', 'FITFIUSDT', 'FLMUSDT', 'FLOWUSDT', 'FLRUSDT', 'FTMUSDT', 'FXSUSDT', 'GALAUSDT', 'GALUSDT', 'GFTUSDT', 'GLMRUSDT', 'GMTUSDT', 'GMXUSDT', 'GPTUSDT', 'GRTUSDT', 'GTCUSDT', 'HBARUSDT', 'HFTUSDT', 'HIGHUSDT', 'HNTUSDT', 'HOOKUSDT', 'HOTUSDT', 'ICPUSDT', 'ICXUSDT', 'IDUSDT', 'ILVUSDT', 'IMXUSDT', 'INJUSDT', 'IOSTUSDT', 'IOTAUSDT', 'IOTXUSDT', 'JASMYUSDT', 'JOEUSDT', 'JSTUSDT', 'KAVAUSDT', 'KDAUSDT', 'KLAYUSDT', 'KNCUSDT', 'KSMUSDT', 'LDOUSDT', 'LINAUSDT', 'LINKUSDT', 'LITUSDT', 'LOOKSUSDT', 'LPTUSDT', 'LQTYUSDT', 'LRCUSDT', 'LTCUSDT', 'LUNA2USDT', 'MAGICUSDT', 'MANAUSDT', 'MASKUSDT', 'MATICUSDT', 'MINAUSDT', 'MKRUSDT', 'MTLUSDT', 'NEARUSDT', 'NEOUSDT', 'NKNUSDT', 'OCEANUSDT', 'OGNUSDT', 'OMGUSDT', 'ONEUSDT', 'ONTUSDT', 'OPUSDT', 'PAXGUSDT', 'PEOPLEUSDT', 'QTUMUSDT', 'RDNTUSDT', 'REEFUSDT', 'RENUSDT', 'REQUSDT', 'RLCUSDT', 'RNDRUSDT', 'ROSEUSDT', 'RPLUSDT', 'RSRUSDT', 'RSS3USDT', 'RUNEUSDT', 'RVNUSDT', 'SANDUSDT', 'SCRTUSDT', 'SCUSDT', 'SFPUSDT', 'SHIB1000USDT', 'SKLUSDT', 'SLPUSDT', 'SNXUSDT', 'SOLUSDT', 'SPELLUSDT', 'SSVUSDT', 'STGUSDT', 'STMXUSDT', 'STORJUSDT', 'STXUSDT', 'SUNUSDT', 'SUSHIUSDT', 'SWEATUSDT', 'SXPUSDT', 'THETAUSDT', 'TLMUSDT', 'TOMOUSDT', 'TRBUSDT', 'TRUUSDT', 'TRXUSDT', 'TUSDT', 'TWTUSDT', 'UNFIUSDT', 'UNIUSDT', 'USDCUSDT', 'VETUSDT', 'WAVESUSDT', 'WOOUSDT', 'XCNUSDT', 'XEMUSDT', 'XLMUSDT', 'XMRUSDT', 'XNOUSDT', 'XRPUSDT', 'XTZUSDT', 'YFIUSDT', 'YGGUSDT', 'ZECUSDT', 'ZENUSDT', 'ZILUSDT', 'ZRXUSDT']

Получение исторических дневных данных

После того, как мы выбрали бессрочный USDT можно приступить к сбору данных. В таблице ниже показаны аргументы, которые нам необходимо учитывать для получения исторических данных. Обратите внимание, что параметр interval, показанный в таблице ниже, относится к частоте передачи данных, т. е. 1 = 1 минута.

ПараметрОбязательныйТипКомментарий
categorytruestringТип продукта spot, linear, inverse
symboltruestringSymbol name
intervaltrueint/stringKline interval. 1, 3, 5, 15, 30, 60, 120, 240, 360, 720, D, M, W
startfalseintegerThe start timestamp (ms)
endfalseintegerThe end timestamp (ms)

В таблице ниже показаны параметры ответа. Функция format_data, приведенная выше, извлекает информацию из списка API и форматирует ее в dataframe pandas.

categorystringТипа продукта
symbolstringSymbol name
listarrayAn string array of individual candleSort in reverse by startTimelist[0]: startTime – Start time of the candle (ms)list[1]: openPrice – Open pricelist[2]: highPrice – Highest pricelist[3]: lowPrice – Lowest pricelist[4]: closePrice – Close price. Is the last traded price when the candle is not closedlist[5]: volume – Trade volume. Unit of contract: pieces of contract. Unit of spot: quantity of coinslist[6]: turnover – Turnover. Unit of figure: quantity of quota coin

Приведенный ниже скрипт Python вызывает метод get_kline из Pybit. Обратите внимание, что мы не передаем аргумент временной метки starts/end, к которому мы вернемся позже в этой статье.

response = session.get_kline(category='linear', 
                             symbol='ETHUSDT', 
                             interval='D').get('result')

def format_data(response):
    '''

    Parameters
    ----------
    respone : dict
        response from calling get_klines() method from pybit.

    Returns
    -------
    dataframe of ohlc data with date as index

    '''
    data = response.get('list', None)
    
    if not data:
        return 
    
    data = pd.DataFrame(data,
                        columns =[
                            'timestamp',
                            'open',
                            'high',
                            'low',
                            'close',
                            'volume',
                            'turnover'
                            ],
                        )
    
    f = lambda x: dt.datetime.utcfromtimestamp(int(x)/1000)
    data.index = data.timestamp.apply(f)
    return data[::-1].apply(pd.to_numeric)

df = format_data(response)

print(df)
'''

               timestamp         open  ...        volume      turnover
timestamp                              ...                            
2022-10-12  1.665533e+12  1279.300049  ...  7.275909e+05  9.415818e+08
2022-10-13  1.665619e+12  1293.849976  ...  2.185120e+06  2.725300e+09
2022-10-14  1.665706e+12  1286.500000  ...  1.124476e+06  1.480705e+09
2022-10-15  1.665792e+12  1295.650024  ...  5.074429e+05  6.510826e+08
2022-10-16  1.665878e+12  1274.250000  ...  5.975026e+05  7.729099e+08
                 ...          ...  ...           ...           ...
2023-04-25  1.682381e+12  1841.000000  ...  8.319169e+05  1.524671e+09
2023-04-26  1.682467e+12  1865.099976  ...  1.701774e+06  3.202957e+09
2023-04-27  1.682554e+12  1865.209961  ...  1.035564e+06  1.968957e+09
2023-04-28  1.682640e+12  1907.699951  ...  5.036653e+05  9.560499e+08
2023-04-29  1.682726e+12  1890.010010  ...  2.651855e+05  5.038554e+08

[200 rows x 7 columns]  

Проблема этого подхода в том, что мы ограничены только 200 строками данных. Поэтому, если мы хотим, чтобы данные превышали (в данном случае) 200 дней, нам придется выполнить несколько вызовов функций. Допустим, мы хотим получить почасовые данные по DOGE с начала 2023 года. Нам нужно сделать несколько обращений к методам API.

def get_last_timestamp(df):
    return int(df.timestamp[-1:].values[0])

start = int(dt.datetime(2023, 1, 1).timestamp()* 1000)

interval = 60
symbol = 'DOGEUSDT'
df = pd.DataFrame()

while True:
    response = session.get_kline(category='linear', 
                                 symbol=symbol, 
                                 start=start,
                                 interval=interval).get('result')
    
    latest = format_data(response)
    
    if not isinstance(latest, pd.DataFrame):
        break
    
    start = get_last_timestamp(latest)
    
    time.sleep(0.1)
    
    df = pd.concat([df, latest])
    print(f'Collecting data starting {dt.datetime.fromtimestamp(start/1000)}')
    if len(latest) == 1: break

df.drop_duplicates(subset=['timestamp'], keep='last', inplace=True)

Получение данных книги заявок

Книга заявок криптовалют аналогична книге заявок любого другого актива, но она специфична для таких криптовалют, как Bitcoin или Ethereum.

В книге заявок криптовалюты вы увидите текущие предложения и предложения по конкретной криптовалюте, а также количество предлагаемой криптовалюты и цену, запрашиваемую за нее.

На стороне покупателя люди делают ставки на покупку определенного количества криптовалюты по определенной цене. Что касается продажи, люди размещают запросы на продажу определенного количества криптовалюты по определенной цене.

В книге заявок обычно вверху отображаются самые высокие предложения и самые низкие предложения. Это дает трейдерам представление о текущей глубине рынка, а также о спросе и предложении криптовалюты.

Трейдеры используют информацию в книге заявок, чтобы принимать обоснованные решения о том, когда покупать или продавать криптовалюту. Например, если на определенном уровне цен имеется много ордеров на покупку, это может указывать на то, что спрос на криптовалюту растет и цена, вероятно, вырастет. И наоборот, если на определенном уровне цен имеется много ордеров на продажу, это может указывать на наличие большого предложения и вероятность падения цены.

response = session.get_orderbook(
    category="linear",
    symbol="DOGEUSDT",
    limit=50).get('result')


def format_order_book(response):
    '''
    

    Parameters
    ----------
    response : dict
    
    Returns
    -------
    two list of lists containing bid/ask price with associated volume

    '''
    bids = response.get('b')
    asks = response.get('a')
    
    return bids, asks
    



bids, asks = format_order_book(response)          

for bid in bids:
    print(f'Bid price - {bid[0]} , quantity = {bid[1]}')


'''
Bid price - 0.081 , quantity = 1177521
Bid price - 0.08099 , quantity = 936765
Bid price - 0.08098 , quantity = 541063
Bid price - 0.08097 , quantity = 483457
Bid price - 0.08096 , quantity = 1211693
'''

Получение суммы открытых позиций(open interest)

Open interest — это общее количество непогашенных фьючерсных контрактов, расчет по которым ещё не был произведён. Другими словами, он представляет собой количество контрактов, которые в настоящее время открыты или активны на рынке.

Когда кто-то покупает или продает фьючерсный контракт, сумма активных позиций увеличивается на единицу. Когда кто-то закрывает позицию, продавая или покупая контракт, чтобы компенсировать свою первоначальную сделку, сумма активных позиций уменьшается на единицу.

Открытый интерес является важным индикатором ликвидности рынка и настроений, поскольку он отражает количество участников рынка, которые активно торгуют конкретным фьючерсным контрактом. Высокий открытый интерес говорит о том, что существует большая торговая активность и интерес к контракту, тогда как низкий открытый интерес может указывать на то, что рынок менее активен или менее популярен.

Входные аргументы аналогичны методу get_klines, который мы использовали ранее. Однако по какой-то причине интервал кажется другим. Также обратите внимание на цикл по словарям: это связано с тем, что Pandas, похоже, не нравятся 7 нулей в конце, и иногда он возвращает NaN, а иногда нет. Поэтому мы используем решение, как показано ниже.

ПараметрыОбязательныйТипКомментарий
categorytruestringProduct type. linear,inverse
symboltruestringSymbol name
intervalTimetruestringInterval. 5min,15min,30min,1h,4h,1d
startTimefalseintegerThe start timestamp (ms)
endTimefalseintegerThe end timestamp (ms)
limitfalseintegerLimit for data size
def format_oi(response):
    '''
    

    Parameters
    ----------
    respone : dict
        response from calling get_open_interest

    Returns
    -------
    dataframe of open interest and timestamp

    '''
    data = response.get('list', None)
    
    if not data:
        return 
    
    ois =[] 
    tss = []
    for row in data:
        oi = float(row.get('openInterest'))
        ts = int(row.get('timestamp'))
        ois.append(oi)
        tss.append(ts)
        
    data = pd.DataFrame()
    data['open_interest'] = ois
    data['timestamp'] = tss
    
    f = lambda x: dt.datetime.utcfromtimestamp(int(x)/1000)
    data.index = data.timestamp.apply(f)
    return data[::-1]



response = session.get_open_interest(
    category="linear",
    symbol="DOGEUSDT",
    intervalTime="1h",
    limit=200
).get('result')



oi = format_oi(response)

'''
                     openInterest     timestamp
timestamp                                      
2023-04-28 01:00:00   934277376.0  1.682644e+12
2023-04-28 02:00:00   935817856.0  1.682647e+12
2023-04-28 03:00:00   935150784.0  1.682651e+12
2023-04-28 04:00:00   934870976.0  1.682654e+12
2023-04-28 05:00:00   933942976.0  1.682658e+12

'''

Если вы хотите получить данные о сумме открытых позиций за более чем 200 периодов, вы можете применить ту же логику, которую мы использовали ранее для метода get_klines.

To top