{"componentChunkName":"component---src-templates-blog-post-js","path":"/volatility-oracle-prototype/","result":{"data":{"site":{"siteMetadata":{"title":"/dev/yukarinoki"}},"markdownRemark":{"id":"c377435e-e5ec-597d-acdd-fa57862b3435","excerpt":"日本語要約: DeFiに不足しているボラティリティデータを提供するオンチェーンOracleのプロダクトコンセプトです。オーダーブックデータからrealized volatilityを算出し、スマートコントラクトに配信する仕組みをTypeScriptプロトタイプとSolidity…","html":"<blockquote>\n<p><strong>日本語要約</strong>: DeFiに不足しているボラティリティデータを提供するオンチェーンOracleのプロダクトコンセプトです。オーダーブックデータからrealized volatilityを算出し、スマートコントラクトに配信する仕組みをTypeScriptプロトタイプとSolidityインターフェースのコード例とともに提案します。</p>\n</blockquote>\n<p>I’ve been thinking about a gap in DeFi infrastructure that seems surprisingly under-served: volatility data. We have robust price oracles, but almost nothing purpose-built for serving volatility estimates on-chain. This post walks through a product concept I’ve been prototyping — a volatility oracle that computes realized vol from high-frequency orderbook data and makes it available to smart contracts.</p>\n<h2 id=\"the-problem-defi-needs-volatility-not-just-price\" style=\"position:relative;\"><a href=\"#the-problem-defi-needs-volatility-not-just-price\" aria-label=\"the problem defi needs volatility not just price permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The Problem: DeFi Needs Volatility, Not Just Price</h2>\n<p>Price oracles are table stakes at this point. Every lending protocol, every DEX, every derivatives platform relies on some form of price feed. But volatility? That’s a different story entirely.</p>\n<p>Think about who actually needs vol data on-chain:</p>\n<p><strong>Options protocols</strong> are the obvious case. You can’t price options without implied volatility, and you can’t calibrate your vol surface without realized vol as a reference. Protocols that sell options on-chain are essentially flying blind or relying on off-chain computation that users have to trust.</p>\n<p><strong>Risk management</strong> in lending protocols is another big one. Liquidation thresholds are typically static — you set a collateral ratio of 150% and call it a day. But a 150% ratio means very different things when ETH is trading at 10% annualized vol versus 80%. A vol-aware liquidation engine could dynamically adjust thresholds, reducing unnecessary liquidations during calm markets and protecting the protocol during volatile ones.</p>\n<p><strong>Liquidation engines</strong> themselves could benefit from vol-adjusted parameters. If you know volatility is spiking, you can widen your liquidation buffers proactively rather than reacting after the damage is done.</p>\n<p>The current state of affairs is that protocols either hardcode assumptions about volatility, compute it off-chain in trusted backends, or simply ignore it. None of these are great.</p>\n<h2 id=\"the-concept\" style=\"position:relative;\"><a href=\"#the-concept\" aria-label=\"the concept permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The Concept</h2>\n<p>The idea is straightforward: ingest high-frequency orderbook data from major exchanges, compute realized volatility using multiple estimators, and push the results on-chain as an oracle feed that any smart contract can consume.</p>\n<p>Here’s the high-level architecture:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-text line-numbers\"><code class=\"language-text\">Binance WS → Aggregator (0.5s VWAP) → Vol Calculator → Oracle Contract → DeFi Consumers</code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>The key insight is that orderbook microstructure data — the actual bids and asks updating dozens of times per second — gives us much better volatility estimates than the traditional approach of using daily OHLC candles. We’re capturing information about price dynamics that gets lost when you downsample to hourly or daily bars.</p>\n<p>The aggregator computes volume-weighted average prices at 500ms intervals, giving us a clean price series that incorporates the full depth of the orderbook rather than just last-trade prices. This feeds into the volatility calculator, which maintains rolling windows and outputs annualized vol estimates. Those estimates get pushed to a Solidity oracle contract whenever they change by more than a configurable threshold.</p>\n<h2 id=\"volatility-computation-multiple-estimators\" style=\"position:relative;\"><a href=\"#volatility-computation-multiple-estimators\" aria-label=\"volatility computation multiple estimators permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Volatility Computation: Multiple Estimators</h2>\n<p>Not all volatility estimators are created equal. I’m implementing several and letting consumers choose which one suits their use case.</p>\n<h3 id=\"standard-realized-volatility\" style=\"position:relative;\"><a href=\"#standard-realized-volatility\" aria-label=\"standard realized volatility permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Standard Realized Volatility</h3>\n<p>The classic approach. Take a rolling window of log returns, compute the standard deviation, annualize it.</p>\n<p>$$\\sigma<em>{realized} = \\sqrt{\\frac{252}{n} \\sum</em>{i=1}^{n} (r_i - \\bar{r})^2}$$</p>\n<p>Simple, well-understood, but inefficient — it only uses closing prices and throws away intra-period information.</p>\n<h3 id=\"parkinson-estimator\" style=\"position:relative;\"><a href=\"#parkinson-estimator\" aria-label=\"parkinson estimator permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Parkinson Estimator</h3>\n<p>Uses the high-low range within each period, which captures more information about price dynamics:</p>\n<p>$$\\sigma<em>{parkinson} = \\sqrt{\\frac{1}{4n \\ln 2} \\sum</em>{i=1}^{n} (\\ln H<em>i - \\ln L</em>i)^2}$$</p>\n<p>This is roughly 5x more efficient than the close-to-close estimator for the same number of observations. The tradeoff is that it assumes continuous trading (no gaps), which is fine for crypto markets.</p>\n<h3 id=\"garman-klass-estimator\" style=\"position:relative;\"><a href=\"#garman-klass-estimator\" aria-label=\"garman klass estimator permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Garman-Klass Estimator</h3>\n<p>Goes further by using full OHLC data:</p>\n<p>$$\\sigma<em>{GK} = \\sqrt{\\frac{1}{n} \\sum</em>{i=1}^{n} \\left[ \\frac{1}{2}(\\ln H<em>i - \\ln L</em>i)^2 - (2\\ln 2 - 1)(\\ln C<em>i - \\ln O</em>i)^2 \\right]}$$</p>\n<p>Even more efficient, roughly 8x better than close-to-close for the same observation count.</p>\n<h3 id=\"why-microstructure-data-matters\" style=\"position:relative;\"><a href=\"#why-microstructure-data-matters\" aria-label=\"why microstructure data matters permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why Microstructure Data Matters</h3>\n<p>With traditional OHLC data from daily candles, you’re working with maybe 30 data points for a monthly vol estimate. With 500ms VWAP snapshots from orderbook data, you get ~170,000 observations per day. Even accounting for the autocorrelation in high-frequency data (which you need to correct for), the statistical precision of your vol estimate is dramatically better.</p>\n<p>More importantly, you can detect vol regime changes in minutes rather than days. For DeFi protocols that need to react quickly — say, tightening liquidation parameters during a flash crash — this responsiveness is the whole point.</p>\n<h2 id=\"live-dashboard-prototype\" style=\"position:relative;\"><a href=\"#live-dashboard-prototype\" aria-label=\"live dashboard prototype permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Live Dashboard Prototype</h2>\n<p>Here’s an interactive prototype of the volatility oracle dashboard. It simulates a real-time BTC price feed and computes all three volatility estimators continuously. Try adjusting the window size and update threshold, or hit “Inject Volatility Spike” to see how each estimator responds to sudden regime changes.</p>\n<iframe src=\"/visualizations/vol-oracle-dashboard.html\" width=\"100%\" height=\"600\" frameborder=\"0\" style=\"border: 1px solid #30363d; border-radius: 2px;\"></iframe>\n<h2 id=\"typescript-prototype-real-time-vol-computation\" style=\"position:relative;\"><a href=\"#typescript-prototype-real-time-vol-computation\" aria-label=\"typescript prototype real time vol computation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>TypeScript Prototype: Real-Time Vol Computation</h2>\n<p>Here’s the core of the prototype. This service connects to a WebSocket feed, maintains a rolling window of VWAP prices, and computes realized vol on demand.</p>\n<div class=\"gatsby-highlight\" data-language=\"typescript\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-typescript line-numbers\"><code class=\"language-typescript\"><span class=\"token keyword\">import</span> WebSocket <span class=\"token keyword\">from</span> <span class=\"token string\">\"ws\"</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">interface</span> <span class=\"token class-name\">PricePoint</span> <span class=\"token punctuation\">{</span>\n  timestamp<span class=\"token operator\">:</span> <span class=\"token builtin\">number</span><span class=\"token punctuation\">;</span>\n  vwap<span class=\"token operator\">:</span> <span class=\"token builtin\">number</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">VolatilityService</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">private</span> prices<span class=\"token operator\">:</span> PricePoint<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">private</span> <span class=\"token keyword\">readonly</span> windowSize<span class=\"token operator\">:</span> <span class=\"token builtin\">number</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">private</span> <span class=\"token keyword\">readonly</span> aggregationMs<span class=\"token operator\">:</span> <span class=\"token builtin\">number</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">private</span> currentBucket<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> sumPQ<span class=\"token operator\">:</span> <span class=\"token builtin\">number</span><span class=\"token punctuation\">;</span> sumQ<span class=\"token operator\">:</span> <span class=\"token builtin\">number</span><span class=\"token punctuation\">;</span> ts<span class=\"token operator\">:</span> <span class=\"token builtin\">number</span> <span class=\"token punctuation\">}</span> <span class=\"token operator\">|</span> <span class=\"token keyword\">null</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">windowSize <span class=\"token operator\">=</span> <span class=\"token number\">3600</span><span class=\"token punctuation\">,</span> aggregationMs <span class=\"token operator\">=</span> <span class=\"token number\">500</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>windowSize <span class=\"token operator\">=</span> windowSize<span class=\"token punctuation\">;</span> <span class=\"token comment\">// seconds of history to keep</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>aggregationMs <span class=\"token operator\">=</span> aggregationMs<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">connectToFeed</span><span class=\"token punctuation\">(</span>wsUrl<span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">,</span> <span class=\"token builtin\">symbol</span><span class=\"token operator\">:</span> <span class=\"token builtin\">string</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> <span class=\"token keyword\">void</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> ws <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">WebSocket</span><span class=\"token punctuation\">(</span>wsUrl<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    ws<span class=\"token punctuation\">.</span><span class=\"token function\">on</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"message\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">data<span class=\"token operator\">:</span> <span class=\"token builtin\">string</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">const</span> msg <span class=\"token operator\">=</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">parse</span><span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>msg<span class=\"token punctuation\">.</span>s <span class=\"token operator\">===</span> <span class=\"token builtin\">symbol</span> <span class=\"token operator\">&amp;&amp;</span> msg<span class=\"token punctuation\">.</span>e <span class=\"token operator\">===</span> <span class=\"token string\">\"trade\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">ingestTrade</span><span class=\"token punctuation\">(</span>msg<span class=\"token punctuation\">.</span><span class=\"token constant\">T</span><span class=\"token punctuation\">,</span> <span class=\"token function\">parseFloat</span><span class=\"token punctuation\">(</span>msg<span class=\"token punctuation\">.</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token function\">parseFloat</span><span class=\"token punctuation\">(</span>msg<span class=\"token punctuation\">.</span>q<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">private</span> <span class=\"token function\">ingestTrade</span><span class=\"token punctuation\">(</span>timestamp<span class=\"token operator\">:</span> <span class=\"token builtin\">number</span><span class=\"token punctuation\">,</span> price<span class=\"token operator\">:</span> <span class=\"token builtin\">number</span><span class=\"token punctuation\">,</span> qty<span class=\"token operator\">:</span> <span class=\"token builtin\">number</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> <span class=\"token keyword\">void</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> bucketTs <span class=\"token operator\">=</span> Math<span class=\"token punctuation\">.</span><span class=\"token function\">floor</span><span class=\"token punctuation\">(</span>timestamp <span class=\"token operator\">/</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>aggregationMs<span class=\"token punctuation\">)</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>aggregationMs<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>currentBucket <span class=\"token operator\">||</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>currentBucket<span class=\"token punctuation\">.</span>ts <span class=\"token operator\">!==</span> bucketTs<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>currentBucket <span class=\"token operator\">&amp;&amp;</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>currentBucket<span class=\"token punctuation\">.</span>sumQ <span class=\"token operator\">></span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>prices<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n          timestamp<span class=\"token operator\">:</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>currentBucket<span class=\"token punctuation\">.</span>ts<span class=\"token punctuation\">,</span>\n          vwap<span class=\"token operator\">:</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>currentBucket<span class=\"token punctuation\">.</span>sumPQ <span class=\"token operator\">/</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>currentBucket<span class=\"token punctuation\">.</span>sumQ<span class=\"token punctuation\">,</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">pruneOldPrices</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>currentBucket <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> sumPQ<span class=\"token operator\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> sumQ<span class=\"token operator\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> ts<span class=\"token operator\">:</span> bucketTs <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>currentBucket<span class=\"token punctuation\">.</span>sumPQ <span class=\"token operator\">+=</span> price <span class=\"token operator\">*</span> qty<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>currentBucket<span class=\"token punctuation\">.</span>sumQ <span class=\"token operator\">+=</span> qty<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">computeRealizedVol</span><span class=\"token punctuation\">(</span>windowSeconds<span class=\"token operator\">?</span><span class=\"token operator\">:</span> <span class=\"token builtin\">number</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> <span class=\"token builtin\">number</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> window <span class=\"token operator\">=</span> windowSeconds <span class=\"token operator\">||</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>windowSize<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> cutoff <span class=\"token operator\">=</span> Date<span class=\"token punctuation\">.</span><span class=\"token function\">now</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> window <span class=\"token operator\">*</span> <span class=\"token number\">1000</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> relevant <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>prices<span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">p</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> p<span class=\"token punctuation\">.</span>timestamp <span class=\"token operator\">>=</span> cutoff<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>relevant<span class=\"token punctuation\">.</span>length <span class=\"token operator\">&lt;</span> <span class=\"token number\">2</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">const</span> logReturns<span class=\"token operator\">:</span> <span class=\"token builtin\">number</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> relevant<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      logReturns<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>Math<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>relevant<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>vwap <span class=\"token operator\">/</span> relevant<span class=\"token punctuation\">[</span>i <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>vwap<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">const</span> mean <span class=\"token operator\">=</span> logReturns<span class=\"token punctuation\">.</span><span class=\"token function\">reduce</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">a<span class=\"token punctuation\">,</span> b</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> a <span class=\"token operator\">+</span> b<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">/</span> logReturns<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> variance <span class=\"token operator\">=</span>\n      logReturns<span class=\"token punctuation\">.</span><span class=\"token function\">reduce</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">sum<span class=\"token punctuation\">,</span> r</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> sum <span class=\"token operator\">+</span> <span class=\"token punctuation\">(</span>r <span class=\"token operator\">-</span> mean<span class=\"token punctuation\">)</span> <span class=\"token operator\">**</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">/</span> <span class=\"token punctuation\">(</span>logReturns<span class=\"token punctuation\">.</span>length <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Annualize: scale by observations per year</span>\n    <span class=\"token keyword\">const</span> obsPerYear <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token number\">365.25</span> <span class=\"token operator\">*</span> <span class=\"token number\">24</span> <span class=\"token operator\">*</span> <span class=\"token number\">3600</span> <span class=\"token operator\">*</span> <span class=\"token number\">1000</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">/</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>aggregationMs<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> Math<span class=\"token punctuation\">.</span><span class=\"token function\">sqrt</span><span class=\"token punctuation\">(</span>variance <span class=\"token operator\">*</span> obsPerYear<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">private</span> <span class=\"token function\">pruneOldPrices</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> <span class=\"token keyword\">void</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> cutoff <span class=\"token operator\">=</span> Date<span class=\"token punctuation\">.</span><span class=\"token function\">now</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>windowSize <span class=\"token operator\">*</span> <span class=\"token number\">1000</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>prices <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>prices<span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">p</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> p<span class=\"token punctuation\">.</span>timestamp <span class=\"token operator\">>=</span> cutoff<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>The service exposes the current vol estimate via a simple REST endpoint (not shown here for brevity, but it’s a basic Express route returning <code class=\"language-text\">{ annualizedVol, timestamp, windowSeconds, sampleCount }</code>). This is what the oracle updater process polls to decide whether to push a new value on-chain.</p>\n<p>A key design choice: the 500ms VWAP aggregation smooths out individual trade noise while preserving meaningful price movements. If you compute returns on raw trade-by-trade data, you get a lot of microstructure noise (bid-ask bounce, etc.) that inflates your vol estimate. The VWAP bucketing handles this elegantly.</p>\n<h2 id=\"solidity-interface-the-oracle-contract\" style=\"position:relative;\"><a href=\"#solidity-interface-the-oracle-contract\" aria-label=\"solidity interface the oracle contract permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Solidity Interface: The Oracle Contract</h2>\n<p>On the smart contract side, I want something simple and composable. Here’s the interface:</p>\n<div class=\"gatsby-highlight\" data-language=\"solidity\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-solidity line-numbers\"><code class=\"language-solidity\"><span class=\"token comment\">// SPDX-License-Identifier: MIT</span>\n<span class=\"token keyword\">pragma</span> <span class=\"token keyword\">solidity</span> <span class=\"token operator\">^</span><span class=\"token version number\">0.8.19</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">interface</span> <span class=\"token class-name\">IVolatilityOracle</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">struct</span> <span class=\"token class-name\">VolData</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token builtin\">uint256</span> realizedVol<span class=\"token punctuation\">;</span>      <span class=\"token comment\">// Annualized vol in basis points (e.g., 5000 = 50%)</span>\n        <span class=\"token builtin\">uint256</span> parkinsonVol<span class=\"token punctuation\">;</span>     <span class=\"token comment\">// Parkinson estimator</span>\n        <span class=\"token builtin\">uint256</span> garmanKlassVol<span class=\"token punctuation\">;</span>   <span class=\"token comment\">// Garman-Klass estimator</span>\n        <span class=\"token builtin\">uint256</span> timestamp<span class=\"token punctuation\">;</span>        <span class=\"token comment\">// When this was computed</span>\n        <span class=\"token builtin\">uint32</span>  windowSeconds<span class=\"token punctuation\">;</span>    <span class=\"token comment\">// Observation window used</span>\n        <span class=\"token builtin\">uint16</span>  confidence<span class=\"token punctuation\">;</span>       <span class=\"token comment\">// Sample count / quality metric</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">function</span> <span class=\"token function\">getVolatility</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">bytes32</span> pair<span class=\"token punctuation\">)</span> <span class=\"token keyword\">external</span> <span class=\"token keyword\">view</span> <span class=\"token keyword\">returns</span> <span class=\"token punctuation\">(</span>VolData <span class=\"token keyword\">memory</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">function</span> <span class=\"token function\">getRealizedVol</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">bytes32</span> pair<span class=\"token punctuation\">)</span> <span class=\"token keyword\">external</span> <span class=\"token keyword\">view</span> <span class=\"token keyword\">returns</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">uint256</span> vol<span class=\"token punctuation\">,</span> <span class=\"token builtin\">uint256</span> timestamp<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">function</span> <span class=\"token function\">isStale</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">bytes32</span> pair<span class=\"token punctuation\">,</span> <span class=\"token builtin\">uint256</span> maxAge<span class=\"token punctuation\">)</span> <span class=\"token keyword\">external</span> <span class=\"token keyword\">view</span> <span class=\"token keyword\">returns</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">bool</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">event</span> <span class=\"token function\">VolatilityUpdated</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">bytes32</span> <span class=\"token keyword\">indexed</span> pair<span class=\"token punctuation\">,</span> <span class=\"token builtin\">uint256</span> realizedVol<span class=\"token punctuation\">,</span> <span class=\"token builtin\">uint256</span> timestamp<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">contract</span> <span class=\"token class-name\">VolatilityOracle</span> <span class=\"token keyword\">is</span> IVolatilityOracle <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">mapping</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">bytes32</span> <span class=\"token operator\">=></span> VolData<span class=\"token punctuation\">)</span> <span class=\"token keyword\">private</span> _latestVol<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">mapping</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">address</span> <span class=\"token operator\">=></span> <span class=\"token builtin\">bool</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">public</span> authorizedUpdaters<span class=\"token punctuation\">;</span>\n    <span class=\"token builtin\">uint256</span> <span class=\"token keyword\">public</span> updateThresholdBps <span class=\"token operator\">=</span> <span class=\"token number\">100</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Only update if vol changed by >1%</span>\n\n    <span class=\"token keyword\">modifier</span> <span class=\"token function\">onlyUpdater</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">require</span><span class=\"token punctuation\">(</span>authorizedUpdaters<span class=\"token punctuation\">[</span>msg<span class=\"token punctuation\">.</span>sender<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"unauthorized\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">_</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">function</span> <span class=\"token function\">pushUpdate</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">bytes32</span> pair<span class=\"token punctuation\">,</span> VolData <span class=\"token keyword\">calldata</span> data<span class=\"token punctuation\">)</span> <span class=\"token keyword\">external</span> onlyUpdater <span class=\"token punctuation\">{</span>\n        VolData <span class=\"token keyword\">storage</span> current <span class=\"token operator\">=</span> _latestVol<span class=\"token punctuation\">[</span>pair<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n        <span class=\"token builtin\">uint256</span> delta <span class=\"token operator\">=</span> <span class=\"token function\">_absDiff</span><span class=\"token punctuation\">(</span>current<span class=\"token punctuation\">.</span>realizedVol<span class=\"token punctuation\">,</span> data<span class=\"token punctuation\">.</span>realizedVol<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">require</span><span class=\"token punctuation\">(</span>\n            delta <span class=\"token operator\">*</span> <span class=\"token number\">10000</span> <span class=\"token operator\">/</span> <span class=\"token punctuation\">(</span>current<span class=\"token punctuation\">.</span>realizedVol <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">>=</span> updateThresholdBps<span class=\"token punctuation\">,</span>\n            <span class=\"token string\">\"change below threshold\"</span>\n        <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        _latestVol<span class=\"token punctuation\">[</span>pair<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> data<span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">emit</span> <span class=\"token function\">VolatilityUpdated</span><span class=\"token punctuation\">(</span>pair<span class=\"token punctuation\">,</span> data<span class=\"token punctuation\">.</span>realizedVol<span class=\"token punctuation\">,</span> data<span class=\"token punctuation\">.</span>timestamp<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">function</span> <span class=\"token function\">getVolatility</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">bytes32</span> pair<span class=\"token punctuation\">)</span> <span class=\"token keyword\">external</span> <span class=\"token keyword\">view</span> <span class=\"token keyword\">returns</span> <span class=\"token punctuation\">(</span>VolData <span class=\"token keyword\">memory</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> _latestVol<span class=\"token punctuation\">[</span>pair<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">function</span> <span class=\"token function\">getRealizedVol</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">bytes32</span> pair<span class=\"token punctuation\">)</span> <span class=\"token keyword\">external</span> <span class=\"token keyword\">view</span> <span class=\"token keyword\">returns</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">uint256</span><span class=\"token punctuation\">,</span> <span class=\"token builtin\">uint256</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        VolData <span class=\"token keyword\">storage</span> d <span class=\"token operator\">=</span> _latestVol<span class=\"token punctuation\">[</span>pair<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>d<span class=\"token punctuation\">.</span>realizedVol<span class=\"token punctuation\">,</span> d<span class=\"token punctuation\">.</span>timestamp<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">function</span> <span class=\"token function\">isStale</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">bytes32</span> pair<span class=\"token punctuation\">,</span> <span class=\"token builtin\">uint256</span> maxAge<span class=\"token punctuation\">)</span> <span class=\"token keyword\">external</span> <span class=\"token keyword\">view</span> <span class=\"token keyword\">returns</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">bool</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> block<span class=\"token punctuation\">.</span>timestamp <span class=\"token operator\">-</span> _latestVol<span class=\"token punctuation\">[</span>pair<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>timestamp <span class=\"token operator\">></span> maxAge<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">function</span> <span class=\"token function\">_absDiff</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">uint256</span> a<span class=\"token punctuation\">,</span> <span class=\"token builtin\">uint256</span> b<span class=\"token punctuation\">)</span> <span class=\"token keyword\">internal</span> <span class=\"token keyword\">pure</span> <span class=\"token keyword\">returns</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">uint256</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> a <span class=\"token operator\">></span> b <span class=\"token operator\">?</span> a <span class=\"token operator\">-</span> b <span class=\"token punctuation\">:</span> b <span class=\"token operator\">-</span> a<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>A few design decisions worth noting:</p>\n<p><strong>Push model with threshold.</strong> The updater only sends a transaction when vol has changed meaningfully (configurable threshold, defaulting to 1% relative change). This keeps gas costs manageable — during stable markets, updates might happen every few minutes; during volatile periods, more frequently.</p>\n<p><strong>Staleness check built in.</strong> Consumers can call <code class=\"language-text\">isStale()</code> to verify the data is fresh enough for their use case. A lending protocol might tolerate 5-minute-old data; an options protocol might want sub-minute freshness.</p>\n<p><strong>Multiple estimators in one struct.</strong> Different consumers have different needs. By publishing all three estimators in a single update, we amortize the gas cost across multiple use cases.</p>\n<p><strong>Basis points representation.</strong> Using uint256 with basis points (50% vol = 5000 bps) avoids floating point entirely while giving sufficient precision for any practical application.</p>\n<h2 id=\"monitoring-dashboard\" style=\"position:relative;\"><a href=\"#monitoring-dashboard\" aria-label=\"monitoring dashboard permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Monitoring Dashboard</h2>\n<p>I’ve been building a simple dashboard to visualize the feed in real time — nothing fancy, just a React frontend with a chart showing the rolling vol estimate, the raw VWAP prices it’s computed from, and the on-chain update history. It’s useful for debugging and for demonstrating to potential integrators that the feed is responsive and accurate.</p>\n<p>The most interesting visualization is overlaying the three estimators. During normal markets they track closely, but during dislocations (flash crashes, sudden liquidity events) the Parkinson estimator reacts fastest because it captures the intra-bucket range expansion immediately. Watching them diverge and reconverge is genuinely interesting from a market microstructure perspective.</p>\n<h2 id=\"challenges-and-future-work\" style=\"position:relative;\"><a href=\"#challenges-and-future-work\" aria-label=\"challenges and future work permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Challenges and Future Work</h2>\n<p>This prototype works, but there’s a gap between “works on my laptop” and “production oracle that protocols depend on.” Here’s what I’m thinking about:</p>\n<h3 id=\"gas-costs\" style=\"position:relative;\"><a href=\"#gas-costs\" aria-label=\"gas costs permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Gas Costs</h3>\n<p>Even with the threshold-based update mechanism, gas costs add up. On L1 Ethereum, pushing updates every few minutes for multiple pairs gets expensive quickly. The obvious answer is deploying on L2s (Arbitrum, Base, etc.) where updates cost fractions of a cent. You could also explore a pull-based model where consumers pay for their own reads from an off-chain data availability layer, but that adds complexity.</p>\n<h3 id=\"multi-source-aggregation\" style=\"position:relative;\"><a href=\"#multi-source-aggregation\" aria-label=\"multi source aggregation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Multi-Source Aggregation</h3>\n<p>Relying on a single exchange’s orderbook is a centralization risk and a manipulation vector. The production version needs to aggregate across multiple venues — Binance, OKX, Bybit, Coinbase — and use some form of outlier detection to handle cases where one venue’s data diverges (possibly due to manipulation or technical issues).</p>\n<p>I’m thinking a median-of-estimators approach across venues, with automatic exclusion of any source that deviates more than 2 standard deviations from the median. This is similar to how existing price oracle networks handle multi-source aggregation.</p>\n<h3 id=\"manipulation-resistance\" style=\"position:relative;\"><a href=\"#manipulation-resistance\" aria-label=\"manipulation resistance permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Manipulation Resistance</h3>\n<p>This is the hard problem. If someone knows that a DeFi protocol uses this vol oracle to set liquidation thresholds, they could theoretically manipulate the underlying orderbook data to spike the vol estimate, causing the protocol to widen thresholds, and then exploit the looser parameters.</p>\n<p>Defenses include: using longer observation windows (harder to sustain manipulation), requiring consistent signals across multiple venues, implementing rate-of-change limits on the oracle output (vol can’t jump more than X% per update), and incorporating TWAP-style smoothing.</p>\n<h3 id=\"integration-with-oracle-networks\" style=\"position:relative;\"><a href=\"#integration-with-oracle-networks\" aria-label=\"integration with oracle networks permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Integration with Oracle Networks</h3>\n<p>The end game isn’t running this as a standalone service. It’s getting vol data integrated into existing oracle networks so that it benefits from their existing security models, node operator sets, and consumer ecosystems. The computation methodology described here could run as a module within a decentralized oracle network, with multiple independent node operators each computing vol from their own data sources and reaching consensus on the output.</p>\n<h3 id=\"further-estimator-research\" style=\"position:relative;\"><a href=\"#further-estimator-research\" aria-label=\"further estimator research permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Further Estimator Research</h3>\n<p>There are more sophisticated approaches worth exploring: realized kernels (which handle microstructure noise more elegantly), jump-robust estimators (bi-power variation), and multi-scale realized volatility. Each has tradeoffs between noise sensitivity, computation cost, and the assumptions they make about the price process.</p>\n<h2 id=\"wrapping-up\" style=\"position:relative;\"><a href=\"#wrapping-up\" aria-label=\"wrapping up permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Wrapping Up</h2>\n<p>I think there’s a real product here. The DeFi options market is growing, lending protocols are getting more sophisticated about risk management, and everyone needs better vol data. The gap between “price oracle” and “volatility oracle” is mostly an engineering challenge at this point — the statistical methods are well-established, the data sources exist, and the smart contract interface is straightforward.</p>\n<p>The prototype is running locally, ingesting Binance trade data and computing vol estimates that look reasonable when compared against Deribit’s implied vol surface. Next steps are multi-venue aggregation, a proper deployment on a testnet, and conversations with potential consumers about what API they actually want.</p>\n<p>If you’re building something in the DeFi derivatives or risk management space and would find a vol oracle useful, I’d love to hear about your requirements. The interface design should be driven by actual consumer needs rather than my assumptions about what’s useful.</p>","tableOfContents":"<ul>\n<li><a href=\"/volatility-oracle-prototype/#the-problem-defi-needs-volatility-not-just-price\">The Problem: DeFi Needs Volatility, Not Just Price</a></li>\n<li><a href=\"/volatility-oracle-prototype/#the-concept\">The Concept</a></li>\n<li>\n<p><a href=\"/volatility-oracle-prototype/#volatility-computation-multiple-estimators\">Volatility Computation: Multiple Estimators</a></p>\n<ul>\n<li><a href=\"/volatility-oracle-prototype/#standard-realized-volatility\">Standard Realized Volatility</a></li>\n<li><a href=\"/volatility-oracle-prototype/#parkinson-estimator\">Parkinson Estimator</a></li>\n<li><a href=\"/volatility-oracle-prototype/#garman-klass-estimator\">Garman-Klass Estimator</a></li>\n<li><a href=\"/volatility-oracle-prototype/#why-microstructure-data-matters\">Why Microstructure Data Matters</a></li>\n</ul>\n</li>\n<li><a href=\"/volatility-oracle-prototype/#live-dashboard-prototype\">Live Dashboard Prototype</a></li>\n<li><a href=\"/volatility-oracle-prototype/#typescript-prototype-real-time-vol-computation\">TypeScript Prototype: Real-Time Vol Computation</a></li>\n<li><a href=\"/volatility-oracle-prototype/#solidity-interface-the-oracle-contract\">Solidity Interface: The Oracle Contract</a></li>\n<li><a href=\"/volatility-oracle-prototype/#monitoring-dashboard\">Monitoring Dashboard</a></li>\n<li>\n<p><a href=\"/volatility-oracle-prototype/#challenges-and-future-work\">Challenges and Future Work</a></p>\n<ul>\n<li><a href=\"/volatility-oracle-prototype/#gas-costs\">Gas Costs</a></li>\n<li><a href=\"/volatility-oracle-prototype/#multi-source-aggregation\">Multi-Source Aggregation</a></li>\n<li><a href=\"/volatility-oracle-prototype/#manipulation-resistance\">Manipulation Resistance</a></li>\n<li><a href=\"/volatility-oracle-prototype/#integration-with-oracle-networks\">Integration with Oracle Networks</a></li>\n<li><a href=\"/volatility-oracle-prototype/#further-estimator-research\">Further Estimator Research</a></li>\n</ul>\n</li>\n<li><a href=\"/volatility-oracle-prototype/#wrapping-up\">Wrapping Up</a></li>\n</ul>","frontmatter":{"title":"Building a Volatility Oracle Prototype: Computing Realized Volatility from Orderbook Data and Serving It On-Chain","date":"April 10, 2026","description":"A product concept for an on-chain volatility oracle that computes realized volatility from orderbook microstructure data, with TypeScript prototype and Solidity interface."}}},"pageContext":{"slug":"/volatility-oracle-prototype/","previous":{"fields":{"slug":"/polymarket-orderbook-analysis/"},"frontmatter":{"title":"Analyzing Bid-Ask Spreads and Liquidity Shifts in Polymarket's 5-Minute Binary Option Orderbooks"}},"next":null}}}