Интересная ситуация со ставкой фондирования ByBit SUN Perpetual 14.07.2024
В минувшее воскресенье Никита Ануфриев пригласил меня на свой YouTube канал провести прямой эфир. Получилось очень даже ничего. Никита, спасибо!
Было достаточно много обратной связи. Всем, кто её оставил, огромное спасибо! Какой бы она не была :)
"Хейтеры, люблю вас!" (с)
Но отдельного внимания заслуживает комментарий Aleksandr Chernikov, потому что именно он вдохновил меня на написание этой статьи.
И касается это одной из моих любимых тем — ставки фондирования.
Intro
Сегодняшняя наша статья будет касаться монетки SUN, а точнее бессрочного фьючерсного usd-margin контрактов на эту монетку на бирже ByBit.
Не будем углубляться в фундаментальную составляющую этого проекта. С ним вы можете ознакомиться на официальном сайте проекта.
Важно кое-что другое. Последнюю неделю монетка активно растёт: +15%, в то время как широкий рынок дал ~3%.
13.07.2024 в 17:39 UTC+3 в показателе Funding rate по бессрочного фьючерсного контракта ByBit SUN Perpetual начали происходить аномалии — он стал экстремально отрицательным.
На самом деле обычное дело, когда на экстремумах движений растаскивают базовый актив и производный инструмент без экспирации, чтобы длинные позиции по последнему были более привлекательными. А потом во всех закупившихся на хаях прокатывают на хуях... перераспределяют риски :)
Считаем funding rate
Про funding rate или ставку фондирования у меня есть отдельная статья. Там вы можете ознакомиться с природой этого явления.
Но дабы соблюсти все формальности мы сходим на биржу ByBit и заберём все формулы.
Ключевая составляющая в формировании ставки фондирования это премиум или Premium index, который по сути равен разнице между ценой маркировки дериватива, для которого производятся расчеты, и индексной ценой.
Цена маркировки — если очень упрощенно, средняя цена между лучшими ask и bid заявками.
Индексная цена — средневзвешенная по объёму цена базового актива.
Хорошо, давайте рассчитаем индексную цену для SUN. Тем более биржа ByBit очень любезно посчитала для нас все необходимые весовые коэффициенты.
Корректнее будет сделать это с использованием взвешивания по объёму. Я сделаю в двух вариантах — с коэффициентами, которые отдает биржа и через объёмное взвешивание (с коэффициентами у меня, кстати, не получилось. Но исходный код индикатора я оставлю, может быть кто-то допилит).
Для расчётов будем использовать TradingView и язык pinescript.
Чтобы убедиться, что данные TradingView валидны и соответствуют биржевым, сходим на каждую биржу и сравним котировки.
Что-то на финике совсем грустно...
Да, бывают расхождения. Но в целом мы можем доверять котировкам Tradingview.
Tradingview забирает котировки с бирж, но формальность, я считаю, нужно соблюсти.
Отлично. Приступаем к расчетам. Исходный код индикатора ниже, а также доступен по ссылке.
//@version=5
indicator(title = "Index price", shorttitle = "Index price", overlay = false)
// Inputs
var string displayModeInput = input.string(defval = "Default", title = "Display mode", options = ["Default", "Normalized"], group = "Display settings")
var string calculationModeInput = input.string(defval = "Volume", title = "Calculation mode", options = ["Const", "Volume"], group = "Calculations settings")
// Market data parsingvar string timeframe = syminfo.type == "futures" and timeframe.isintraday ? "1D" : timeframe.period
var string binaceSymbol = str.replace(source = "BINANCE:" + syminfo.ticker, target = ".P", replacement = "", occurrence = 0)
float binaceClose = request.security(symbol = binaceSymbol, timeframe = timeframe, expression = close , ignore_invalid_symbol = true)
float binaceVolume = request.security(symbol = binaceSymbol, timeframe = timeframe, expression = volume , ignore_invalid_symbol = true)
binaceClose := na(x = binaceClose) == true ? 0 : binaceClose
binaceVolume := na(x = binaceVolume) == true ? 0 : binaceVolume
var string bitfinexSymbol = str.replace(source = "BITFINEX:" + syminfo.ticker, target = ".P", replacement = "", occurrence = 0)
float bitfinexClose = request.security(symbol = bitfinexSymbol, timeframe = timeframe, expression = close, ignore_invalid_symbol = true)
float bitfinexVolume = request.security(symbol = bitfinexSymbol, timeframe = timeframe, expression = volume, ignore_invalid_symbol = true)
bitfinexClose := na(x = bitfinexClose) == true ? 0 : bitfinexClose
bitfinexVolume := na(x = bitfinexVolume) == true ? 0 : bitfinexVolume
var string bitgetSymbol = str.replace(source = "BITGET:" + syminfo.ticker, target = ".P", replacement = "", occurrence = 0)float bitgetClose = request.security(symbol = bitgetSymbol, timeframe = timeframe, expression = close , ignore_invalid_symbol = true)
float bitgetVolume = request.security(symbol = bitgetSymbol, timeframe = timeframe, expression = volume , ignore_invalid_symbol = true)
bitgetClose := na(x = bitgetClose) == true ? 0 : bitgetClose
bitgetVolume := na(x = bitgetVolume) == true ? 0 : bitgetVolume
var string bybitSymbol = str.replace(source = "BYBIT:" + syminfo.ticker, target = ".P", replacement = "", occurrence = 0)
float bybitClose = request.security(symbol = bybitSymbol, timeframe = timeframe, expression = close , ignore_invalid_symbol = true)
float bybitVolume = request.security(symbol = bybitSymbol, timeframe = timeframe, expression = volume , ignore_invalid_symbol = true)
bybitClose := na(x = bybitClose) == true ? 0 : bybitClose
bybitVolume := na(x = bybitVolume) == true ? 0 : bybitVolume
var string gateSymbol = str.replace(source = "GATE:" + syminfo.ticker, target = ".P", replacement = "", occurrence = 0)
float gateClose = request.security(symbol = gateSymbol, timeframe = timeframe, expression = close , ignore_invalid_symbol = true)
float gateVolume = request.security(symbol = gateSymbol, timeframe = timeframe, expression = volume , ignore_invalid_symbol = true)
gateClose := na(x = gateClose) == true ? 0 : gateClose
gateVolume := na(x = gateVolume) == true ? 0 : gateVolume
var string kucoinSymbol = str.replace(source = "KUCOIN:" + syminfo.ticker, target = ".P", replacement = "", occurrence = 0)
float kucoinClose = request.security(symbol = kucoinSymbol, timeframe = timeframe, expression = close , ignore_invalid_symbol = true)
float kucoinVolume = request.security(symbol = kucoinSymbol, timeframe = timeframe, expression = volume , ignore_invalid_symbol = true)
kucoinClose := na(x = kucoinClose) == true ? 0 : kucoinClose
kucoinVolume := na(x = kucoinVolume) == true ? 0 : kucoinVolume
// Calculations
float chartPrice = closefloat indexPrice = na
if calculationModeInput == "Volume"
float totalVolume = binaceVolume + bitfinexVolume + bitgetVolume + bybitVolume + gateVolume + kucoinVolume indexPrice := (binaceClose * binaceVolume + bitfinexClose * bitfinexVolume + bitgetClose * bitgetVolume + bybitClose * bybitVolume + gateClose * gateVolume + kucoinClose * kucoinVolume) / totalVolume
else
indexPrice := binaceClose * 0.7869 + bitfinexClose * 0.0001 + bitgetClose * 0.0188 + bybitClose * 0.0673 + gateClose * 0.1042 + kucoinClose * 0.0223
if displayModeInput == "Normalized"
chartPrice := close - indexPrice
indexPrice := 0.0
// Plot
plot(series = chartPrice, title = "Close price", color = color.white, style = plot.style_stepline)
plot(series = indexPrice, title = "Close price", color = color.orange, style = plot.style_stepline)
Ну что, а теперь самое интересное. Идём на биржу ByBit и смотрим, какую индексную цену посчитали они.
Давайте чуть крупнее сделаем, чтобы было лучше видно.
Как мы видим то, что биржа посчитала в качестве индексной цены, не соответствует действительности. А значит расчеты по ставке фондирования произведены неверно: ставка фондирования должна была быть экстремально положительной, а не экстремально отрицательной.
Чтобы ставка фондирования была экстремально положительной, цена маркировки должна быть выше индексной цены (то, что было по факту). Чтобы ставка фондирования была экстремально отрицательной, цена маркировки должна быть ниже индексной цены (то, что посчитал ByBit).
Outro
- знают арбитражеры и шортисты, что у них откусили часть доходности?
- знают ли об этом лонгисты, которые залетели в SUN Perpetual (возможно с целью заработать ту самую ставку фондирования)?
- Или в какой-то момент времени ByBit стала заинтересована в том, чтобы производный инструмент начал сильнее отрываться от базового актива?
Или я опять что-то напутал. Никогда не исключаю :)
UPD: на втором прямом эфире Александр добавил важную деталь. На бирже OKX SUN стоил сильно дороже, чем на всех других биржах. Но как раз в этот момент монету делистнули (с чем, скорее всего, и связано расхождение), поэтому проверить не получится ¯\_(ツ)_/¯. Так что не катим бочку на ByBit :) Но всё равно было интересно.