Для разработчиков / Реальные активы

Как формируется цена

Два метода агрегации, один публикатор. Арифметика ниже делает цену устойчивой к плохому поведению площадки; не она делает цену достойной доверия. Это последний раздел, и именно его стоит прочитать, прежде чем что-либо ликвидировать по этим числам.

Откуда берётся цена

Thirteen feeds are aggregated from five public spot venues, each subscribed with that venue's own product id. The other twenty have no venue leg and come from Pyth Network's Hermes service alone.

ИсточникЧто
Спотовые площадкиCoinbase, Kraken, Bitstamp, Gemini, Bitfinexкаждая подписана с собственным идентификатором продукта этой площадки, взятым из каталога
Второй источникPyth Network, через его сервис Hermesединственный источник для двадцати фидов без стороны площадок и перекрёстная проверка для остальных тринадцати

Два метода отказывают по-разному, и потребителю нужны оба поведения. Фид, опирающийся на биржи, переживает погасшую площадку, потому что медиана берётся по пяти и каждая несёт собственную свежесть. Фид с единственным источником недоступность своего источника пережить не может и говорит об этом, а не гадает.

Когда площадка засчитывается

Каждая площадка оценивается сама по себе, прежде чем что-либо объединяется. Правила применяются в этом порядке, и первое же несработавшее убирает площадку из медианы для этой оценки:

ПравилоПорог
Connection statemust be onlinea venue whose socket is down is never fresh, whatever its last quote said
Quote age10 smeasured on a MONOTONIC receive clock, never on the exchange's timestamp or the host's wall clock
Delivery lag5 s either waya timestamp trailing its receipt means the socket is replaying a backlog; one leading it means the venue dates quotes in the future. The whole venue sits out rather than falling through to its last trade
Spread50 bpsthe mid is used when the book is uncrossed and tighter than this
Last trade60 sthe fallback when no usable mid exists, inside its own longer window
Свежесть судится по монотонным часам

Не по метке времени биржи и не по настенным часам хоста. Площадка со спешащими или отстающими часами не может выдать собственную котировку за свежую, а хост, часы которого прыгнули, не может разом обесценить все площадки. Метка времени биржи используется ровно для одного: для проверки задержки доставки, которая сравнивает её с моментом получения в обе стороны.

Лучшие bid и ask предпочитаются, когда стакан свежий, не перекрещен и уже предела спреда. Иначе на замену встаёт последняя сделка, внутри собственного, более длинного окна. Площадка, чей сокет проигрывает накопившийся хвост, убирается целиком, а не проваливается к своей последней сделке, потому что эта сделка опоздала ровно настолько же.

Медиана

  1. Evaluate every venue against the rules above and keep the fresh ones.
  2. If fewer than minSources are fresh, publish nothing and report the reason - no_sources when none is fresh, too_few_sources otherwise. Nothing thin is ever published.
  3. Take the median of what survives.
  4. If the spread between the included venues exceeds 200 bps and dropping one would still leave minSources, drop the venue furthest from the median - on a tie the older observation - and take the median again. At most one venue is dropped.
  5. Round half-even to the feed's decimals. The result is an integer, not a float.
  6. Date the aggregate with the NEWEST included quote, capped at the current wall clock so no venue with a fast clock can date a median into the future.

degraded is set when the median rested on exactly minSources venues: still published, one drop-out from silence.

Слишком тонкий фид публикует ничего, а не что-нибудь

minSources задаётся отдельно для каждого фида и равен 3 на каждом фиде, опирающемся на биржи. Ниже него ответа нет вовсе: никакое последнее известное значение в сети не переопубликовывается, раунд не продвигается, а updatedAt перестаёт двигаться. Сервис всё ещё сообщает последний хороший ответ как lastKnown для диагностики, и это поле явным образом не является ценой, по которой можно торговать.

Агрегат датируется самой свежей включённой котировкой и ограничен сверху текущими настенными часами. Важны обе половины: площадка, чья последняя сделка шестидесятисекундной давности заменила устаревший стакан, не должна датировать медиану, остальные входы которой моложе секунды, и ни одна площадка со спешащими часами не может вытолкнуть время наблюдения в будущее - где контракт пропустил бы его как причину 4.

Перекрёстная проверка и замена

An exchange-backed feed that also has a Pyth leg is cross-checked against it on every evaluation. Within 100 bps the two are recorded as agreeing; beyond it the feed is marked diverged and the dispersion flag is raised.

When the venues go stale, Pyth may stand in for them - but only if the two agreed recently and are not diverging now. A feed publishing from the stand-in is marked degraded and its source reads pyth rather than exchanges-median, so a consumer can tell. If they are diverged and Pyth is fresh, the feed publishes nothing and reports cross_check_diverged.

Это раскрывают два поля. crossCheckBps - текущее расстояние между двумя методами, а source говорит, какой из них произвёл раунд, который вы держите - 1 для медианы площадок, 2 для второго источника. Фид, у которого source сменился, остаётся действительной ценой, произведённой другим способом; если для вашего продукта это важно, следите за полем, а не выводите его.

Второй источник

Каждое обновление от второго источника проходит эти проверки, прежде чем получить право стать ценой. Отклонённое обновление увеличивает счётчик по причине, видимый по каждому фиду на маршрутах источника и аудита сервиса:

ПроверкаПредел
Exponentpinned on the first updateany later drift is rejected, so a silent rescaling cannot pass
Slot and publish timemust advancean update that does not move them forward is dropped
Future tolerance5 sa publish time further ahead than this is rejected
Confidence50 bps crypto and index, 30 equity, 10 commodity and fxthe reported confidence interval as a fraction of the price; wider is rejected
EMA band10 % crypto and index, 5 % elsewherea jump away from the exponential moving average needs a SECOND sample within 100 bps of the first before it is used. A lone spike is dropped
Freshness10 s since receipt, 30 s publish lagboth measured at receipt on the monotonic clock

Без учётных данных двадцать из тридцати трёх фидов молчат

The upstream needs a credential. Without one it answers unauthorised and every feed with no venue leg stays unpublished - twenty of the thirty-three, which is the whole real-world set plus XMR/USD.

The thirteen exchange-backed feeds continue: they are computed from public venues and need no credential. What they lose is the cross-check and the stand-in, since neither can be established without a Pyth price to compare against. Readiness reports this as a warning rather than a failure, so the service looks healthy while two thirds of the catalog is silent - check the per-feed status, not the service's.

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

Как она попадает в сеть

  1. The aggregating service holds no signing key at all. It computes prices and serves them on an internal port.
  2. The node's publisher polls that port, authenticates the body with a shared HMAC of the exact bytes, and re-checks every item against on-chain state before signing - mirroring the contract's own skip rules so a bad item costs a counter rather than gas.
  3. The batch is written as ONE system transaction per EVM block, signed by the publisher key, which lives in the node's process and is used by nothing else in it.
  4. The service then reads its own result back off the chain and reports it, which is what the onchain field of every FeedView is.

At most 64 feeds go into one batch by default, and the contract's own maxBatch caps it again. A batch older than 2 s is not published.

Суть в разделении труда. Всё медленное или ненадёжное - опрос, аутентификация, чтение каталога, отбор, кодирование, подписание и дозапись в журнал упреждающей записи - происходит вне пути запечатывания, который получает готовую транзакцию и применяет её по цене любой другой транзакции. А поскольку публикатор перед подписанием перепроверяет каждый элемент по ончейн-состоянию, повторяя собственные правила пропуска контракта, агрегатор, отправивший что-то плохое, стоит счётчика, а не раунда.

Модель доверия

A price is as trustworthy as the operator that produces blocks, and no more. The publisher is the block producer.

  • One party operates the node, holds the publisher key and orders transactions. A price inherits exactly the assumption that already governs ordering.
  • Nothing on chain arbitrates a price. There is no second publisher, no dispute window and no slashing: the contract checks that an item is well formed, positive, not from the future and not older than the feed's last observation, and then writes it.
  • The owner role can add a feed, change a feed's policy, rotate the publisher and adjust the batch and tolerance parameters. Ownership transfer is two-step. Those are the only write paths that are not the publisher's.
  • Splitting the key from the computation limits one failure, not the other: compromising the aggregating service lets an attacker propose prices, and every one is still re-checked and signed by the node. Compromising the node is the end of the argument.
  • If you liquidate on these prices, that is the assumption you are taking, and it is the one to state to your own users.

Ничто из сказанного выше этого не меняет. Правила площадок, медиана, отбрасывание выбросов и перекрёстная проверка делают цену устойчивой к плохому поведению источника, а это реальный и частый отказ. Против стороны, которая подписывает, они не делают ничего. Читайте их как контроль качества, а не как консенсус.

Практическое следствие для интегратора: эти цены подходят продукту, пользователям которого сказано, кто их производит, и они несут то же допущение, что и упорядочивание ваших собственных транзакций - так что если вы уже принимаете это допущение, чтобы вообще пользоваться сетью, потребление фидов не добавляет ни одного нового. Если вашей конструкции нужна цена, которую не может подделать ни одна отдельная сторона, этот слой её не даёт, и никакой параметр этого не изменит.