<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Andrew Rodn</title>
    <description>The latest articles on DEV Community by Andrew Rodn (@andrewrodn).</description>
    <link>https://dev.to/andrewrodn</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4145437%2F0c2d444e-6cbd-46a1-b76d-d23447263a12.jpg</url>
      <title>DEV Community: Andrew Rodn</title>
      <link>https://dev.to/andrewrodn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/andrewrodn"/>
    <language>en</language>
    <item>
      <title>Building a Cross-Venue Market Maker: Pricing Polymarket's Equity Books Off Binance Perps</title>
      <dc:creator>Andrew Rodn</dc:creator>
      <pubDate>Tue, 20 Oct 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/followsm/building-a-cross-venue-market-maker-pricing-polymarkets-equity-books-off-binance-perps-1316</link>
      <guid>https://dev.to/followsm/building-a-cross-venue-market-maker-pricing-polymarkets-equity-books-off-binance-perps-1316</guid>
      <description>&lt;h3&gt;
  
  
  📚 The Quantitative Microstructure &amp;amp; Cross-Market Series by FollowSM
&lt;/h3&gt;

&lt;p&gt;Part 3 showed that Binance's 24/7 equity perps price the US opening gap before the bell: regressing the official gap on the perp's overnight move gives slope 1.00 and R² = 0.998$. Polymarket lists a daily &lt;em&gt;"TSLA Up or Down on …"&lt;/em&gt; market for the same twelve tickers. Both venues price the same close, so if the perp is the better price, it should also be the better &lt;em&gt;fair value&lt;/em&gt; for Polymarket.&lt;/p&gt;

&lt;p&gt;This part asks whether that is tradable. Can a market maker quote Polymarket's equity books around a probability computed from the perp, and keep what it earns once fees, adverse selection, latency and a proper placebo test are included? And which of the risk tools from Parts 1–3 (session-aware σ, the early exit, the toxicity breaker) help a &lt;em&gt;market maker&lt;/em&gt; rather than a hedger?&lt;/p&gt;

&lt;p&gt;We used &lt;strong&gt;1,537 Polymarket market-nights across 12 equity perps&lt;/strong&gt; (January–September 2026) for the study, and &lt;strong&gt;1,313 of them for a fill-by-fill backtest&lt;/strong&gt; that replays every historical taker order against our quotes.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The perp is the better probability in every session.&lt;/strong&gt; When the perp-implied and Polymarket probabilities differ by more than 5¢, the market resolves on the perp's side &lt;strong&gt;62.5%&lt;/strong&gt; of the time during regular hours (n = 4,651) and 55–58% overnight, post-market and on weekends. Pre-market is a coin flip (51%).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;There is no multi-minute lead.&lt;/strong&gt; Both venues move in the same minute (correlation 0.42 in regular hours, 0.13 off-hours). What remains at a one-minute lag is small (0.02–0.03). After a large perp move, Polymarket drifts a further 1.4¢ toward it over the next hour.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In sample, quoting around the perp's fair value made money; quoting around Polymarket's own mid lost it.&lt;/strong&gt; Same fills model, same nights (January–September): &lt;strong&gt;+$6.2k&lt;/strong&gt; (Sharpe 1.7) against &lt;strong&gt;−$46.5k&lt;/strong&gt;. With a 4¢ half-spread: +$7.9k (Sharpe 2.6).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It survives placebos.&lt;/strong&gt; All 20 seeds that quote off another night's perp path lose between −$18k and −$31k.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speed matters in seconds, not minutes.&lt;/strong&gt; Quote updates at 250 ms and 1 s perform identically; at 5 s P&amp;amp;L falls 22%; at 60 s the book loses $19k to faster takers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Most of the Shield doesn't transfer.&lt;/strong&gt; Session-aware σ was worth doing: wall-clock σ earned $0.6k; minutes-to-close σ earned $6.2k. But a perp delta hedge cost $26k–$83k and never paid for itself. The one-hour early exit lowered the tail by 15% and cost almost the entire edge. The toxicity breaker barely mattered.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It is small and it faded.&lt;/strong&gt; The best variant made ~$42 a trading day across 11 books. Almost all of it came before mid-June.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It did not survive out of sample.&lt;/strong&gt; We re-ran the unchanged backtest on the 11 trading days after the study ended (29 September – 13 October, 120 market-nights). The fair-value quoter &lt;strong&gt;lost $2,956&lt;/strong&gt; (−8.6¢ per filled share), more than quoting Polymarket's own mid (−$1,377), and 18 of 20 placebo seeds did at least as well. Read the in-sample result as history, not as a strategy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Code repositories: &lt;a href="https://github.com/Follow-SM/tick-microstructure-research" rel="noopener noreferrer"&gt;tick-microstructure-research&lt;/a&gt; (&lt;code&gt;tmr tradfi pm-fetch&lt;/code&gt;, &lt;code&gt;tmr tradfi pm-analyze&lt;/code&gt;) and &lt;a href="https://github.com/Follow-SM/dynamic-inventory-hedger" rel="noopener noreferrer"&gt;dynamic-inventory-hedger&lt;/a&gt; (&lt;code&gt;research/backtest_confluence.py&lt;/code&gt;). Everything comes from public data.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 1. The Lead-Lag Discovery (and the One-Minute Lead That Wasn't)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Data
&lt;/h3&gt;

&lt;p&gt;For each Up/Down market we pulled every taker fill from Polymarket's public data API (wallet, transaction hash, size, price, side) and the CLOB's 1-minute price history, then laid both onto the perp's minute grid from the previous official close to the resolving close. These markets are small. The median night trades &lt;strong&gt;$1.0k–$3.0k&lt;/strong&gt; of taker volume for single stocks and $29k for SPY. The median taker order is 15 shares (about $7).&lt;/p&gt;

&lt;h3&gt;
  
  
  A Trap Worth Describing
&lt;/h3&gt;

&lt;p&gt;Our first pass showed the perp leading Polymarket by exactly one minute: correlation 0.41 at lag −1 and 0.01 at lag 0 during regular hours. It looked like a clean latency edge. It was a timestamp bug.&lt;/p&gt;

&lt;p&gt;CLOB history points are stamped &lt;strong&gt;3–15 seconds after&lt;/strong&gt; each minute boundary, not on it. Taking "the last point before the minute ends" therefore reads the price from ~56 seconds earlier than the perp's close for that minute. That builds a one-minute lag into every row. Near-zero correlation at lag 0 next to a strong peak at exactly one step is the signature of an alignment error, not of a market. The fix is to sample the first history point &lt;em&gt;after&lt;/em&gt; each minute ends; a regression test in the repo now pins this.&lt;/p&gt;

&lt;h3&gt;
  
  
  What the Aligned Data Says
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj6x0xexk4ahdzkoeimm9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj6x0xexk4ahdzkoeimm9.png" alt="Lead-lag"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fig 1. Cross-correlation of Polymarket probability changes and perp returns. Negative lag = perp moves first.&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;1-minute correlation&lt;/th&gt;
&lt;th&gt;perp first (−1)&lt;/th&gt;
&lt;th&gt;same minute (0)&lt;/th&gt;
&lt;th&gt;Polymarket first (+1)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;regular hours (298k minutes)&lt;/td&gt;
&lt;td&gt;0.024&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.417&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.014&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;off-hours (2.2M minutes)&lt;/td&gt;
&lt;td&gt;0.032&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.125&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.009&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Price discovery is shared inside the minute, with a small tilt toward the perp. Event studies give the same picture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;After a large off-hours perp move&lt;/strong&gt; (|5 min| ≥ the symbol's 99th percentile, n = 5,268), Polymarket moves 3.0¢ in the 30 minutes up to and including the move, then drifts a further &lt;strong&gt;1.4¢&lt;/strong&gt; [1.1, 1.7] toward it over the next 60 minutes. The adjustment is partial and slow, not delayed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;After a Polymarket jump of ≥ 10¢ in 5 minutes&lt;/strong&gt; (n = 6,383), the perp had already moved 10.5 bps in the preceding 30 minutes. It adds only 1.2 bps [−0.6, +3.0] afterwards, and 2 of 20 random-timing placebos did as well.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Whale sweeps"&lt;/strong&gt; are rare in markets this thin. Using a $1,000 floor (which always binds), there were 159 sweeps. The perp's 60-minute move after them is +5.5 bps [−0.4, +12.3], and 3 of 20 placebos matched it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Who Is Right When They Disagree
&lt;/h3&gt;

&lt;p&gt;A perp-implied probability for an Up/Down market is a digital option: P(Up) = Φ(ln(S/K)/σ), with S the perp de-biased by its basis at the prior close, K the prior official close, and σ the standard deviation of ln(close/S) at the same time of day over the symbol's previous 20 nights. Every σ is point-in-time. We sampled every 30 minutes of every night:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Session&lt;/th&gt;
&lt;th&gt;Samples&lt;/th&gt;
&lt;th&gt;Brier Perp&lt;/th&gt;
&lt;th&gt;Brier Polymarket&lt;/th&gt;
&lt;th&gt;Perp Side Right When They Differ &amp;gt; 5¢&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Weekend / Holiday&lt;/td&gt;
&lt;td&gt;25,408&lt;/td&gt;
&lt;td&gt;0.250&lt;/td&gt;
&lt;td&gt;0.255&lt;/td&gt;
&lt;td&gt;58.3% [57.4–59.2]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Overnight&lt;/td&gt;
&lt;td&gt;21,654&lt;/td&gt;
&lt;td&gt;0.230&lt;/td&gt;
&lt;td&gt;0.232&lt;/td&gt;
&lt;td&gt;56.6% [55.2–58.0]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pre-market&lt;/td&gt;
&lt;td&gt;14,959&lt;/td&gt;
&lt;td&gt;0.213&lt;/td&gt;
&lt;td&gt;0.215&lt;/td&gt;
&lt;td&gt;51.4% [49.8–53.0]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Regular Hours&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;12,348&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.140&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.142&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;62.5% [61.1–63.9]&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Post-market&lt;/td&gt;
&lt;td&gt;10,120&lt;/td&gt;
&lt;td&gt;0.247&lt;/td&gt;
&lt;td&gt;0.249&lt;/td&gt;
&lt;td&gt;55.6% [53.3–58.0]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpdxsz2qzl082d0gufnbt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpdxsz2qzl082d0gufnbt.png" alt="Calibration by session"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Fig 2. Left: how often the market resolved on the perp's side when the two disagreed. Right: Brier difference with 95% bootstrap intervals; every session is above zero.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The Brier gaps are small (0.001–0.005) because both venues are mostly right about the easy nights. The disagreements are where the money is.&lt;/p&gt;

&lt;p&gt;Two side findings:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Off-hours Polymarket flow does &lt;strong&gt;not&lt;/strong&gt; predict the part of the gap the perp misses: Polymarket's overnight probability change and its taker imbalance are &lt;em&gt;negatively&lt;/em&gt; related to it (ρ −0.14 and −0.10). Polymarket follows the perp, including its overshoots.&lt;/li&gt;
&lt;li&gt;In 21 earnings EPS-beat markets, Polymarket was on the right side an hour before the release 18 times, but it had already priced that in. The median time for it to reach 90% on the outcome after the release was zero minutes.&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  Part 2. The Fair-Value Engine
&lt;/h2&gt;

&lt;p&gt;The quoter needs three inputs, all available in real time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;S   = last perp trade / (1 + basis at the prior 16:00 close)     Binance aggTrade stream 
K   = prior official close                                        known all night
σ²  = variance of ln(close / S) still to come                     estimated from previous nights

FV  = Φ( (ln(S/K) − σ²/2) / σ )                                   the hedger's own digital model
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only hard part is &lt;strong&gt;σ&lt;/strong&gt;. We tested three versions of it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Wall-clock σ&lt;/strong&gt;, the crypto default: &lt;code&gt;natr_15m&lt;/code&gt; spread evenly over the remaining time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Session σ&lt;/strong&gt;, from Part 3: per-minute variances by session plus an opening-jump term, summed to the close.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minutes-to-close σ&lt;/strong&gt;: mean ln(C/S)² at the same distance from the close over the previous 20 nights, pooled ±15 minutes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Part 3 found session σ was the biggest lever for a hedger. For a quoter it helped (+$3.4k against +$0.6k for wall-clock σ), but it still left edge on the table in regular hours, exactly when Polymarket prices off the live stock. Measuring the remaining variance directly at each minutes-to-close doubled the result. It is also what the calibration table above uses. We chose it after seeing the session-σ backtest, so it is judged below by placebos and a split-half test, not by its total alone.&lt;/p&gt;

&lt;p&gt;Quotes are &lt;code&gt;FV ± half-spread&lt;/code&gt;, skewed by inventory. A fair-value quote never leans past Polymarket's last mid ± 0.5¢, so the book always rests as a maker.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 3. The Backtest, with Placebo Control
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How Fills Work
&lt;/h3&gt;

&lt;p&gt;Every historical taker order is replayed against our quotes. An order fills us only if it traded &lt;strong&gt;strictly through&lt;/strong&gt; our price (its worst print below our bid or above our ask), at our price, up to 100 shares per order. An order that only touched our price never fills us: we assume we are last in the queue. Quotes are recomputed for every order using information from 250 ms before it. Makers pay no Polymarket fee. The finance-category taker fee (shares × 0.04 × p(1−p)) applies only when we flatten. The 25% maker rebate is paid pro rata from a daily pool and is &lt;strong&gt;not&lt;/strong&gt; credited. Perp hedges pay 5 bps and walk the Binance tape (Part 3's IOC model). The book is fail-closed: it posts no quote without a perp print in the last 60 s or a Polymarket mid, and no hedge without a perp bar.&lt;/p&gt;

&lt;p&gt;The inventory cap is 500 shares. The mean peak inventory was about 250 shares (~$125).&lt;/p&gt;

&lt;h3&gt;
  
  
  Results: 1,313 Market-Nights, 11 Symbols, 147 Trading Days
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;strategy&lt;/th&gt;
&lt;th&gt;P&amp;amp;L&lt;/th&gt;
&lt;th&gt;Sharpe (daily, ×√252)&lt;/th&gt;
&lt;th&gt;ES 5% per night&lt;/th&gt;
&lt;th&gt;¢ per filled share&lt;/th&gt;
&lt;th&gt;share of taker volume&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;naive: quote Polymarket's own mid&lt;/td&gt;
&lt;td&gt;−$46,495&lt;/td&gt;
&lt;td&gt;−14.5&lt;/td&gt;
&lt;td&gt;−$307&lt;/td&gt;
&lt;td&gt;−2.89&lt;/td&gt;
&lt;td&gt;22.5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fair value, wall-clock σ&lt;/td&gt;
&lt;td&gt;+$649&lt;/td&gt;
&lt;td&gt;0.2&lt;/td&gt;
&lt;td&gt;−$320&lt;/td&gt;
&lt;td&gt;+0.08&lt;/td&gt;
&lt;td&gt;13.3%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fair value, session σ&lt;/td&gt;
&lt;td&gt;+$3,445&lt;/td&gt;
&lt;td&gt;0.9&lt;/td&gt;
&lt;td&gt;−$217&lt;/td&gt;
&lt;td&gt;+0.41&lt;/td&gt;
&lt;td&gt;14.9%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;fair value, minutes-to-close σ&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;+$6,211&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.7&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;−$239&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;+0.87&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;12.3%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;… with a 4¢ half-spread&lt;/td&gt;
&lt;td&gt;+$7,912&lt;/td&gt;
&lt;td&gt;2.6&lt;/td&gt;
&lt;td&gt;−$222&lt;/td&gt;
&lt;td&gt;+1.70&lt;/td&gt;
&lt;td&gt;8.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Quoting around your own venue's mid is the classic losing market maker. Takers trade through you when they know better, and in these books they usually know the perp. Moving the centre to the perp's fair value changes the sign.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk9q3guuooo9vfgnqtjs5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk9q3guuooo9vfgnqtjs5.png" alt="Cumulative P&amp;amp;L"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Fig 3. Cumulative P&amp;amp;L. Shaded bands: 20 placebo seeds for the full Shield + Sword system (purple) and for the minutes-to-close fair value (green).&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Placebos
&lt;/h3&gt;

&lt;p&gt;Each placebo seed quotes with the same strategy, but its "perp" is &lt;strong&gt;another night's perp path&lt;/strong&gt; (same symbol, aligned on time to the close). That gives realistic, perp-shaped noise that carries no information about tonight. On the 1,174 nights that had enough donor history:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;system&lt;/th&gt;
&lt;th&gt;real&lt;/th&gt;
&lt;th&gt;20 placebo seeds&lt;/th&gt;
&lt;th&gt;seeds ≥ real&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;minutes-to-close fair value&lt;/td&gt;
&lt;td&gt;+$5,263&lt;/td&gt;
&lt;td&gt;−$30,818 to −$18,015&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0 / 20&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;full Shield + Sword (session σ, hedged)&lt;/td&gt;
&lt;td&gt;−$38,527&lt;/td&gt;
&lt;td&gt;−$72,999 to −$67,679&lt;/td&gt;
&lt;td&gt;0 / 20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;off-hours only, flat by 09:25&lt;/td&gt;
&lt;td&gt;−$1,039&lt;/td&gt;
&lt;td&gt;−$12,873 to −$9,356&lt;/td&gt;
&lt;td&gt;0 / 20&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The information in the perp is real in every configuration. Whether a configuration &lt;em&gt;makes money&lt;/em&gt; is a separate question.&lt;/p&gt;
&lt;h3&gt;
  
  
  Speed
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Quote Update Latency&lt;/th&gt;
&lt;th&gt;250 ms&lt;/th&gt;
&lt;th&gt;1 s&lt;/th&gt;
&lt;th&gt;5 s&lt;/th&gt;
&lt;th&gt;60 s&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Minutes-to-close fair value&lt;/td&gt;
&lt;td&gt;+$6,211&lt;/td&gt;
&lt;td&gt;+$6,211&lt;/td&gt;
&lt;td&gt;+$4,865&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;−$19,355&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F10opnxh05ahphl8zwnph.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F10opnxh05ahphl8zwnph.png" alt="Latency"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The edge lives in the seconds after the perp moves. A book that refreshes once a minute is the one being picked off. Someone on Polymarket is already reacting to the perp inside a minute.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Shield, Component by Component
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Added to the Fair-Value Book&lt;/th&gt;
&lt;th&gt;P&amp;amp;L&lt;/th&gt;
&lt;th&gt;ES 5%&lt;/th&gt;
&lt;th&gt;P&amp;amp;L Std per night&lt;/th&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Nothing (minutes-to-close σ)&lt;/td&gt;
&lt;td&gt;+$6,211&lt;/td&gt;
&lt;td&gt;−$239&lt;/td&gt;
&lt;td&gt;$115&lt;/td&gt;
&lt;td&gt;Benchmark&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;+ Exit 1 h early + toxicity breaker&lt;/td&gt;
&lt;td&gt;+$107&lt;/td&gt;
&lt;td&gt;−$204&lt;/td&gt;
&lt;td&gt;$90&lt;/td&gt;
&lt;td&gt;Tail −15%, edge gone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;+ Perp delta hedge ($5k band)&lt;/td&gt;
&lt;td&gt;−$26,235&lt;/td&gt;
&lt;td&gt;−$252&lt;/td&gt;
&lt;td&gt;$77&lt;/td&gt;
&lt;td&gt;Hedge cost $26.3k&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full system with session σ, $500 band&lt;/td&gt;
&lt;td&gt;−$43,612&lt;/td&gt;
&lt;td&gt;−$282&lt;/td&gt;
&lt;td&gt;$75&lt;/td&gt;
&lt;td&gt;Hedge cost $41.2k&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full system with wall-clock σ&lt;/td&gt;
&lt;td&gt;−$91,593&lt;/td&gt;
&lt;td&gt;−$496&lt;/td&gt;
&lt;td&gt;$126&lt;/td&gt;
&lt;td&gt;Hedge cost $82.8k&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Session-aware σ: yes.&lt;/strong&gt; In both the quoter and the hedge it is the difference between losing and not losing. Wall-clock σ doubled the hedge cost, as it did in Part 3.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Early exit: a risk dial, not free.&lt;/strong&gt; Flattening an hour before resolution at mid ∓ 2¢ plus the taker fee cost $5.7k. It removed the expiry jump from the tail, but it gave back almost everything the book earned. It was right for Part 2's 1,000-share &lt;em&gt;directional&lt;/em&gt; position. For a small, two-sided book it is optional.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Perp delta hedge: no.&lt;/strong&gt; A market maker's inventory is small, flips sign, and sits near the money, where a digital's delta is largest. Each rebalance pays 5 bps on a notional far larger than the position. Hedging cost 3–6¢ per filled share against a 0.9¢ edge, and it did not improve the 5% ES.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Toxicity breaker: harmless, rarely binding.&lt;/strong&gt; Pulling quotes while either side of the ±1% book is more than 2.5× the other (re-armed after 5 minutes below 2.0) tripped in about 3% of TSLA's minutes and changed P&amp;amp;L by +$0.7k in the session-σ system.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Stability
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Strategy&lt;/th&gt;
&lt;th&gt;Before 11 June&lt;/th&gt;
&lt;th&gt;After 11 June&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Minutes-to-close fair value&lt;/td&gt;
&lt;td&gt;+$6,105&lt;/td&gt;
&lt;td&gt;+$106&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;… 4¢ half-spread&lt;/td&gt;
&lt;td&gt;+$6,061&lt;/td&gt;
&lt;td&gt;+$1,851&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Session σ fair value&lt;/td&gt;
&lt;td&gt;+$2,534&lt;/td&gt;
&lt;td&gt;+$911&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Both halves are positive, but the second is much weaker. Either competition arrived or the edge was partly luck of the period. We can't tell which from seven months.&lt;/p&gt;
&lt;h3&gt;
  
  
  Out of Sample
&lt;/h3&gt;

&lt;p&gt;After writing the above, we ran the same code, unchanged, on the nights after the study ended. The original period reproduces every number in this article exactly, so the only difference is the dates.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Strategy&lt;/th&gt;
&lt;th&gt;28 Jan – 28 Sep (In-Sample)&lt;/th&gt;
&lt;th&gt;29 Sep – 13 Oct (Out-of-Sample)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Minutes-to-close fair value&lt;/td&gt;
&lt;td&gt;+$6,211 (+0.87¢ / share)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;−$2,956 (−8.6¢ / share)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;… 4¢ half-spread&lt;/td&gt;
&lt;td&gt;+$7,912&lt;/td&gt;
&lt;td&gt;−$2,074&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Session σ fair value&lt;/td&gt;
&lt;td&gt;+$3,445&lt;/td&gt;
&lt;td&gt;−$2,476&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quote Polymarket's own mid&lt;/td&gt;
&lt;td&gt;−$46,495&lt;/td&gt;
&lt;td&gt;−$1,377&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Market-nights&lt;/td&gt;
&lt;td&gt;1,313&lt;/td&gt;
&lt;td&gt;120&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Minutes-to-Close Fair Value vs Placebos&lt;/th&gt;
&lt;th&gt;Real&lt;/th&gt;
&lt;th&gt;20 Placebo Seeds&lt;/th&gt;
&lt;th&gt;Seeds ≥ Real&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;In-sample&lt;/td&gt;
&lt;td&gt;+$5,263&lt;/td&gt;
&lt;td&gt;−$30,818 to −$18,015&lt;/td&gt;
&lt;td&gt;0 / 20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Out-of-sample&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;−$2,956&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;−$3,359 to +$207&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;18 / 20&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Eleven trading days is a short sample, but the sign flipped and the placebo test failed. Every fair-value variant lost, and lost more than quoting Polymarket's own mid. Together with the fade after June, the most likely reading is that faster quoters now price these books off the perp, and the edge we measured belonged to a period when nobody did.&lt;/p&gt;


&lt;h2&gt;
  
  
  Part 4. Production Architecture
&lt;/h2&gt;

&lt;p&gt;What a live version would look like, and which parts FollowSM provides today. Given the out-of-sample result, treat it as a reference architecture to test rather than execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Binance equity perp aggTrades ──► Fair Value Engine: Φ((ln(S/K) − σ²/2)/σ), σ by minutes-to-close
                                        │
Polymarket CLOB book + trades ──► Quoter: FV ± half-spread, inventory skew, post-only,
                                        │       never past Polymarket mid ± 0.5¢
Binance ±1% depth ratio ────────► Circuit Breaker: pull quotes &amp;gt; 2.5, re-arm after 5 min &amp;lt; 2.0

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/ws/v1/toxicity&lt;/code&gt;: the Shield.&lt;/strong&gt; FollowSM streams VPIN, &lt;code&gt;ob_toxicity_1pct&lt;/code&gt; (ask/bid notional within ±1%), volume z-scores and sweep detection &lt;strong&gt;for crypto pairs&lt;/strong&gt;. The breaker in this backtest uses the same &lt;code&gt;ob_toxicity_1pct&lt;/code&gt; definition, computed locally from Binance's equity-perp depth, because the stream does not cover equity perps yet. Part 3 showed which session-aware adjustments those signals need first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/ws/v1/confluence&lt;/code&gt;: the Sword, today.&lt;/strong&gt; The confluence engine joins Polymarket probability changes (&lt;code&gt;prob_delta_15m&lt;/code&gt;), whale sweeps and book toxicity for &lt;strong&gt;crypto&lt;/strong&gt; markets. It emits a risk ladder for makers (&lt;code&gt;WIDEN_SPREAD_1_5X&lt;/code&gt;, &lt;code&gt;WIDEN_SPREAD_2X&lt;/code&gt;, &lt;code&gt;HALT_MAKER_QUOTES&lt;/code&gt;), gated by &lt;code&gt;direction_confidence&lt;/code&gt;, and flags cross-market divergence. It is disabled by default, and it is a defensive signal, not a fair-value feed. &lt;strong&gt;It does not price equity Up/Down markets.&lt;/strong&gt; The fair-value engine above is a reference design you build on top of a Binance feed; the code is in the backtest.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Caveats
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fills are modelled, not traded.&lt;/strong&gt; Strictly-through fills with us last in the queue are conservative on queue position. However, the counterfactual is one-sided: our resting quote might have changed taker behavior.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Selection.&lt;/strong&gt; Minutes-to-close σ and the off-hours variant were added after looking at initial results. Placebos and the split-half test were the in-sample check, while out-of-sample validation provided the final test.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Capacity.&lt;/strong&gt; $6k–$8k over seven months across 11 books represents ~$42–$54 per trading day, with ~$125 of peak inventory per book. Capacity is bounded by $1k–$3k of nightly taker flow per stock. Unmodelled maker rebates could add up to roughly a quarter of a cent per share.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resolution source.&lt;/strong&gt; These markets resolve on Pyth's 1-minute close. We checked against official Yahoo closes and skipped 7 markets with discrepancies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;QQQ&lt;/strong&gt; had insufficient perp data history to include in the backtest.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Reproduce
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Follow-SM/tick-microstructure-research
&lt;span class="nb"&gt;cd &lt;/span&gt;tick-microstructure-research &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;".[parquet]"&lt;/span&gt;
tmr tradfi fetch        &lt;span class="c"&gt;# Binance archives + Yahoo (Part 3)&lt;/span&gt;
tmr tradfi pm-fetch     &lt;span class="c"&gt;# Polymarket markets, taker fills, 1-minute history&lt;/span&gt;
tmr tradfi pm-analyze   &lt;span class="c"&gt;# research/POLYMARKET_REPORT.md, results_polymarket.json, figures&lt;/span&gt;

git clone https://github.com/Follow-SM/dynamic-inventory-hedger
&lt;span class="nb"&gt;cd &lt;/span&gt;dynamic-inventory-hedger &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;".[tradfi]"&lt;/span&gt;
python research/backtest_confluence.py

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Summary Findings across the Series
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The information is real; the edge didn't last.&lt;/strong&gt; A Binance perp is a better probability for Polymarket's equity markets than Polymarket's own price in every session. A quoter monetised that at seconds-level latency from January to mid-June, faded after, and lost money out of sample. Information advantages vanish as execution latency across market participants compresses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep the parts of the Shield that fit the position.&lt;/strong&gt; Session-aware σ (or time-to-close variance) matters for every strategy in this series. The early exit and perp delta hedge were effective for large directional positions (Parts 2–3) but unsuited for small, two-sided market-making books.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check timestamps before confirming leads.&lt;/strong&gt; A lag that appears at exactly one sampling step with zero correlation at step zero indicates alignment join errors rather than market structure dynamics.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Resources &amp;amp; Repositories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Inventory Hedger:&lt;/strong&gt; &lt;a href="https://github.com/Follow-SM/dynamic-inventory-hedger" rel="noopener noreferrer"&gt;github.com/Follow-SM/dynamic-inventory-hedger&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Microstructure Research Toolkit:&lt;/strong&gt; &lt;a href="https://github.com/Follow-SM/tick-microstructure-research" rel="noopener noreferrer"&gt;github.com/Follow-SM/tick-microstructure-research&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python SDK:&lt;/strong&gt; &lt;a href="https://pypi.org/project/followsm-sdk/" rel="noopener noreferrer"&gt;&lt;code&gt;pip install followsm-sdk&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript SDK:&lt;/strong&gt; &lt;a href="https://www.npmjs.com/package/%40followsm/sdk" rel="noopener noreferrer"&gt;&lt;code&gt;npm install @followsm/sdk&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Documentation &amp;amp; Keys:&lt;/strong&gt; &lt;a href="https://follow-sm.com/pricing" rel="noopener noreferrer"&gt;follow-sm.com/pricing&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;FollowSM streams VPIN, 1% book toxicity, sweep detection and smart-money flow for crypto markets today. This study shows what session-aware versions of those signals need before they can be trusted on equity perps.&lt;/p&gt;

&lt;h2&gt;
  
  
  👉 &lt;strong&gt;&lt;a href="https://follow-sm.com/pricing" rel="noopener noreferrer"&gt;Get your API key at follow-sm.com/pricing&lt;/a&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Academic References
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Glosten, L. R., &amp;amp; Milgrom, P. R. (1985). &lt;em&gt;Bid, ask and transaction prices in a specialist market with heterogeneously informed traders&lt;/em&gt;. Journal of Financial Economics, 14(1), 71-100.&lt;/li&gt;
&lt;li&gt;Hasbrouck, J. (1995). &lt;em&gt;One security, many markets: Determining the contributions to price discovery&lt;/em&gt;. The Journal of Finance, 50(4), 1175-1199.&lt;/li&gt;
&lt;li&gt;Brier, G. W. (1950). &lt;em&gt;Verification of forecasts expressed in terms of probability&lt;/em&gt;. Monthly Weather Review, 78(1), 1-3.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: Prediction markets and perpetual futures carry substantial risk of capital loss. Content is provided for quantitative research purposes only and does not constitute financial advice.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>cryptocurrency</category>
      <category>web3</category>
      <category>algotrading</category>
    </item>
    <item>
      <title>Hedging Polymarket Stock Markets With 24/7 Equity Perps: Session Microstructure, Opening Gaps and What Actually Cut Risk</title>
      <dc:creator>Andrew Rodn</dc:creator>
      <pubDate>Tue, 13 Oct 2026 12:46:01 +0000</pubDate>
      <link>https://dev.to/followsm/hedging-polymarket-stock-markets-with-247-equity-perps-session-microstructure-opening-gaps-and-5gj8</link>
      <guid>https://dev.to/followsm/hedging-polymarket-stock-markets-with-247-equity-perps-session-microstructure-opening-gaps-and-5gj8</guid>
      <description>&lt;h2&gt;
  
  
  📚 The Quantitative Microstructure &amp;amp; Cross-Market Series by FollowSM
&lt;/h2&gt;

&lt;p&gt;In Part 2 we hedged Polymarket BTC markets with Binance perps. This time the underlying is a stock. Polymarket lists daily &lt;em&gt;"TSLA Up or Down on …"&lt;/em&gt; markets, and since January 2026 Binance lists USDⓈ-M perps on TSLA, NVDA, AAPL, SPY and eight more, which trade &lt;strong&gt;24/7&lt;/strong&gt;. The stock does not: it closes at 16:00 ET and opens at 09:30 ET (16:30 EEST). The perp keeps trading through the gap.&lt;/p&gt;

&lt;p&gt;That raises three questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Do crypto microstructure tools such as VPIN, volume z-scores and book depth work on a market that has a regular session?&lt;/li&gt;
&lt;li&gt;Does off-hours perp flow predict the opening gap?&lt;/li&gt;
&lt;li&gt;How should a hedger handle the open: trade through it, freeze, or widen its band?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We ran the numbers on &lt;strong&gt;1,663 US opens across 12 equity perps&lt;/strong&gt; (Jan–Sep 2026, BTCUSDT as a 24/7 control) and &lt;strong&gt;1,276 real Polymarket Up/Down markets&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  ⚡ TL;DR
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The perp prices the gap before the bell.&lt;/strong&gt; Regressing the opening gap on the perp's move since the prior close gives slope 1.00 and R² 0.998. The median gap is 74 bps; the median part &lt;em&gt;not&lt;/em&gt; priced by 09:29 ET is 4.3 bps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Off-hours flow doesn't predict the rest.&lt;/strong&gt; Taker imbalance correlates with the gap (ρ = 0.31) only because it moves the price. Against the unpriced remainder, nothing survives a multiple-testing correction, and VPIN shows no relation at all.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Naive crypto alarms break on equities.&lt;/strong&gt; A volume z-score against the last 24 h fires on &lt;strong&gt;~50%&lt;/strong&gt; of the first 15 minutes after the open. The same threshold against the same time slot on comparable days fires on ~1%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The hedge's volatility model matters most.&lt;/strong&gt; Scaling σ by session (overnight, pre-market, the open jump, regular hours) cut the P&amp;amp;L spread by &lt;strong&gt;57%&lt;/strong&gt; and the 5% expected shortfall from −$596 to −$526 per 1,000-share position, at $27 cost. Wall-clock σ, the crypto default, cost $83 and made the tail &lt;em&gt;worse&lt;/em&gt; than not hedging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The open-window freeze did almost nothing&lt;/strong&gt;, and neither did microstructure gating: it did worse than continuous hedging.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Code and data pipeline:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Follow-SM" rel="noopener noreferrer"&gt;
        Follow-SM
      &lt;/a&gt; / &lt;a href="https://github.com/Follow-SM/tick-microstructure-research" rel="noopener noreferrer"&gt;
        tick-microstructure-research
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;tick-microstructure-research&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Do FollowSM's live tick signals actually protect a market maker, and by how much?&lt;/strong&gt; This repo records the live streams, tests the signals against a placebo, and simulates quote cancellation.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Capture.&lt;/strong&gt; It records FollowSM's Enterprise streams (&lt;code&gt;/ws/v1/toxicity&lt;/code&gt;, &lt;code&gt;/ws/v1/confluence&lt;/code&gt;) alongside the venues' own public tick data, which serves as ground truth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Calibrate.&lt;/strong&gt; It profiles the order-book signals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test.&lt;/strong&gt; It tests three hypotheses, each against a control group.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simulate.&lt;/strong&gt; It simulates quote cancellation on real Polymarket books and compares every result with a &lt;strong&gt;placebo&lt;/strong&gt; that fires the same trigger at random times.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Written as a follow-up to the &lt;a href="https://github.com/Follow-SM/dynamic-inventory-hedger#honest-backtest--methodology" rel="noopener noreferrer"&gt;dynamic-inventory-hedger backtest&lt;/a&gt;. That backtest could only rebuild VPIN from 1-minute public bars, and it found no timing value. The question left open was whether &lt;strong&gt;tick-level book and sweep signals&lt;/strong&gt; do better. This repo collects the data needed to answer it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Status: pipeline complete, data collection pending.&lt;/strong&gt; Every number in…&lt;/p&gt;
&lt;/blockquote&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Follow-SM/tick-microstructure-research" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Follow-SM" rel="noopener noreferrer"&gt;
        Follow-SM
      &lt;/a&gt; / &lt;a href="https://github.com/Follow-SM/dynamic-inventory-hedger" rel="noopener noreferrer"&gt;
        dynamic-inventory-hedger
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Dynamic Inventory Hedger&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://pypi.org/project/followsm-sdk/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/b6d6565b57835627619d8282c48036c3a0c551b59fdf4096e7cfcf8518bdc1cb/68747470733a2f2f696d672e736869656c64732e696f2f707970692f762f666f6c6c6f77736d2d73646b2e7376673f6c6162656c3d706970253230696e7374616c6c253230666f6c6c6f77736d2d73646b" alt="PyPI"&gt;&lt;/a&gt;
&lt;a href="https://colab.research.google.com/github/Follow-SM/dynamic-inventory-hedger/blob/main/quickstart.ipynb" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/eff96fda6b2e0fff8cdf2978f89d61aa434bb98c00453ae23dd0aab8d1451633/68747470733a2f2f636f6c61622e72657365617263682e676f6f676c652e636f6d2f6173736574732f636f6c61622d62616467652e737667" alt="Open In Colab"&gt;&lt;/a&gt;
&lt;a href="https://follow-sm.com/pricing" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/56a428a6cfa6fc0567a8c4054af827a2c037bc4a9e3b9d66693319b42d3ce0dd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f466f6c6c6f77534d2d454e54455250524953452532302532343439392532466d6f2d626c756576696f6c6574" alt="Get an API key"&gt;&lt;/a&gt;
&lt;a href="https://github.com/Follow-SM/dynamic-inventory-hedger/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/784362b26e4b3546254f1893e778ba64616e362bd6ac791991d2c9e880a3a64e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e2e737667" alt="License: MIT"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This tool delta-hedges &lt;strong&gt;Polymarket crypto positions&lt;/strong&gt; with &lt;strong&gt;Binance USDⓈ-M perpetual futures&lt;/strong&gt;. How hard it hedges depends on &lt;a href="https://follow-sm.com" rel="nofollow noopener noreferrer"&gt;FollowSM&lt;/a&gt; microstructure toxicity: VPIN percentile, orderbook imbalance, liquidity sweeps and smart-money flow.&lt;/p&gt;
&lt;p&gt;A Polymarket "Bitcoin above $84,000 on Friday" position is really a digital option on BTC. When informed flow hits the market, that position moves before any stop-loss can react. The hedger turns each position into an equivalent perp exposure and then:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;stays unhedged&lt;/strong&gt; while the flow is normal;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;builds a hedge with post-only limit orders&lt;/strong&gt; when toxicity rises;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;neutralises its exposure with price-protected IOC orders&lt;/strong&gt; when toxicity spikes or a liquidity sweep hits;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;unwinds the hedge&lt;/strong&gt; once the flow normalises.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It runs in &lt;strong&gt;paper mode&lt;/strong&gt; by default.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Read the &lt;a href="https://github.com/Follow-SM/dynamic-inventory-hedger#honest-backtest--methodology" rel="noopener noreferrer"&gt;backtest&lt;/a&gt; before relying on toxicity gating.&lt;/strong&gt; On 256 daily BTC markets (Jan–Sep 2026), gating on VPIN rebuilt from public 1-minute data did no better than the same hedges…&lt;/p&gt;
&lt;/blockquote&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Follow-SM/dynamic-inventory-hedger" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  Part 1. Structural differences: a 24/7 perp on a 6.5-hour stock
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Sessions
&lt;/h3&gt;

&lt;p&gt;Every minute is labelled with the NYSE calendar (holidays, early closes and the US/EU daylight-saving mismatch; on 2026-03-09 the open was at 15:30 EET, not 16:30):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;session&lt;/th&gt;
&lt;th&gt;ET&lt;/th&gt;
&lt;th&gt;EEST&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;pre-market&lt;/td&gt;
&lt;td&gt;04:00–09:30&lt;/td&gt;
&lt;td&gt;11:00–16:30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;regular (RTH)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;09:30–16:00&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;16:30–23:00&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;post-market&lt;/td&gt;
&lt;td&gt;16:00–20:00&lt;/td&gt;
&lt;td&gt;23:00–03:00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;overnight&lt;/td&gt;
&lt;td&gt;20:00–04:00 before a trading day&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;closed&lt;/td&gt;
&lt;td&gt;weekends, holidays&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The perps keep the stock's rhythm: 52–62% of single-stock volume trades in RTH, and only 3–7% when the market is closed. SPY and QQQ are more crypto-like (14% and 9% closed), and BTC is flat across sessions.&lt;/p&gt;

&lt;h3&gt;
  
  
  VPIN: global V vs session-aware V
&lt;/h3&gt;

&lt;p&gt;The standard bucket size is V = ADV/50. We also calibrated a session-aware V: each session's trailing 7-day volume rate × 28.8 minutes, so a bucket fills in about the same time in every session.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;TSLAUSDT, share of time VPIN ≥ its trailing p95&lt;/th&gt;
&lt;th&gt;RTH&lt;/th&gt;
&lt;th&gt;pre&lt;/th&gt;
&lt;th&gt;post&lt;/th&gt;
&lt;th&gt;overnight&lt;/th&gt;
&lt;th&gt;closed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;global V (ADV/50)&lt;/td&gt;
&lt;td&gt;13.2%&lt;/td&gt;
&lt;td&gt;13.6%&lt;/td&gt;
&lt;td&gt;14.6%&lt;/td&gt;
&lt;td&gt;12.3%&lt;/td&gt;
&lt;td&gt;11.2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;session-aware V&lt;/td&gt;
&lt;td&gt;1.8%&lt;/td&gt;
&lt;td&gt;4.8%&lt;/td&gt;
&lt;td&gt;1.3%&lt;/td&gt;
&lt;td&gt;5.5%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;20.7%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The session-aware V removes the RTH false alarms but causes a new problem on weekends. Buckets sized to thin weekend flow are small, so the imbalance is noisy, and about 20% of closed-market time reads as toxic. The same holds for every symbol. Neither version is clean. &lt;strong&gt;A session-aware VPIN still needs a minimum bucket size or a separate threshold for closed sessions.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9r7afzge0ew2icdnzc8n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9r7afzge0ew2icdnzc8n.png" alt="VPIN around the US open" width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fig 1. Volume jumps about 80× at 09:30, but VPIN's percentile falls: the burst is two-sided. BTC shows none of this.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Volume z-scores
&lt;/h3&gt;

&lt;p&gt;A volume z-score against the previous 24 h (96 × 15-minute candles), the default for crypto sweep detection, is dominated by the daily cycle:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;minutes 09:30–09:45 ET with z ≥ 6&lt;/th&gt;
&lt;th&gt;naive z&lt;/th&gt;
&lt;th&gt;same slot, comparable days&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;TSLA&lt;/td&gt;
&lt;td&gt;49.7%&lt;/td&gt;
&lt;td&gt;0.2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NVDA&lt;/td&gt;
&lt;td&gt;46.8%&lt;/td&gt;
&lt;td&gt;1.1%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AAPL&lt;/td&gt;
&lt;td&gt;52.0%&lt;/td&gt;
&lt;td&gt;1.5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SPY&lt;/td&gt;
&lt;td&gt;7.8%&lt;/td&gt;
&lt;td&gt;1.3%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BTC (control)&lt;/td&gt;
&lt;td&gt;1.4%&lt;/td&gt;
&lt;td&gt;0.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Any "liquidity sweep" rule ported from crypto will fire on half the opening minutes. It needs a seasonal baseline keyed by session, and weekend/holiday days must not share a baseline with trading days.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 2. Gaps and overnight toxicity
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Depth thinning before the open
&lt;/h3&gt;

&lt;p&gt;We measured depth within ±1% of mid from Binance's 30-second &lt;code&gt;bookDepth&lt;/code&gt; snapshots. The 15-minute pre-open window (09:15–09:29) shows &lt;strong&gt;no&lt;/strong&gt; thinning: the ratio to the same day's 08:00–09:00 depth is 0.97–1.01 for every symbol, and the same on the top-decile gap days (1.00 vs 0.99).&lt;/p&gt;

&lt;p&gt;The thinning is shorter than that. Median depth drops to about &lt;strong&gt;0.8×&lt;/strong&gt; in the last minutes before the bell and on the open, and to about &lt;strong&gt;0.7×&lt;/strong&gt; on big-gap days. It recovers within about five minutes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fozm43633rl02asdqrbgi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fozm43633rl02asdqrbgi.png" alt="Depth around the US open" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fig 2. ±1% depth relative to the same morning. The dip lasts minutes, not a quarter-hour. Red: days with |gap| ≥ 253 bps, including overnight news.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The pre-open depth ratio did not predict gap size (ρ = 0.007) or post-open volatility (ρ = 0.03).&lt;/p&gt;

&lt;h3&gt;
  
  
  Does overnight toxicity predict the gap?
&lt;/h3&gt;

&lt;p&gt;We define the gap as the Yahoo open over the prior close, and the unpriced &lt;strong&gt;residual&lt;/strong&gt; as the gap minus the perp's move up to 09:29.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;signal&lt;/th&gt;
&lt;th&gt;vs gap&lt;/th&gt;
&lt;th&gt;vs residual&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;off-hours taker imbalance&lt;/td&gt;
&lt;td&gt;ρ +0.31, 62% direction&lt;/td&gt;
&lt;td&gt;ρ +0.03 (p = 0.16)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pre-open taker imbalance&lt;/td&gt;
&lt;td&gt;ρ +0.19, 57% direction&lt;/td&gt;
&lt;td&gt;ρ +0.06 (p = 0.013)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;book log-imbalance at 09:29&lt;/td&gt;
&lt;td&gt;ρ −0.12&lt;/td&gt;
&lt;td&gt;ρ −0.02 (p = 0.54)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VPIN percentile at 09:29 vs |gap|&lt;/td&gt;
&lt;td&gt;ρ +0.02 (p = 0.33)&lt;/td&gt;
&lt;td&gt;ρ +0.04 (p = 0.16)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Flow "predicts" the gap only because flow moves the perp price, and the perp price already &lt;em&gt;is&lt;/em&gt; the gap forecast. After removing that, the best signal is ρ = 0.06, a 55.7% hit rate, at p = 0.013 across six tests. That fails a Bonferroni correction, and we don't claim it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 3. Cross-venue price discovery
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;gap regressed on&lt;/th&gt;
&lt;th&gt;n&lt;/th&gt;
&lt;th&gt;slope&lt;/th&gt;
&lt;th&gt;R²&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;perp move, prior close → 09:29&lt;/td&gt;
&lt;td&gt;1,663&lt;/td&gt;
&lt;td&gt;1.002&lt;/td&gt;
&lt;td&gt;0.998&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Binance index move&lt;/td&gt;
&lt;td&gt;1,663&lt;/td&gt;
&lt;td&gt;0.991&lt;/td&gt;
&lt;td&gt;0.968&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;perp, after weekends/holidays only&lt;/td&gt;
&lt;td&gt;347&lt;/td&gt;
&lt;td&gt;0.995&lt;/td&gt;
&lt;td&gt;0.994&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The perp's sign matched the gap's on &lt;strong&gt;99.7%&lt;/strong&gt; of opens with |gap| ≥ 10 bps. By the bell, the perp is the price.&lt;/p&gt;

&lt;p&gt;At 1-minute resolution, lead-lag against the Binance index and Yahoo 1m bars peaks at lag 0 in every session. The one exception is closed hours, where the perp leads the index by a minute. That is expected: the index blends dxFeed, Kaiko and Pyth, and on weekends it partly tracks the perp itself, so it is not an independent reference. Any lead faster than a minute is beyond what this data can resolve.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 4. The strategy: hedging an Up/Down market through the open
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Positions.&lt;/strong&gt; Each Polymarket &lt;em&gt;" Up or Down on "&lt;/em&gt; market resolves on whether the official close beats the prior trading day's close. We buy 1,000 shares of Up (and, mirrored, of Down) at the prior close and delta-hedge with the perp until the market's final 5 minutes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Markets.&lt;/strong&gt; 1,819 markets were found. 1,276 were simulated after skips: 481 for the 20-day variance warm-up, 55 listed after the prior close, and 7 whose resolution disagreed with Yahoo's closes. QQQ had no usable markets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execution.&lt;/strong&gt; IOC orders walk the real Binance tick tape from decision time plus latency; any unfilled remainder pays +5 bps. Fees and funding are charged.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fail-closed and hysteresis.&lt;/strong&gt; Missing minutes or an empty tape mean no trade, never an optimistic fill. The gated strategy keeps the Part 2 hysteresis re-arm thresholds.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;strategy (per 1,000-share position)&lt;/th&gt;
&lt;th&gt;mean P&amp;amp;L&lt;/th&gt;
&lt;th&gt;P&amp;amp;L std&lt;/th&gt;
&lt;th&gt;5% ES&lt;/th&gt;
&lt;th&gt;p95 max DD&lt;/th&gt;
&lt;th&gt;cost&lt;/th&gt;
&lt;th&gt;perp traded&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;unhedged&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;$504&lt;/td&gt;
&lt;td&gt;−$596&lt;/td&gt;
&lt;td&gt;$875&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;continuous, wall-clock σ&lt;/td&gt;
&lt;td&gt;−$83&lt;/td&gt;
&lt;td&gt;$331&lt;/td&gt;
&lt;td&gt;−$792&lt;/td&gt;
&lt;td&gt;$997&lt;/td&gt;
&lt;td&gt;$83&lt;/td&gt;
&lt;td&gt;$782k&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;open-window freeze (±5 min), wall-clock σ&lt;/td&gt;
&lt;td&gt;−$82&lt;/td&gt;
&lt;td&gt;$338&lt;/td&gt;
&lt;td&gt;−$808&lt;/td&gt;
&lt;td&gt;$1,026&lt;/td&gt;
&lt;td&gt;$83&lt;/td&gt;
&lt;td&gt;$759k&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;continuous, session σ&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;−$27&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$217&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;−$526&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$685&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$27&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$273k&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;freeze, session σ&lt;/td&gt;
&lt;td&gt;−$26&lt;/td&gt;
&lt;td&gt;$219&lt;/td&gt;
&lt;td&gt;−$525&lt;/td&gt;
&lt;td&gt;$689&lt;/td&gt;
&lt;td&gt;$26&lt;/td&gt;
&lt;td&gt;$268k&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;microstructure-gated&lt;/td&gt;
&lt;td&gt;−$196&lt;/td&gt;
&lt;td&gt;$421&lt;/td&gt;
&lt;td&gt;−$1,039&lt;/td&gt;
&lt;td&gt;$991&lt;/td&gt;
&lt;td&gt;$199&lt;/td&gt;
&lt;td&gt;$693k&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;placebo gate (10-seed avg)&lt;/td&gt;
&lt;td&gt;−$211&lt;/td&gt;
&lt;td&gt;$411&lt;/td&gt;
&lt;td&gt;−$1,054&lt;/td&gt;
&lt;td&gt;$1,037&lt;/td&gt;
&lt;td&gt;$214&lt;/td&gt;
&lt;td&gt;$689k&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9tmspfp7oze3ujwl9i4v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9tmspfp7oze3ujwl9i4v.png" alt="P&amp;amp;L and drawdown" width="799" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fig 3. Per-position P&amp;amp;L and tail risk: unhedged vs continuous vs freeze, under both volatility models.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Backtest Findings:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Session σ is the whole result.&lt;/strong&gt; The wall-clock model spreads the day's variance evenly across 24 hours, but most of a stock's variance lands in the opening jump and regular hours. So it misjudges the remaining variance, and its delta is jumpier. It trades about 3× the notional and pays 3× the cost, and its tail is worse than doing nothing. After weekends and holidays its cost rises to $139.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The freeze window is irrelevant.&lt;/strong&gt; It saves about $1 of opening-window cost and changes nothing else, whichever σ model it uses. The perp has priced the gap by 09:30, so there is little left to avoid.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Latency matters only at the extreme.&lt;/strong&gt; Delaying the fill from 0 to 250 ms changes nothing. At 1,000 ms, cost rises from $83 to $92.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Widening the deadband is a cost dial, not a risk tool.&lt;/strong&gt; Raising the rebalance band from $500 to $5,000 cuts wall-clock cost from $74 to $24. But the 5% ES only improves to −$716, still worse than unhedged. A wider band cannot fix a wrong σ.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gating doesn't help.&lt;/strong&gt; The gated strategy had a better 5% ES than all ten placebo seeds, but a wider P&amp;amp;L spread than all of them. Both lose badly to plain continuous hedging, so we don't count it as an edge.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Even the best hedge keeps a −$526 ES, because a binary settles with a jump that no perp hedge can follow through the final minutes. That is the same lesson as the BTC study.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Short history.&lt;/strong&gt; Eight months at most per symbol, and the newest perps (QQQ, SPY, AAPL, MSFT) have under six.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reference prices.&lt;/strong&gt; Yahoo closes are the reference; the 7 markets whose resolution disagreed with them were skipped, not patched. Yahoo post-market 1m bars are sparse, so post-session correlations with Yahoo are near zero and are not informative.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fills.&lt;/strong&gt; Queue position is not modelled for passive orders, and IOC fills assume we trade after the observed prints at their prices. Hedge notionals ($0.3–0.8M per position over a day) are small against RTH volume but not against weekend volume.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Entry prices.&lt;/strong&gt; Polymarket entry uses the CLOB price history at the prior close, not a real fill.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🛠 Reproduce
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="o"&gt;[&lt;/span&gt;https://github.com/Follow-SM/tick-microstructure-research]&lt;span class="o"&gt;(&lt;/span&gt;https://github.com/Follow-SM/tick-microstructure-research&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;tick-microstructure-research &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;".[parquet]"&lt;/span&gt;
tmr tradfi fetch      &lt;span class="c"&gt;# ~1.4 GB of public Binance archives + Yahoo, checksum-verified&lt;/span&gt;
tmr tradfi analyze    &lt;span class="c"&gt;# research/TRADFI_REPORT.md, results_tradfi.json, figures&lt;/span&gt;

git clone &lt;span class="o"&gt;[&lt;/span&gt;https://github.com/Follow-SM/dynamic-inventory-hedger]&lt;span class="o"&gt;(&lt;/span&gt;https://github.com/Follow-SM/dynamic-inventory-hedger&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;dynamic-inventory-hedger &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;".[tradfi]"&lt;/span&gt;
python research/backtest_tradfi.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Get started
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The hedger:&lt;/strong&gt; &lt;a href="https://github.com/Follow-SM/dynamic-inventory-hedger" rel="noopener noreferrer"&gt;dynamic-inventory-hedger&lt;/a&gt;. Paper mode by default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The research toolkit:&lt;/strong&gt; &lt;a href="https://github.com/Follow-SM/tick-microstructure-research" rel="noopener noreferrer"&gt;tick-microstructure-research&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python SDK:&lt;/strong&gt; &lt;a href="https://pypi.org/project/followsm-sdk/" rel="noopener noreferrer"&gt;&lt;code&gt;pip install followsm-sdk&lt;/code&gt;&lt;/a&gt; · &lt;strong&gt;TypeScript:&lt;/strong&gt; &lt;a href="https://www.npmjs.com/package/@followsm/sdk" rel="noopener noreferrer"&gt;&lt;code&gt;npm install @followsm/sdk&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;FollowSM streams VPIN, 1% book toxicity, sweep detection and smart-money flow for crypto markets today. This study shows what session-aware versions of those signals need before they can be trusted on equity perps.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://follow-sm.com/pricing" rel="noopener noreferrer"&gt;Get your API key at follow-sm.com/pricing&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;References: Easley, López de Prado &amp;amp; O'Hara (2012), "Flow Toxicity and Liquidity in a High-Frequency World", Review of Financial Studies. Barclay &amp;amp; Hendershott (2003), "Price Discovery and Trading After Hours", Review of Financial Studies.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Not financial advice. Prediction markets and perpetual futures carry substantial risk of loss.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cryptocurrency</category>
      <category>python</category>
      <category>web3</category>
      <category>algotrading</category>
    </item>
    <item>
      <title>We Built a Microstructure-Gated Hedger for Polymarket: Here is What 250+ Real Market Backtests Taught Us</title>
      <dc:creator>Andrew Rodn</dc:creator>
      <pubDate>Tue, 06 Oct 2026 11:57:53 +0000</pubDate>
      <link>https://dev.to/followsm/we-built-a-microstructure-gated-hedger-for-polymarket-here-is-what-250-real-market-backtests-3hai</link>
      <guid>https://dev.to/followsm/we-built-a-microstructure-gated-hedger-for-polymarket-here-is-what-250-real-market-backtests-3hai</guid>
      <description>&lt;h3&gt;
  
  
  📚 The Quantitative Microstructure &amp;amp; Cross-Market Series by FollowSM
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Part 1:&lt;/strong&gt; &lt;a href="https://dev.to/followsm/detecting-orderbook-toxicity-polymarket-divergence-building-a-microstructure-circuit-breaker-ef9"&gt;Detecting Orderbook Toxicity &amp;amp; Polymarket Divergence: Building a Microstructure Circuit Breaker&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Packages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python (PyPI):&lt;/strong&gt; &lt;a href="https://pypi.org/project/followsm-sdk/" rel="noopener noreferrer"&gt;&lt;code&gt;pip install followsm-sdk&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node.js (npm):&lt;/strong&gt; &lt;a href="https://www.npmjs.com/package/@followsm/sdk" rel="noopener noreferrer"&gt;&lt;code&gt;npm install @followsm/sdk&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We built an open-source hedger that delta-hedges Polymarket BTC positions with Binance perpetual futures and scales the hedge with order-flow toxicity. The logic: stay unhedged while the flow is calm, hedge half when VPIN climbs, go fully neutral when it spikes or a liquidity sweep hits.&lt;/p&gt;

&lt;p&gt;Then we backtested it on &lt;strong&gt;256 real daily Polymarket markets&lt;/strong&gt; covering nine months, and it mostly didn't work.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📊 &lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gating on VPIN rebuilt from public 1-minute data added nothing.&lt;/strong&gt; A placebo, with the same hedges at randomly shifted times, did as well. On P&amp;amp;L spread it did as well or better in 19 of 20 seeds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High VPIN did not warn of big moves.&lt;/strong&gt; The top-5% VPIN regime was followed by a tail-sized BTC move &lt;em&gt;less&lt;/em&gt; often than average: 0.54–0.61× the base rate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Most of the tail is the jump at expiry.&lt;/strong&gt; A binary option's delta explodes in its final hour, and no perp hedge keeps up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What worked was constant delta neutrality plus an exit one hour before resolution.&lt;/strong&gt; With a wider rebalance band, that cut the 5% expected shortfall roughly in half, from −$742 to −$385 per 1,000-share position. Hedging cost fell to $36.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Everything below is reproducible from public data:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Follow-SM" rel="noopener noreferrer"&gt;
        Follow-SM
      &lt;/a&gt; / &lt;a href="https://github.com/Follow-SM/dynamic-inventory-hedger" rel="noopener noreferrer"&gt;
        dynamic-inventory-hedger
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Dynamic Inventory Hedger&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://pypi.org/project/followsm-sdk/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/b6d6565b57835627619d8282c48036c3a0c551b59fdf4096e7cfcf8518bdc1cb/68747470733a2f2f696d672e736869656c64732e696f2f707970692f762f666f6c6c6f77736d2d73646b2e7376673f6c6162656c3d706970253230696e7374616c6c253230666f6c6c6f77736d2d73646b" alt="PyPI"&gt;&lt;/a&gt;
&lt;a href="https://colab.research.google.com/github/Follow-SM/dynamic-inventory-hedger/blob/main/quickstart.ipynb" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/eff96fda6b2e0fff8cdf2978f89d61aa434bb98c00453ae23dd0aab8d1451633/68747470733a2f2f636f6c61622e72657365617263682e676f6f676c652e636f6d2f6173736574732f636f6c61622d62616467652e737667" alt="Open In Colab"&gt;&lt;/a&gt;
&lt;a href="https://follow-sm.com/pricing" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/56a428a6cfa6fc0567a8c4054af827a2c037bc4a9e3b9d66693319b42d3ce0dd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f466f6c6c6f77534d2d454e54455250524953452532302532343439392532466d6f2d626c756576696f6c6574" alt="Get an API key"&gt;&lt;/a&gt;
&lt;a href="https://github.com/Follow-SM/dynamic-inventory-hedger/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/784362b26e4b3546254f1893e778ba64616e362bd6ac791991d2c9e880a3a64e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e2e737667" alt="License: MIT"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This tool delta-hedges &lt;strong&gt;Polymarket crypto positions&lt;/strong&gt; with &lt;strong&gt;Binance USDⓈ-M perpetual futures&lt;/strong&gt;. How hard it hedges depends on &lt;a href="https://follow-sm.com" rel="nofollow noopener noreferrer"&gt;FollowSM&lt;/a&gt; microstructure toxicity: VPIN percentile, orderbook imbalance, liquidity sweeps and smart-money flow.&lt;/p&gt;
&lt;p&gt;A Polymarket "Bitcoin above $84,000 on Friday" position is really a digital option on BTC. When informed flow hits the market, that position moves before any stop-loss can react. The hedger turns each position into an equivalent perp exposure and then:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;stays unhedged&lt;/strong&gt; while the flow is normal;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;builds a hedge with post-only limit orders&lt;/strong&gt; when toxicity rises;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;neutralises its exposure with price-protected IOC orders&lt;/strong&gt; when toxicity spikes or a liquidity sweep hits;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;unwinds the hedge&lt;/strong&gt; once the flow normalises.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It runs in &lt;strong&gt;paper mode&lt;/strong&gt; by default.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Read the &lt;a href="https://github.com/Follow-SM/dynamic-inventory-hedger#honest-backtest--methodology" rel="noopener noreferrer"&gt;backtest&lt;/a&gt; before relying on toxicity gating.&lt;/strong&gt; On 256 daily BTC markets (Jan–Sep 2026), gating on VPIN rebuilt from public 1-minute data did no better than the same hedges…&lt;/p&gt;
&lt;/blockquote&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Follow-SM/dynamic-inventory-hedger" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  1. The idea
&lt;/h2&gt;

&lt;p&gt;A Polymarket position such as &lt;em&gt;"Will the price of Bitcoin be above $84,000 on Friday?"&lt;/em&gt; is a &lt;strong&gt;digital option&lt;/strong&gt; on BTC. These markets settle on the Binance BTC/USDT close, the same price a Binance perp tracks. So the position has a delta you can hedge.&lt;/p&gt;

&lt;p&gt;Take a strike K, spot S and volatility to expiry σ_τ. The YES price is roughly N(d), where&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;σ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;τ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mop"&gt;ln&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;span class="mord"&gt;/&lt;/span&gt;&lt;span class="mord mathnormal"&gt;K&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;σ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;τ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;/2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;The perp-equivalent exposure of N shares is&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;Δ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;$&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;N&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;∂&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;ln&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;∂&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;N&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;σ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;τ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;φ&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;At the money with one day left (σ&lt;em&gt;τ ≈ 2%), that is about &lt;strong&gt;$20 of perp per share&lt;/strong&gt;. A 1,000-share position, worth at most $1,000 at settlement, behaves like a $20,000 BTC position. Near expiry, σ&lt;/em&gt;τ → 0 and the delta blows up.&lt;/p&gt;

&lt;p&gt;The hedger runs four layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Signals.&lt;/strong&gt; FollowSM microstructure (VPIN percentile, 1% book toxicity, liquidity sweeps, smart-money flow) maps to one of three levels: &lt;code&gt;NORMAL&lt;/code&gt;, &lt;code&gt;PRE_HEDGING_ALERT&lt;/code&gt;, &lt;code&gt;EMERGENCY_HEDGE_EXECUTION&lt;/code&gt;. Hysteresis stops it flip-flopping.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inventory.&lt;/strong&gt; Polymarket positions become Δ$ per underlying.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execution.&lt;/strong&gt; Hedge 0% / 50% / 100% by level. Post-only slices when patient, price-protected IOC when urgent, and a hard inventory limit throughout.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Risk.&lt;/strong&gt; Spread and slippage guards, a failure circuit breaker, and a JSONL journal.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The hypothesis was simple: &lt;strong&gt;informed flow shows up in the microstructure before the price moves, so hedging only then should get most of the protection at a fraction of the cost.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The test
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Universe.&lt;/strong&gt; Every daily &lt;em&gt;"Bitcoin above $K on &amp;lt;date&amp;gt;"&lt;/em&gt; event from 2 January to 28 September 2026. At 24 hours before resolution, the book holds &lt;strong&gt;1,000 shares of the strike nearest spot&lt;/strong&gt;, held to the official resolution. Each market is run twice, long YES and long NO. The two books mirror each other, so directional drift cancels. The sample is 256 markets (512 books); 8 were skipped because no strike was priced between 0.10 and 0.90 at entry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Replay.&lt;/strong&gt; Minute by minute, using the hedger's &lt;strong&gt;own code&lt;/strong&gt;: the same evaluator, delta model and &lt;code&gt;decide()&lt;/code&gt; function that run live.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Polymarket marks come from the public CLOB minute price history.&lt;/li&gt;
&lt;li&gt;The hedge trades the Binance USDⓈ-M BTCUSDT perp at the minute close.&lt;/li&gt;
&lt;li&gt;Maker fee 2 bps (post-only, assumed filled within the minute); taker 5 bps + 1 bp slippage (IOC).&lt;/li&gt;
&lt;li&gt;Real funding payments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Signals.&lt;/strong&gt; Rebuilt from Binance's public 1-minute spot klines, which carry the exact taker-buy notional per bar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VPIN&lt;/strong&gt; with $1M notional buckets and a 50-bucket window. &lt;code&gt;vpin_percentile&lt;/code&gt; is its rank within the previous 7 days. A robustness run uses activity-scaled buckets (trailing 7-day average daily volume / 50).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Liquidity sweep:&lt;/strong&gt; a 15-minute volume Z-score ≥ 6 together with a 15-minute move ≥ 2 × NATR.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not tested:&lt;/strong&gt; 1% order-book toxicity, smart-money sweeps and Polymarket book flow have no public history, so they are off in this backtest.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is our own reconstruction for research, not FollowSM's production feed. Keep that in mind for everything below.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Strategy&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Unhedged&lt;/td&gt;
&lt;td&gt;Never trades the perp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inventory limit only&lt;/td&gt;
&lt;td&gt;Hedges only the delta above $25k&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Toxicity-gated&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Repo defaults: 0% / 50% / 100% by level, plus the inventory limit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Placebo&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The gated level path shifted by a random offset in time (20 seeds): same share of time hedged, same regime lengths, wrong timing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Always hedged&lt;/td&gt;
&lt;td&gt;100% delta hedge at every level&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;strong&gt;placebo&lt;/strong&gt; is the key control. If toxicity timing carries information, the gated hedger must beat the same hedges placed at random times. Beating "unhedged" alone isn't enough, because any hedge reduces variance.&lt;/p&gt;


&lt;h2&gt;
  
  
  3. Results
&lt;/h2&gt;

&lt;p&gt;USD per 1,000-share position, $1M buckets:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Strategy&lt;/th&gt;
&lt;th&gt;Mean P&amp;amp;L&lt;/th&gt;
&lt;th&gt;Std dev&lt;/th&gt;
&lt;th&gt;Expected shortfall 5%&lt;/th&gt;
&lt;th&gt;Worst&lt;/th&gt;
&lt;th&gt;Hedge cost&lt;/th&gt;
&lt;th&gt;Perp traded&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Unhedged&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;473&lt;/td&gt;
&lt;td&gt;−742&lt;/td&gt;
&lt;td&gt;−885&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inventory limit only&lt;/td&gt;
&lt;td&gt;−115&lt;/td&gt;
&lt;td&gt;394&lt;/td&gt;
&lt;td&gt;−829&lt;/td&gt;
&lt;td&gt;−1,177&lt;/td&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;td&gt;$288k&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Toxicity-gated&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;−152&lt;/td&gt;
&lt;td&gt;383&lt;/td&gt;
&lt;td&gt;−887&lt;/td&gt;
&lt;td&gt;−1,177&lt;/td&gt;
&lt;td&gt;134&lt;/td&gt;
&lt;td&gt;$408k&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Placebo&lt;/strong&gt; (mean, 20 seeds)&lt;/td&gt;
&lt;td&gt;−159&lt;/td&gt;
&lt;td&gt;375&lt;/td&gt;
&lt;td&gt;−887&lt;/td&gt;
&lt;td&gt;−1,211&lt;/td&gt;
&lt;td&gt;141&lt;/td&gt;
&lt;td&gt;$429k&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Always 100% hedged&lt;/td&gt;
&lt;td&gt;−130&lt;/td&gt;
&lt;td&gt;242&lt;/td&gt;
&lt;td&gt;−719&lt;/td&gt;
&lt;td&gt;−1,020&lt;/td&gt;
&lt;td&gt;130&lt;/td&gt;
&lt;td&gt;$649k&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Unhedged mean P&amp;amp;L is 0 because YES and NO mirror each other. Every hedged strategy's mean equals minus its hedging cost; the hedges earn no alpha, they only reshape risk.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0u49fpw8wj9nk4tss5xc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0u49fpw8wj9nk4tss5xc.png" alt="Tail risk vs hedging cost" width="799" height="444"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Finding 1: the toxicity timing adds nothing
&lt;/h3&gt;

&lt;p&gt;The gated hedger and the placebo are indistinguishable: expected shortfall −887 for both, and standard deviation 383 against 375. Across the 20 placebo seeds, random timing matched or beat the gated strategy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;on expected shortfall in &lt;strong&gt;50%&lt;/strong&gt; of seeds;&lt;/li&gt;
&lt;li&gt;on standard deviation in &lt;strong&gt;95%&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The activity-scaled VPIN run gave the same picture: 55% and 95%.&lt;/p&gt;

&lt;p&gt;Gating also did worse than hedging all the time. It paid about the same cost, $134 against $130, but cut P&amp;amp;L variance by 34% where always-hedging cut it by 74%. Once costs are counted, it had a &lt;em&gt;worse&lt;/em&gt; tail than not hedging at all.&lt;/p&gt;
&lt;h3&gt;
  
  
  Finding 2: VPIN from 1-minute data did not flag tail moves
&lt;/h3&gt;

&lt;p&gt;This result undercuts the premise itself. We split every minute of the nine months by VPIN percentile, then asked: how often did a top-1% BTC move (by size) follow within 15 minutes?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F47amjtdb0jnpg8hpbp0e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F47amjtdb0jnpg8hpbp0e.png" alt="VPIN regime vs tail-move frequency" width="799" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;VPIN percentile&lt;/th&gt;
&lt;th&gt;Share of time&lt;/th&gt;
&lt;th&gt;Mean |15m move|&lt;/th&gt;
&lt;th&gt;Tail-move rate vs base ($1M buckets)&lt;/th&gt;
&lt;th&gt;Activity-scaled buckets&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&amp;lt; 0.60&lt;/td&gt;
&lt;td&gt;60%&lt;/td&gt;
&lt;td&gt;0.165%&lt;/td&gt;
&lt;td&gt;1.24×&lt;/td&gt;
&lt;td&gt;1.05×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.60–0.85&lt;/td&gt;
&lt;td&gt;25%&lt;/td&gt;
&lt;td&gt;0.132%&lt;/td&gt;
&lt;td&gt;0.65×&lt;/td&gt;
&lt;td&gt;1.03×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.85–0.95&lt;/td&gt;
&lt;td&gt;10%&lt;/td&gt;
&lt;td&gt;0.121%&lt;/td&gt;
&lt;td&gt;0.64×&lt;/td&gt;
&lt;td&gt;1.02×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;≥ 0.95&lt;/td&gt;
&lt;td&gt;5%&lt;/td&gt;
&lt;td&gt;0.120%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.61×&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.54×&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;With fixed $1M buckets the relation runs &lt;strong&gt;backwards&lt;/strong&gt;: high VPIN comes before calmer markets. With activity-scaled buckets it is flat, then backwards at the top.&lt;/p&gt;

&lt;p&gt;The worst position in the sample shows what this means in practice. It was a NO on &lt;em&gt;"Bitcoin above $64k on August 17"&lt;/em&gt; that lost $885 unhedged. With $1M buckets the evaluator stayed &lt;code&gt;NORMAL&lt;/code&gt; for all 24 hours, and the gated line moves only because the inventory limit kicked in. With activity-scaled buckets it raised &lt;code&gt;PRE_HEDGING_ALERT&lt;/code&gt; during the calm first 13 hours, then went quiet before the collapse:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvcqu343n4468ym3g40ln.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvcqu343n4468ym3g40ln.png" alt="Worst position, activity-scaled VPIN" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In our previous article, &lt;em&gt;Detecting Orderbook Toxicity &amp;amp; Polymarket Divergence&lt;/em&gt;, we reported a 1.4× tail-move lift for slow VPIN over 60 days. We called it "a hint, not a result" because it rested on about five events. With nine months of data and a rolling percentile, the hint does not hold up. The other observation from that article does hold: with fast $1M buckets the relationship ran backwards there too.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why 1-minute VPIN fails: the blurring problem
&lt;/h3&gt;

&lt;p&gt;VPIN was designed for &lt;strong&gt;trade-by-trade&lt;/strong&gt; data: fill fixed-volume buckets in the order trades happen, and measure how one-sided each bucket is. Rebuilding it from 1-minute bars breaks this in three ways.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Everything inside a minute becomes one number.&lt;/strong&gt; A minute that prints $56M is split pro rata into 56 buckets of $1M, all with that minute's single buy/sell ratio. The order inside the minute is lost: a one-sided sweep at second 5 and a rebound at second 40 look identical to steady two-way flow. A crash with its rebound averages to "balanced", and VPIN &lt;em&gt;drops&lt;/em&gt; at the exact moment flow is most toxic. The 22 August case study in &lt;a href="https://github.com/Follow-SM/hft-toxicity-circuit-breaker" rel="noopener noreferrer"&gt;hft-toxicity-circuit-breaker&lt;/a&gt; showed exactly this: fast VPIN collapsed as $43M of two-sided volume poured into the rebound.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quiet markets look toxic.&lt;/strong&gt; In thin hours a $1M bucket spans many minutes of sparse, often one-sided flow, so the imbalance reads high. The busiest, most dangerous minutes fill dozens of buckets with averaged-out flow. That is how you get the inverse relation above.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VPIN looks backwards.&lt;/strong&gt; A 50-bucket window reports on flow that has already traded. By the time it peaks, the move it describes has often happened, and markets tend to calm afterwards. Andersen &amp;amp; Bondarenko (2014) reached a similar conclusion about VPIN and the 2010 Flash Crash.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;None of this proves microstructure gating is useless. It shows that &lt;strong&gt;1-minute public bars can't carry the signal&lt;/strong&gt;. In the 22 August sweep, what moved first was one-sided taker flow &lt;em&gt;inside&lt;/em&gt; the minute and the bid side thinning within 1% of mid. Only tick-level trade data and L1/L2 book snapshots can see those: per-trade VPIN, &lt;code&gt;ob_toxicity_1pct&lt;/code&gt;, depth imbalance and sweep detection.&lt;/p&gt;

&lt;p&gt;We couldn't test any of that here because none of it has public history. That is the honest limit of this study, and the next experiment is below.&lt;/p&gt;
&lt;h3&gt;
  
  
  Finding 3: the tail is the expiry jump, and early exit + delta neutrality fixes most of it
&lt;/h3&gt;

&lt;p&gt;Look at the worst position again: most of the damage happens in the final hour. A digital option's delta, φ(d)/σ&lt;em&gt;τ, explodes as σ&lt;/em&gt;τ → 0 near the strike. No perp hedge can track a delta that swings by tens of thousands of dollars within minutes. The hedger zeroes delta in the final 5 minutes by design, which leaves the settlement jump fully exposed.&lt;/p&gt;

&lt;p&gt;So we ran two changes that don't depend on any signal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Exit one hour before resolution.&lt;/strong&gt; Close the Polymarket position at the market price, 60 minutes early.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stay delta-neutral the whole time&lt;/strong&gt; (hedge ratio 1.0 at every level), with a wider rebalance band so the hedge doesn't churn.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhgqbhj1xycmic9c9ds70.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhgqbhj1xycmic9c9ds70.png" alt="Early exit + delta neutrality" width="799" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Strategy&lt;/th&gt;
&lt;th&gt;Mean P&amp;amp;L&lt;/th&gt;
&lt;th&gt;Std dev&lt;/th&gt;
&lt;th&gt;Expected shortfall 5%&lt;/th&gt;
&lt;th&gt;Worst&lt;/th&gt;
&lt;th&gt;Hedge cost&lt;/th&gt;
&lt;th&gt;Perp traded&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Unhedged, to expiry&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;473&lt;/td&gt;
&lt;td&gt;−742&lt;/td&gt;
&lt;td&gt;−885&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unhedged, exit 1h early&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;402&lt;/td&gt;
&lt;td&gt;−682&lt;/td&gt;
&lt;td&gt;−839&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gated, exit 1h early&lt;/td&gt;
&lt;td&gt;−145&lt;/td&gt;
&lt;td&gt;324&lt;/td&gt;
&lt;td&gt;−717&lt;/td&gt;
&lt;td&gt;−870&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;$385k&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Always hedged, exit 1h early, $150 rebalance band&lt;/td&gt;
&lt;td&gt;−127&lt;/td&gt;
&lt;td&gt;171&lt;/td&gt;
&lt;td&gt;−509&lt;/td&gt;
&lt;td&gt;−776&lt;/td&gt;
&lt;td&gt;126&lt;/td&gt;
&lt;td&gt;$610k&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Always hedged, exit 1h early, $5,000 band&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;−38&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;164&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;−385&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;−535&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;36&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$158k&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;
  ▶ Full rebalance-band sweep (always hedged, exit 1h early)
  &lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rebalance band&lt;/th&gt;
&lt;th&gt;Mean P&amp;amp;L&lt;/th&gt;
&lt;th&gt;Std dev&lt;/th&gt;
&lt;th&gt;Expected shortfall 5%&lt;/th&gt;
&lt;th&gt;Worst&lt;/th&gt;
&lt;th&gt;Hedge cost&lt;/th&gt;
&lt;th&gt;Perp traded&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$150&lt;/td&gt;
&lt;td&gt;−127&lt;/td&gt;
&lt;td&gt;171&lt;/td&gt;
&lt;td&gt;−509&lt;/td&gt;
&lt;td&gt;−776&lt;/td&gt;
&lt;td&gt;126&lt;/td&gt;
&lt;td&gt;$610k&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$500&lt;/td&gt;
&lt;td&gt;−113&lt;/td&gt;
&lt;td&gt;171&lt;/td&gt;
&lt;td&gt;−494&lt;/td&gt;
&lt;td&gt;−760&lt;/td&gt;
&lt;td&gt;112&lt;/td&gt;
&lt;td&gt;$539k&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$1,000&lt;/td&gt;
&lt;td&gt;−96&lt;/td&gt;
&lt;td&gt;169&lt;/td&gt;
&lt;td&gt;−472&lt;/td&gt;
&lt;td&gt;−731&lt;/td&gt;
&lt;td&gt;94&lt;/td&gt;
&lt;td&gt;$451k&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$2,500&lt;/td&gt;
&lt;td&gt;−58&lt;/td&gt;
&lt;td&gt;164&lt;/td&gt;
&lt;td&gt;−421&lt;/td&gt;
&lt;td&gt;−638&lt;/td&gt;
&lt;td&gt;57&lt;/td&gt;
&lt;td&gt;$263k&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$5,000&lt;/td&gt;
&lt;td&gt;−38&lt;/td&gt;
&lt;td&gt;164&lt;/td&gt;
&lt;td&gt;−385&lt;/td&gt;
&lt;td&gt;−535&lt;/td&gt;
&lt;td&gt;36&lt;/td&gt;
&lt;td&gt;$158k&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;br&gt;
&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Three points stand out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Exiting early alone helps a little&lt;/strong&gt; (−742 → −682). Constant delta neutrality does most of the work once the settlement jump is gone (→ −509).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Churn was the real cost.&lt;/strong&gt; With a $150 rebalance band, a position worth at most $1,000 turned over $610k of perp in a day. At maker fees, that alone is about $122. A $5,000 band cut turnover by three-quarters, &lt;strong&gt;lowered&lt;/strong&gt; the tail (−385), and brought the cost down to $36.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Both VPIN definitions gave the same result&lt;/strong&gt; to within a few dollars. None of these strategies use VPIN.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A caution on the band: the grid was chosen in-sample, and the best value sits at its edge. Treat "wider is better" as a direction, not a tuned parameter.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Caveats
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rebuilt signals only.&lt;/strong&gt; These are our reconstruction from 1-minute public data, not FollowSM's tick-level feed. Book toxicity, smart-money sweeps and Polymarket book flow were not tested. The conclusion is &lt;em&gt;"1-minute VPIN gating doesn't help"&lt;/em&gt;, not &lt;em&gt;"microstructure gating can't help"&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Narrow scope.&lt;/strong&gt; Only BTC daily at-the-money markets were tested, over nine months. Other underlyings, strikes far from the money, and short-dated Up/Down markets may behave differently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Noisy tail.&lt;/strong&gt; Expected shortfall rests on the worst 25 of 512 books.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimistic execution.&lt;/strong&gt; Post-only fills are assumed to be immediate. The early Polymarket exit is marked at the minute price, with no spread or slippage modelled; a real exit pays the spread.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manual exit.&lt;/strong&gt; The hedger doesn't trade Polymarket, so the early exit is your job.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5. What we'd do with a Polymarket crypto book tomorrow
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Hedge the delta constantly.&lt;/strong&gt; Don't try to time it with 1-minute order-flow statistics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use a wide rebalance band.&lt;/strong&gt; Binary deltas swing hard; a tight band pays fees to chase noise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Get out before the final hour.&lt;/strong&gt; Delta hedging can't manage the settlement jump; not holding the position through it can.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test microstructure gating on the data it was designed for.&lt;/strong&gt; That means tick-level trades and L2 books, logged live and replayed through the same harness. The hedger's journal already records every metric it acts on, so a few weeks of live paper trading gives the dataset this backtest lacked. That is our next experiment.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the hedger that means:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;BASELINE_HEDGE_RATIO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.0
&lt;span class="nv"&gt;PRE_HEDGE_RATIO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.0
&lt;span class="nv"&gt;EMERGENCY_HEDGE_RATIO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.0
&lt;span class="nv"&gt;MIN_REBALANCE_USD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5000   &lt;span class="c"&gt;# in-sample; see the caveat above&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;plus your own exit an hour before resolution.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  ▶ Reproduce the backtest (no API keys needed)
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Follow-SM/dynamic-inventory-hedger.git
&lt;span class="nb"&gt;cd &lt;/span&gt;dynamic-inventory-hedger
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;".[research]"&lt;/span&gt;
python research/backtest.py                    &lt;span class="c"&gt;# $1M buckets&lt;/span&gt;
&lt;span class="nv"&gt;VPIN_BUCKET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;adv python research/backtest.py    &lt;span class="c"&gt;# activity-scaled buckets&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The first run downloads and caches about nine months of public Binance and Polymarket data. Results land in &lt;code&gt;research/results_*.json&lt;/code&gt; and charts in &lt;code&gt;research/assets/&lt;/code&gt;.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Get started
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The hedger:&lt;/strong&gt; &lt;a href="https://github.com/Follow-SM/dynamic-inventory-hedger" rel="noopener noreferrer"&gt;dynamic-inventory-hedger&lt;/a&gt;. Paper mode by default, then Binance demo, then live.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python SDK:&lt;/strong&gt; &lt;a href="https://pypi.org/project/followsm-sdk/" rel="noopener noreferrer"&gt;&lt;code&gt;pip install followsm-sdk&lt;/code&gt;&lt;/a&gt; · &lt;strong&gt;TypeScript:&lt;/strong&gt; &lt;a href="https://www.npmjs.com/package/@followsm/sdk" rel="noopener noreferrer"&gt;&lt;code&gt;npm install @followsm/sdk&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Related:&lt;/strong&gt; &lt;a href="https://github.com/Follow-SM/hft-toxicity-circuit-breaker" rel="noopener noreferrer"&gt;hft-toxicity-circuit-breaker&lt;/a&gt; · &lt;a href="https://github.com/Follow-SM/polymarket-arbitrage-starter-kit" rel="noopener noreferrer"&gt;polymarket-arbitrage-starter-kit&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The triggers this backtest couldn't reach (1% book toxicity, depth imbalance, sweep detection and smart-money flow) are what FollowSM streams live.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Free&lt;/th&gt;
&lt;th&gt;DEVELOPER ($199/mo)&lt;/th&gt;
&lt;th&gt;ENTERPRISE ($499/mo)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;REST requests/min&lt;/td&gt;
&lt;td&gt;30 (per IP)&lt;/td&gt;
&lt;td&gt;300&lt;/td&gt;
&lt;td&gt;1,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;/ws/v1/confluence&lt;/code&gt; stream (the hedger's &lt;code&gt;SIGNAL_SOURCE=stream&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://follow-sm.com/pricing" rel="noopener noreferrer"&gt;Get your API key at follow-sm.com/pricing&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;References: Easley, López de Prado &amp;amp; O'Hara (2012), "Flow Toxicity and Liquidity in a High-Frequency World", Review of Financial Studies. Andersen &amp;amp; Bondarenko (2014), "VPIN and the Flash Crash", Journal of Financial Markets.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Not financial advice. Prediction markets and perpetual futures carry substantial risk of loss.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cryptocurrency</category>
      <category>python</category>
      <category>web3</category>
      <category>algotrading</category>
    </item>
    <item>
      <title>Detecting Orderbook Toxicity &amp; Polymarket Divergence: Building a Microstructure Circuit Breaker</title>
      <dc:creator>Andrew Rodn</dc:creator>
      <pubDate>Tue, 29 Sep 2026 11:00:00 +0000</pubDate>
      <link>https://dev.to/followsm/detecting-orderbook-toxicity-polymarket-divergence-building-a-microstructure-circuit-breaker-ef9</link>
      <guid>https://dev.to/followsm/detecting-orderbook-toxicity-polymarket-divergence-building-a-microstructure-circuit-breaker-ef9</guid>
      <description>&lt;p&gt;&lt;strong&gt;Packages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python (PyPI):&lt;/strong&gt; &lt;a href="https://pypi.org/project/followsm-sdk/" rel="noopener noreferrer"&gt;&lt;code&gt;pip install followsm-sdk&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node.js (npm):&lt;/strong&gt; &lt;a href="https://www.npmjs.com/package/@followsm/sdk" rel="noopener noreferrer"&gt;&lt;code&gt;npm install @followsm/sdk&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On &lt;strong&gt;22 August 2026, between 05:07 and 05:10 UTC&lt;/strong&gt;, BTCUSDT on Binance fell from 78,528 to 76,742, a 1.8k drop in three minutes. The 05:10 minute alone printed &lt;strong&gt;$56.3M&lt;/strong&gt; of notional. The ten minutes before it averaged under $1M per minute.&lt;/p&gt;

&lt;p&gt;On Polymarket, the 15-minute &lt;em&gt;"Bitcoin Up or Down, 05:00–05:15 UTC"&lt;/em&gt; market pays out on whether BTC ends the window above its opening price of about 78,470. Binance's first one-second close below that level came at &lt;strong&gt;05:07:12&lt;/strong&gt;. In the ten seconds before it, Polymarket's "Up" contract traded between 0.49 and 0.63. In the twenty seconds after it, "Up" traded down to &lt;strong&gt;0.23&lt;/strong&gt;, and by 05:07:50 it was near &lt;strong&gt;0.10&lt;/strong&gt;. By 05:10 it was below 0.01.&lt;/p&gt;

&lt;p&gt;Both venues repriced within seconds. Any maker quote left resting through those seconds was a free option for whoever saw the move first.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Correction, 2 October 2026: an earlier version said Polymarket lagged Binance by about a minute. That came from lining up Polymarket's one-minute price history, whose points are stamped a few seconds after each minute, with the wrong Binance bar. Polymarket's trade-by-trade record shows it repriced within seconds. Section 4 and the reproduction script are fixed.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This article covers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Theory:&lt;/strong&gt; VPIN, L1/L2 orderbook imbalance and the robust volume Z-score, with the maths behind each.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The problem:&lt;/strong&gt; how market makers get adverse-selected during news shocks and prediction-market sweeps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implementation:&lt;/strong&gt; a streaming circuit breaker in Python on &lt;a href="https://pypi.org/project/followsm-sdk/" rel="noopener noreferrer"&gt;&lt;code&gt;followsm-sdk&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Case study:&lt;/strong&gt; the 22 August sweep, measured honestly. That includes the part where VPIN &lt;em&gt;didn't&lt;/em&gt; see it coming.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;📊 All numbers below come from public data (Binance klines and Polymarket's CLOB price history). The script that reproduces them is linked at the end.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  1. Theory
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1.1 VPIN: Volume-Synchronized Probability of Informed Trading
&lt;/h3&gt;

&lt;p&gt;The classic &lt;strong&gt;PIN&lt;/strong&gt; model (Easley, Kiefer, O'Hara &amp;amp; Paperman, 1996) treats order flow as a mix of two groups:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;uninformed traders&lt;/strong&gt;, arriving on both sides at rate ε;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;informed traders&lt;/strong&gt;, who show up with probability α on "information days" and trade one-sidedly at rate μ.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The probability that a given trade is informed is&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;PIN&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;αμ&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ε&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;αμ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Estimating PIN by maximum likelihood is slow and unstable at intraday frequency. &lt;strong&gt;VPIN&lt;/strong&gt; (Easley, López de Prado &amp;amp; O'Hara, 2012) replaces the estimation with a volume-clock approximation.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cut the trade tape into buckets of &lt;strong&gt;equal traded volume&lt;/strong&gt; &lt;code&gt;V&lt;/code&gt;, not equal time. Volume clocks speed up exactly when information is arriving.&lt;/li&gt;
&lt;li&gt;Split each bucket τ into buyer-initiated volume V^B and seller-initiated volume V^S.&lt;/li&gt;
&lt;li&gt;Average the absolute imbalance over the last &lt;code&gt;n&lt;/code&gt; buckets:&lt;/li&gt;
&lt;/ol&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;VPIN&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop op-limits"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;τ&lt;/span&gt;&lt;span class="mrel mtight"&gt;=&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="mop op-symbol large-op"&gt;∑&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;V&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen"&gt;∣&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;V&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;τ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;V&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;τ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;S&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;∣&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Why this approximates PIN: the expected imbalance per bucket is about αμ, and the expected bucket volume is αμ + 2ε, so VPIN converges to the same ratio.&lt;/p&gt;

&lt;p&gt;On equities, the original paper had to &lt;em&gt;infer&lt;/em&gt; trade direction (bulk volume classification). Crypto venues give it to you for free: every Binance trade carries an &lt;code&gt;isBuyerMaker&lt;/code&gt; flag, and every kline carries the exact taker-buy notional. There is no classification error.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The parameter that matters most is &lt;code&gt;V&lt;/code&gt;.&lt;/strong&gt; The original paper used V = 1/50 of average daily volume (ADV) and n = 50, so VPIN covers roughly one trading day.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;V&lt;/code&gt; too small&lt;/strong&gt; relative to the market's trade size: most buckets fill with one or two trades. Each such bucket is almost entirely one-sided, and VPIN drifts toward 1 regardless of information content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;V&lt;/code&gt; too large:&lt;/strong&gt; VPIN barely moves inside an event.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Calibrate &lt;code&gt;V&lt;/code&gt; per symbol. A fixed dollar bucket across BTC and a small-cap alt measures two different things.&lt;/p&gt;

&lt;p&gt;Even calibrated, raw VPIN levels differ between pairs, because trade-size distributions differ. The robust signal is VPIN's rank within its own history, which is how the original paper reports it (as a CDF). FollowSM calibrates buckets per symbol and publishes that rank as &lt;code&gt;vpin_percentile&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.2 L1 and L2 orderbook imbalance
&lt;/h3&gt;

&lt;p&gt;VPIN looks at &lt;em&gt;executed&lt;/em&gt; flow. The book shows &lt;em&gt;resting&lt;/em&gt; intent. At the top of the book (L1):&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;I&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;L&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;q&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;q&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;q&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;∈&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;[&lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mclose"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;where p_b, q_b are the best bid price and size and p_a, q_a the best ask. L1 is noisy and easy to spoof, so we also aggregate depth within a band of ±k around the mid m (the L2 view):&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;±&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;bid&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop op-symbol large-op"&gt;∑&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;≥&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;k&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;q&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;±&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;ask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop op-symbol large-op"&gt;∑&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;j&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;≤&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;k&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;j&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;q&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;j&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;imbalance&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;k&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;±&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;bid&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;±&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;ask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;±&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;bid&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;ob&amp;nbsp;toxicity&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1%&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord text mtight"&gt;&lt;span class="mord mtight"&gt;bid&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;±&lt;/span&gt;&lt;span class="mord mtight"&gt;1%&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;±&lt;/span&gt;&lt;span class="mord mtight"&gt;1%&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;ask&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;An &lt;code&gt;ob_toxicity_1pct&lt;/code&gt; above 2 means there is twice as much resting sell notional as buy notional within 1% of mid. The bid side is thin, and a market sell of modest size will walk through it.&lt;/p&gt;

&lt;p&gt;What matters here is the &lt;em&gt;change&lt;/em&gt;, not the level. Books are persistently skewed on many pairs. In a sample of FollowSM's live full-book stream (2 October 2026), SOLUSDT's ratio sat above 2 in about 80% of frames and BNBUSDT's in about half, with nothing unusual happening. A fixed ratio threshold would halt those pairs all day. FollowSM therefore also publishes &lt;code&gt;ob_imbalance_percentile&lt;/code&gt;, the ±1% imbalance ranked against the symbol's own recent history, and a breaker should react to a sudden departure from the recent norm, for example a reading in either extreme tail of that percentile, or:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;∣&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;imbalance&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1%&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;EWMA&lt;/span&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;λ&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;imbalance&lt;/span&gt;&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;1%&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)∣&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;δ&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  1.3 Robust volume Z-score
&lt;/h3&gt;

&lt;p&gt;Volume is heavy-tailed, so a mean/standard-deviation Z-score is dominated by the very outliers you're trying to detect. Use the median and the median absolute deviation (MAD) instead:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;z&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;V&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0.6745&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mop"&gt;&lt;span class="mord mathrm"&gt;MAD&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;V&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;span class="mbin mtight"&gt;−&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;k&lt;/span&gt;&lt;span class="mord mtight"&gt;..&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;span class="mbin mtight"&gt;−&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;V&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mop"&gt;&lt;span class="mord mathrm"&gt;median&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;V&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;span class="mbin mtight"&gt;−&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;k&lt;/span&gt;&lt;span class="mord mtight"&gt;..&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;span class="mbin mtight"&gt;−&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;The 0.6745 factor makes the MAD comparable to a standard deviation under normality. When the current candle is still open, pro-rate its volume by elapsed time before comparing, or the Z-score under-counts early in the window.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.4 Cross-venue divergence with Polymarket
&lt;/h3&gt;

&lt;p&gt;Crypto prediction markets carry an implied probability p for an outcome that is a direct function of spot. Examples are &lt;em&gt;"Will BTC be above $82k on 26 September?"&lt;/em&gt; and &lt;em&gt;"BTC Up or Down in the next 15 minutes"&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Give each market a direction d: +1 if a YES is bullish for spot, −1 if bearish, 0 if ambiguous. The two venues &lt;strong&gt;diverge&lt;/strong&gt; when:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop"&gt;&lt;span class="mord mathrm"&gt;sign&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;Δ&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;15&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;&lt;span class="mrel"&gt;&lt;span class="mord vbox"&gt;&lt;span class="thinbox"&gt;&lt;span class="rlap"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="inner"&gt;&lt;span class="mord"&gt;&lt;span class="mrel"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="fix"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop"&gt;&lt;span class="mord mathrm"&gt;sign&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;Δ&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;15&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;and&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;∣&lt;/span&gt;&lt;span class="mord"&gt;Δ&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;15&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;∣&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0.05&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;In words: spot is going one way and the prediction market is pricing the other. Either someone knows something, or one venue is about to be run over. Neither is a good time to be quoting size.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The problem: adverse selection in bursts
&lt;/h2&gt;

&lt;p&gt;A market maker earns the spread on uninformed flow and loses on informed flow. Over a normal day, informed flow is a small share of fills and the spread covers it. The losses are not spread evenly, though. They arrive in bursts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;News shocks.&lt;/strong&gt; A headline hits, the fastest participants lift or hit everything on the book, and resting quotes are filled at stale prices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Liquidation cascades.&lt;/strong&gt; Forced sellers are uninformed individually, but a cascade is predictable once it starts. Anyone who sees it early trades against your stale bids.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prediction-market sweeps.&lt;/strong&gt; Polymarket's short-dated crypto markets price off spot. When Binance moves, the trader who reacts first sweeps every Polymarket quote still priced off the old spot. On a 15-minute binary, "stale" can mean a 60-cent error on a $1 contract.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 The fix is not predicting the move; nobody reliably does that. The fix is &lt;strong&gt;not being there when it happens&lt;/strong&gt;: pull or widen quotes within milliseconds of the flow turning toxic, and put them back once it normalises. That is a circuit breaker.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  3. Implementation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;followsm-sdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://pypi.org/project/followsm-sdk/" rel="noopener noreferrer"&gt;&lt;code&gt;followsm-sdk&lt;/code&gt;&lt;/a&gt; exposes FollowSM's Binance microstructure metrics and its Binance × Polymarket confluence snapshots as typed pydantic models. The main ones are &lt;code&gt;SymbolToxicityMetrics&lt;/code&gt;, &lt;code&gt;ConfluenceSnapshot&lt;/code&gt; and &lt;code&gt;RiskConfig&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  3.1 One snapshot (free tier, no key)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;followsm_sdk&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FollowSMClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RateLimitExceededException&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FollowSMClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# no key: free, IP-rate-limited tier
&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;snap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_confluence_snapshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BTCUSDT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;RateLimitExceededException&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;SystemExit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;More headroom: https://follow-sm.com/pricing&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;micro&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;snap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;binance_microstructure&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vpin=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;micro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vpin&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; ob_toxicity_1pct=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;micro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ob_toxicity_1pct&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
      &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;spot_15m=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;micro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;price_delta_15m_pct&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;snap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;polymarket_confluence&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;active_events&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;market_slug&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: p=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;implied_probability&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
          &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prob_delta_15m=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prob_delta_15m&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; direction=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;direction&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;divergence:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;snap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;composite_signals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cross_market_divergence_flag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;backend action:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;snap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;composite_signals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recommended_action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  3.2 Your own risk ladder
&lt;/h3&gt;

&lt;p&gt;The backend returns a conservative &lt;code&gt;recommended_action&lt;/code&gt;. You can re-derive it locally with your own thresholds:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;followsm_sdk&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FollowSMClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RiskConfig&lt;/span&gt;

&lt;span class="n"&gt;risk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RiskConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;vpin_percentile_widen_threshold&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# -&amp;gt; WIDEN_SPREAD_2X
&lt;/span&gt;    &lt;span class="n"&gt;vpin_percentile_halt_threshold&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.97&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# with divergence -&amp;gt; HALT_MAKER_QUOTES
&lt;/span&gt;        &lt;span class="n"&gt;vpin_percentile_halt_threshold&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.97&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# with divergence -&amp;gt; HALT_MAKER_QUOTES
&lt;/span&gt;    &lt;span class="n"&gt;ob_imbalance_percentile_low&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.005&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;# a 1% book in either extreme tail of its own history
&lt;/span&gt;    &lt;span class="n"&gt;ob_imbalance_percentile_high&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.995&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;#   also counts as toxic
&lt;/span&gt;    &lt;span class="n"&gt;ob_toxicity_threshold&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;             &lt;span class="c1"&gt;# fixed ask/bid ratio used only while that percentile warms up
&lt;/span&gt;    &lt;span class="n"&gt;min_semantic_confidence&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;# never HALT on an ambiguously mapped market
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FollowSMClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;risk_config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;risk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;snap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_confluence_snapshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BTCUSDT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;evaluate_risk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;snap&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  &lt;span class="c1"&gt;# NONE | WIDEN_SPREAD_1_5X | WIDEN_SPREAD_2X | HALT_MAKER_QUOTES
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The ladder in full. "Toxic" means &lt;code&gt;vpin_percentile&lt;/code&gt; at or above the threshold, &lt;strong&gt;or&lt;/strong&gt; &lt;code&gt;ob_imbalance_percentile&lt;/code&gt; in either tail (&lt;code&gt;ob_toxicity_1pct&lt;/code&gt; above &lt;code&gt;ob_toxicity_threshold&lt;/code&gt; while the percentile warms up). This needs &lt;code&gt;followsm-sdk&lt;/code&gt; 1.6.0 or later:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Condition&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;vpin_percentile ≥ vpin_percentile_halt_threshold&lt;/code&gt; (or a toxic book) &lt;strong&gt;and&lt;/strong&gt; divergence&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;HALT_MAKER_QUOTES&lt;/code&gt; (downgraded to 1.5x if &lt;code&gt;direction_confidence&lt;/code&gt; &amp;lt; &lt;code&gt;min_semantic_confidence&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;vpin_percentile ≥ vpin_percentile_widen_threshold&lt;/code&gt;, or a toxic book&lt;/td&gt;
&lt;td&gt;&lt;code&gt;WIDEN_SPREAD_2X&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;divergence alone&lt;/td&gt;
&lt;td&gt;&lt;code&gt;WIDEN_SPREAD_1_5X&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;otherwise&lt;/td&gt;
&lt;td&gt;&lt;code&gt;NONE&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  3.3 A streaming circuit breaker
&lt;/h3&gt;

&lt;p&gt;Polling is fine for a Polymarket bot quoting every few seconds. A market maker needs ticks. The Enterprise stream &lt;code&gt;/ws/v1/toxicity&lt;/code&gt; pushes every symbol's &lt;code&gt;SymbolToxicityMetrics&lt;/code&gt; from sub-10ms in-memory snapshots:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;followsm_sdk&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FollowSMClient&lt;/span&gt;

&lt;span class="n"&gt;PCTL_TRIP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PCTL_REARM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.80&lt;/span&gt;
&lt;span class="n"&gt;BOOK_TAIL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OB_TOX_FALLBACK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lopsided_book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ob_imbalance_percentile&lt;/span&gt;  &lt;span class="c1"&gt;# ±1% imbalance ranked vs this symbol's own history
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# warming up: fall back to a fixed ask/bid ratio
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ob_toxicity_1pct&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;OB_TOX_FALLBACK&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;BOOK_TAIL&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;BOOK_TAIL&lt;/span&gt;


&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cancel_quotes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;KILL SWITCH &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: cancelling resting maker quotes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# call your OMS here
&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FollowSMClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FOLLOWSM_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  &lt;span class="c1"&gt;# ENTERPRISE key
&lt;/span&gt;    &lt;span class="n"&gt;halted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stream_toxicity&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;pctl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vpin_percentile&lt;/span&gt;  &lt;span class="c1"&gt;# VPIN ranked vs this symbol's own history; None while warming up
&lt;/span&gt;        &lt;span class="n"&gt;toxic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pctl&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;pctl&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;PCTL_TRIP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nf"&gt;lopsided_book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;toxic&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;halted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;halted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;cancel_quotes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;halted&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pctl&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;pctl&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;PCTL_REARM&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;lopsided_book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;halted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;discard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RE-ARM &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The gap between &lt;code&gt;PCTL_TRIP&lt;/code&gt; and &lt;code&gt;PCTL_REARM&lt;/code&gt; is &lt;strong&gt;hysteresis&lt;/strong&gt;. Without it, a VPIN percentile oscillating around 0.90 would cancel and re-post your quotes on every tick.&lt;/p&gt;

&lt;p&gt;The production version adds the rest of what a real desk needs:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Follow-SM" rel="noopener noreferrer"&gt;
        Follow-SM
      &lt;/a&gt; / &lt;a href="https://github.com/Follow-SM/hft-toxicity-circuit-breaker" rel="noopener noreferrer"&gt;
        hft-toxicity-circuit-breaker
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;HFT Toxicity Circuit Breaker&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://pypi.org/project/followsm-sdk/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/b6d6565b57835627619d8282c48036c3a0c551b59fdf4096e7cfcf8518bdc1cb/68747470733a2f2f696d672e736869656c64732e696f2f707970692f762f666f6c6c6f77736d2d73646b2e7376673f6c6162656c3d706970253230696e7374616c6c253230666f6c6c6f77736d2d73646b" alt="PyPI"&gt;&lt;/a&gt;
&lt;a href="https://colab.research.google.com/github/Follow-SM/hft-toxicity-circuit-breaker/blob/main/quickstart.ipynb" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/eff96fda6b2e0fff8cdf2978f89d61aa434bb98c00453ae23dd0aab8d1451633/68747470733a2f2f636f6c61622e72657365617263682e676f6f676c652e636f6d2f6173736574732f636f6c61622d62616467652e737667" alt="Open In Colab"&gt;&lt;/a&gt;
&lt;a href="https://follow-sm.com/pricing" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/56a428a6cfa6fc0567a8c4054af827a2c037bc4a9e3b9d66693319b42d3ce0dd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f466f6c6c6f77534d2d454e54455250524953452532302532343439392532466d6f2d626c756576696f6c6574" alt="Get an API key"&gt;&lt;/a&gt;
&lt;a href="https://github.com/Follow-SM/hft-toxicity-circuit-breaker/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/784362b26e4b3546254f1893e778ba64616e362bd6ac791991d2c9e880a3a64e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e2e737667" alt="License: MIT"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A kill switch for market makers, built on FollowSM's &lt;strong&gt;Enterprise WebSocket streams&lt;/strong&gt; (&lt;code&gt;/ws/v1/toxicity&lt;/code&gt; and &lt;code&gt;/ws/v1/confluence&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;It evaluates every Binance microstructure tick in memory. When order flow turns toxic, it fires &lt;strong&gt;cancellation callbacks&lt;/strong&gt; and &lt;strong&gt;signed webhooks&lt;/strong&gt; for your resting maker quotes, before informed traders pick them off.&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;09:14:49 INFO    | Guarding BTCUSDT, ETHUSDT, SOLUSDT
09:19:19 INFO    | Breaker evaluation latency: n=3699 p50=21.4us p99=48.7us max=118.7us
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Real output from the live Enterprise streams, 2 October 2026: five quiet minutes, no trips. When one fires, it looks like this (illustrative values):&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;WARNING | SOLUSDT NONE -&amp;gt; HALT_MAKER_QUOTES [toxicity] ob_imbalance_percentile 0.996 in tail (ob_toxicity_1pct 3.10) | vpin=0.212 pctl=0.41 ob_tox_1pct=3.10 eval=24.0us feed_age=180ms
WARNING | KILL SWITCH: cancelling every resting maker quote on SOLUSDT
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Market makers lose money through &lt;strong&gt;adverse selection&lt;/strong&gt;: their quotes get filled by traders who know more than they do. The damage clusters in short bursts…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Follow-SM/hft-toxicity-circuit-breaker" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;On top of the loop above, it adds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Depth-imbalance spike detection&lt;/strong&gt; (EWMA deviation of the 1% band, §1.2).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A second leg on &lt;code&gt;/ws/v1/confluence&lt;/code&gt;&lt;/strong&gt;, evaluated locally with &lt;code&gt;evaluate_risk_action(snapshot, RiskConfig(...))&lt;/code&gt;, so the effective action per symbol is the more severe of the two legs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A cooldown&lt;/strong&gt; before re-arming.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fail-closed reconnects.&lt;/strong&gt; A dropped stream halts every symbol it guards until fresh frames arrive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non-blocking callbacks.&lt;/strong&gt; Cancellations and HMAC-signed webhooks are scheduled as asyncio tasks, so a slow webhook never delays the next tick.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Evaluation stays in-process and synchronous. On live FollowSM data it measured &lt;strong&gt;p50 = 4.7 µs, p99 = 24.9 µs&lt;/strong&gt; per frame on a laptop. The latency budget belongs to the network, not the decision.&lt;/p&gt;

&lt;p&gt;For the Polymarket side, the starter kit runs the same ladder on REST polling. It widens or halts its CLOB (central limit order book) quotes, and skews them toward the spot-implied fair value:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;center&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;mid&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop"&gt;&lt;span class="mord mathrm"&gt;clip&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="delimsizing size1"&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;k&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;100&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;Δ&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;15&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⋅&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;Δ&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;15&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;±&lt;/span&gt;&lt;span class="mord"&gt;0.05&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="delimsizing size1"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Follow-SM" rel="noopener noreferrer"&gt;
        Follow-SM
      &lt;/a&gt; / &lt;a href="https://github.com/Follow-SM/polymarket-arbitrage-starter-kit" rel="noopener noreferrer"&gt;
        polymarket-arbitrage-starter-kit
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Polymarket Arbitrage Starter Kit&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://pypi.org/project/followsm-sdk/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/b6d6565b57835627619d8282c48036c3a0c551b59fdf4096e7cfcf8518bdc1cb/68747470733a2f2f696d672e736869656c64732e696f2f707970692f762f666f6c6c6f77736d2d73646b2e7376673f6c6162656c3d706970253230696e7374616c6c253230666f6c6c6f77736d2d73646b" alt="PyPI"&gt;&lt;/a&gt;
&lt;a href="https://colab.research.google.com/github/Follow-SM/polymarket-arbitrage-starter-kit/blob/main/quickstart.ipynb" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/eff96fda6b2e0fff8cdf2978f89d61aa434bb98c00453ae23dd0aab8d1451633/68747470733a2f2f636f6c61622e72657365617263682e676f6f676c652e636f6d2f6173736574732f636f6c61622d62616467652e737667" alt="Open In Colab"&gt;&lt;/a&gt;
&lt;a href="https://follow-sm.com/pricing" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/6cab1d708ba53bd705c20c72f427288da6c998d15e6cd5d355a2a636c5bbbf51/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f466f6c6c6f77534d2d444556454c4f5045522532302532343139392532466d6f2d626c756576696f6c6574" alt="Get an API key"&gt;&lt;/a&gt;
&lt;a href="https://github.com/Follow-SM/polymarket-arbitrage-starter-kit/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/784362b26e4b3546254f1893e778ba64616e362bd6ac791991d2c9e880a3a64e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e2e737667" alt="License: MIT"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;An asynchronous Python market-making bot for &lt;strong&gt;Polymarket CLOB&lt;/strong&gt; that uses &lt;strong&gt;Binance spot microstructure&lt;/strong&gt; as its risk signal. It is built on &lt;a href="https://pypi.org/project/followsm-sdk/" rel="nofollow noopener noreferrer"&gt;&lt;code&gt;followsm-sdk&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Binance spot usually reprices before crypto prediction markets do. This bot uses that lead in two ways:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Defence.&lt;/strong&gt; It pulls or widens its Polymarket maker quotes when Binance order flow turns toxic (high VPIN, one-sided 1% depth) or when the two venues disagree.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Offence.&lt;/strong&gt; It skews its quotes toward the spot-implied fair value before the prediction market catches up.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;2026-09-26 10:53:07 INFO bot | BTCUSDT vpin=0.697 ob_tox_1pct=2.61 prob_delta_15m=+0.003 spot_15m=+0.072% -&amp;gt; WIDEN_SPREAD_2X (backend: WIDEN_SPREAD_2X)
2026-09-26 10:53:07 INFO bot | Quoting bitcoin-above-82k-on-september-26-2026: mid=0.994 bid=0.97 ask=0.99 (2.0x spread)
2026-09-26 10:53:07 INFO bot.execution | [PAPER] BUY 10.00 YES @ 0.97 (token 8168161214…)
2026-09-26 10:53:07 INFO bot.execution | [PAPER] SELL 10.00 YES @ 0.99 (token 8168161214…)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How it works&lt;/h2&gt;
&lt;/div&gt;

  &lt;div class="js-render-enrichment-target"&gt;
    &lt;div class="render-plaintext-hidden"&gt;
      &lt;pre&gt;flowchart LR
    A[FollowSM API&amp;lt;br/&amp;gt;get_confluence_snapshot] --&amp;gt;|every POLL_INTERVAL_SECS| B[market_monitor.py&amp;lt;br/&amp;gt;MarketSignal]
    B --&amp;gt;&lt;/pre&gt;…&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Follow-SM/polymarket-arbitrage-starter-kit" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  4. Case study: the 22 August 2026 BTC sweep
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Setup.&lt;/strong&gt; 86,400 one-minute BTCUSDT klines from Binance (28 July – 26 September 2026), with the exact taker-buy notional per bar. I computed VPIN two ways, both with n = 50:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;slow:&lt;/strong&gt; V = ADV/50 ≈ $23.3M, the original paper's calibration;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;fast:&lt;/strong&gt; V = $1M, a desk-style short horizon.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I then took the &lt;strong&gt;largest 15-minute drop&lt;/strong&gt; in the sample after a 7-day warm-up, plus Polymarket's public CLOB price history and trades for the matching 15-minute &lt;em&gt;Up or Down&lt;/em&gt; market.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.1 What happened
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;UTC&lt;/th&gt;
&lt;th&gt;Close&lt;/th&gt;
&lt;th&gt;Notional&lt;/th&gt;
&lt;th&gt;Taker-buy share&lt;/th&gt;
&lt;th&gt;VPIN fast (7d pctl)&lt;/th&gt;
&lt;th&gt;VPIN slow&lt;/th&gt;
&lt;th&gt;Polymarket "Up"*&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;04:55&lt;/td&gt;
&lt;td&gt;78,541&lt;/td&gt;
&lt;td&gt;$0.5M&lt;/td&gt;
&lt;td&gt;0.72&lt;/td&gt;
&lt;td&gt;0.236 (23%)&lt;/td&gt;
&lt;td&gt;0.130&lt;/td&gt;
&lt;td&gt;0.505&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;05:00&lt;/td&gt;
&lt;td&gt;78,532&lt;/td&gt;
&lt;td&gt;$1.0M&lt;/td&gt;
&lt;td&gt;0.69&lt;/td&gt;
&lt;td&gt;0.228 (21%)&lt;/td&gt;
&lt;td&gt;0.130&lt;/td&gt;
&lt;td&gt;0.545&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;05:03&lt;/td&gt;
&lt;td&gt;78,544&lt;/td&gt;
&lt;td&gt;$1.2M&lt;/td&gt;
&lt;td&gt;0.48&lt;/td&gt;
&lt;td&gt;0.211 (16%)&lt;/td&gt;
&lt;td&gt;0.130&lt;/td&gt;
&lt;td&gt;0.655&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;05:06&lt;/td&gt;
&lt;td&gt;78,528&lt;/td&gt;
&lt;td&gt;$0.6M&lt;/td&gt;
&lt;td&gt;0.66&lt;/td&gt;
&lt;td&gt;0.200 (14%)&lt;/td&gt;
&lt;td&gt;0.130&lt;/td&gt;
&lt;td&gt;0.635&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;05:07&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;78,286&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$2.9M&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.17&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.210 (16%)&lt;/td&gt;
&lt;td&gt;0.130&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.085&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;05:08&lt;/td&gt;
&lt;td&gt;78,138&lt;/td&gt;
&lt;td&gt;$3.1M&lt;/td&gt;
&lt;td&gt;0.37&lt;/td&gt;
&lt;td&gt;0.207 (16%)&lt;/td&gt;
&lt;td&gt;0.130&lt;/td&gt;
&lt;td&gt;0.035&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;05:09&lt;/td&gt;
&lt;td&gt;77,802&lt;/td&gt;
&lt;td&gt;$10.9M&lt;/td&gt;
&lt;td&gt;0.40&lt;/td&gt;
&lt;td&gt;0.200 (14%)&lt;/td&gt;
&lt;td&gt;0.130&lt;/td&gt;
&lt;td&gt;0.005&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;05:10&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;76,742&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$56.3M&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.34&lt;/td&gt;
&lt;td&gt;0.326 (63%)&lt;/td&gt;
&lt;td&gt;0.140&lt;/td&gt;
&lt;td&gt;0.001&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;05:11&lt;/td&gt;
&lt;td&gt;77,087&lt;/td&gt;
&lt;td&gt;$43.4M&lt;/td&gt;
&lt;td&gt;0.49&lt;/td&gt;
&lt;td&gt;0.062 (0%)&lt;/td&gt;
&lt;td&gt;0.142&lt;/td&gt;
&lt;td&gt;0.001&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;* The first Polymarket price-history point after the Binance bar closed. Points are stamped a few seconds past each minute.&lt;/p&gt;

&lt;p&gt;Over the full 15 minutes, &lt;strong&gt;$84M&lt;/strong&gt; traded, a robust volume Z-score of &lt;strong&gt;22.8&lt;/strong&gt; against the prior five hours. The "Up" market resolves Up if BTC finishes the 05:00–05:15 window above where it started.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.2 What the data says, and what it doesn't
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;VPIN did not predict this sweep.&lt;/strong&gt; At the start of the window, slow VPIN was 0.130, the &lt;strong&gt;4th percentile&lt;/strong&gt; of its trailing week. Fast VPIN was at the 23rd percentile. Neither moved until the crash minute itself, and fast VPIN then &lt;em&gt;collapsed&lt;/em&gt; as $43M of two-sided volume poured in during the rebound.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ This matches the academic record. VPIN's headline result, a rising reading hours before the 2010 Flash Crash, was contested by Andersen &amp;amp; Bondarenko (2014), who showed that much of the effect depended on the trade-classification scheme. Anyone selling VPIN as a crystal ball is selling something.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;The conditional edge is weak.&lt;/strong&gt; Across 5,087 non-overlapping 15-minute windows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With slow VPIN in its top decile, the chance that the next 15 minutes contained a move in the top 1% of sizes (≥ 0.70%) was &lt;strong&gt;1.37%&lt;/strong&gt;, against &lt;strong&gt;0.95%&lt;/strong&gt; otherwise: a &lt;strong&gt;1.4x lift&lt;/strong&gt;. That rests on roughly five events, so treat it as a hint, not a result.&lt;/li&gt;
&lt;li&gt;With fast buckets, the relationship &lt;strong&gt;inverted&lt;/strong&gt; (0.29% vs 1.09%, 0.3x). Short-horizon VPIN on 1-minute bars mostly flags quiet, one-sided drift, not the start of a cascade.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What did move first was one-sided flow and a volume burst.&lt;/strong&gt; At 05:07, 83% of taker notional was selling, on three times the notional of the preceding minutes. That is the fingerprint a tick-level feed is built to catch: per-trade buckets, 1% book toxicity and depth-imbalance spikes. One-minute bars blur it. Klines also can't show the bid side thinning within 1% of mid, which is exactly what &lt;code&gt;ob_toxicity_1pct&lt;/code&gt; measures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Polymarket repriced within seconds.&lt;/strong&gt; Minute bars can't show this, so I checked Binance's one-second klines against Polymarket's individual trades. Binance first closed a second below the window's opening price (78,470.15) at 05:07:12. Polymarket "Up" traded at 0.62–0.68 in the ten seconds to 05:07:02, 0.49–0.63 in the next ten, 0.31–0.48 in the ten seconds after the cross, 0.23–0.30 in the ten after that, and 0.08–0.13 by 05:07:42–52. A resting "Up" bid had seconds, not a minute, to get out of the way. (The market settles on Chainlink's BTC/USD feed, so Binance is a proxy here; both ended the window below the opening price.)&lt;/p&gt;

&lt;h3&gt;
  
  
  4.3 Lessons for the breaker
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Don't trip on VPIN alone.&lt;/strong&gt; Use it as a &lt;em&gt;regime&lt;/em&gt; input that widens spreads, and let fast signals (taker imbalance, 1% book toxicity, depth-imbalance spikes, volume bursts) trigger the halt. That is why the breaker above ORs several conditions and the ladder reserves &lt;code&gt;HALT_MAKER_QUOTES&lt;/code&gt; for VPIN &lt;em&gt;plus&lt;/em&gt; divergence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Calibrate &lt;code&gt;V&lt;/code&gt; per symbol&lt;/strong&gt;, and set thresholds from each symbol's own distribution. A VPIN of 0.70 means something different on BTC than on a thin alt, and something different again with different bucket sizes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Latency beats prediction.&lt;/strong&gt; In this sweep, Polymarket had done most of its repricing within about 20 seconds of Binance crossing the window's opening price, and the Binance book moved faster still. The decision window was seconds on both venues. A breaker that reacts in microseconds to a streamed tick is worth more than a model that claims to forecast.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch the other venue.&lt;/strong&gt; Cross-venue divergence (spot down while a bullish-if-YES market still prices high) is the cheapest adverse-selection signal available to a Polymarket market maker. It doesn't require predicting anything, only noticing that two prices for the same risk disagree.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;/p&gt;
  ▶ Reproduce the case study (no API keys needed)
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Follow-SM/hft-toxicity-circuit-breaker.git
&lt;span class="nb"&gt;cd &lt;/span&gt;hft-toxicity-circuit-breaker
pip &lt;span class="nb"&gt;install &lt;/span&gt;httpx &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; python research/vpin_case_study.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The script uses only public Binance klines and Polymarket's public CLOB price history and trades.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Get started
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python:&lt;/strong&gt; &lt;a href="https://pypi.org/project/followsm-sdk/" rel="noopener noreferrer"&gt;&lt;code&gt;pip install followsm-sdk&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript / Node:&lt;/strong&gt; &lt;a href="https://www.npmjs.com/package/@followsm/sdk" rel="noopener noreferrer"&gt;&lt;code&gt;npm install @followsm/sdk&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Polymarket bot (REST, runs on the free tier):&lt;/strong&gt; &lt;a href="https://github.com/Follow-SM/polymarket-arbitrage-starter-kit" rel="noopener noreferrer"&gt;polymarket-arbitrage-starter-kit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tick-level kill switch (Enterprise WebSocket):&lt;/strong&gt; &lt;a href="https://github.com/Follow-SM/hft-toxicity-circuit-breaker" rel="noopener noreferrer"&gt;hft-toxicity-circuit-breaker&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Free&lt;/th&gt;
&lt;th&gt;DEVELOPER ($199/mo)&lt;/th&gt;
&lt;th&gt;ENTERPRISE ($499/mo)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;REST requests/min&lt;/td&gt;
&lt;td&gt;30 (per IP)&lt;/td&gt;
&lt;td&gt;300&lt;/td&gt;
&lt;td&gt;1,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Binance pairs&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;50+&lt;/td&gt;
&lt;td&gt;50+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Snapshot latency&lt;/td&gt;
&lt;td&gt;Standard&lt;/td&gt;
&lt;td&gt;Sub-10ms in-memory&lt;/td&gt;
&lt;td&gt;Sub-10ms in-memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;/ws/v1/toxicity&lt;/code&gt; + &lt;code&gt;/ws/v1/confluence&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://follow-sm.com/pricing" rel="noopener noreferrer"&gt;Get your API key at follow-sm.com/pricing&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;References: Easley, Kiefer, O'Hara &amp;amp; Paperman (1996), "Liquidity, Information, and Infrequently Traded Stocks", Journal of Finance. Easley, López de Prado &amp;amp; O'Hara (2012), "Flow Toxicity and Liquidity in a High-Frequency World", Review of Financial Studies. Andersen &amp;amp; Bondarenko (2014), "VPIN and the Flash Crash", Journal of Financial Markets.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Not financial advice. Trading crypto and prediction markets carries substantial risk of loss.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>algotrading</category>
      <category>cryptocurrency</category>
      <category>web3</category>
    </item>
  </channel>
</rss>
