Если у вас еще не установлена библиотека 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”, как показано ниже.
category | true | string | Тип продукта: spot,linear,inverse,option |
symbol | false | string | Обозначение |
baseCoin | false | string | Базовая монета. Только для опций |
expDate | false | string | Expiry 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 минута.
Параметр | Обязательный | Тип | Комментарий |
---|---|---|---|
category | true | string | Тип продукта spot, linear, inverse |
symbol | true | string | Symbol name |
interval | true | int/string | Kline interval. 1, 3, 5, 15, 30, 60, 120, 240, 360, 720, D, M, W |
start | false | integer | The start timestamp (ms) |
end | false | integer | The end timestamp (ms) |
В таблице ниже показаны параметры ответа. Функция format_data, приведенная выше, извлекает информацию из списка API и форматирует ее в dataframe pandas.
category | string | Типа продукта |
symbol | string | Symbol name |
list | array | An 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
, а иногда нет. Поэтому мы используем решение, как показано ниже.
Параметры | Обязательный | Тип | Комментарий |
---|---|---|---|
category | true | string | Product type. linear,inverse |
symbol | true | string | Symbol name |
intervalTime | true | string | Interval. 5min,15min,30min,1h,4h,1d |
startTime | false | integer | The start timestamp (ms) |
endTime | false | integer | The end timestamp (ms) |
limit | false | integer | Limit 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.