Meme Atlas AZ · why-prices-differ

價格都寫 USD,為何仍不是同一個數字?

從輸入市場、換算路徑、異常過濾、權重、範圍與時間,重建全域聚合、CEX 與 DEX 價格的資料血統。

發布
更新
編輯責任
Meme Atlas AZ

三個公開頁面在同一分鐘被打開,都在某資產旁邊印著 USD,末位卻沒有完全相同。這不是先找「錯的那個」的理由,而是追問每個數字怎麼出現的起點。其中一個可能聚合多個市場,一個可能是單一中心化場所的委託簿頂層,另一個則是指定鏈上某一資金池的局部報價。

「都以 USD 顯示」只說明最後的計價單位同名,不說明上游市場、換算路徑、異常排除、權重、時間或可執行範圍相同。要解釋差異,有用的產物是一張價格血統單,不是一張來源名次表。

一個價格先問它收了哪些輸入

價格血統的第一欄是 input set。資料供應商可以收多個場所的 ticker,另一個供應商可以使用不同場所、地區或報價幣。就算市場名單相同,某一筆 ticker 因數據品質、暫停或異常條件被排除,最終輸入也會不同。

第二欄是 conversion path。某市場直接以美元報價,另一市場以穩定資產或其他資產報價,供應商要再經一條匯率路徑轉成 USD。最後螢幕都寫 USD,中間經過的觀察時點和轉換來源卻可能不同。

第三欄是 filter 與 weight。異常輸入如何辨認,成交量如何作權重,沒有數據的市場如何處理,都會改變最後的聚合結果。CoinGecko 公開方法列出 initial ticker set、anomaly 與 outlier exclusion、conversion path 和 VWAP,說明它的顯示價是一條處理鏈的輸出。這是該供應商的方法,不是所有頁面共用的隱形公式。

還有一欄常被略過:上游 observation 與頁面 fetch time 並不相同。頁面在某秒取得聚合結果,不代表每個 ticker、匯率與池快照都在該秒產生。若供應商沒有公開每層時間,就分別保存已知的 provider timestamp 與本站取得時間,未知的上游時點維持未知,不把一個頁面時間複製到整條處理鏈。

顯示精度也可能放大「看起來相同」或「看起來不同」的印象。頁面上的小數位、縮寫與四捨五入屬於呈現層;若來源另有較完整的原始欄位,紀錄應把原始值與顯示字串分開保存。若只能看到格式化文字,就只比較該顯示精度,不反推出供應商內部保存了更多位數,也不把末位差異直接解釋成市場方法不同。

更新節奏則要依可觀察證據描述。兩次重新取得仍顯示同一數字,可以記錄這兩個取得時點與相同結果,卻不能在沒有文件或回應欄位時斷言頁面採用何種快取、多久刷新,或上游市場沒有變動。反過來,兩頁在數秒內先後改值,也只證明各自可見輸出改變,不證明它們使用完全同步的輸入批次。

全域聚合價是處理結果,不是委託單

全域聚合價方便用來閱讀廣範市場脈絡,但它不是某一場所當下掛著的 bid 或 ask,也不是保證能以該值取得任意數量的報價。CoinGecko 的支援文件直接說明,其價格為 volume-weighted aggregation,不同地區、市場或單一場所可以與聚合結果不同。

因此,一筆全域價格應標明 provider、asset identity、quote currency、method 和 actual observation timestamp。如果頁面只有本站取得時間,不應將它改寫成每一個上游 ticker 在同一刻觀察。頁面被打開的時間,只能回答頁面層的行為。

聚合層還可能在原始價格之外保存資料品質狀態。某個輸入被排除、延遲或暫時沒有數據時,最後數值仍可能存在,但輸入集合已和上一輪不同。因此,兩次全域價格的差異不必完全來自市場成交,也可能包含可用市場集合或過濾結果的變化。沒有方法版本與狀態欄,就不能把所有變動都歸因於同一原因。

正規化紀錄至少要保留資產身分、原始 quote、顯示 quote、報價方向與單位尺度。這些欄位能揭示兩個 USD 數字在進入畫面前是否經過不同路徑,但不能用來猜測未公開的內部公式。若 conversion path 或輸入單位沒有來源,該欄維持 unknown;僅因最後單位一致,不補寫一條假定的換算鏈。

CEX 畫面要辨認最後成交與委託簿

單一 CEX 市場裡,最後成交、最佳 bid、最佳 ask 和更深的委託簿價位回答不同問題。最後成交是已發生事件;最佳買賣價是畫面快照的頂層;更深的價位與數量才描述可見委託。Coinbase 的公開文件還把 Level 1、聚合 Level 2 和未聚合 Level 3 分開,顯示「委託簿」本身也不是單一視圖。

將 CEX 價格寫進紀錄時,至少要留場所、product、欄位種類、報價方向、可見價位及時間。一筆 last trade 不應被重新命名為一張完整委託簿,一筆 best ask 也不代表不限數量的市場價。

還要注意 product 本身的報價貨幣。某場所的資產/穩定資產市場與資產/法幣市場即使在頁面上都換算成 USD,也不是同一個原始 product。若頁面先讀取本地報價,再使用另一來源換算,紀錄要把原始幣對和轉換步驟都留下,不能只保存最後顯示單位。

DEX 價格綁在單一 pair 與報價方向

DEX Screener 的公開欄位把 `chainId`、`pairAddress`、`baseToken`、`quoteToken` 和 `priceUsd` 放在 pair 結構中。這種結構已經告訴讀者:這個價格屬於指定鏈、指定成對資產與指定池,不是沒有地址的 global market。base 與 quote 對調還會改變顯示方向,所以價格必須與幣對一起讀。

`pairCreatedAt` 只說明資金池的建立時間,不是這次 `priceUsd` 的 observation time。如果實際觀察時間缺失,就是時間未確認,不能借用池的誕生日。同樣,欄位為 `null`、missing、stale 或 failed 時保留原狀,不寫零。

一個池若使用非 USD 報價資產,`priceUsd` 還可能依賴額外的美元換算來源。此時 pair 的局部交換關係與最後美元值是兩層證據:前者由 base、quote 與池狀態界定,後者還要依賴報價資產的換算路徑。只保存 `priceUsd` 會看不出差異究竟出在池內相對價格,還是池外換算。

同樣顯示 USD 也沒有對齊範圍

一個 provider-global aggregation 可能含多個 CEX 和 DEX ticker,單一 CEX 視圖只含特定 product,單一 DEX 報價只含特定 pair。三者都使用 USD 對齊最後單位,可以方便人閱讀,卻不會將三種 scope 融成同一市場。一個聚合值與一個局部值不同,可以是方法的正常結果。

時間也是範圍。兩筆觀察即使接近,也不能修復不同資產、不同鏈、不同合約、不同方向或不同市場層級。時間接近不是身分和 scope 的替代品。

三類價格各自需要哪些血統欄位

供應商聚合價要保存 ticker set、filter、weight 與 conversion path;CEX 資料要保存 product、book level、bid/ask 與 timestamp;DEX 資料則要保存 chain、pair、base/quote、pool 與 timestamp。欄位不同不是格式問題,而是三種市場物件的證據邊界。

不同範圍只作分區呈現

CoinGecko 的全域價格、CEX 畫面與 DEX 單池價格各自保留市場範圍、來源與時間。本站不以資產白名單、時間窗或百分比門檻把它們合成徽記,也不將 provider-global market cap 或 FDV 與 pool-level 同名欄位合併。

DOGE 的原生資產範圍不與代幣池身分靜默接合;FLOKI 的多鏈範圍也不能由任一單池代表。SHIB、PEPE、BONK 與 WIF 的池資料仍須核對完整 chain、contract 或 mint 與 pair,但核對結果只決定該池是否能被獨立展示,不產生額外差值。

把價差寫成可重現的來源記錄

一筆價差記錄不需要宣布誰「比較準」。它應留下兩邊的 asset identity、market scope、欄位類型、input set、conversion path、filter、weight、source observation 和 site fetch time。不適用的欄位可明寫不適用,沒有資料的欄位保留未知。

當兩個數字再次分歧,研究者可檢查是市場名單改變、異常值被排除、匯率路徑不同、權重已調整,還是一邊原本就只代表單一池。這種記錄把差異變成可討論的方法問題,不會把一個沒有來源的價格挪成事實基準。

最後還要保留一欄「這個差異仍不能說明什麼」。沒有交易方向與數量時,價差不能直接說明可執行結果;沒有完整市場範圍時,也不能說明哪個來源代表整體市場。血統單的目的,是界定各數字能支持的範圍與剩餘未知,而不是把不同方法壓成單一結論。

內容來源