<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>thepragmaticquant — tsbootstrap</title><description>A time series bootstrap library for Python that resamples while preserving the dependence a plain bootstrap destroys, with conformal uncertainty.</description><link>https://thepragmaticquant.com/</link><item><title>Count the bytes, not the FLOPs</title><link>https://thepragmaticquant.com/why-we-stopped-materializing-arrays/</link><guid isPermaLink="true">https://thepragmaticquant.com/why-we-stopped-materializing-arrays/</guid><description>Why tsbootstrap stopped materializing arrays and carrying state. A routine bootstrap job can materialize a 160 MB tensor whose only purpose is to be averaged and thrown away. How tsbootstrap&apos;s hot path stopped building it, including the one path where the incumbent still wins.</description><pubDate>Sat, 11 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;tldr&quot;&gt;&lt;p&gt;TL;DR: tsbootstrap’s fast path used to build every bootstrap replicate into one giant batched tensor: on a routine job, a &lt;strong&gt;160 MB&lt;/strong&gt; tensor pushed out to main memory and hauled back to produce one summary number per replicate. We rebuilt the hot path around two rules: never materialize an array whose only consumer is a reduction, and never carry state you can derive. Every head-to-head benchmark cell now favors the fused path; the settled benchmark grid sustains &lt;strong&gt;3.1x to 20x&lt;/strong&gt; on the longer series. The last stubborn cell, where the runtime was mostly Python building random-number seeds, dropped from &lt;strong&gt;13.1 ms to 0.55 ms&lt;/strong&gt; in the redesign’s validation run once we deleted the seed objects.
&lt;br/&gt;&lt;br/&gt;The full replicate tensor is still available when you want it, and on that materializing path our default backend remains slower than the incumbent. That row is printed below with the rest.&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Early this summer, in the middle of a performance push I thought was going well, we ran tsbootstrap’s block-bootstrap engine head-to-head against arch, a mature econometrics library whose bootstrap loop has had years of polish, for the first time. We lost. At a realistic workload, a few thousand replicates of a few-thousand-point series, the whole call came back several times slower end-to-end, on the machine we developed on, before the compiled engine this article describes existed. Every release we had ever shipped carried that loss; users hitting exactly that workload had been paying it the whole time, and nothing in our tooling would ever have told us.&lt;/p&gt;

&lt;p&gt;I had not seen it coming: our benchmark suite had only ever compared the library against its own history. A regression suite tells you when you get slower than yesterday; it cannot tell you that you ship slower than the other library, at the exact workload where users would notice. The day a head-to-head existed, the loss appeared. It had been there all along.&lt;/p&gt;
&lt;p&gt;The profiler’s first answer was the ordinary one. Most of the measured deficit was removable interpreter tax: a per-replicate Python index loop, thousands of seed objects spawned per call, stacked object wrapping. But beneath it sat a second, structural problem, the reason the reflexive fix could not win either. The reflexive fix for Python overhead is to batch: replace the loop with a single vectorized NumPy operation. Batching removes the interpreter from the inner loop and swaps it for &lt;em&gt;B&lt;/em&gt;-fold traffic through main memory (&lt;em&gt;B&lt;/em&gt; being the number of bootstrap replicates, the count every cost in this story scales with) because the batched design materializes every replicate at once. The incumbent’s replicate loop is ordinary Python too. It wins by keeping its working set (the data its loop actively touches) small enough to live in cache, consuming each resample the moment it exists. We were not going to beat that by batching harder.&lt;/p&gt;
&lt;p&gt;Here is the machine’s side of the argument. A CPU core computes only on what it holds in its registers. Think of that as your hands. Behind them sit the caches: L1, a desk you can reach without looking up; L2, the shelf behind you; L3, shared with the other cores, a cabinet down the hall. Behind all of that is DRAM: main memory, the warehouse across the street, bigger and slower at every step, orders of magnitude in latency top to bottom. The hardware hides none of that from your runtime; it hides it only from your source code.&lt;/p&gt;
&lt;p&gt;Now put a bootstrap on that machine. A bootstrap, one time for anyone who has not run one: it re-draws your data thousands of times to see how much a statistic would wobble across plausible alternate samples, and each redrawn copy is a &lt;em&gt;replicate&lt;/em&gt;. Take a modest, entirely realistic job: a series of &lt;em&gt;n&lt;/em&gt; = 10,000 observations, &lt;em&gt;B&lt;/em&gt; = 2,000 bootstrap replicates, &lt;code&gt;float64&lt;/code&gt; (8 bytes per number). Build all the replicates at once, the way a batched NumPy design wants to, and you have asked for a &lt;em&gt;B&lt;/em&gt; x &lt;em&gt;n&lt;/em&gt; tensor: 10,000 x 2,000 x 8 bytes = &lt;strong&gt;160 MB&lt;/strong&gt;. That is far beyond the tens of megabytes of L3 a core complex sees. Every byte of that tensor is written out to main memory, then hauled back in so the statistic can read it once, and if the statistic is a mean, the answer you keep is 2,000 numbers. Sixteen kilobytes, bought with 160 MB of round trips.&lt;/p&gt;

&lt;section class=&quot;scrub full tsq-live&quot; aria-label=&quot;scroll-scrubbed set piece: bootstrap replicates assemble into a 160 megabyte tensor, flood past the schematic cache boundary into main memory, then collapse into a 16 kilobyte bar of one statistic per replicate&quot;&gt;&lt;div class=&quot;stage&quot;&gt; &lt;svg class=&quot;tsq-svg&quot; viewBox=&quot;0 0 880 560&quot; aria-hidden=&quot;true&quot; focusable=&quot;false&quot;&gt; &lt;!-- DRAM field (below the boundary) --&gt; &lt;rect class=&quot;tsq-dram&quot; x=&quot;40&quot; y=&quot;346&quot; width=&quot;800&quot; height=&quot;186&quot; rx=&quot;6&quot;&gt;&lt;/rect&gt; &lt;text class=&quot;tsq-label&quot; x=&quot;816&quot; y=&quot;516&quot; text-anchor=&quot;end&quot;&gt;main memory (DRAM)&lt;/text&gt; &lt;!-- cache boundary (schematic) --&gt; &lt;line class=&quot;tsq-boundary&quot; x1=&quot;40&quot; y1=&quot;346&quot; x2=&quot;840&quot; y2=&quot;346&quot;&gt;&lt;/line&gt; &lt;text class=&quot;tsq-label&quot; x=&quot;56&quot; y=&quot;332&quot;&gt;cache boundary&lt;/text&gt; &lt;!-- source block: your data --&gt; &lt;g&gt; &lt;rect class=&quot;tsq-src&quot; x=&quot;60&quot; y=&quot;52&quot; width=&quot;200&quot; height=&quot;64&quot; rx=&quot;6&quot;&gt;&lt;/rect&gt; &lt;text class=&quot;tsq-srclabel&quot; x=&quot;160&quot; y=&quot;80&quot; text-anchor=&quot;middle&quot;&gt;your data&lt;/text&gt; &lt;text class=&quot;tsq-srcsub&quot; x=&quot;160&quot; y=&quot;104&quot; text-anchor=&quot;middle&quot;&gt;n = 10,000 · float64&lt;/text&gt; &lt;/g&gt; &lt;!-- byte counter (stepped, pre-rendered numerals crossfaded by the scrub) --&gt; &lt;text class=&quot;tsq-ctrlabel&quot; x=&quot;820&quot; y=&quot;60&quot; text-anchor=&quot;end&quot;&gt;replicate tensor&lt;/text&gt; &lt;g class=&quot;tsq-ctr&quot;&gt; &lt;text class=&quot;tsq-c tsq-c1&quot; x=&quot;820&quot; y=&quot;102&quot; text-anchor=&quot;end&quot;&gt;8 MB&lt;/text&gt; &lt;text class=&quot;tsq-c tsq-c2&quot; x=&quot;820&quot; y=&quot;102&quot; text-anchor=&quot;end&quot;&gt;40 MB&lt;/text&gt; &lt;text class=&quot;tsq-c tsq-c3&quot; x=&quot;820&quot; y=&quot;102&quot; text-anchor=&quot;end&quot;&gt;80 MB&lt;/text&gt; &lt;text class=&quot;tsq-c tsq-c4&quot; x=&quot;820&quot; y=&quot;102&quot; text-anchor=&quot;end&quot;&gt;120 MB&lt;/text&gt; &lt;text class=&quot;tsq-c tsq-c5&quot; x=&quot;820&quot; y=&quot;102&quot; text-anchor=&quot;end&quot;&gt;160 MB&lt;/text&gt; &lt;text class=&quot;tsq-c tsq-c6&quot; x=&quot;820&quot; y=&quot;102&quot; text-anchor=&quot;end&quot;&gt;16 kB&lt;/text&gt; &lt;/g&gt; &lt;!-- the stack: replicate rows stamped out of the source (beat 1), flooded past the
           boundary (beat 2, outer group), collapsed into the bar (beat 3, inner group) --&gt; &lt;g class=&quot;tsq-flood&quot;&gt; &lt;g class=&quot;tsq-collapse&quot;&gt; &lt;rect class=&quot;tsq-row tsq-r1&quot; x=&quot;300&quot; y=&quot;140&quot; width=&quot;520&quot; height=&quot;12&quot; rx=&quot;3&quot; style=&quot;--tsq-dy: -56px&quot;&gt;&lt;/rect&gt; &lt;rect class=&quot;tsq-row tsq-r2&quot; x=&quot;300&quot; y=&quot;157&quot; width=&quot;520&quot; height=&quot;12&quot; rx=&quot;3&quot; style=&quot;--tsq-dy: -73px&quot;&gt;&lt;/rect&gt; &lt;rect class=&quot;tsq-row tsq-r3&quot; x=&quot;300&quot; y=&quot;174&quot; width=&quot;520&quot; height=&quot;12&quot; rx=&quot;3&quot; style=&quot;--tsq-dy: -90px&quot;&gt;&lt;/rect&gt; &lt;rect class=&quot;tsq-row tsq-r4&quot; x=&quot;300&quot; y=&quot;191&quot; width=&quot;520&quot; height=&quot;12&quot; rx=&quot;3&quot; style=&quot;--tsq-dy: -107px&quot;&gt;&lt;/rect&gt; &lt;rect class=&quot;tsq-row tsq-r5&quot; x=&quot;300&quot; y=&quot;208&quot; width=&quot;520&quot; height=&quot;12&quot; rx=&quot;3&quot; style=&quot;--tsq-dy: -124px&quot;&gt;&lt;/rect&gt; &lt;rect class=&quot;tsq-row tsq-r6&quot; x=&quot;300&quot; y=&quot;225&quot; width=&quot;520&quot; height=&quot;12&quot; rx=&quot;3&quot; style=&quot;--tsq-dy: -141px&quot;&gt;&lt;/rect&gt; &lt;rect class=&quot;tsq-row tsq-r7&quot; x=&quot;300&quot; y=&quot;242&quot; width=&quot;520&quot; height=&quot;12&quot; rx=&quot;3&quot; style=&quot;--tsq-dy: -158px&quot;&gt;&lt;/rect&gt; &lt;rect class=&quot;tsq-row tsq-r8&quot; x=&quot;300&quot; y=&quot;259&quot; width=&quot;520&quot; height=&quot;12&quot; rx=&quot;3&quot; style=&quot;--tsq-dy: -175px&quot;&gt;&lt;/rect&gt; &lt;rect class=&quot;tsq-row tsq-r9&quot; x=&quot;300&quot; y=&quot;276&quot; width=&quot;520&quot; height=&quot;12&quot; rx=&quot;3&quot; style=&quot;--tsq-dy: -192px&quot;&gt;&lt;/rect&gt; &lt;rect class=&quot;tsq-row tsq-r10&quot; x=&quot;300&quot; y=&quot;293&quot; width=&quot;520&quot; height=&quot;12&quot; rx=&quot;3&quot; style=&quot;--tsq-dy: -209px&quot;&gt;&lt;/rect&gt; &lt;rect class=&quot;tsq-row tsq-r11&quot; x=&quot;300&quot; y=&quot;310&quot; width=&quot;520&quot; height=&quot;12&quot; rx=&quot;3&quot; style=&quot;--tsq-dy: -226px&quot;&gt;&lt;/rect&gt; &lt;rect class=&quot;tsq-row tsq-r12&quot; x=&quot;300&quot; y=&quot;327&quot; width=&quot;520&quot; height=&quot;12&quot; rx=&quot;3&quot; style=&quot;--tsq-dy: -243px&quot;&gt;&lt;/rect&gt; &lt;/g&gt; &lt;/g&gt; &lt;!-- the answer: one statistic per replicate (beat 3) --&gt; &lt;g class=&quot;tsq-bargroup&quot;&gt; &lt;rect class=&quot;tsq-bar&quot; x=&quot;300&quot; y=&quot;300&quot; width=&quot;520&quot; height=&quot;12&quot; rx=&quot;4&quot;&gt;&lt;/rect&gt; &lt;text class=&quot;tsq-barlabel&quot; x=&quot;300&quot; y=&quot;290&quot;&gt;one statistic per replicate: (B, d)&lt;/text&gt; &lt;/g&gt; &lt;/svg&gt; &lt;div class=&quot;tsq-heads&quot;&gt; &lt;p class=&quot;tsq-head tsq-h1&quot;&gt;Every replicate is a copy of your data.&lt;/p&gt; &lt;p class=&quot;tsq-head tsq-h2&quot;&gt;The tensor is B times larger than the data. It lives in DRAM.&lt;/p&gt; &lt;p class=&quot;tsq-head tsq-h3&quot;&gt;Gather and reduce in the same pass. Keep only the answer.&lt;/p&gt; &lt;p class=&quot;tsq-head tsq-h4&quot;&gt;
20 MB where 1.94 GB stood, B&amp;nbsp;=&amp;nbsp;50,000.
&lt;small&gt;measured 2026-07-04 on v0.4.0; the streaming path is unchanged since&lt;/small&gt; &lt;/p&gt; &lt;/div&gt; &lt;/div&gt;&lt;/section&gt; &lt;div class=&quot;tsq-fallback full&quot;&gt; &lt;figure class=&quot;full&quot; data-astro-cid-bj3fsypb&gt; &lt;div class=&quot;svgfig svgfig-chart&quot; role=&quot;img&quot; aria-label=&quot;Three-panel diagram of the same bootstrap job. First panel, labelled assemble, the batched design: a small block marked your data stamps out replicate rows that stack into a growing tensor, with a byte counter climbing to 160 megabytes. Second panel, labelled flood, the batched design: the stacked tensor has crossed a dashed line marked cache boundary, schematic, and sits in a grey field labelled main memory, every row shaded to show it has been written out; the byte counter holds at 160 megabytes, annotated B times the data, past every cache. Third panel, labelled collapse, the fix: fused reduce: the rows fold into a single thin bar labelled one statistic per replicate, the byte counter reads sixteen kilobytes, and the tensor is gone.&quot; data-astro-cid-bj3fsypb&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; width=&quot;880&quot; id=&quot;fig-tsb-03-tensor-never-fits&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 880 1240&quot; font-family=&quot;var(--mono)&quot;&gt;&lt;style&gt;#fig-tsb-03-tensor-never-fits [fill=&quot;#1a1d23&quot; i]{fill:var(--bg)}#fig-tsb-03-tensor-never-fits [stroke=&quot;#1a1d23&quot; i]{stroke:var(--bg)}#fig-tsb-03-tensor-never-fits [fill=&quot;#18181b&quot; i]{fill:var(--bg-panel)}#fig-tsb-03-tensor-never-fits [stroke=&quot;#18181b&quot; i]{stroke:var(--bg-panel)}#fig-tsb-03-tensor-never-fits [fill=&quot;#2c2f37&quot; i]{fill:var(--current-line)}#fig-tsb-03-tensor-never-fits [stroke=&quot;#2c2f37&quot; i]{stroke:var(--current-line)}#fig-tsb-03-tensor-never-fits [fill=&quot;#f4f5f7&quot; i]{fill:var(--fg)}#fig-tsb-03-tensor-never-fits [stroke=&quot;#f4f5f7&quot; i]{stroke:var(--fg)}#fig-tsb-03-tensor-never-fits [fill=&quot;#8a8f98&quot; i]{fill:var(--comment)}#fig-tsb-03-tensor-never-fits [stroke=&quot;#8a8f98&quot; i]{stroke:var(--comment)}&lt;/style&gt;
  &lt;style&gt;
    :where(#tnf-root) text { font-family: var(--mono); }
    .tnf-panel { fill: var(--current-line); opacity: 0.28; }
    .tnf-title { fill: var(--fg); font-size: 24px; font-weight: 700; }
    .tnf-note { fill: var(--comment); font-size: 18px; }
    .tnf-label { fill: var(--comment); font-size: 17px; }
    .tnf-ctr { fill: var(--fg); font-size: 40px; font-weight: 700; }
    .tnf-row { fill: #e69f00; }
    .tnf-rowdim { fill: #e69f00; opacity: 0.5; }
    .tnf-rowghost { fill: #e69f00; opacity: 0.14; }
    .tnf-src { fill: #6272a4; }
    .tnf-srctext { fill: var(--fg); font-size: 18px; font-weight: 600; }
    .tnf-srcsub { fill: var(--fg); font-size: 14px; opacity: 0.85; }
    .tnf-bar { fill: #56b4e9; }
    .tnf-bartext { fill: #56b4e9; font-size: 18px; font-weight: 600; }
    .tnf-bound { stroke: var(--comment); stroke-width: 2.5; stroke-dasharray: 10 8; }
    .tnf-dram { fill: var(--current-line); opacity: 0.55; }
    .tnf-arrow { stroke: var(--comment); stroke-width: 2.5; fill: none; }
    .tnf-arrow-heavy { stroke: var(--comment); stroke-width: 4.5; fill: none; }
    .tnf-arrowhead { fill: var(--comment); }
  &lt;/style&gt;
  &lt;g id=&quot;tnf-root&quot;&gt;
    &lt;!-- ============ panel 1: assemble ============ --&gt;
    &lt;rect class=&quot;tnf-panel&quot; x=&quot;28&quot; y=&quot;28&quot; width=&quot;824&quot; height=&quot;352&quot; rx=&quot;10&quot; /&gt;
    &lt;text class=&quot;tnf-title&quot; x=&quot;52&quot; y=&quot;72&quot;&gt;1 · assemble &lt;tspan class=&quot;tnf-note&quot;&gt;: the batched design&lt;/tspan&gt;&lt;/text&gt;
    &lt;text class=&quot;tnf-ctr&quot; x=&quot;820&quot; y=&quot;84&quot; text-anchor=&quot;end&quot;&gt;160 MB&lt;/text&gt;
    &lt;text class=&quot;tnf-label&quot; x=&quot;820&quot; y=&quot;110&quot; text-anchor=&quot;end&quot;&gt;byte counter climbs&lt;/text&gt;

    &lt;rect class=&quot;tnf-src&quot; x=&quot;52&quot; y=&quot;140&quot; width=&quot;192&quot; height=&quot;62&quot; rx=&quot;6&quot; /&gt;
    &lt;text class=&quot;tnf-srctext&quot; x=&quot;148&quot; y=&quot;167&quot; text-anchor=&quot;middle&quot;&gt;your data&lt;/text&gt;
    &lt;text class=&quot;tnf-srcsub&quot; x=&quot;148&quot; y=&quot;190&quot; text-anchor=&quot;middle&quot;&gt;n = 10,000 · float64&lt;/text&gt;

    &lt;line class=&quot;tnf-arrow&quot; x1=&quot;248&quot; y1=&quot;171&quot; x2=&quot;288&quot; y2=&quot;171&quot; /&gt;
    &lt;path class=&quot;tnf-arrowhead&quot; d=&quot;M 288 165 L 300 171 L 288 177 Z&quot; /&gt;

    &lt;rect class=&quot;tnf-row&quot; x=&quot;312&quot; y=&quot;124&quot; width=&quot;508&quot; height=&quot;15&quot; rx=&quot;3&quot; /&gt;
    &lt;rect class=&quot;tnf-row&quot; x=&quot;312&quot; y=&quot;145&quot; width=&quot;508&quot; height=&quot;15&quot; rx=&quot;3&quot; /&gt;
    &lt;rect class=&quot;tnf-row&quot; x=&quot;312&quot; y=&quot;166&quot; width=&quot;508&quot; height=&quot;15&quot; rx=&quot;3&quot; /&gt;
    &lt;rect class=&quot;tnf-row&quot; x=&quot;312&quot; y=&quot;187&quot; width=&quot;508&quot; height=&quot;15&quot; rx=&quot;3&quot; /&gt;
    &lt;rect class=&quot;tnf-row&quot; x=&quot;312&quot; y=&quot;208&quot; width=&quot;508&quot; height=&quot;15&quot; rx=&quot;3&quot; /&gt;
    &lt;rect class=&quot;tnf-row&quot; x=&quot;312&quot; y=&quot;229&quot; width=&quot;508&quot; height=&quot;15&quot; rx=&quot;3&quot; /&gt;
    &lt;rect class=&quot;tnf-row&quot; x=&quot;312&quot; y=&quot;250&quot; width=&quot;508&quot; height=&quot;15&quot; rx=&quot;3&quot; /&gt;
    &lt;rect class=&quot;tnf-row&quot; x=&quot;312&quot; y=&quot;271&quot; width=&quot;508&quot; height=&quot;15&quot; rx=&quot;3&quot; /&gt;
    &lt;text class=&quot;tnf-note&quot; x=&quot;52&quot; y=&quot;322&quot;&gt;every replicate is a full copy of the data:&lt;/text&gt;
    &lt;text class=&quot;tnf-note&quot; x=&quot;52&quot; y=&quot;348&quot;&gt;B = 2,000 × n = 10,000 × 8 bytes = 160 MB&lt;/text&gt;

    &lt;!-- ============ panel 2: flood ============ --&gt;
    &lt;rect class=&quot;tnf-panel&quot; x=&quot;28&quot; y=&quot;440&quot; width=&quot;824&quot; height=&quot;352&quot; rx=&quot;10&quot; /&gt;
    &lt;text class=&quot;tnf-title&quot; x=&quot;52&quot; y=&quot;484&quot;&gt;2 · flood &lt;tspan class=&quot;tnf-note&quot;&gt;: the batched design&lt;/tspan&gt;&lt;/text&gt;

    &lt;text class=&quot;tnf-ctr&quot; x=&quot;820&quot; y=&quot;496&quot; text-anchor=&quot;end&quot;&gt;160 MB&lt;/text&gt;
    &lt;text class=&quot;tnf-label&quot; x=&quot;820&quot; y=&quot;522&quot; text-anchor=&quot;end&quot;&gt;B times the data, past every cache&lt;/text&gt;
    &lt;rect class=&quot;tnf-src&quot; x=&quot;52&quot; y=&quot;500&quot; width=&quot;150&quot; height=&quot;52&quot; rx=&quot;6&quot; /&gt;
    &lt;text class=&quot;tnf-srctext&quot; x=&quot;127&quot; y=&quot;532&quot; text-anchor=&quot;middle&quot;&gt;your data&lt;/text&gt;

    &lt;text class=&quot;tnf-label&quot; x=&quot;248&quot; y=&quot;570&quot;&gt;cache boundary, schematic&lt;/text&gt;
    &lt;line class=&quot;tnf-bound&quot; x1=&quot;52&quot; y1=&quot;580&quot; x2=&quot;828&quot; y2=&quot;580&quot; /&gt;
    &lt;rect class=&quot;tnf-dram&quot; x=&quot;52&quot; y=&quot;584&quot; width=&quot;776&quot; height=&quot;150&quot; rx=&quot;6&quot; /&gt;

    &lt;rect class=&quot;tnf-rowdim&quot; x=&quot;312&quot; y=&quot;600&quot; width=&quot;508&quot; height=&quot;15&quot; rx=&quot;3&quot; /&gt;
    &lt;rect class=&quot;tnf-rowdim&quot; x=&quot;316&quot; y=&quot;621&quot; width=&quot;508&quot; height=&quot;15&quot; rx=&quot;3&quot; /&gt;
    &lt;rect class=&quot;tnf-rowdim&quot; x=&quot;312&quot; y=&quot;642&quot; width=&quot;508&quot; height=&quot;15&quot; rx=&quot;3&quot; /&gt;
    &lt;rect class=&quot;tnf-rowdim&quot; x=&quot;316&quot; y=&quot;663&quot; width=&quot;508&quot; height=&quot;15&quot; rx=&quot;3&quot; /&gt;
    &lt;rect class=&quot;tnf-rowdim&quot; x=&quot;312&quot; y=&quot;684&quot; width=&quot;508&quot; height=&quot;15&quot; rx=&quot;3&quot; /&gt;
    &lt;text class=&quot;tnf-label&quot; x=&quot;520&quot; y=&quot;722&quot; text-anchor=&quot;end&quot;&gt;main memory (DRAM)&lt;/text&gt;
    &lt;text class=&quot;tnf-note&quot; x=&quot;52&quot; y=&quot;750&quot;&gt;B times larger than the data,&lt;/text&gt;
    &lt;text class=&quot;tnf-note&quot; x=&quot;52&quot; y=&quot;772&quot;&gt;the tensor outgrows the caches:&lt;/text&gt;
    &lt;text class=&quot;tnf-note&quot; x=&quot;52&quot; y=&quot;794&quot;&gt;written out to DRAM, read back once&lt;/text&gt;

    &lt;!-- ============ panel 3: collapse ============ --&gt;
    &lt;rect class=&quot;tnf-panel&quot; x=&quot;28&quot; y=&quot;852&quot; width=&quot;824&quot; height=&quot;352&quot; rx=&quot;10&quot; /&gt;
    &lt;text class=&quot;tnf-title&quot; x=&quot;52&quot; y=&quot;896&quot;&gt;3 · collapse &lt;tspan class=&quot;tnf-note&quot;&gt;: the fused reduce&lt;/tspan&gt;&lt;/text&gt;
    &lt;text class=&quot;tnf-ctr&quot; x=&quot;820&quot; y=&quot;908&quot; text-anchor=&quot;end&quot;&gt;16 kB&lt;/text&gt;
    &lt;text class=&quot;tnf-label&quot; x=&quot;820&quot; y=&quot;934&quot; text-anchor=&quot;end&quot;&gt;byte counter drops&lt;/text&gt;

    &lt;rect class=&quot;tnf-rowghost&quot; x=&quot;312&quot; y=&quot;940&quot; width=&quot;508&quot; height=&quot;15&quot; rx=&quot;3&quot; /&gt;
    &lt;rect class=&quot;tnf-rowghost&quot; x=&quot;312&quot; y=&quot;961&quot; width=&quot;508&quot; height=&quot;15&quot; rx=&quot;3&quot; /&gt;
    &lt;rect class=&quot;tnf-rowghost&quot; x=&quot;312&quot; y=&quot;982&quot; width=&quot;508&quot; height=&quot;15&quot; rx=&quot;3&quot; /&gt;
    &lt;rect class=&quot;tnf-rowghost&quot; x=&quot;312&quot; y=&quot;1003&quot; width=&quot;508&quot; height=&quot;15&quot; rx=&quot;3&quot; /&gt;

    &lt;line class=&quot;tnf-arrow-heavy&quot; x1=&quot;566&quot; y1=&quot;1022&quot; x2=&quot;566&quot; y2=&quot;1056&quot; /&gt;
    &lt;path class=&quot;tnf-arrowhead&quot; d=&quot;M 557 1054 L 566 1072 L 575 1054 Z&quot; /&gt;

    &lt;rect class=&quot;tnf-bar&quot; x=&quot;312&quot; y=&quot;1080&quot; width=&quot;508&quot; height=&quot;12&quot; rx=&quot;4&quot; /&gt;
    &lt;text class=&quot;tnf-bartext&quot; x=&quot;52&quot; y=&quot;1122&quot;&gt;one statistic per replicate&lt;/text&gt;
    &lt;text class=&quot;tnf-note&quot; x=&quot;52&quot; y=&quot;1152&quot;&gt;gather and reduce in the same pass:&lt;/text&gt;
    &lt;text class=&quot;tnf-note&quot; x=&quot;52&quot; y=&quot;1178&quot;&gt;no tensor, only the answer is kept&lt;/text&gt;
  &lt;/g&gt;
&lt;/svg&gt;
&lt;/div&gt; &lt;figcaption data-astro-cid-bj3fsypb&gt;The batched design&apos;s tensor: assembled, flooding past the cache boundary, and collapsed into the answer. The boundary is schematic; the byte counts are arithmetic on the worked example. At a larger job (fifty thousand replicates of a shorter series) the materializing path peaked at 1.94 GB where the streaming path held 20 MB, roughly 97x (measured 2026-07-04 on version 0.4.0; the streaming path is unchanged since).&lt;/figcaption&gt; &lt;details class=&quot;data-table&quot; data-astro-cid-bj3fsypb&gt; &lt;summary data-astro-cid-bj3fsypb&gt;data table&lt;/summary&gt;  &lt;div class=&quot;data-table-scroll&quot; data-astro-cid-bj3fsypb&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;quantity&lt;/th&gt;&lt;th&gt;value&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;replicate tensor, worked example (&lt;em&gt;n&lt;/em&gt; = 10,000, &lt;em&gt;B&lt;/em&gt; = 2,000, float64)&lt;/td&gt;&lt;td&gt;160 MB&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;answer kept (one mean per replicate)&lt;/td&gt;&lt;td&gt;16 kB&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;peak memory at &lt;em&gt;B&lt;/em&gt; = 50,000 on an &lt;em&gt;n&lt;/em&gt; = 2,000 series: materialize vs streaming&lt;/td&gt;&lt;td&gt;1.94 GB vs 20 MB (~97x), measured 2026-07-04 on v0.4.0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;peak resident memory at the worked example’s shape, stationary-block resample (measured 2026-07-11): materialize vs streaming&lt;/td&gt;&lt;td&gt;617 MB vs 234 MB, where 234 MB is the bare process baseline; the streaming run is indistinguishable from a run that computes nothing. The materialize delta exceeds the 160 MB tensor because the path also holds a returned copy and the index matrix&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt; &lt;/details&gt; &lt;/figure&gt;  &lt;/div&gt;
&lt;p&gt;The tsbootstrap that ships today never builds that tensor on its fast path. The story of how it stopped: The first wall is memory traffic: the bytes themselves, moving through the hierarchy. The second took longer to see, because it hides inside the language runtime and the library’s own design, not the hardware: the cost of &lt;em&gt;state&lt;/em&gt; (allocated objects and seeded generators) that exists only to make randomness happen in the right order. We stopped materializing arrays, and we stopped carrying state.&lt;/p&gt;
&lt;h2 id=&quot;wall-one-memory-traffic&quot;&gt;Wall one: memory traffic&lt;a class=&quot;heading-anchor&quot; href=&quot;#wall-one-memory-traffic&quot; aria-label=&quot;Link to this section&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Start with what the batched design actually does. To bootstrap a series with blocks (contiguous runs resampled whole, so the short-range dependence that makes a series a series survives inside each block; &lt;a href=&quot;https://thepragmaticquant.com/your-bootstrap-is-lying-to-you/&quot;&gt;the first piece in this series&lt;/a&gt; is about what happens when it doesn’t), you draw random block starts, expand them into resample indices, gather the data through those indices, and compute your statistic on each replicate. The batched version does each of those as one array operation over all &lt;em&gt;B&lt;/em&gt; replicates: build a &lt;code&gt;(B, n)&lt;/code&gt; index matrix, gather into a &lt;code&gt;(B, n, d)&lt;/code&gt; values tensor (d is just the number of columns in your series), then reduce along the middle axis.&lt;/p&gt;
&lt;p&gt;Count the work in each cell of that tensor. Eight bytes written on the way out. Eight bytes read back for the reduction. Roughly one floating-point addition, one addition per sixteen bytes moved, where a compute-bound kernel like a matrix multiply does hundreds of operations for every byte it pulls. That ratio, the &lt;em&gt;arithmetic intensity&lt;/em&gt; (how much computing you do per byte you move), is the number that decides whether your workload is limited by the processor or by the memory system. Ours is about as low as arithmetic intensity gets. The cores were never the constraint; they spent the benchmark waiting on memory. The gather is slow not because the code is interpreted but because its arithmetic intensity is far too low to keep the processor busy: it is a bytes problem being graded as a FLOPs problem.&lt;/p&gt;
&lt;p&gt;The incumbent’s loop, seen this way, stops looking old-fashioned and starts looking correct. One replicate at a time means one &lt;code&gt;(n, d)&lt;/code&gt; resample at a time: a working set that fits in cache, is consumed by the statistic immediately, and is gone before the next one arrives. That working set never grows with &lt;em&gt;B&lt;/em&gt;, so DRAM barely enters its story. The batched design’s traffic grows linearly with &lt;em&gt;B&lt;/em&gt;, and once the tensor outgrows the last cache level, every additional replicate’s bytes take the round trip through main memory. NumPy’s programming model quietly couples two decisions that are really separate: batching the dispatch and batching the bytes. The loop was winning because it never built the thing we were building.&lt;/p&gt;
&lt;p&gt;Here is the whole argument as accounting, on the worked example: &lt;em&gt;n&lt;/em&gt; = 10,000, &lt;em&gt;B&lt;/em&gt; = 2,000, &lt;code&gt;float64&lt;/code&gt;, one mean per replicate. Redo it on a napkin for your own workload; the ratio is the point.&lt;/p&gt;






























&lt;div class=&quot;table-scroll&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;quantity&lt;/th&gt;&lt;th&gt;materialize path&lt;/th&gt;&lt;th&gt;fused, streaming path&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;intermediate allocated&lt;/td&gt;&lt;td&gt;160 MB, the full replicate tensor&lt;/td&gt;&lt;td&gt;one &lt;code&gt;(n,)&lt;/code&gt; index row + one &lt;code&gt;(n, d)&lt;/code&gt; scratch per thread (~80 kB each)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;bytes through DRAM&lt;/td&gt;&lt;td&gt;at least twice the tensor: written out, read back&lt;/td&gt;&lt;td&gt;consumed in cache, per work item&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;useful output kept&lt;/td&gt;&lt;td&gt;16 kB, one mean per replicate&lt;/td&gt;&lt;td&gt;16 kB, the same answer&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;bytes moved per byte of answer&lt;/td&gt;&lt;td&gt;~20,000 : 1&lt;/td&gt;&lt;td&gt;~1 : 1&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;None of this is a new insight: compilers have fused loops to avoid intermediate arrays for decades, and every numerical programmer eventually meets the memory wall. What is worth knowing is that the same wall now dominates transformer training and serving. FlashAttention, the kernel that reshaped both, describes its own core move in the caption of its first figure: it uses “tiling to prevent materialization of the large N × N attention matrix”, and that one refusal, plus fusing the surrounding operations into a single kernel, yielded a 7.6x speedup on GPT-2’s attention. The hierarchy it plays against is the GPU’s version of ours: an A100’s main memory streams at up to 2.0 TB/s, while the tiny on-chip SRAM (192 KB per streaming multiprocessor) runs roughly ten times faster. Same shape, same conclusion: keep the working set in fast memory; never write the big intermediate at all. FlashAttention is the proof that the old compiler principle still binds at datacenter scale.&lt;/p&gt;
&lt;h2 id=&quot;one-pass-and-nothing-left-behind&quot;&gt;One pass, and nothing left behind&lt;a class=&quot;heading-anchor&quot; href=&quot;#one-pass-and-nothing-left-behind&quot; aria-label=&quot;Link to this section&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The fix is a single compiled kernel that does everything the batched pipeline did, per replicate and in one pass, without ever building the &lt;em&gt;B&lt;/em&gt;-wide tensor. Per-worker scratch still exists, but it is &lt;em&gt;n&lt;/em&gt;-sized and transient, not &lt;em&gt;B&lt;/em&gt; times the data. The standard name for this is &lt;em&gt;kernel fusion&lt;/em&gt;: instead of separate passes that hand each other arrays, one loop body builds, gathers, and reduces for one replicate and emits only the statistic.&lt;/p&gt;
&lt;p&gt;Each replicate is one unit of parallel work. The kernel gives it a private &lt;code&gt;(n,)&lt;/code&gt; index buffer and a private &lt;code&gt;(n, d)&lt;/code&gt; scratch, builds that replicate’s resample indices into the buffer, gathers values through them column by column, applies the reducer (mean, variance, standard deviation, or a quantile) in the same loop body, and writes one row of the &lt;code&gt;(B, d)&lt;/code&gt; output. The 160 MB tensor from the opening never exists; peak memory is the source data, per-worker scratch, and the 16 kB we actually wanted. The kernel is compiled to machine code the first time it runs, a just-in-time (JIT) compilation, and that first-call cost is paid off the hot path by an explicit warm-up sweep when the compiled backend loads.&lt;/p&gt;
&lt;span class=&quot;marginnote&quot; role=&quot;note&quot;&gt;The same byte-mindedness shows up in smaller knobs: resample index tensors are &lt;code&gt;int32&lt;/code&gt; rather than int64, halving their footprint (with an explicit raise the moment an index would exceed what 32 bits can address, rather than a silent overflow), and the returned simulation tensor can be requested in float32 while every model fit and every reduction stays &lt;code&gt;float64&lt;/code&gt;. Storage-dtype choices, both of them, made for traffic.&lt;/span&gt;
&lt;p&gt;From the outside it is one argument. The materializing call and the fused call take the same method spec and the same seed:&lt;/p&gt;
&lt;div class=&quot;codeblock&quot;&gt;&lt;div class=&quot;codeblock-head&quot;&gt;&lt;span class=&quot;lang&quot;&gt;python&lt;/span&gt;&lt;button type=&quot;button&quot; class=&quot;copy-btn&quot; data-copy aria-label=&quot;Copy code&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect width=&quot;14&quot; height=&quot;14&quot; x=&quot;8&quot; y=&quot;8&quot; rx=&quot;2&quot; ry=&quot;2&quot;&gt;&lt;/rect&gt;&lt;path d=&quot;M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span class=&quot;copy-label&quot;&gt;Copy&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark-default&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e6edf3;--shiki-light-bg:#fff;--shiki-dark-bg:#0d1117;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; numpy &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; np&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; tsbootstrap &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; MovingBlock, bootstrap, bootstrap_reduce&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;x &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; np.random.default_rng(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;).standard_normal(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;10_000&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#8B949E&quot;&gt;# the materializing path: every replicate, as arrays&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;res &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; bootstrap(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;    x, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;method&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;MovingBlock(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;block_length&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#A5D6FF&quot;&gt;&amp;quot;auto&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;    n_bootstraps&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;2_000&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;random_state&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#8B949E&quot;&gt;# the fused path: same resampling, one pass, only the statistic survives&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;red &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; bootstrap_reduce(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;    x, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;method&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;MovingBlock(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;block_length&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#A5D6FF&quot;&gt;&amp;quot;auto&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;statistic&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#A5D6FF&quot;&gt;&amp;quot;mean&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;    n_bootstraps&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;2_000&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;random_state&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;backend&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#A5D6FF&quot;&gt;&amp;quot;compiled&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;lo, hi &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; red.quantile(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;0.05&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;), red.quantile(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;0.95&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The memory consequence is not subtle. In a peak-memory sweep over &lt;em&gt;B&lt;/em&gt; (measured 2026-07-04 on version 0.4.0; the streaming path is unchanged since), holding the full replicate tensor at &lt;em&gt;B&lt;/em&gt; = 50,000 on an &lt;em&gt;n&lt;/em&gt; = 2,000 series cost &lt;strong&gt;1.94 GB&lt;/strong&gt;; the reduce path over the same fifty thousand replicates peaked at &lt;strong&gt;20 MB&lt;/strong&gt;, roughly 97x lighter. The reduce path’s peak grows with the number of statistics you keep, not with the length of the paths (&lt;em&gt;B&lt;/em&gt; rows of answers instead of &lt;em&gt;B&lt;/em&gt; full series, which is the whole point), so fifty thousand replicates stops being a capacity-planning question.&lt;/p&gt;
&lt;p&gt;Fusing the pass won the big workloads. It did not win everything. The cell it refused to win is where the second wall shows itself.&lt;/p&gt;
&lt;h2 id=&quot;wall-two-the-state-you-carry&quot;&gt;Wall two: the state you carry&lt;a class=&quot;heading-anchor&quot; href=&quot;#wall-two-the-state-you-carry&quot; aria-label=&quot;Link to this section&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After the fused kernel shipped, one benchmark cell refused to move: the smallest one, an i.i.d. resample (independent draws, no blocks, the simplest bootstrap there is) of a short series: 200 observations, 999 replicates. Still losing to the incumbent, run after run, while its neighbors fell by multiples. The cell’s total time held at 13.1 milliseconds like it was nailed there. A kernel this small finishes in microseconds; something else owned the clock. I finally profiled the &lt;em&gt;entire&lt;/em&gt; call, not the part I was proud of.&lt;/p&gt;
&lt;p&gt;The kernel was innocent. It was barely running.&lt;/p&gt;
&lt;p&gt;About &lt;strong&gt;95%&lt;/strong&gt; of that cell’s wall time was spent &lt;em&gt;before the kernel launched&lt;/em&gt;, in Python, setting up random-number seeds. And this is not a fixed dispatch cost: it is an O(&lt;em&gt;B&lt;/em&gt;) scaling tax, a serial object-allocation loop that dominates the clock on small jobs and grows linearly to tax the biggest ones before the kernel even starts.&lt;/p&gt;

&lt;figure class=&quot;full&quot; data-astro-cid-bj3fsypb&gt; &lt;video autoplay muted loop playsinline preload=&quot;none&quot; poster=&quot;/assets/terminal/tsb-03-derive-dont-carry.frame1.png&quot; aria-label=&quot;An animated loop that returns to this labelled still. A split screen runs the same job on both sides: 999 bootstrap replicates of a 200-observation series, each side with its own elapsed-time readout. On the left, labelled &apos;carry state&apos;, a conveyor stamps out seed objects one at a time with a running count toward 999 while the compute kernel sits greyed out and idle; a proportion bar shows about ninety-five percent of the elapsed time spent on the conveyor, and the readout stops at 13.1 milliseconds with a thin sliver marked as actual kernel compute. On the right, labelled &apos;derive state&apos;, there is no queue: a single 128-bit root key fans out to all replicate indices at once through a box labelled key of root and b, Philox-4x32-10, the same constants cuRAND ships, glossed as NVIDIA&apos;s GPU random number generator; the kernel lights immediately, the readout stops at 0.55 milliseconds, and a label reads checksum: identical. The freeze frame shows both elapsed times side by side with the scoped ratio 23.8x end-to-end at n equals 200 and the caption: the object list was the workload.&quot; class=&quot;has-portrait&quot; data-poster-portrait=&quot;/assets/terminal/tsb-03-derive-dont-carry.portrait.frame1.png&quot; data-astro-cid-bj3fsypb&gt; &lt;source src=&quot;https://thepragmaticquant.com/assets/terminal/tsb-03-derive-dont-carry.portrait.webm&quot; type=&quot;video/webm&quot; media=&quot;(max-width: 620px)&quot; data-astro-cid-bj3fsypb&gt; &lt;source src=&quot;https://thepragmaticquant.com/assets/terminal/tsb-03-derive-dont-carry.portrait.mp4&quot; type=&quot;video/mp4&quot; media=&quot;(max-width: 620px)&quot; data-astro-cid-bj3fsypb&gt; &lt;source src=&quot;https://thepragmaticquant.com/assets/terminal/tsb-03-derive-dont-carry.webm&quot; type=&quot;video/webm&quot; data-astro-cid-bj3fsypb&gt; &lt;source src=&quot;https://thepragmaticquant.com/assets/terminal/tsb-03-derive-dont-carry.mp4&quot; type=&quot;video/mp4&quot; data-astro-cid-bj3fsypb&gt; &lt;/video&gt; &lt;figcaption data-astro-cid-bj3fsypb&gt;The same workload, twice, in the state redesign&apos;s validation run. On the left the per-replicate seed objects are built one by one in Python before any resampling happens, about 95% of the elapsed time, while the kernel waits. On the right each replicate&apos;s key is a pure function of one root key and its own index, derived inside the kernel: 13.1 ms becomes 0.55 ms (23.8x end-to-end at n = 200) with identical kernel arithmetic.&lt;/figcaption&gt; &lt;details class=&quot;data-table&quot; data-astro-cid-bj3fsypb&gt; &lt;summary data-astro-cid-bj3fsypb&gt;data table&lt;/summary&gt;  &lt;div class=&quot;data-table-scroll&quot; data-astro-cid-bj3fsypb&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;design&lt;/th&gt;&lt;th&gt;state per stream&lt;/th&gt;&lt;th&gt;this cell (&lt;em&gt;n&lt;/em&gt; = 200, &lt;em&gt;B&lt;/em&gt; = 999)&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Mersenne Twister (the classic default)&lt;/td&gt;&lt;td&gt;~2.5 kB carried per stream&lt;/td&gt;&lt;td&gt;n/a&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;em&gt;B&lt;/em&gt; seed objects materialized in Python&lt;/td&gt;&lt;td&gt;one object per replicate, built serially&lt;/td&gt;&lt;td&gt;13.1 ms (~95% seed setup)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;keys derived in-kernel from one 128-bit root&lt;/td&gt;&lt;td&gt;none, a pure function of (root, replicate)&lt;/td&gt;&lt;td&gt;0.55 ms&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt; &lt;/details&gt; &lt;/figure&gt; 
&lt;p&gt;Reproducibility in tsbootstrap is a per-replicate contract: replicate i is bound to its own random stream, stable no matter how the work is chunked or how many threads run it. The obvious implementation is to materialize the streams: spawn &lt;em&gt;B&lt;/em&gt; seed objects up front, one per replicate, and hand them out. Correct, and O(&lt;em&gt;B&lt;/em&gt;) Python objects allocated on every call. For big workloads the kernel dwarfed it; for small ones the setup &lt;em&gt;was&lt;/em&gt; the runtime. We had stopped materializing the data tensor and were still materializing a tensor of state.&lt;/p&gt;
&lt;span class=&quot;marginnote&quot; role=&quot;note&quot;&gt;Terminology, one time: a PRNG, short for pseudorandom number generator, is the deterministic algorithm behind every “random” draw in scientific computing. Give it the same seed and it replays the same sequence, which is what makes a bootstrap reproducible at all.&lt;/span&gt;
&lt;p&gt;Wall two has two faces. The first is ordinary Python overhead: allocating &lt;em&gt;B&lt;/em&gt; objects, looping &lt;em&gt;B&lt;/em&gt; times, on every call. The second is deeper than Python, and it is the reason GPU people solved this a decade before we needed it. Conventional PRNGs are, in the words of the Random123 paper that changed that corner of computing, “designed as sequentially dependent state transformations”: each draw mutates a state block that the next draw depends on. State means memory: a Mersenne Twister instance drags around about 2.5 kB of it. Worse than the bytes is the sequencing. State that must evolve in order resists being handed to ten thousand independent workers.&lt;/p&gt;
&lt;p&gt;The alternative the Random123 authors proposed, counter-based generators that “require little or no memory for state,” inverts the design. Stop treating randomness as a machine you advance; treat it as a pure function: hand it a key and a counter, get back bits, no state anywhere. Any worker can compute draw &lt;em&gt;k&lt;/em&gt; of stream &lt;em&gt;b&lt;/em&gt; without computing any other draw first.&lt;/p&gt;
&lt;p&gt;So we deleted the seed objects, and the nailed-down cell fell: &lt;strong&gt;13.1 ms before, 0.55 ms after&lt;/strong&gt;, on the same box in the redesign’s validation run, with identical kernel arithmetic. Nothing about the math changed. The setup work simply no longer exists.&lt;/p&gt;
&lt;p&gt;Here is what replaced it. The executor now takes a single 128-bit root key and the replicate count, and each backend derives its streams from there; inside the compiled kernel, each replicate’s key is computed from the root and the replicate index by a few integer mixing rounds: nothing allocated, nothing carried, no Python in sight. Our disease was Pythonic, object-allocation cost rather than per-thread kilobytes, but it was exactly the disease Random123 diagnosed: state carried in sequence where a pure function should be. The key for replicate &lt;em&gt;b&lt;/em&gt; is now a pure function of (root, &lt;em&gt;b&lt;/em&gt;); any specific draw is a pure function of that key and a counter. That sentence is the whole design, and its consequences are the guarantees: run the replicates on one thread or eight, in any order, and the output is bitwise identical, because there is no shared state for a schedule to touch. That guarantee is not pedantry: it is what makes a CI failure mean a real regression rather than thread-schedule noise, and what lets a published interval replay byte for byte months later on a machine with a different core count.&lt;/p&gt;
&lt;p&gt;The generator doing the drawing deserves its precise name. The compiled kernels run Philox-4x32-10, the counter-based generator from that same Random123 paper (Salmon et al., SC 2011): ten rounds, the canonical multiplier constants. It is the identical algorithm, with the identical constants, that NVIDIA ships as cuRAND’s Philox device generator, and the same splittable-key philosophy JAX built its entire random API around. The 32-bit variant was chosen deliberately so the integer index streams can one day be made bit-identical between this CPU kernel and an array-backend GPU port. A statistics library on a laptop and a datacenter training run, drawing their randomness from the same ten rounds of the same function, for the same reason: state does not parallelize; functions do. None of this touches the default: the shipping default backend is unchanged and byte-for-byte compatible with previous releases, and the Philox path is opt-in via &lt;code&gt;backend=&amp;quot;compiled&amp;quot;&lt;/code&gt;: equal to the default in distribution, not bit-identical to it.&lt;/p&gt;
&lt;p&gt;A hand-rolled generator inside a compiled kernel is also exactly the kind of code that fails silently: a wrong-but-plausible RNG sails through smoke tests and quietly skews every interval you ever publish. So the kernel is never trusted on its own word. The key-derivation math lives twice (once inside the kernel, once in a deliberately slow, dependency-free reference module that takes a different arithmetic path), so a bug in one implementation cannot hide behind agreement with itself; the round function is pinned against the published Random123 known-answer vectors (the paper’s own input-output pairs, which the algorithm must reproduce exactly); and the fused, materializing, and index-only paths all share one index-generation code path, so they cannot drift apart per seed.&lt;/p&gt;
&lt;span class=&quot;marginnote&quot; role=&quot;note&quot;&gt;The default backend’s own machinery: plain NumPy PCG64 streams, one per replicate; even its chunking uses a fixed chunk size (never derived from available RAM), so accumulation order and results cannot vary across machines. And the compiled path raises loudly if the compiled extra is missing rather than falling back silently.&lt;/span&gt;
&lt;h2 id=&quot;two-optimizations-we-measured-and-deleted&quot;&gt;Two optimizations we measured and deleted&lt;a class=&quot;heading-anchor&quot; href=&quot;#two-optimizations-we-measured-and-deleted&quot; aria-label=&quot;Link to this section&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The rebuild was not a straight line. Two other ideas were measured during development, on the development machine, and both were reverted; the verdicts, not the multipliers, are what matters.&lt;/p&gt;




















&lt;div class=&quot;table-scroll&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;hypothesis&lt;/th&gt;&lt;th&gt;verdict&lt;/th&gt;&lt;th&gt;why&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;shared scratch: pre-allocate one buffer block per chunk of replicates instead of per-work-item temporaries&lt;/td&gt;&lt;td&gt;implemented, proven bitwise-identical, net regression on every cell, reverted&lt;/td&gt;&lt;td&gt;the allocator was already pooling per-iteration buffers; the shared scratch defeated SIMD auto-vectorization&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;cache-blocked gather: sort or tile the resample reads for locality&lt;/td&gt;&lt;td&gt;every locality fix measured as a net loss, disqualified&lt;/td&gt;&lt;td&gt;the stall is bandwidth-bound, and any reorder breaks bitwise identity&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;The shared scratch was classic advice (allocation is overhead, pooling is virtue), and it lost even single-threaded, because the JIT runtime already pools small per-iteration allocations, and rows of a shared block are strided views (rows spaced apart in memory rather than contiguous), which the auto-vectorizer, the compiler pass that processes several array elements per instruction, refuses to touch. The cache-blocked gather’s diagnosis even measured out (the gather really is memory-stall-bound), but every locality-improving reorder cost more in bookkeeping than it recovered in bandwidth, and because floating-point addition is not associative, reordering the accumulation changes the last bits of the result, which the bitwise-reproducibility contract forbids.&lt;/p&gt;
&lt;p&gt;Both hypotheses were plausible enough that a design debate would have shipped them. The measurements killed them in an afternoon, and both verdicts are pinned so neither gets re-attempted. Burying an idea is far cheaper than maintaining one.&lt;/p&gt;
&lt;h2 id=&quot;the-scoreboard-losses-included&quot;&gt;The scoreboard, losses included&lt;a class=&quot;heading-anchor&quot; href=&quot;#the-scoreboard-losses-included&quot; aria-label=&quot;Link to this section&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Everything above was measured on dedicated hardware so the numbers mean something: 8-core AMD EPYC Milan cloud instances with dedicated vCPUs, 30 GB of RAM, Ubuntu 24.04 (kernel 6.8), exact package versions pinned in each run’s committed manifest. Sixteen cells: the observation-resampling methods crossed with a range of series lengths and replicate counts, our fused reduce path against the incumbent’s equivalent loop. Every cell’s time is the median of 15 settled timed runs after an explicit warm-up, on the shipping versions of both libraries (tsbootstrap 0.6.1 against arch 8.0.0), one receipt, measured 2026-07-11.&lt;/p&gt;
&lt;p&gt;All sixteen cells favor the fused path, and the concession below holds beside them. On the sustained workloads (the longer series where the engines are past their fixed overheads) the settled grid holds &lt;strong&gt;3.1x to 20x&lt;/strong&gt;. The settled timing exists because single-draw timing failed us first: when we re-timed the grid with one draw per cell, the incumbent’s own control numbers moved 22 to 74 percent between runs of identical code on identical instance types (the box noise exceeded the effect), so nothing measured single-draw is quoted here. The smallest cells post far larger multiples still, and we do not quote them either: at that size the comparison measures the incumbent’s per-replicate dispatch overhead as much as it measures our kernel.&lt;/p&gt;
&lt;p&gt;One more disclosure that belongs next to the range: the fused path runs parallel across all eight cores, and the incumbent’s loop is single-threaded by construction. That concurrency is part of what the fused design buys, not a handicap we imposed on the comparison, but you should know the multiple contains it.&lt;/p&gt;
&lt;p&gt;And one path still loses. If you want the full &lt;code&gt;(B, n, d)&lt;/code&gt; replicate tensor as plain NumPy arrays (the materializing path, the thing the whole article is about not doing), the incumbent’s loop is faster than our default path in every cell of the grid, by 1.2x to 3.1x on the settled 2026-07-11 grid, depending on the cell. That row is a design position, printed with the rest. Materializing is the incumbent’s home game, and it plays it well; we spent our budget on the path where the statistic is the product, because for the statistic-shaped questions a bootstrap exists to answer, nobody needed the tensor in the first place.&lt;/p&gt;

&lt;figure class=&quot;full&quot; data-astro-cid-bj3fsypb&gt; &lt;div class=&quot;svgfig svgfig-chart&quot; role=&quot;img&quot; aria-label=&quot;Horizontal chart of benchmark results across sixteen workload cells, all series from the settled grid measured 2026-07-11 on a dedicated cloud benchmark box, each cell the median of 15 settled timed runs. Each row is one cell; a bold vertical rule marks parity, labelled arch equals 1.0x, and the horizontal axis reads speedup over arch&apos;s per-replicate loop. Filled dots for the fused reduce path sit right of parity in every row, with the sustained large-series cells spanning 3.1x to 20x; two short-workload cells render as capped arrows at the axis edge, annotated that their multiples partly measure the incumbent&apos;s per-replicate overhead, and every n equals 200 row carries a dagger pointing to a short-workloads dispatch-overhead footnote. Squares for the tsbootstrap default numpy path sit left of parity in every row (the legend states it loses in all sixteen cells, and an annotation anchored to the orange cluster repeats that each square is a cell we lose), marking the configuration where the incumbent is faster, by 1.2x to 3.1x. The once-stubborn smallest cell carries a badge reading state redesign: 13.1 milliseconds to 0.55 milliseconds, see companion figure.&quot; data-astro-cid-bj3fsypb&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; width=&quot;928&quot; id=&quot;fig-tsb-03-results-grid&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 928 1104&quot; role=&quot;img&quot; aria-label=&quot;results grid: speedup vs the incumbent across sixteen benchmark cells&quot;&gt;&lt;style&gt;#fig-tsb-03-results-grid [fill=&quot;#1a1d23&quot; i]{fill:var(--bg)}#fig-tsb-03-results-grid [stroke=&quot;#1a1d23&quot; i]{stroke:var(--bg)}#fig-tsb-03-results-grid [fill=&quot;#18181b&quot; i]{fill:var(--bg-panel)}#fig-tsb-03-results-grid [stroke=&quot;#18181b&quot; i]{stroke:var(--bg-panel)}#fig-tsb-03-results-grid [fill=&quot;#2c2f37&quot; i]{fill:var(--current-line)}#fig-tsb-03-results-grid [stroke=&quot;#2c2f37&quot; i]{stroke:var(--current-line)}#fig-tsb-03-results-grid [fill=&quot;#f4f5f7&quot; i]{fill:var(--fg)}#fig-tsb-03-results-grid [stroke=&quot;#f4f5f7&quot; i]{stroke:var(--fg)}#fig-tsb-03-results-grid [fill=&quot;#8a8f98&quot; i]{fill:var(--comment)}#fig-tsb-03-results-grid [stroke=&quot;#8a8f98&quot; i]{stroke:var(--comment)}&lt;/style&gt;
&lt;rect width=&quot;928&quot; height=&quot;1104&quot; fill=&quot;#1a1d23&quot;/&gt;
&lt;style&gt;
    :where(#trg-root) text { font-family: var(--mono); fill: var(--fg); }
    .trg-title { font-size: 24px; font-weight: bold; }
    .trg-sub { font-size: 18px; fill: var(--comment); }
    .trg-hdr { font-size: 19px; font-weight: bold; }
    .trg-row { font-size: 18px; fill: var(--comment); dominant-baseline: middle; }
    .trg-leg { font-size: 18px; dominant-baseline: middle; }
    .trg-tick { font-size: 18px; fill: var(--comment); }
    .trg-tickb { font-size: 18px; fill: var(--fg); font-weight: bold; }
    .trg-grid { stroke: var(--current-line); stroke-width: 1; }
    .trg-parity { stroke: var(--fg); stroke-width: 2.5; }
    .trg-rowline { stroke: var(--current-line); stroke-width: 0.75; }
    .trg-red { fill: #56b4e9; }
    .trg-val { fill: var(--bg); stroke: #56b4e9; stroke-width: 2; }
    .trg-np { fill: #e69f00; }
    .trg-arrow { stroke: #56b4e9; stroke-width: 3; }
    .trg-arrowhead { fill: #56b4e9; }
    .trg-badge { font-size: 18px; font-weight: bold; dominant-baseline: middle; }
    .trg-badgebg { fill: var(--bg); stroke: #56b4e9; stroke-width: 1; }
    .trg-note { font-size: 18px; fill: var(--comment); }
    .trg-ann { font-size: 18px; font-weight: bold; fill: #e69f00; }
    .trg-annline { stroke: #e69f00; stroke-width: 1.5; stroke-dasharray: 4 4; }
    .trg-atitle { font-size: 18px; font-weight: bold; }
&lt;/style&gt;
&lt;g id=&quot;trg-root&quot;&gt;
&lt;text class=&quot;trg-title&quot; x=&quot;24&quot; y=&quot;38&quot;&gt;Sixteen cells, wins and losses on one axis&lt;/text&gt;
&lt;text class=&quot;trg-sub&quot; x=&quot;24&quot; y=&quot;64&quot;&gt;vs the incumbent&amp;#8217;s per-replicate loop, log scale&lt;/text&gt;
&lt;text class=&quot;trg-sub&quot; x=&quot;24&quot; y=&quot;86&quot;&gt;right of parity = tsbootstrap faster&lt;/text&gt;
&lt;text class=&quot;trg-sub&quot; x=&quot;24&quot; y=&quot;108&quot;&gt;all series from the settled 2026-07-11 grid: median of 15 timed runs,&lt;/text&gt;
&lt;text class=&quot;trg-sub&quot; x=&quot;24&quot; y=&quot;130&quot;&gt;dedicated box &amp;#183; n = series length &amp;#183; B = replicates&lt;/text&gt;

&lt;circle class=&quot;trg-red&quot; cx=&quot;34&quot; cy=&quot;156&quot; r=&quot;6&quot;/&gt;
&lt;text class=&quot;trg-leg&quot; x=&quot;46&quot; y=&quot;161&quot;&gt;compiled reduce (fused path)&lt;/text&gt;
&lt;circle class=&quot;trg-val&quot; cx=&quot;390&quot; cy=&quot;156&quot; r=&quot;5.5&quot;/&gt;
&lt;text class=&quot;trg-leg&quot; x=&quot;402&quot; y=&quot;161&quot;&gt;compiled, full arrays&lt;/text&gt;
&lt;rect class=&quot;trg-np&quot; x=&quot;29&quot; y=&quot;175&quot; width=&quot;10&quot; height=&quot;10&quot;/&gt;
&lt;text class=&quot;trg-leg&quot; x=&quot;46&quot; y=&quot;185&quot;&gt;tsbootstrap default numpy path: loses in all 16 cells (left of parity)&lt;/text&gt;

&lt;line class=&quot;trg-grid&quot; x1=&quot;289.0&quot; y1=&quot;226&quot; x2=&quot;289.0&quot; y2=&quot;826&quot;/&gt;
&lt;text class=&quot;trg-tick&quot; text-anchor=&quot;middle&quot; x=&quot;289.0&quot; y=&quot;848&quot;&gt;0.5x&lt;/text&gt;
&lt;line class=&quot;trg-parity&quot; x1=&quot;378.7&quot; y1=&quot;226&quot; x2=&quot;378.7&quot; y2=&quot;826&quot;/&gt;
&lt;text class=&quot;trg-tickb&quot; text-anchor=&quot;middle&quot; x=&quot;378.7&quot; y=&quot;848&quot;&gt;arch = 1.0x&lt;/text&gt;
&lt;line class=&quot;trg-grid&quot; x1=&quot;468.4&quot; y1=&quot;226&quot; x2=&quot;468.4&quot; y2=&quot;826&quot;/&gt;
&lt;text class=&quot;trg-tick&quot; text-anchor=&quot;middle&quot; x=&quot;468.4&quot; y=&quot;848&quot;&gt;2x&lt;/text&gt;
&lt;line class=&quot;trg-grid&quot; x1=&quot;586.9&quot; y1=&quot;226&quot; x2=&quot;586.9&quot; y2=&quot;826&quot;/&gt;
&lt;text class=&quot;trg-tick&quot; text-anchor=&quot;middle&quot; x=&quot;586.9&quot; y=&quot;848&quot;&gt;5x&lt;/text&gt;
&lt;line class=&quot;trg-grid&quot; x1=&quot;676.6&quot; y1=&quot;226&quot; x2=&quot;676.6&quot; y2=&quot;826&quot;/&gt;
&lt;text class=&quot;trg-tick&quot; text-anchor=&quot;middle&quot; x=&quot;676.6&quot; y=&quot;848&quot;&gt;10x&lt;/text&gt;
&lt;line class=&quot;trg-grid&quot; x1=&quot;766.3&quot; y1=&quot;226&quot; x2=&quot;766.3&quot; y2=&quot;826&quot;/&gt;
&lt;text class=&quot;trg-tick&quot; text-anchor=&quot;middle&quot; x=&quot;766.3&quot; y=&quot;848&quot;&gt;20x&lt;/text&gt;
&lt;line class=&quot;trg-grid&quot; x1=&quot;856.0&quot; y1=&quot;226&quot; x2=&quot;856.0&quot; y2=&quot;826&quot;/&gt;
&lt;text class=&quot;trg-tick&quot; text-anchor=&quot;middle&quot; x=&quot;856.0&quot; y=&quot;848&quot;&gt;40x&lt;/text&gt;
&lt;text class=&quot;trg-hdr&quot; x=&quot;24&quot; y=&quot;240&quot;&gt;i.i.d.&lt;/text&gt;
&lt;line class=&quot;trg-rowline&quot; x1=&quot;214&quot; y1=&quot;265&quot; x2=&quot;856&quot; y2=&quot;265&quot;/&gt;
&lt;text class=&quot;trg-row&quot; text-anchor=&quot;end&quot; x=&quot;202&quot; y=&quot;265&quot;&gt;&amp;#8224; n=200 B=999&lt;/text&gt;
&lt;rect class=&quot;trg-np&quot; x=&quot;277.7&quot; y=&quot;260&quot; width=&quot;10&quot; height=&quot;10&quot;/&gt;
&lt;circle class=&quot;trg-val&quot; cx=&quot;471.0&quot; cy=&quot;265&quot; r=&quot;5.5&quot;/&gt;
&lt;circle class=&quot;trg-red&quot; cx=&quot;724.6&quot; cy=&quot;265&quot; r=&quot;6&quot;/&gt;
&lt;line class=&quot;trg-rowline&quot; x1=&quot;214&quot; y1=&quot;295&quot; x2=&quot;856&quot; y2=&quot;295&quot;/&gt;
&lt;text class=&quot;trg-row&quot; text-anchor=&quot;end&quot; x=&quot;202&quot; y=&quot;295&quot;&gt;&amp;#8224; n=200 B=10,000&lt;/text&gt;
&lt;rect class=&quot;trg-np&quot; x=&quot;243.3&quot; y=&quot;290&quot; width=&quot;10&quot; height=&quot;10&quot;/&gt;
&lt;circle class=&quot;trg-val&quot; cx=&quot;518.2&quot; cy=&quot;295&quot; r=&quot;5.5&quot;/&gt;
&lt;circle class=&quot;trg-red&quot; cx=&quot;756.5&quot; cy=&quot;295&quot; r=&quot;6&quot;/&gt;
&lt;line class=&quot;trg-rowline&quot; x1=&quot;214&quot; y1=&quot;325&quot; x2=&quot;856&quot; y2=&quot;325&quot;/&gt;
&lt;text class=&quot;trg-row&quot; text-anchor=&quot;end&quot; x=&quot;202&quot; y=&quot;325&quot;&gt;n=2,000 B=999&lt;/text&gt;
&lt;rect class=&quot;trg-np&quot; x=&quot;271.1&quot; y=&quot;320&quot; width=&quot;10&quot; height=&quot;10&quot;/&gt;
&lt;circle class=&quot;trg-val&quot; cx=&quot;390.7&quot; cy=&quot;325&quot; r=&quot;5.5&quot;/&gt;
&lt;circle class=&quot;trg-red&quot; cx=&quot;528.2&quot; cy=&quot;325&quot; r=&quot;6&quot;/&gt;
&lt;line class=&quot;trg-rowline&quot; x1=&quot;214&quot; y1=&quot;355&quot; x2=&quot;856&quot; y2=&quot;355&quot;/&gt;
&lt;text class=&quot;trg-row&quot; text-anchor=&quot;end&quot; x=&quot;202&quot; y=&quot;355&quot;&gt;n=2,000 B=10,000&lt;/text&gt;
&lt;rect class=&quot;trg-np&quot; x=&quot;247.1&quot; y=&quot;350&quot; width=&quot;10&quot; height=&quot;10&quot;/&gt;
&lt;circle class=&quot;trg-val&quot; cx=&quot;448.5&quot; cy=&quot;355&quot; r=&quot;5.5&quot;/&gt;
&lt;circle class=&quot;trg-red&quot; cx=&quot;652.6&quot; cy=&quot;355&quot; r=&quot;6&quot;/&gt;
&lt;text class=&quot;trg-hdr&quot; x=&quot;24&quot; y=&quot;390&quot;&gt;moving block&lt;/text&gt;
&lt;line class=&quot;trg-rowline&quot; x1=&quot;214&quot; y1=&quot;415&quot; x2=&quot;856&quot; y2=&quot;415&quot;/&gt;
&lt;text class=&quot;trg-row&quot; text-anchor=&quot;end&quot; x=&quot;202&quot; y=&quot;415&quot;&gt;&amp;#8224; n=200 B=999&lt;/text&gt;
&lt;rect class=&quot;trg-np&quot; x=&quot;323.0&quot; y=&quot;410&quot; width=&quot;10&quot; height=&quot;10&quot;/&gt;
&lt;circle class=&quot;trg-val&quot; cx=&quot;587.8&quot; cy=&quot;415&quot; r=&quot;5.5&quot;/&gt;
&lt;circle class=&quot;trg-red&quot; cx=&quot;833.1&quot; cy=&quot;415&quot; r=&quot;6&quot;/&gt;
&lt;line class=&quot;trg-rowline&quot; x1=&quot;214&quot; y1=&quot;445&quot; x2=&quot;856&quot; y2=&quot;445&quot;/&gt;
&lt;text class=&quot;trg-row&quot; text-anchor=&quot;end&quot; x=&quot;202&quot; y=&quot;445&quot;&gt;&amp;#8224; n=200 B=10,000&lt;/text&gt;
&lt;rect class=&quot;trg-np&quot; x=&quot;274.7&quot; y=&quot;440&quot; width=&quot;10&quot; height=&quot;10&quot;/&gt;
&lt;circle class=&quot;trg-val&quot; cx=&quot;582.9&quot; cy=&quot;445&quot; r=&quot;5.5&quot;/&gt;
&lt;line class=&quot;trg-arrow&quot; x1=&quot;822.0&quot; y1=&quot;445&quot; x2=&quot;849.0&quot; y2=&quot;445&quot;/&gt;
&lt;path class=&quot;trg-arrowhead&quot; d=&quot;M 856.0 445 l -9 -5 l 0 10 z&quot;/&gt;
&lt;line class=&quot;trg-rowline&quot; x1=&quot;214&quot; y1=&quot;475&quot; x2=&quot;856&quot; y2=&quot;475&quot;/&gt;
&lt;text class=&quot;trg-row&quot; text-anchor=&quot;end&quot; x=&quot;202&quot; y=&quot;475&quot;&gt;n=2,000 B=999&lt;/text&gt;
&lt;rect class=&quot;trg-np&quot; x=&quot;338.8&quot; y=&quot;470&quot; width=&quot;10&quot; height=&quot;10&quot;/&gt;
&lt;circle class=&quot;trg-val&quot; cx=&quot;508.1&quot; cy=&quot;475&quot; r=&quot;5.5&quot;/&gt;
&lt;circle class=&quot;trg-red&quot; cx=&quot;670.9&quot; cy=&quot;475&quot; r=&quot;6&quot;/&gt;
&lt;line class=&quot;trg-rowline&quot; x1=&quot;214&quot; y1=&quot;505&quot; x2=&quot;856&quot; y2=&quot;505&quot;/&gt;
&lt;text class=&quot;trg-row&quot; text-anchor=&quot;end&quot; x=&quot;202&quot; y=&quot;505&quot;&gt;n=2,000 B=10,000&lt;/text&gt;
&lt;rect class=&quot;trg-np&quot; x=&quot;264.8&quot; y=&quot;500&quot; width=&quot;10&quot; height=&quot;10&quot;/&gt;
&lt;circle class=&quot;trg-val&quot; cx=&quot;471.2&quot; cy=&quot;505&quot; r=&quot;5.5&quot;/&gt;
&lt;circle class=&quot;trg-red&quot; cx=&quot;753.4&quot; cy=&quot;505&quot; r=&quot;6&quot;/&gt;
&lt;text class=&quot;trg-hdr&quot; x=&quot;24&quot; y=&quot;540&quot;&gt;circular block&lt;/text&gt;
&lt;line class=&quot;trg-rowline&quot; x1=&quot;214&quot; y1=&quot;565&quot; x2=&quot;856&quot; y2=&quot;565&quot;/&gt;
&lt;text class=&quot;trg-row&quot; text-anchor=&quot;end&quot; x=&quot;202&quot; y=&quot;565&quot;&gt;&amp;#8224; n=200 B=999&lt;/text&gt;
&lt;rect class=&quot;trg-np&quot; x=&quot;333.0&quot; y=&quot;560&quot; width=&quot;10&quot; height=&quot;10&quot;/&gt;
&lt;circle class=&quot;trg-val&quot; cx=&quot;598.1&quot; cy=&quot;565&quot; r=&quot;5.5&quot;/&gt;
&lt;circle class=&quot;trg-red&quot; cx=&quot;845.5&quot; cy=&quot;565&quot; r=&quot;6&quot;/&gt;
&lt;line class=&quot;trg-rowline&quot; x1=&quot;214&quot; y1=&quot;595&quot; x2=&quot;856&quot; y2=&quot;595&quot;/&gt;
&lt;text class=&quot;trg-row&quot; text-anchor=&quot;end&quot; x=&quot;202&quot; y=&quot;595&quot;&gt;&amp;#8224; n=200 B=10,000&lt;/text&gt;
&lt;rect class=&quot;trg-np&quot; x=&quot;286.6&quot; y=&quot;590&quot; width=&quot;10&quot; height=&quot;10&quot;/&gt;
&lt;circle class=&quot;trg-val&quot; cx=&quot;601.8&quot; cy=&quot;595&quot; r=&quot;5.5&quot;/&gt;
&lt;line class=&quot;trg-arrow&quot; x1=&quot;822.0&quot; y1=&quot;595&quot; x2=&quot;849.0&quot; y2=&quot;595&quot;/&gt;
&lt;path class=&quot;trg-arrowhead&quot; d=&quot;M 856.0 595 l -9 -5 l 0 10 z&quot;/&gt;
&lt;line class=&quot;trg-rowline&quot; x1=&quot;214&quot; y1=&quot;625&quot; x2=&quot;856&quot; y2=&quot;625&quot;/&gt;
&lt;text class=&quot;trg-row&quot; text-anchor=&quot;end&quot; x=&quot;202&quot; y=&quot;625&quot;&gt;n=2,000 B=999&lt;/text&gt;
&lt;rect class=&quot;trg-np&quot; x=&quot;353.4&quot; y=&quot;620&quot; width=&quot;10&quot; height=&quot;10&quot;/&gt;
&lt;circle class=&quot;trg-val&quot; cx=&quot;550.7&quot; cy=&quot;625&quot; r=&quot;5.5&quot;/&gt;
&lt;circle class=&quot;trg-red&quot; cx=&quot;706.3&quot; cy=&quot;625&quot; r=&quot;6&quot;/&gt;
&lt;line class=&quot;trg-rowline&quot; x1=&quot;214&quot; y1=&quot;655&quot; x2=&quot;856&quot; y2=&quot;655&quot;/&gt;
&lt;text class=&quot;trg-row&quot; text-anchor=&quot;end&quot; x=&quot;202&quot; y=&quot;655&quot;&gt;n=2,000 B=10,000&lt;/text&gt;
&lt;rect class=&quot;trg-np&quot; x=&quot;291.3&quot; y=&quot;650&quot; width=&quot;10&quot; height=&quot;10&quot;/&gt;
&lt;circle class=&quot;trg-val&quot; cx=&quot;510.2&quot; cy=&quot;655&quot; r=&quot;5.5&quot;/&gt;
&lt;circle class=&quot;trg-red&quot; cx=&quot;779.1&quot; cy=&quot;655&quot; r=&quot;6&quot;/&gt;
&lt;text class=&quot;trg-hdr&quot; x=&quot;24&quot; y=&quot;690&quot;&gt;stationary block&lt;/text&gt;
&lt;line class=&quot;trg-rowline&quot; x1=&quot;214&quot; y1=&quot;715&quot; x2=&quot;856&quot; y2=&quot;715&quot;/&gt;
&lt;text class=&quot;trg-row&quot; text-anchor=&quot;end&quot; x=&quot;202&quot; y=&quot;715&quot;&gt;&amp;#8224; n=200 B=999&lt;/text&gt;
&lt;rect class=&quot;trg-np&quot; x=&quot;261.0&quot; y=&quot;710&quot; width=&quot;10&quot; height=&quot;10&quot;/&gt;
&lt;circle class=&quot;trg-val&quot; cx=&quot;575.2&quot; cy=&quot;715&quot; r=&quot;5.5&quot;/&gt;
&lt;circle class=&quot;trg-red&quot; cx=&quot;747.8&quot; cy=&quot;715&quot; r=&quot;6&quot;/&gt;
&lt;line class=&quot;trg-rowline&quot; x1=&quot;214&quot; y1=&quot;745&quot; x2=&quot;856&quot; y2=&quot;745&quot;/&gt;
&lt;text class=&quot;trg-row&quot; text-anchor=&quot;end&quot; x=&quot;202&quot; y=&quot;745&quot;&gt;&amp;#8224; n=200 B=10,000&lt;/text&gt;
&lt;rect class=&quot;trg-np&quot; x=&quot;226.1&quot; y=&quot;740&quot; width=&quot;10&quot; height=&quot;10&quot;/&gt;
&lt;circle class=&quot;trg-val&quot; cx=&quot;563.2&quot; cy=&quot;745&quot; r=&quot;5.5&quot;/&gt;
&lt;circle class=&quot;trg-red&quot; cx=&quot;764.6&quot; cy=&quot;745&quot; r=&quot;6&quot;/&gt;
&lt;line class=&quot;trg-rowline&quot; x1=&quot;214&quot; y1=&quot;775&quot; x2=&quot;856&quot; y2=&quot;775&quot;/&gt;
&lt;text class=&quot;trg-row&quot; text-anchor=&quot;end&quot; x=&quot;202&quot; y=&quot;775&quot;&gt;n=2,000 B=999&lt;/text&gt;
&lt;rect class=&quot;trg-np&quot; x=&quot;272.9&quot; y=&quot;770&quot; width=&quot;10&quot; height=&quot;10&quot;/&gt;
&lt;circle class=&quot;trg-val&quot; cx=&quot;502.7&quot; cy=&quot;775&quot; r=&quot;5.5&quot;/&gt;
&lt;circle class=&quot;trg-red&quot; cx=&quot;577.3&quot; cy=&quot;775&quot; r=&quot;6&quot;/&gt;
&lt;line class=&quot;trg-rowline&quot; x1=&quot;214&quot; y1=&quot;805&quot; x2=&quot;856&quot; y2=&quot;805&quot;/&gt;
&lt;text class=&quot;trg-row&quot; text-anchor=&quot;end&quot; x=&quot;202&quot; y=&quot;805&quot;&gt;n=2,000 B=10,000&lt;/text&gt;
&lt;rect class=&quot;trg-np&quot; x=&quot;246.6&quot; y=&quot;800&quot; width=&quot;10&quot; height=&quot;10&quot;/&gt;
&lt;circle class=&quot;trg-val&quot; cx=&quot;508.0&quot; cy=&quot;805&quot; r=&quot;5.5&quot;/&gt;
&lt;circle class=&quot;trg-red&quot; cx=&quot;695.1&quot; cy=&quot;805&quot; r=&quot;6&quot;/&gt;
&lt;rect class=&quot;trg-badgebg&quot; x=&quot;283&quot; y=&quot;228&quot; width=&quot;621&quot; height=&quot;28&quot; rx=&quot;4&quot;/&gt;
&lt;text class=&quot;trg-badge&quot; x=&quot;291&quot; y=&quot;242&quot;&gt;state redesign: 13.1 ms &amp;#8594; 0.55 ms &amp;#8212; see companion figure&lt;/text&gt;

&lt;line class=&quot;trg-annline&quot; x1=&quot;251.6&quot; y1=&quot;813&quot; x2=&quot;110&quot; y2=&quot;860&quot;/&gt;
&lt;rect class=&quot;trg-np&quot; x=&quot;24&quot; y=&quot;866&quot; width=&quot;10&quot; height=&quot;10&quot;/&gt;
&lt;text class=&quot;trg-ann&quot; x=&quot;42&quot; y=&quot;876&quot;&gt;a cell we lose,&lt;/text&gt;
&lt;text class=&quot;trg-ann&quot; x=&quot;42&quot; y=&quot;898&quot;&gt;in every row&lt;/text&gt;

&lt;text class=&quot;trg-atitle&quot; text-anchor=&quot;middle&quot; x=&quot;510&quot; y=&quot;940&quot;&gt;speedup over arch&amp;#8217;s per-replicate loop (log scale, clipped near 40x)&lt;/text&gt;
&lt;text class=&quot;trg-note&quot; x=&quot;24&quot; y=&quot;976&quot;&gt;&amp;#9654; capped arrows: short-workload cells beyond the 40x clip;&lt;/text&gt;
&lt;text class=&quot;trg-note&quot; x=&quot;24&quot; y=&quot;998&quot;&gt;their multiples partly measure the incumbent&amp;#8217;s per-replicate&lt;/text&gt;
&lt;text class=&quot;trg-note&quot; x=&quot;24&quot; y=&quot;1020&quot;&gt;dispatch overhead, so no on-axis positions are given.&lt;/text&gt;
&lt;text class=&quot;trg-note&quot; x=&quot;24&quot; y=&quot;1048&quot;&gt;&amp;#8224; short workloads (n=200): the multiple includes&lt;/text&gt;
&lt;text class=&quot;trg-note&quot; x=&quot;24&quot; y=&quot;1070&quot;&gt;the incumbent&amp;#8217;s dispatch overhead.&lt;/text&gt;
&lt;/g&gt;
&lt;/svg&gt;
&lt;/div&gt; &lt;figcaption data-astro-cid-bj3fsypb&gt;The grid, wins and losses on one chart, every series from the settled 2026-07-11 grid (median of 15 timed runs per cell). Fused reduce path: all sixteen cells favor tsbootstrap, 3.1x to 20x on the sustained workloads, a multiple that includes the fused path&apos;s eight-core parallelism against the incumbent&apos;s single-threaded loop. The squares left of parity are the concession: ask for the full replicate tensor on the default path and the incumbent is faster in every cell.&lt;/figcaption&gt; &lt;details class=&quot;data-table&quot; data-astro-cid-bj3fsypb&gt; &lt;summary data-astro-cid-bj3fsypb&gt;data table&lt;/summary&gt;  &lt;div class=&quot;data-table-scroll&quot; data-astro-cid-bj3fsypb&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;path&lt;/th&gt;&lt;th&gt;cells&lt;/th&gt;&lt;th&gt;result&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;fused reduce (compiled, parallel across 8 cores; the incumbent’s loop is single-threaded)&lt;/td&gt;&lt;td&gt;16 / 16&lt;/td&gt;&lt;td&gt;3.1x to 20x sustained on the settled 2026-07-11 grid, median of 15 timed runs per cell&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;the once-stubborn cell (i.i.d., &lt;em&gt;n&lt;/em&gt; = 200, &lt;em&gt;B&lt;/em&gt; = 999)&lt;/td&gt;&lt;td&gt;n/a&lt;/td&gt;&lt;td&gt;13.1 ms -&amp;gt; 0.55 ms in the state-redesign validation run (0.49 ms in the settled grid’s own timing)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;materializing path (default backend)&lt;/td&gt;&lt;td&gt;0 / 16&lt;/td&gt;&lt;td&gt;incumbent faster in every cell, 1.2x to 3.1x&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt; &lt;/details&gt; &lt;/figure&gt; 

&lt;figure class=&quot;full&quot; data-astro-cid-bj3fsypb&gt; &lt;div class=&quot;svgfig svgfig-chart&quot; role=&quot;img&quot; aria-label=&quot;Grouped bar chart comparing two ways of running the same bootstrap workload, labeled materialize and fused, measured 2026-07-11 with hardware performance counters, empty-loop baseline subtracted. Cache references per iteration: 159 million materialized against 5.8 million fused, a factor of 27. Cache misses per iteration: 6.2 million against 53 thousand, a factor of 116. Data-TLB misses: 47 thousand against 138, a factor of 342. A derived panel shows the L1 data-cache miss rate at 8.6 percent for the materializing path against 2.9 percent fused, and a second panel below it shows peak resident memory at 617 megabytes against 234, where 234 megabytes is the bare process baseline.&quot; data-astro-cid-bj3fsypb&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; width=&quot;928&quot; id=&quot;fig-tsb-03-cache-counters&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 928 732&quot; role=&quot;img&quot; aria-label=&quot;hardware counter comparison, materialize vs fused, log-scale grouped bars with derived miss-rate and peak-RSS panels&quot;&gt;&lt;style&gt;#fig-tsb-03-cache-counters [fill=&quot;#1a1d23&quot; i]{fill:var(--bg)}#fig-tsb-03-cache-counters [stroke=&quot;#1a1d23&quot; i]{stroke:var(--bg)}#fig-tsb-03-cache-counters [fill=&quot;#18181b&quot; i]{fill:var(--bg-panel)}#fig-tsb-03-cache-counters [stroke=&quot;#18181b&quot; i]{stroke:var(--bg-panel)}#fig-tsb-03-cache-counters [fill=&quot;#2c2f37&quot; i]{fill:var(--current-line)}#fig-tsb-03-cache-counters [stroke=&quot;#2c2f37&quot; i]{stroke:var(--current-line)}#fig-tsb-03-cache-counters [fill=&quot;#f4f5f7&quot; i]{fill:var(--fg)}#fig-tsb-03-cache-counters [stroke=&quot;#f4f5f7&quot; i]{stroke:var(--fg)}#fig-tsb-03-cache-counters [fill=&quot;#8a8f98&quot; i]{fill:var(--comment)}#fig-tsb-03-cache-counters [stroke=&quot;#8a8f98&quot; i]{stroke:var(--comment)}&lt;/style&gt;
&lt;rect width=&quot;928&quot; height=&quot;732&quot; fill=&quot;#1a1d23&quot;/&gt;
&lt;style&gt;
    :where(#tcc-root) text { font-family: var(--mono); fill: var(--fg); }
    .tcc-title { font-size: 24px; font-weight: bold; }
    .tcc-sub { font-size: 18px; fill: var(--comment); }
    .tcc-ptitle { font-size: 19px; font-weight: bold; }
    .tcc-glab { font-size: 18px; fill: var(--fg); dominant-baseline: middle; }
    .tcc-val { font-size: 18px; font-weight: bold; dominant-baseline: middle; }
    .tcc-tick { font-size: 18px; fill: var(--comment); }
    .tcc-grid { stroke: var(--current-line); stroke-width: 1; }
    .tcc-mat { fill: #e69f00; }
    .tcc-fus { fill: #56b4e9; }
    .tcc-base { stroke: var(--comment); stroke-width: 2; stroke-dasharray: 6 4; }
    .tcc-baselab { font-size: 18px; fill: var(--comment); }
    .tcc-leg { font-size: 18px; dominant-baseline: middle; }
    .tcc-atitle { font-size: 18px; font-weight: bold; }
&lt;/style&gt;
&lt;g id=&quot;tcc-root&quot;&gt;
&lt;text class=&quot;tcc-title&quot; x=&quot;24&quot; y=&quot;40&quot;&gt;What the hardware counted&lt;/text&gt;
&lt;text class=&quot;tcc-sub&quot; x=&quot;24&quot; y=&quot;68&quot;&gt;same workload both paths &amp;#183; per iteration,&lt;/text&gt;
&lt;text class=&quot;tcc-sub&quot; x=&quot;24&quot; y=&quot;90&quot;&gt;empty-loop baseline subtracted from both paths&lt;/text&gt;
&lt;text class=&quot;tcc-sub&quot; x=&quot;24&quot; y=&quot;112&quot;&gt;measured 2026-07-11 on the dedicated bench box (AMD EPYC-Milan Processor)&lt;/text&gt;
&lt;rect class=&quot;tcc-mat&quot; x=&quot;24&quot; y=&quot;130&quot; width=&quot;16&quot; height=&quot;16&quot; rx=&quot;2&quot;/&gt;
&lt;text class=&quot;tcc-leg&quot; x=&quot;48&quot; y=&quot;139&quot;&gt;materialize (full replicate tensor)&lt;/text&gt;
&lt;rect class=&quot;tcc-fus&quot; x=&quot;460&quot; y=&quot;130&quot; width=&quot;16&quot; height=&quot;16&quot; rx=&quot;2&quot;/&gt;
&lt;text class=&quot;tcc-leg&quot; x=&quot;484&quot; y=&quot;139&quot;&gt;fused reduce (streaming)&lt;/text&gt;
&lt;line class=&quot;tcc-grid&quot; x1=&quot;220.0&quot; y1=&quot;160&quot; x2=&quot;220.0&quot; y2=&quot;372&quot;/&gt;
&lt;text class=&quot;tcc-tick&quot; text-anchor=&quot;middle&quot; x=&quot;220.0&quot; y=&quot;394&quot;&gt;100&lt;/text&gt;
&lt;line class=&quot;tcc-grid&quot; x1=&quot;302.9&quot; y1=&quot;160&quot; x2=&quot;302.9&quot; y2=&quot;372&quot;/&gt;
&lt;text class=&quot;tcc-tick&quot; text-anchor=&quot;middle&quot; x=&quot;302.9&quot; y=&quot;394&quot;&gt;1k&lt;/text&gt;
&lt;line class=&quot;tcc-grid&quot; x1=&quot;385.7&quot; y1=&quot;160&quot; x2=&quot;385.7&quot; y2=&quot;372&quot;/&gt;
&lt;text class=&quot;tcc-tick&quot; text-anchor=&quot;middle&quot; x=&quot;385.7&quot; y=&quot;394&quot;&gt;10k&lt;/text&gt;
&lt;line class=&quot;tcc-grid&quot; x1=&quot;468.6&quot; y1=&quot;160&quot; x2=&quot;468.6&quot; y2=&quot;372&quot;/&gt;
&lt;text class=&quot;tcc-tick&quot; text-anchor=&quot;middle&quot; x=&quot;468.6&quot; y=&quot;394&quot;&gt;100k&lt;/text&gt;
&lt;line class=&quot;tcc-grid&quot; x1=&quot;551.4&quot; y1=&quot;160&quot; x2=&quot;551.4&quot; y2=&quot;372&quot;/&gt;
&lt;text class=&quot;tcc-tick&quot; text-anchor=&quot;middle&quot; x=&quot;551.4&quot; y=&quot;394&quot;&gt;1M&lt;/text&gt;
&lt;line class=&quot;tcc-grid&quot; x1=&quot;634.3&quot; y1=&quot;160&quot; x2=&quot;634.3&quot; y2=&quot;372&quot;/&gt;
&lt;text class=&quot;tcc-tick&quot; text-anchor=&quot;middle&quot; x=&quot;634.3&quot; y=&quot;394&quot;&gt;10M&lt;/text&gt;
&lt;line class=&quot;tcc-grid&quot; x1=&quot;717.1&quot; y1=&quot;160&quot; x2=&quot;717.1&quot; y2=&quot;372&quot;/&gt;
&lt;text class=&quot;tcc-tick&quot; text-anchor=&quot;middle&quot; x=&quot;717.1&quot; y=&quot;394&quot;&gt;100M&lt;/text&gt;
&lt;line class=&quot;tcc-grid&quot; x1=&quot;800.0&quot; y1=&quot;160&quot; x2=&quot;800.0&quot; y2=&quot;372&quot;/&gt;
&lt;text class=&quot;tcc-tick&quot; text-anchor=&quot;middle&quot; x=&quot;800.0&quot; y=&quot;394&quot;&gt;1B&lt;/text&gt;
&lt;text class=&quot;tcc-glab&quot; text-anchor=&quot;end&quot; x=&quot;208&quot; y=&quot;191&quot;&gt;cache references&lt;/text&gt;
&lt;rect class=&quot;tcc-mat&quot; x=&quot;220&quot; y=&quot;168&quot; width=&quot;513.9&quot; height=&quot;22&quot; rx=&quot;2&quot;/&gt;
&lt;text class=&quot;tcc-val&quot; x=&quot;749.9&quot; y=&quot;180&quot;&gt;159M&lt;/text&gt;
&lt;rect class=&quot;tcc-fus&quot; x=&quot;220&quot; y=&quot;192&quot; width=&quot;395.0&quot; height=&quot;22&quot; rx=&quot;2&quot;/&gt;
&lt;text class=&quot;tcc-val&quot; x=&quot;631.0&quot; y=&quot;204&quot;&gt;5.84M &amp;#183; 27x fewer&lt;/text&gt;
&lt;text class=&quot;tcc-glab&quot; text-anchor=&quot;end&quot; x=&quot;208&quot; y=&quot;267&quot;&gt;cache misses&lt;/text&gt;
&lt;rect class=&quot;tcc-mat&quot; x=&quot;220&quot; y=&quot;244&quot; width=&quot;396.9&quot; height=&quot;22&quot; rx=&quot;2&quot;/&gt;
&lt;text class=&quot;tcc-val&quot; x=&quot;632.9&quot; y=&quot;256&quot;&gt;6.17M&lt;/text&gt;
&lt;rect class=&quot;tcc-fus&quot; x=&quot;220&quot; y=&quot;268&quot; width=&quot;225.8&quot; height=&quot;22&quot; rx=&quot;2&quot;/&gt;
&lt;text class=&quot;tcc-val&quot; x=&quot;461.8&quot; y=&quot;280&quot;&gt;53.1k &amp;#183; 116x fewer&lt;/text&gt;
&lt;text class=&quot;tcc-glab&quot; text-anchor=&quot;end&quot; x=&quot;208&quot; y=&quot;343&quot;&gt;dTLB load misses&lt;/text&gt;
&lt;rect class=&quot;tcc-mat&quot; x=&quot;220&quot; y=&quot;320&quot; width=&quot;221.5&quot; height=&quot;22&quot; rx=&quot;2&quot;/&gt;
&lt;text class=&quot;tcc-val&quot; x=&quot;457.5&quot; y=&quot;332&quot;&gt;47.1k&lt;/text&gt;
&lt;rect class=&quot;tcc-fus&quot; x=&quot;220&quot; y=&quot;344&quot; width=&quot;11.6&quot; height=&quot;22&quot; rx=&quot;2&quot;/&gt;
&lt;text class=&quot;tcc-val&quot; x=&quot;247.6&quot; y=&quot;356&quot;&gt;138 &amp;#183; 342x fewer&lt;/text&gt;
&lt;text class=&quot;tcc-atitle&quot; text-anchor=&quot;middle&quot; x=&quot;510&quot; y=&quot;424&quot;&gt;hardware events per iteration (log scale)&lt;/text&gt;

&lt;text class=&quot;tcc-ptitle&quot; x=&quot;24&quot; y=&quot;468&quot;&gt;L1 dcache miss rate (derived)&lt;/text&gt;
&lt;text class=&quot;tcc-glab&quot; text-anchor=&quot;end&quot; x=&quot;208&quot; y=&quot;505&quot;&gt;misses / loads&lt;/text&gt;
&lt;rect class=&quot;tcc-mat&quot; x=&quot;220&quot; y=&quot;482&quot; width=&quot;464.4&quot; height=&quot;22&quot; rx=&quot;2&quot;/&gt;
&lt;text class=&quot;tcc-val&quot; x=&quot;700.4&quot; y=&quot;494&quot;&gt;8.6%&lt;/text&gt;
&lt;rect class=&quot;tcc-fus&quot; x=&quot;220&quot; y=&quot;506&quot; width=&quot;156.6&quot; height=&quot;22&quot; rx=&quot;2&quot;/&gt;
&lt;text class=&quot;tcc-val&quot; x=&quot;392.6&quot; y=&quot;518&quot;&gt;2.9%&lt;/text&gt;

&lt;text class=&quot;tcc-ptitle&quot; x=&quot;24&quot; y=&quot;566&quot;&gt;peak resident memory&lt;/text&gt;
&lt;text class=&quot;tcc-glab&quot; text-anchor=&quot;end&quot; x=&quot;208&quot; y=&quot;603&quot;&gt;same workload&lt;/text&gt;
&lt;rect class=&quot;tcc-mat&quot; x=&quot;220&quot; y=&quot;580&quot; width=&quot;555.3&quot; height=&quot;22&quot; rx=&quot;2&quot;/&gt;
&lt;text class=&quot;tcc-val&quot; x=&quot;791.3&quot; y=&quot;592&quot;&gt;617 MB&lt;/text&gt;
&lt;rect class=&quot;tcc-fus&quot; x=&quot;220&quot; y=&quot;604&quot; width=&quot;210.6&quot; height=&quot;22&quot; rx=&quot;2&quot;/&gt;
&lt;text class=&quot;tcc-val&quot; x=&quot;446.6&quot; y=&quot;616&quot;&gt;234 MB&lt;/text&gt;
&lt;line class=&quot;tcc-base&quot; x1=&quot;430.6&quot; y1=&quot;570&quot; x2=&quot;430.6&quot; y2=&quot;634&quot;/&gt;
&lt;text class=&quot;tcc-baselab&quot; x=&quot;220&quot; y=&quot;658&quot;&gt;fused peak = bare-process baseline (234 MB):&lt;/text&gt;
&lt;text class=&quot;tcc-baselab&quot; x=&quot;220&quot; y=&quot;680&quot;&gt;no measurable memory added; materialize adds&lt;/text&gt;
&lt;text class=&quot;tcc-baselab&quot; x=&quot;220&quot; y=&quot;702&quot;&gt;+383 MB on the same workload&lt;/text&gt;
&lt;/g&gt;
&lt;/svg&gt;
&lt;/div&gt; &lt;figcaption data-astro-cid-bj3fsypb&gt;What the hardware counted while both paths ran the same workload (a stationary-block resample at the worked example&apos;s shape, *n* = 10,000, *B* = 2,000) on the same box (measured 2026-07-11; empty-loop baseline subtracted; the miss rate is derived from the null-subtracted counts). The materializing path touches memory 27x more often, misses cache 116x more often, and misses the TLB (the small hardware cache that translates program addresses to physical memory pages) 342x more often. These are the receipts for every claim in this section.&lt;/figcaption&gt; &lt;details class=&quot;data-table&quot; data-astro-cid-bj3fsypb&gt; &lt;summary data-astro-cid-bj3fsypb&gt;data table&lt;/summary&gt;  &lt;div class=&quot;data-table-scroll&quot; data-astro-cid-bj3fsypb&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;raw counter (per iteration, null-subtracted)&lt;/th&gt;&lt;th&gt;materialize path&lt;/th&gt;&lt;th&gt;fused path&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;cache references&lt;/td&gt;&lt;td&gt;159,490,000&lt;/td&gt;&lt;td&gt;5,844,000&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;cache misses&lt;/td&gt;&lt;td&gt;6,171,000&lt;/td&gt;&lt;td&gt;53,100&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;dTLB (data TLB) misses&lt;/td&gt;&lt;td&gt;47,112&lt;/td&gt;&lt;td&gt;138&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;derived / measured separately&lt;/th&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;L1 dcache miss rate (from the null-subtracted counts)&lt;/td&gt;&lt;td&gt;8.6%&lt;/td&gt;&lt;td&gt;2.9%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;peak resident memory, the RAM the process actually occupies (234 MB = bare process baseline; the materialize delta exceeds the 160 MB tensor because the path also holds a returned copy and the index matrix)&lt;/td&gt;&lt;td&gt;617 MB&lt;/td&gt;&lt;td&gt;234 MB&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt; &lt;/details&gt; &lt;/figure&gt; &lt;script type=&quot;module&quot; src=&quot;https://thepragmaticquant.com/vercel/path0/src/components/Figure.astro?astro&amp;type=script&amp;index=0&amp;lang.ts&quot;&gt;&lt;/script&gt;
&lt;p&gt;The whole rebuild, in three moves:&lt;/p&gt;





















&lt;div class=&quot;table-scroll&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;the move&lt;/th&gt;&lt;th&gt;the reason&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;never materialize an array whose only consumer is a reduction&lt;/td&gt;&lt;td&gt;the tensor’s bytes cost more than its arithmetic; the answer was 16 kB, the intermediate was 160 MB&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;fuse the pass: build, gather, reduce in one loop body&lt;/td&gt;&lt;td&gt;a working set that fits in cache is the difference between cache latency and DRAM round trips&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;derive state, never carry it&lt;/td&gt;&lt;td&gt;&lt;em&gt;B&lt;/em&gt; seed objects were 95% of a workload; a key derived from (root, replicate) is free, order-independent, and bitwise reproducible&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;section class=&quot;faq&quot; aria-label=&quot;Frequently asked questions&quot; data-astro-cid-z6gx6xcw&gt; &lt;h2 data-astro-cid-z6gx6xcw&gt;Frequently asked questions&lt;/h2&gt; &lt;div class=&quot;faq-list&quot; data-astro-cid-z6gx6xcw&gt; &lt;details class=&quot;faq-item&quot; open data-astro-cid-z6gx6xcw&gt; &lt;summary data-astro-cid-z6gx6xcw&gt;Why would a bootstrap be limited by memory rather than by computation?&lt;/summary&gt; &lt;div class=&quot;faq-a&quot; data-astro-cid-z6gx6xcw&gt;Because its arithmetic intensity is very low: resampling moves eight-byte values around and then does roughly one floating-point operation per value for a statistic like the mean. When a batched implementation materializes all *B* replicates at once, the resulting tensor is far larger than the caches, so every byte takes a round trip through main memory. The processor spends the workload waiting on that traffic, not computing. The fix is to process one replicate at a time inside a fused kernel so the working set stays cache-resident.&lt;/div&gt; &lt;/details&gt;&lt;details class=&quot;faq-item&quot; open data-astro-cid-z6gx6xcw&gt; &lt;summary data-astro-cid-z6gx6xcw&gt;What is a counter-based random number generator?&lt;/summary&gt; &lt;div class=&quot;faq-a&quot; data-astro-cid-z6gx6xcw&gt;A conventional pseudorandom generator is a state machine: each draw updates internal state that the next draw depends on, which forces sequential execution and per-stream memory. A counter-based generator such as Philox is a pure function instead: it maps a (key, counter) pair straight to random bits, with no carried state. That means any parallel worker can compute any draw of any stream independently and in any order. tsbootstrap&amp;#39;s compiled backend derives a Philox-4x32-10 key for each replicate from a single 128-bit root key inside the kernel.&lt;/div&gt; &lt;/details&gt;&lt;details class=&quot;faq-item&quot; open data-astro-cid-z6gx6xcw&gt; &lt;summary data-astro-cid-z6gx6xcw&gt;Does the compiled backend change my results?&lt;/summary&gt; &lt;div class=&quot;faq-a&quot; data-astro-cid-z6gx6xcw&gt;The default backend is unchanged: NumPy PCG64 streams, one per replicate, reproducing previous releases byte for byte. The compiled backend is opt-in and uses its own counter-based streams, so its replicates are equal in distribution to the default path but not bit-identical to it. Within the compiled backend, results are bitwise reproducible for a given seed regardless of thread count or execution order, and the library raises an explicit error if the compiled extra is unavailable rather than silently falling back.&lt;/div&gt; &lt;/details&gt;&lt;details class=&quot;faq-item&quot; open data-astro-cid-z6gx6xcw&gt; &lt;summary data-astro-cid-z6gx6xcw&gt;When is the fused compiled path the wrong choice?&lt;/summary&gt; &lt;div class=&quot;faq-a&quot; data-astro-cid-z6gx6xcw&gt;When you actually need the full materialized tensor of resampled series (for a custom diagnostic that inspects whole paths, for example), the materializing path exists for exactly that, and the incumbent&amp;#39;s per-replicate loop is quicker at producing the fully materialized array than our default path. The fused path is built for the common case where the bootstrap&amp;#39;s output is a statistic per replicate, and there it wins the benchmark grid in every cell.&lt;/div&gt; &lt;/details&gt; &lt;/div&gt; &lt;script type=&quot;application/ld+json&quot;&gt;{&quot;@context&quot;:&quot;https://schema.org&quot;,&quot;@type&quot;:&quot;FAQPage&quot;,&quot;mainEntity&quot;:[{&quot;@type&quot;:&quot;Question&quot;,&quot;name&quot;:&quot;Why would a bootstrap be limited by memory rather than by computation?&quot;,&quot;acceptedAnswer&quot;:{&quot;@type&quot;:&quot;Answer&quot;,&quot;text&quot;:&quot;Because its arithmetic intensity is very low: resampling moves eight-byte values around and then does roughly one floating-point operation per value for a statistic like the mean. When a batched implementation materializes all *B* replicates at once, the resulting tensor is far larger than the caches, so every byte takes a round trip through main memory. The processor spends the workload waiting on that traffic, not computing. The fix is to process one replicate at a time inside a fused kernel so the working set stays cache-resident.&quot;}},{&quot;@type&quot;:&quot;Question&quot;,&quot;name&quot;:&quot;What is a counter-based random number generator?&quot;,&quot;acceptedAnswer&quot;:{&quot;@type&quot;:&quot;Answer&quot;,&quot;text&quot;:&quot;A conventional pseudorandom generator is a state machine: each draw updates internal state that the next draw depends on, which forces sequential execution and per-stream memory. A counter-based generator such as Philox is a pure function instead: it maps a (key, counter) pair straight to random bits, with no carried state. That means any parallel worker can compute any draw of any stream independently and in any order. tsbootstrap&apos;s compiled backend derives a Philox-4x32-10 key for each replicate from a single 128-bit root key inside the kernel.&quot;}},{&quot;@type&quot;:&quot;Question&quot;,&quot;name&quot;:&quot;Does the compiled backend change my results?&quot;,&quot;acceptedAnswer&quot;:{&quot;@type&quot;:&quot;Answer&quot;,&quot;text&quot;:&quot;The default backend is unchanged: NumPy PCG64 streams, one per replicate, reproducing previous releases byte for byte. The compiled backend is opt-in and uses its own counter-based streams, so its replicates are equal in distribution to the default path but not bit-identical to it. Within the compiled backend, results are bitwise reproducible for a given seed regardless of thread count or execution order, and the library raises an explicit error if the compiled extra is unavailable rather than silently falling back.&quot;}},{&quot;@type&quot;:&quot;Question&quot;,&quot;name&quot;:&quot;When is the fused compiled path the wrong choice?&quot;,&quot;acceptedAnswer&quot;:{&quot;@type&quot;:&quot;Answer&quot;,&quot;text&quot;:&quot;When you actually need the full materialized tensor of resampled series (for a custom diagnostic that inspects whole paths, for example), the materializing path exists for exactly that, and the incumbent&apos;s per-replicate loop is quicker at producing the fully materialized array than our default path. The fused path is built for the common case where the bootstrap&apos;s output is a statistic per replicate, and there it wins the benchmark grid in every cell.&quot;}}]}&lt;/script&gt; &lt;/section&gt; &lt;!-- Mobile collapse (UX audit F-40): each Q/A pair is a &lt;details&gt;, server-rendered
     OPEN so the answers are visible with no JS, in print, on desktop, and to crawlers
     (the full text is always in the DOM; the FAQPage JSON-LD above is untouched).
     At phone widths this script collapses the pairs so the questions are scannable
     and an answer expands on tap; widening the viewport re-opens everything (which
     also repairs any keyboard-toggled state before the desktop pointer-events lock
     makes it unreachable). astro:page-load covers view-transition navigations. --&gt; &lt;script type=&quot;module&quot; src=&quot;https://thepragmaticquant.com/vercel/path0/src/components/Faq.astro?astro&amp;type=script&amp;index=0&amp;lang.ts&quot;&gt;&lt;/script&gt;
&lt;p&gt;The fastest code in this library is the code that no longer runs: the tensor nobody builds, the seed objects nobody allocates. Performance work sounds like adding cleverness; the two biggest wins here were subtractions. Somewhere in your own hot path there is probably a 160 MB array whose only job is to be read once and averaged, and next to it a few thousand small state objects built on every call, because carrying state was the design that came to mind first, and main memory bills you by the byte for both, whether or not you ever look. You find these things the way we did: profile the whole call, count the bytes. The FLOPs were never the bill.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://thepragmaticquant.com/your-bootstrap-is-lying-to-you/&quot;&gt;The first piece in this series&lt;/a&gt; was about a resampler quietly deleting the structure in your data. This one was about a design quietly deleting your performance, byte by byte, in arrays you never needed and state you never had to carry. What happens when the data refuses to be a rectangle? tsbootstrap already packs panels of unequal-length series into one flat array behind a row-offset table (compressed-sparse-row bookkeeping, the layout sparse linear algebra has leaned on for decades), and how a thousand ragged series share one fused pass without padding a single one is where this track goes next.&lt;/p&gt;</content:encoded><category>tsbootstrap</category><category>performance</category><category>memory</category><category>engineering</category></item><item><title>Your bootstrap is lying to you</title><link>https://thepragmaticquant.com/your-bootstrap-is-lying-to-you/</link><guid isPermaLink="true">https://thepragmaticquant.com/your-bootstrap-is-lying-to-you/</guid><description>The ordinary bootstrap assumes your observations are independent. Feed it a time series and it quietly shuffles away the autocorrelation, then hands you a confidence interval too narrow to be true: a nominal 90% interval that covers the truth about half the time. Here is the failure on real numbers, and the block bootstrap that keeps the dependence and tells you most of the truth.</description><pubDate>Mon, 06 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;tldr&quot;&gt;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: The ordinary bootstrap resamples your observations at random, which silently assumes they carry no information about each other. On a time series that assumption fails, and the price is a confidence interval that is far too narrow: on an autocorrelated series I built with a true mean of exactly zero, the i.i.d. bootstrap’s standard error for the mean came out &lt;strong&gt;2.4x too small&lt;/strong&gt;, and in a repeated coverage study on fresh series from the same process its nominal &lt;strong&gt;90%&lt;/strong&gt; interval covered the true mean only &lt;strong&gt;49.6%&lt;/strong&gt; of the time: a “90% interval” that is really a coin flip.&lt;/p&gt;&lt;p&gt;Resampling contiguous &lt;em&gt;blocks&lt;/em&gt; instead of single points keeps the dependence and lifts that coverage to &lt;strong&gt;79.7%&lt;/strong&gt;. It does not fully fix it, and by how much is part of the story.&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;I built a time series whose mean I knew exactly, because I chose it: zero. Then I asked a bootstrap for a 90% confidence interval on that mean, the way you would ask any statistics library, and it answered &lt;code&gt;[-0.51, -0.19]&lt;/code&gt;. Read that back. A ninety-percent interval that does not contain zero is a ninety-percent-confident claim that the mean is &lt;em&gt;negative&lt;/em&gt; (a real, signed effect) on data I generated to have no such thing. The interval was tight, it was confident, and it was wrong.&lt;/p&gt;
&lt;p&gt;Nothing in the call was exotic. The series was an AR(1) process, the simplest autocorrelated series there is: each value is 0.7 times the previous value plus a fresh random shock. &lt;em&gt;Autocorrelation&lt;/em&gt; just means today’s value carries information about tomorrow’s, the thing that makes a time series a time series and not a bag of independent draws. I used the default bootstrap, the one every tutorial reaches for first. And it lied to me by a factor of two, with a straight face.&lt;/p&gt;
&lt;p&gt;This is the failure the whole tsbootstrap library exists to fix. Here is where the lie enters, and what to do about it.&lt;/p&gt;
&lt;h2 id=&quot;what-the-bootstrap-actually-does&quot;&gt;What the bootstrap actually does&lt;a class=&quot;heading-anchor&quot; href=&quot;#what-the-bootstrap-actually-does&quot; aria-label=&quot;Link to this section&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;em&gt;bootstrap&lt;/em&gt; is one of the most useful ideas in applied statistics: to find out how uncertain a number is, resample your data with replacement many times, recompute the number on each resample, and look at how much it wobbles. You have one dataset, but the bootstrap manufactures thousands of plausible alternate datasets out of it and lets the number’s spread across them stand in for the uncertainty you could not otherwise measure. No formula, no parametric model you have to name out loud. It is close to magic, and it usually works.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;usually&lt;/em&gt; is doing a lot of work. The ordinary bootstrap (i.i.d., for &lt;em&gt;independent and identically distributed&lt;/em&gt;, the label you will see in the figures) draws each resampled observation independently and uniformly from your data: pick a row at random, put it back, pick another. That independence is the entire assumption. Drawing observations independently is a mathematical statement that the order of your data does not matter, that the rows are &lt;em&gt;interchangeable&lt;/em&gt;. For a bag of independent measurements, they are. For a time series, they are not, and shuffling them destroys the one property that made the data worth collecting in order.&lt;/p&gt;

&lt;figure class=&quot;full&quot; data-astro-cid-bj3fsypb&gt; &lt;video autoplay muted loop playsinline preload=&quot;none&quot; poster=&quot;/assets/terminal/tsb-a1-block-retiling.frame1.png&quot; aria-label=&quot;An animated loop that returns to this labelled still. A three-part schematic sharing one source. At the top, a single autocorrelated AR(1) wave, the original series, divided into contiguous blocks by faint dashed seams. Below it, two panels. Left, labelled &apos;block bootstrap&apos; in blue: contiguous blocks are re-tiled into a replicate that still rises and falls like a wave, with the block seams marked. Right, labelled &apos;i.i.d. bootstrap&apos; in orange: the same points are shuffled into a dense spiky band with no wave left. At the bottom, a standard-error number line reads off what each mechanism reports for the mean: i.i.d. 0.10 in orange, block 0.18 in blue, against the analytic true 0.24 drawn as a grey dashed reference rule.&quot; class=&quot;has-portrait&quot; data-poster-portrait=&quot;/assets/terminal/tsb-a1-block-retiling.portrait.frame1.png&quot; data-astro-cid-bj3fsypb&gt; &lt;source src=&quot;https://thepragmaticquant.com/assets/terminal/tsb-a1-block-retiling.portrait.webm&quot; type=&quot;video/webm&quot; media=&quot;(max-width: 620px)&quot; data-astro-cid-bj3fsypb&gt; &lt;source src=&quot;https://thepragmaticquant.com/assets/terminal/tsb-a1-block-retiling.portrait.mp4&quot; type=&quot;video/mp4&quot; media=&quot;(max-width: 620px)&quot; data-astro-cid-bj3fsypb&gt; &lt;source src=&quot;https://thepragmaticquant.com/assets/terminal/tsb-a1-block-retiling.webm&quot; type=&quot;video/webm&quot; data-astro-cid-bj3fsypb&gt; &lt;source src=&quot;https://thepragmaticquant.com/assets/terminal/tsb-a1-block-retiling.mp4&quot; type=&quot;video/mp4&quot; data-astro-cid-bj3fsypb&gt; &lt;/video&gt; &lt;figcaption data-astro-cid-bj3fsypb&gt;The same series, resampled two ways. The block bootstrap lifts out contiguous chunks, so the resampled series still moves like the original; the i.i.d. bootstrap shuffles single points and shreds the wave into noise. The shredded version looks more ‘random,’ and that is why it reports a smaller standard error (the typical miss you should expect between the sample mean and the true mean) than the truth (grey line).&lt;/figcaption&gt; &lt;details class=&quot;data-table&quot; data-astro-cid-bj3fsypb&gt; &lt;summary data-astro-cid-bj3fsypb&gt;data table&lt;/summary&gt;  &lt;div class=&quot;data-table-scroll&quot; data-astro-cid-bj3fsypb&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;quantity&lt;/th&gt;&lt;th&gt;SE of the mean&lt;/th&gt;&lt;th&gt;reads as&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;i.i.d. shuffle&lt;/td&gt;&lt;td&gt;0.097&lt;/td&gt;&lt;td&gt;the collapse (dependence discarded)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;moving-block&lt;/td&gt;&lt;td&gt;0.176&lt;/td&gt;&lt;td&gt;dependence kept&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;analytic truth&lt;/td&gt;&lt;td&gt;0.236&lt;/td&gt;&lt;td&gt;the yardstick&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt; &lt;/details&gt; &lt;/figure&gt; &lt;script type=&quot;module&quot; src=&quot;https://thepragmaticquant.com/vercel/path0/src/components/Figure.astro?astro&amp;type=script&amp;index=0&amp;lang.ts&quot;&gt;&lt;/script&gt;
&lt;p&gt;Watch the two panels. On the right, the i.i.d. shuffle takes my autocorrelated wave and scatters its points at random; the resampled series looks like static. On the left, the block bootstrap lifts out contiguous runs of the series and lays them back down intact, so the resampled version still rises and falls in the same lazy way the original did. That static-looking version is the one that &lt;em&gt;understates&lt;/em&gt; uncertainty, the opposite of what your gut says.&lt;/p&gt;
&lt;h2 id=&quot;why-shredding-the-wave-shrinks-the-interval&quot;&gt;Why shredding the wave shrinks the interval&lt;a class=&quot;heading-anchor&quot; href=&quot;#why-shredding-the-wave-shrinks-the-interval&quot; aria-label=&quot;Link to this section&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When observations are positively autocorrelated, they move in the same direction for a while. A run of above-average values tends to be followed by more above-average values before the series wanders back. That persistence means your sample does not contain as much &lt;em&gt;independent&lt;/em&gt; information as its length suggests: two hundred points that each nudge their neighbor are worth fewer than two hundred points drawn fresh and independent. Fewer effective observations means the sample mean is a shakier estimate of the true mean than the raw count of points implies.&lt;/p&gt;
&lt;p&gt;You can put a number on “fewer.” For an AR(1) at &lt;code&gt;phi = 0.7&lt;/code&gt; (&lt;code&gt;phi&lt;/code&gt; is that 0.7 multiplier from earlier, how strongly each value leans on the last), the &lt;em&gt;effective sample size&lt;/em&gt; (the number of independent points that would carry the same information about the mean) is &lt;code&gt;n / ((1 + phi) / (1 - phi))&lt;/code&gt; (the denominator counts how much each point merely repeats its neighbors’ information), which for my two hundred points is &lt;code&gt;200 / 5.67 = 35&lt;/code&gt;. Two hundred autocorrelated readings are worth about thirty-five independent ones. The i.i.d. bootstrap computes the uncertainty of a mean built from two hundred independent points; the truth is the uncertainty of a mean built from thirty-five. That shrinkage, two hundred down to thirty-five, is where the factor of 2.4 comes from: uncertainty in a mean shrinks with the square root of the number of independent points, so the inflation is the square root of the ratio, &lt;code&gt;sqrt(200 / 35) = 2.4&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The i.i.d. bootstrap never sees any of this. By drawing points independently, it builds resampled series that have no autocorrelation at all: it manufactures the “two hundred independent points” fiction whole, and it measures the wobble of the mean &lt;em&gt;under that fiction&lt;/em&gt;. So it reports the uncertainty you would have if your data were independent, which is smaller, often much smaller, than the uncertainty you actually have. The scattered series on the right of the figure is not a bug in the resampling; it is the resampling doing just what it was designed to do, on data that violates its one assumption.&lt;/p&gt;
&lt;p&gt;The block bootstrap fixes this by resampling contiguous blocks (chunks of consecutive observations) instead of single points. Because each block is a run of real, consecutive data, it carries the local ups and downs with it. Glue enough blocks together and the resampled series keeps the autocorrelation of the original, so the wobble of its mean reflects the real, reduced information content of dependent data. It resamples in a way that respects the assumption the i.i.d. bootstrap breaks.&lt;/p&gt;
&lt;span class=&quot;marginnote&quot; role=&quot;note&quot;&gt;The version in the figure is the &lt;em&gt;moving-block&lt;/em&gt; bootstrap: slide a window of fixed length along the series, and resample whole windows with replacement. It is the oldest and simplest of the block methods; the others differ in how they choose and glue the blocks, and they get their own article later in this series.&lt;/span&gt;
&lt;h2 id=&quot;how-wide-should-the-interval-actually-be&quot;&gt;How wide should the interval actually be?&lt;a class=&quot;heading-anchor&quot; href=&quot;#how-wide-should-the-interval-actually-be&quot; aria-label=&quot;Link to this section&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I do not have to guess at the truth here, because I built the data. For an AR(1) series you can write the honest standard error of the mean in closed form. The &lt;em&gt;standard error&lt;/em&gt; is just the typical size of the gap between your sample mean and the true mean, how far off you should expect to be. For independent data it is &lt;code&gt;sigma / sqrt(n)&lt;/code&gt;, the data’s typical spread divided by the square root of the count, where &lt;code&gt;sigma&lt;/code&gt; is the standard deviation of the series itself, not of the shocks driving it. For an AR(1) with autocorrelation &lt;code&gt;phi&lt;/code&gt;, dependence inflates it by a factor that depends only on &lt;code&gt;phi&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;SE_true = (sigma / sqrt(n)) * sqrt((1 + phi) / (1 - phi))&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;That square-root factor is the whole story. At &lt;code&gt;phi = 0.7&lt;/code&gt; it equals &lt;code&gt;sqrt(1.7 / 0.3) = 2.38&lt;/code&gt;. The honest standard error of the mean is nearly two and a half times larger than the one you would get by pretending the data were independent, and the i.i.d. bootstrap, by construction, targets the independent one. It is 2.4x too confident, before you have done anything wrong yourself.&lt;/p&gt;
&lt;span class=&quot;marginnote&quot; role=&quot;note&quot;&gt;The factor is a property of &lt;em&gt;how autocorrelated the data is&lt;/em&gt;, not of which block method you pick. At &lt;code&gt;phi = 0.3&lt;/code&gt; it is only 1.36, so the lie is mild; at &lt;code&gt;phi = 0.9&lt;/code&gt; it is 4.36, and a naive 90% interval misses the truth most of the time. Stronger dependence, bigger lie. My &lt;code&gt;phi = 0.7&lt;/code&gt; sits in the range plenty of real economic and sensor series actually occupy.&lt;/span&gt;
&lt;p&gt;Put the standard errors side by side and the collapse is obvious. On my one example series, the i.i.d. bootstrap’s standard error for the mean is 0.097. Every block method lands far higher, 0.16 to 0.20, and the analytic truth is 0.24. The i.i.d. bar is about two-fifths the height of the truth.&lt;/p&gt;
&lt;figure class=&quot;full&quot; data-astro-cid-bj3fsypb&gt; &lt;div class=&quot;svgfig svgfig-chart&quot; role=&quot;img&quot; aria-label=&quot;Horizontal bar chart of the bootstrap standard error of the mean for one AR(1) series, sorted short to tall. The i.i.d. bar at 0.097 is drawn in orange with a vermillion label &apos;2.4x too small&apos;; it is visibly about half the length of the rest. The block methods cluster higher in blue: stationary 0.163, tapered 0.170, moving 0.176, circular 0.197. A grey vertical reference rule at 0.236 is labelled &apos;true long-run SE&apos;. The i.i.d. bar falls far short of that rule; every block bar reaches most of the way to it.&quot; data-astro-cid-bj3fsypb&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; width=&quot;928&quot; id=&quot;fig-tsb-a1-se-collapse&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 928 410&quot; role=&quot;img&quot; aria-label=&quot;Horizontal bar chart of the bootstrap standard error of the mean for one AR(1) series, sorted short to tall. The i.i.d. bar at 0.097 is drawn in orange and labelled 2.4x too small; it is about half the length of the rest. The block methods cluster higher in blue: stationary 0.163, tapered 0.170, moving 0.176, circular 0.197. A grey dashed vertical reference rule at 0.236 is labelled true long-run SE. The i.i.d. bar falls far short of that rule; every block bar reaches most of the way to it.&quot;&gt;&lt;style&gt;#fig-tsb-a1-se-collapse [fill=&quot;#1a1d23&quot; i]{fill:var(--bg)}#fig-tsb-a1-se-collapse [stroke=&quot;#1a1d23&quot; i]{stroke:var(--bg)}#fig-tsb-a1-se-collapse [fill=&quot;#18181b&quot; i]{fill:var(--bg-panel)}#fig-tsb-a1-se-collapse [stroke=&quot;#18181b&quot; i]{stroke:var(--bg-panel)}#fig-tsb-a1-se-collapse [fill=&quot;#2c2f37&quot; i]{fill:var(--current-line)}#fig-tsb-a1-se-collapse [stroke=&quot;#2c2f37&quot; i]{stroke:var(--current-line)}#fig-tsb-a1-se-collapse [fill=&quot;#f4f5f7&quot; i]{fill:var(--fg)}#fig-tsb-a1-se-collapse [stroke=&quot;#f4f5f7&quot; i]{stroke:var(--fg)}#fig-tsb-a1-se-collapse [fill=&quot;#8a8f98&quot; i]{fill:var(--comment)}#fig-tsb-a1-se-collapse [stroke=&quot;#8a8f98&quot; i]{stroke:var(--comment)}&lt;/style&gt;
&lt;rect width=&quot;928&quot; height=&quot;410&quot; fill=&quot;#1a1d23&quot;/&gt;
&lt;style&gt;
    :where(#sec-root) text { font-family: var(--mono); fill: var(--fg); }
    .sec-title { font-size: 21px; font-weight: bold; }
    .sec-sub { font-size: 16px; fill: var(--comment); }
    .sec-grid { stroke: var(--current-line); stroke-width: 1; }
    .sec-axis { stroke: var(--comment); stroke-width: 1; }
    .sec-tick { font-size: 16px; fill: var(--comment); text-anchor: middle; }
    .sec-atitle { font-size: 16px; fill: var(--fg); font-weight: bold; text-anchor: middle; }
    .sec-row { font-size: 16px; text-anchor: end; dominant-baseline: middle; }
    .sec-rowsub { font-size: 16px; fill: var(--comment); text-anchor: end; dominant-baseline: middle; }
    .sec-valb { font-size: 16px; fill: #56b4e9; font-weight: bold; dominant-baseline: middle; }
    .sec-valo { font-size: 16px; fill: #e69f00; font-weight: bold; dominant-baseline: middle; }
    .sec-flag { font-size: 16px; fill: #d55e00; font-weight: bold; dominant-baseline: middle; }
    .sec-reflab { font-size: 16px; fill: var(--comment); font-weight: bold; text-anchor: middle; }
  &lt;/style&gt;
&lt;g id=&quot;sec-root&quot;&gt;
&lt;text class=&quot;sec-title&quot; x=&quot;24&quot; y=&quot;34&quot;&gt;Standard error of the mean, six ways to measure it&lt;/text&gt;
&lt;text class=&quot;sec-sub&quot; x=&quot;24&quot; y=&quot;58&quot;&gt;one AR(1) series, phi=0.7 &amp;#183; SE axis starts at 0, no truncation&lt;/text&gt;
&lt;line class=&quot;sec-grid&quot; x1=&quot;200.0&quot; y1=&quot;96&quot; x2=&quot;200.0&quot; y2=&quot;344&quot;/&gt;
&lt;text class=&quot;sec-tick&quot; x=&quot;200.0&quot; y=&quot;366&quot;&gt;0.00&lt;/text&gt;
&lt;line class=&quot;sec-grid&quot; x1=&quot;309.6&quot; y1=&quot;96&quot; x2=&quot;309.6&quot; y2=&quot;344&quot;/&gt;
&lt;text class=&quot;sec-tick&quot; x=&quot;309.6&quot; y=&quot;366&quot;&gt;0.05&lt;/text&gt;
&lt;line class=&quot;sec-grid&quot; x1=&quot;419.2&quot; y1=&quot;96&quot; x2=&quot;419.2&quot; y2=&quot;344&quot;/&gt;
&lt;text class=&quot;sec-tick&quot; x=&quot;419.2&quot; y=&quot;366&quot;&gt;0.10&lt;/text&gt;
&lt;line class=&quot;sec-grid&quot; x1=&quot;528.8&quot; y1=&quot;96&quot; x2=&quot;528.8&quot; y2=&quot;344&quot;/&gt;
&lt;text class=&quot;sec-tick&quot; x=&quot;528.8&quot; y=&quot;366&quot;&gt;0.15&lt;/text&gt;
&lt;line class=&quot;sec-grid&quot; x1=&quot;638.5&quot; y1=&quot;96&quot; x2=&quot;638.5&quot; y2=&quot;344&quot;/&gt;
&lt;text class=&quot;sec-tick&quot; x=&quot;638.5&quot; y=&quot;366&quot;&gt;0.20&lt;/text&gt;
&lt;line class=&quot;sec-grid&quot; x1=&quot;748.1&quot; y1=&quot;96&quot; x2=&quot;748.1&quot; y2=&quot;344&quot;/&gt;
&lt;text class=&quot;sec-tick&quot; x=&quot;748.1&quot; y=&quot;366&quot;&gt;0.25&lt;/text&gt;
&lt;line class=&quot;sec-axis&quot; x1=&quot;200&quot; y1=&quot;344&quot; x2=&quot;770.0&quot; y2=&quot;344&quot;/&gt;
&lt;line class=&quot;sec-axis&quot; x1=&quot;200&quot; y1=&quot;96&quot; x2=&quot;200&quot; y2=&quot;344&quot;/&gt;
&lt;text class=&quot;sec-atitle&quot; x=&quot;485&quot; y=&quot;390&quot;&gt;bootstrap standard error of the mean&lt;/text&gt;
&lt;line x1=&quot;716.7&quot; y1=&quot;90&quot; x2=&quot;716.7&quot; y2=&quot;344&quot; stroke=&quot;#8a8f98&quot; stroke-width=&quot;2&quot; stroke-dasharray=&quot;6 4&quot;/&gt;
&lt;rect x=&quot;598&quot; y=&quot;73&quot; width=&quot;238&quot; height=&quot;20&quot; fill=&quot;#1a1d23&quot;/&gt;
&lt;text class=&quot;sec-reflab&quot; x=&quot;716.7&quot; y=&quot;87&quot;&gt;true long-run SE = 0.236&lt;/text&gt;
&lt;text class=&quot;sec-row&quot; x=&quot;192&quot; y=&quot;121&quot;&gt;i.i.d.&lt;/text&gt;
&lt;text class=&quot;sec-rowsub&quot; x=&quot;192&quot; y=&quot;139&quot;&gt;(naive baseline)&lt;/text&gt;
&lt;rect x=&quot;200&quot; y=&quot;106&quot; width=&quot;212.9&quot; height=&quot;30&quot; fill=&quot;#e69f00&quot;/&gt;
&lt;text class=&quot;sec-valo&quot; x=&quot;422.9&quot; y=&quot;121&quot;&gt;0.097&lt;/text&gt;
&lt;text class=&quot;sec-flag&quot; x=&quot;478.9&quot; y=&quot;121&quot;&gt;&amp;#9664; 2.4x too small&lt;/text&gt;
&lt;text class=&quot;sec-row&quot; x=&quot;192&quot; y=&quot;169&quot;&gt;stationary&lt;/text&gt;
&lt;text class=&quot;sec-rowsub&quot; x=&quot;192&quot; y=&quot;187&quot;&gt;block&lt;/text&gt;
&lt;rect x=&quot;200&quot; y=&quot;154&quot; width=&quot;358.0&quot; height=&quot;30&quot; fill=&quot;#56b4e9&quot;/&gt;
&lt;text class=&quot;sec-valb&quot; x=&quot;568.0&quot; y=&quot;169&quot;&gt;0.163&lt;/text&gt;
&lt;text class=&quot;sec-row&quot; x=&quot;192&quot; y=&quot;217&quot;&gt;tapered&lt;/text&gt;
&lt;text class=&quot;sec-rowsub&quot; x=&quot;192&quot; y=&quot;235&quot;&gt;block&lt;/text&gt;
&lt;rect x=&quot;200&quot; y=&quot;202&quot; width=&quot;373.6&quot; height=&quot;30&quot; fill=&quot;#56b4e9&quot;/&gt;
&lt;text class=&quot;sec-valb&quot; x=&quot;583.6&quot; y=&quot;217&quot;&gt;0.170&lt;/text&gt;
&lt;text class=&quot;sec-row&quot; x=&quot;192&quot; y=&quot;265&quot;&gt;moving&lt;/text&gt;
&lt;text class=&quot;sec-rowsub&quot; x=&quot;192&quot; y=&quot;283&quot;&gt;block&lt;/text&gt;
&lt;rect x=&quot;200&quot; y=&quot;250&quot; width=&quot;385.6&quot; height=&quot;30&quot; fill=&quot;#56b4e9&quot;/&gt;
&lt;text class=&quot;sec-valb&quot; x=&quot;595.6&quot; y=&quot;265&quot;&gt;0.176&lt;/text&gt;
&lt;text class=&quot;sec-row&quot; x=&quot;192&quot; y=&quot;313&quot;&gt;circular&lt;/text&gt;
&lt;text class=&quot;sec-rowsub&quot; x=&quot;192&quot; y=&quot;331&quot;&gt;block&lt;/text&gt;
&lt;rect x=&quot;200&quot; y=&quot;298&quot; width=&quot;432.1&quot; height=&quot;30&quot; fill=&quot;#56b4e9&quot;/&gt;
&lt;text class=&quot;sec-valb&quot; x=&quot;642.1&quot; y=&quot;313&quot;&gt;0.197&lt;/text&gt;
&lt;/g&gt;&lt;/svg&gt;
&lt;/div&gt; &lt;figcaption data-astro-cid-bj3fsypb&gt;Standard error of the mean, one series, six ways to measure it. The naive i.i.d. bootstrap (orange) collapses to 41% of the true long-run standard error (grey rule). Every block method (blue) reaches most of the way to it, though notice none of them quite gets there, which will matter in a moment. The gaps between the four block bars are single-series noise, not a ranking.&lt;/figcaption&gt; &lt;details class=&quot;data-table&quot; data-astro-cid-bj3fsypb&gt; &lt;summary data-astro-cid-bj3fsypb&gt;data table&lt;/summary&gt;  &lt;div class=&quot;data-table-scroll&quot; data-astro-cid-bj3fsypb&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;method&lt;/th&gt;&lt;th&gt;SE of the mean&lt;/th&gt;&lt;th&gt;vs. true (0.236)&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;i.i.d. (naive baseline)&lt;/td&gt;&lt;td&gt;0.097&lt;/td&gt;&lt;td&gt;41%, collapsed&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;stationary block&lt;/td&gt;&lt;td&gt;0.163&lt;/td&gt;&lt;td&gt;69%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;tapered block&lt;/td&gt;&lt;td&gt;0.170&lt;/td&gt;&lt;td&gt;72%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;moving block&lt;/td&gt;&lt;td&gt;0.176&lt;/td&gt;&lt;td&gt;75%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;circular block&lt;/td&gt;&lt;td&gt;0.197&lt;/td&gt;&lt;td&gt;84%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;analytic true long-run SE&lt;/td&gt;&lt;td&gt;0.236&lt;/td&gt;&lt;td&gt;100% (reference)&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt; &lt;/details&gt; &lt;/figure&gt; 
&lt;h2 id=&quot;i-have-shipped-this-exact-mistake&quot;&gt;I have shipped this exact mistake&lt;a class=&quot;heading-anchor&quot; href=&quot;#i-have-shipped-this-exact-mistake&quot; aria-label=&quot;Link to this section&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I did not learn this from a textbook warning. I learned it because I once reported a result that was not there.&lt;/p&gt;
&lt;p&gt;Years ago I had a run of daily measurements and a question about whether their average had shifted from a baseline of zero. I did the responsible-looking thing: I bootstrapped a confidence interval instead of trusting a formula, the interval excluded zero, and I wrote down that the shift was real. It was not. The measurements were autocorrelated (of course they were, they were daily readings of a slow physical process), and my “responsible” bootstrap had shredded that dependence the same way the figure above shredded the wave. The effect I found was nothing more than the interval’s collapse. Nobody caught it, because nothing looked wrong; a tight interval that excludes zero is the most ordinary output in the world. That is the quiet part of this failure that unsettles me most. It does not announce itself.&lt;/p&gt;
&lt;h2 id=&quot;so-how-often-does-it-actually-lie&quot;&gt;So how often does it actually lie?&lt;a class=&quot;heading-anchor&quot; href=&quot;#so-how-often-does-it-actually-lie&quot; aria-label=&quot;Link to this section&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One series and one anecdote are not evidence, so I ran the experiment properly. Generate a fresh AR(1) series with &lt;code&gt;phi = 0.7&lt;/code&gt;, length 200, true mean zero. Compute the i.i.d. bootstrap’s 90% percentile interval and the moving-block bootstrap’s 90% percentile interval for the mean, the same simple interval construction for both, so the only thing that differs between them is the resampler. Check whether each one contains the true mean of zero. Do that two thousand times and count.&lt;/p&gt;
&lt;p&gt;This is a &lt;em&gt;coverage&lt;/em&gt; study, the honest test of any confidence interval. A method that advertises 90% coverage is making a falsifiable promise: across many datasets, its intervals should contain the truth 90% of the time. Fewer than that and the interval is too narrow; the “confidence” is inflated.&lt;/p&gt;
&lt;p&gt;The i.i.d. bootstrap’s nominal 90% interval covered the true mean &lt;strong&gt;49.6% of the time&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Not 90%. Not 85%. A coin flip. Half the time the interval you would have reported, and believed, does not contain the answer, and it never tells you which half you are in.&lt;/p&gt;
&lt;p&gt;Consider what that does to everyday inference. A 90% interval that excludes zero is the standard way people declare an effect “significant” at the 10% level. If that interval is really covering the truth half the time on autocorrelated data, then every such call on the mean of a series with this much dependence carries a one-in-two error rate, not the one-in-ten it advertises. The analyst did nothing careless; the default resampler shipped them the wrong width. I am not claiming this voids any particular published result; I am claiming the gap between 90% and 49.6% is large enough that the burden is on the interval to prove it earned its confidence, and the ordinary bootstrap on a time series has not.&lt;/p&gt;
&lt;p&gt;The moving-block bootstrap, on the same two thousand series, covered the truth &lt;strong&gt;79.7% of the time&lt;/strong&gt;. Its intervals were about twice as wide on average. That extra width is the uncertainty that was really there all along, the uncertainty the i.i.d. bootstrap deleted.&lt;/p&gt;
&lt;span class=&quot;marginnote&quot; role=&quot;note&quot;&gt;The 49.6% is not a fluke of the simulation. You can predict the expected i.i.d. coverage from a closed-form normal approximation using the same &lt;code&gt;phi = 0.7&lt;/code&gt;: it comes out to 51.0%. The measured 49.6% lands within 1.5 percentage points of that (consistent with Monte-Carlo noise), so the undercoverage is structural, not a simulation artifact.&lt;/span&gt;
&lt;figure class=&quot;full&quot; data-astro-cid-bj3fsypb&gt; &lt;div class=&quot;svgfig svgfig-chart&quot; role=&quot;img&quot; aria-label=&quot;Horizontal chart of measured coverage on a single 0 to 100 percent scale. A grey dashed reference rule at 90 percent is labelled &apos;the promise: 90%&apos;. The i.i.d. bootstrap bar, in orange, stops at 49.6 percent and is flagged in vermillion as a coin flip, with a faint 50 percent coin-flip tick beneath it. The moving-block bootstrap bar, in blue, reaches 79.7 percent, most of the way to the rule but visibly short of it.&quot; data-astro-cid-bj3fsypb&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; width=&quot;900&quot; id=&quot;fig-tsb-a1-coverage-gap&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 900 330&quot; role=&quot;img&quot; aria-label=&quot;Horizontal chart of measured coverage on a 0 to 100 percent scale. A grey dashed reference rule at 90 percent is labelled the promise: 90 percent. The i.i.d. bootstrap bar, in orange, stops at 49.6 percent, flagged in vermillion as a coin flip, with a faint 50 percent coin-flip tick beneath it. The moving-block bootstrap bar, in blue, reaches 79.7 percent, most of the way to the rule but short of it.&quot;&gt;&lt;style&gt;#fig-tsb-a1-coverage-gap [fill=&quot;#1a1d23&quot; i]{fill:var(--bg)}#fig-tsb-a1-coverage-gap [stroke=&quot;#1a1d23&quot; i]{stroke:var(--bg)}#fig-tsb-a1-coverage-gap [fill=&quot;#18181b&quot; i]{fill:var(--bg-panel)}#fig-tsb-a1-coverage-gap [stroke=&quot;#18181b&quot; i]{stroke:var(--bg-panel)}#fig-tsb-a1-coverage-gap [fill=&quot;#2c2f37&quot; i]{fill:var(--current-line)}#fig-tsb-a1-coverage-gap [stroke=&quot;#2c2f37&quot; i]{stroke:var(--current-line)}#fig-tsb-a1-coverage-gap [fill=&quot;#f4f5f7&quot; i]{fill:var(--fg)}#fig-tsb-a1-coverage-gap [stroke=&quot;#f4f5f7&quot; i]{stroke:var(--fg)}#fig-tsb-a1-coverage-gap [fill=&quot;#8a8f98&quot; i]{fill:var(--comment)}#fig-tsb-a1-coverage-gap [stroke=&quot;#8a8f98&quot; i]{stroke:var(--comment)}&lt;/style&gt;
&lt;rect width=&quot;900&quot; height=&quot;330&quot; fill=&quot;#1a1d23&quot;/&gt;
&lt;style&gt;
    :where(#cov-root) text { font-family: var(--mono); fill: var(--fg); }
    .cov-title { font-size: 21px; font-weight: bold; }
    .cov-sub { font-size: 16px; fill: var(--comment); }
    .cov-grid { stroke: var(--current-line); stroke-width: 1; }
    .cov-axis { stroke: var(--comment); stroke-width: 1; }
    .cov-tick { font-size: 16px; fill: var(--comment); text-anchor: middle; }
    .cov-atitle { font-size: 16px; fill: var(--fg); font-weight: bold; text-anchor: middle; }
    .cov-row { font-size: 16px; text-anchor: end; dominant-baseline: middle; }
    .cov-rowsub { font-size: 16px; fill: var(--comment); text-anchor: end; dominant-baseline: middle; }
    .cov-valb { font-size: 16px; fill: #56b4e9; font-weight: bold; dominant-baseline: middle; }
    .cov-valo { font-size: 16px; fill: #e69f00; font-weight: bold; dominant-baseline: middle; }
    .cov-flag { font-size: 16px; fill: #d55e00; font-weight: bold; dominant-baseline: middle; }
    .cov-reflab { font-size: 16px; fill: var(--comment); font-weight: bold; text-anchor: middle; }
    .cov-coin { font-size: 16px; fill: var(--comment); text-anchor: middle; opacity: 0.7; }
&lt;/style&gt;
&lt;g id=&quot;cov-root&quot;&gt;
&lt;text class=&quot;cov-title&quot; x=&quot;24&quot; y=&quot;34&quot;&gt;How often the &amp;#8220;90%&amp;#8221; interval held the truth&lt;/text&gt;
&lt;text class=&quot;cov-sub&quot; x=&quot;24&quot; y=&quot;58&quot;&gt;2,000 fresh AR(1) series, phi=0.7, n=200 &amp;#183; same interval recipe, only the resampler differs&lt;/text&gt;
&lt;line class=&quot;cov-grid&quot; x1=&quot;200&quot; y1=&quot;96&quot; x2=&quot;200&quot; y2=&quot;248&quot;/&gt;
&lt;text class=&quot;cov-tick&quot; x=&quot;200&quot; y=&quot;270&quot;&gt;0%&lt;/text&gt;
&lt;line class=&quot;cov-grid&quot; x1=&quot;363&quot; y1=&quot;96&quot; x2=&quot;363&quot; y2=&quot;248&quot;/&gt;
&lt;text class=&quot;cov-tick&quot; x=&quot;363&quot; y=&quot;270&quot;&gt;25%&lt;/text&gt;
&lt;line class=&quot;cov-grid&quot; x1=&quot;526&quot; y1=&quot;96&quot; x2=&quot;526&quot; y2=&quot;248&quot;/&gt;
&lt;text class=&quot;cov-tick&quot; x=&quot;526&quot; y=&quot;270&quot;&gt;50%&lt;/text&gt;
&lt;line class=&quot;cov-grid&quot; x1=&quot;689&quot; y1=&quot;96&quot; x2=&quot;689&quot; y2=&quot;248&quot;/&gt;
&lt;text class=&quot;cov-tick&quot; x=&quot;689&quot; y=&quot;270&quot;&gt;75%&lt;/text&gt;
&lt;line class=&quot;cov-grid&quot; x1=&quot;852&quot; y1=&quot;96&quot; x2=&quot;852&quot; y2=&quot;248&quot;/&gt;
&lt;text class=&quot;cov-tick&quot; x=&quot;852&quot; y=&quot;270&quot;&gt;100%&lt;/text&gt;
&lt;line class=&quot;cov-axis&quot; x1=&quot;200&quot; y1=&quot;248&quot; x2=&quot;852&quot; y2=&quot;248&quot;/&gt;
&lt;line class=&quot;cov-axis&quot; x1=&quot;200&quot; y1=&quot;96&quot; x2=&quot;200&quot; y2=&quot;248&quot;/&gt;
&lt;text class=&quot;cov-atitle&quot; x=&quot;526&quot; y=&quot;300&quot;&gt;share of intervals that contained the true mean&lt;/text&gt;
&lt;line x1=&quot;786.8&quot; y1=&quot;90&quot; x2=&quot;786.8&quot; y2=&quot;248&quot; stroke=&quot;#8a8f98&quot; stroke-width=&quot;2&quot; stroke-dasharray=&quot;6 4&quot;/&gt;
&lt;rect x=&quot;698.8&quot; y=&quot;73&quot; width=&quot;176&quot; height=&quot;20&quot; fill=&quot;#1a1d23&quot;/&gt;
&lt;text class=&quot;cov-reflab&quot; x=&quot;786.8&quot; y=&quot;87&quot;&gt;the promise: 90%&lt;/text&gt;
&lt;text class=&quot;cov-row&quot; x=&quot;192&quot; y=&quot;114&quot;&gt;i.i.d.&lt;/text&gt;
&lt;text class=&quot;cov-rowsub&quot; x=&quot;192&quot; y=&quot;132&quot;&gt;(naive baseline)&lt;/text&gt;
&lt;rect x=&quot;200&quot; y=&quot;106&quot; width=&quot;323.4&quot; height=&quot;34&quot; fill=&quot;#e69f00&quot;/&gt;
&lt;text class=&quot;cov-valo&quot; x=&quot;533.4&quot; y=&quot;123&quot;&gt;49.6%&lt;/text&gt;
&lt;text class=&quot;cov-flag&quot; x=&quot;599.4&quot; y=&quot;123&quot;&gt;&amp;#9664; a coin flip&lt;/text&gt;
&lt;line x1=&quot;526&quot; y1=&quot;144&quot; x2=&quot;526&quot; y2=&quot;154&quot; stroke=&quot;#8a8f98&quot; stroke-width=&quot;1.5&quot; opacity=&quot;0.7&quot;/&gt;
&lt;text class=&quot;cov-coin&quot; x=&quot;526&quot; y=&quot;172&quot;&gt;coin flip: 50%&lt;/text&gt;
&lt;text class=&quot;cov-row&quot; x=&quot;192&quot; y=&quot;204&quot;&gt;moving&lt;/text&gt;
&lt;text class=&quot;cov-rowsub&quot; x=&quot;192&quot; y=&quot;222&quot;&gt;block&lt;/text&gt;
&lt;rect x=&quot;200&quot; y=&quot;196&quot; width=&quot;519.6&quot; height=&quot;34&quot; fill=&quot;#56b4e9&quot;/&gt;
&lt;text class=&quot;cov-valb&quot; x=&quot;729.6&quot; y=&quot;213&quot;&gt;79.7%&lt;/text&gt;
&lt;/g&gt;&lt;/svg&gt;
&lt;/div&gt; &lt;figcaption data-astro-cid-bj3fsypb&gt;The promise against the delivery, on one scale. Both methods advertise the same 90% (grey rule). The i.i.d. bootstrap delivers 49.6%, a coin flip wearing a confidence interval; the moving-block bootstrap delivers 79.7%, most of the way back and measurably not all of it.&lt;/figcaption&gt; &lt;details class=&quot;data-table&quot; data-astro-cid-bj3fsypb&gt; &lt;summary data-astro-cid-bj3fsypb&gt;data table&lt;/summary&gt;  &lt;div class=&quot;data-table-scroll&quot; data-astro-cid-bj3fsypb&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;quantity&lt;/th&gt;&lt;th&gt;coverage&lt;/th&gt;&lt;th&gt;reads as&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;nominal (the promise)&lt;/td&gt;&lt;td&gt;90%&lt;/td&gt;&lt;td&gt;the yardstick&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;i.i.d. bootstrap&lt;/td&gt;&lt;td&gt;49.6%&lt;/td&gt;&lt;td&gt;a coin flip&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;moving-block bootstrap&lt;/td&gt;&lt;td&gt;79.7%&lt;/td&gt;&lt;td&gt;most of the way back&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt; &lt;/details&gt; &lt;/figure&gt; 
&lt;p&gt;But 79.7% is not 90% either. The block bootstrap recovers most of the gap the i.i.d. bootstrap opens, and it stops short. At a series this short, block resampling still understates the truth: you can see it coming in the chart above, where even the tallest block bar fell shy of the grey line. The two shortfalls are not the same kind of wrong: give the block bootstrap a longer series and its coverage climbs toward the 90% it promises, while the i.i.d. bootstrap’s gap never closes, because it is baked into the resampler rather than the sample size. Block bootstrapping is the right tool here, and it is honest about its own limits; a piece that sold it as a cure would be committing a smaller version of the same sin I am describing. An interval that delivers half its promised coverage is a different category of wrong.&lt;/p&gt;
&lt;h2 id=&quot;the-fix-is-contiguity-and-it-is-one-argument&quot;&gt;The fix is contiguity, and it is one argument&lt;a class=&quot;heading-anchor&quot; href=&quot;#the-fix-is-contiguity-and-it-is-one-argument&quot; aria-label=&quot;Link to this section&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Everything above reduces to a single call. The library takes the observed series, the statistic you care about, and a &lt;em&gt;method&lt;/em&gt; (a typed description of how to resample) and returns the interval:&lt;/p&gt;
&lt;div class=&quot;codeblock&quot;&gt;&lt;div class=&quot;codeblock-head&quot;&gt;&lt;span class=&quot;lang&quot;&gt;python&lt;/span&gt;&lt;button type=&quot;button&quot; class=&quot;copy-btn&quot; data-copy aria-label=&quot;Copy code&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect width=&quot;14&quot; height=&quot;14&quot; x=&quot;8&quot; y=&quot;8&quot; rx=&quot;2&quot; ry=&quot;2&quot;&gt;&lt;/rect&gt;&lt;path d=&quot;M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span class=&quot;copy-label&quot;&gt;Copy&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark-default&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e6edf3;--shiki-light-bg:#fff;--shiki-dark-bg:#0d1117;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; numpy &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; np&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; tsbootstrap &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt; IID&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;, MovingBlock, conf_int&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#8B949E&quot;&gt;# an AR(1) series, phi=0.7, n=200, whose true mean is exactly 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#D2A8FF&quot;&gt; ar1&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;(n, phi, seed, burnin&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;500&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;    rng &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; np.random.default_rng(seed)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;    e &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; rng.standard_normal(n &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; burnin)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;    x &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; np.empty(n &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; burnin)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;    x[&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; e[&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; t &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;, n &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; burnin):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;        x[t] &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; phi &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; x[t &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; e[t]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; x[burnin:]                      &lt;/span&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#8B949E&quot;&gt;# drop the burn-in; true mean = 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;x &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; ar1(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;n&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;200&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;phi&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;0.7&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;seed&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;42&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#8B949E&quot;&gt;# the lie: resample observations independently&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;lo, hi, point &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; conf_int(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;    x, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#A5D6FF&quot;&gt;&amp;quot;mean&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;method&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;IID(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;    alpha&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;0.10&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;random_state&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#8B949E&quot;&gt;# -&amp;gt; (-0.508, -0.188)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#8B949E&quot;&gt;# a 90% interval that excludes the true mean, 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#8B949E&quot;&gt;# the fix: resample contiguous blocks, length chosen automatically&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;lo, hi, point &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; conf_int(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;    x, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#A5D6FF&quot;&gt;&amp;quot;mean&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;method&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;MovingBlock(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;block_length&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#A5D6FF&quot;&gt;&amp;quot;auto&amp;quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;    alpha&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;0.10&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;random_state&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#8B949E&quot;&gt;# -&amp;gt; (-0.556, 0.022)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#8B949E&quot;&gt;# now the truth is inside&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The only thing that changed between the lie and the fix is the &lt;code&gt;method&lt;/code&gt;. That is deliberate. There is a small family of block bootstraps (moving, circular, stationary, tapered) and they differ in how they cut the series into blocks and stitch them back together. Each is the right answer to a slightly different question about your data’s structure. The one that chose the block length above did it with a standard automatic rule (Politis and White’s spectral plug-in estimator, the textbook default), so you get a defensible answer with no tuning; a hand-picked length could squeeze out more of the residual gap, but that is a refinement.&lt;/p&gt;
&lt;p&gt;The headline is the thesis this whole series is built on, and it is worth stating plainly, because every later piece is a variation on it: &lt;strong&gt;match the resampler to the assumption your data violates.&lt;/strong&gt; The i.i.d. bootstrap violates independence on a time series and pays for it in coverage. Later you will meet data that breaks &lt;em&gt;other&lt;/em&gt; assumptions (errors whose variance shifts over time, models whose residuals are themselves dependent), and each one has a resampling scheme built to respect what it breaks. The bootstrap is not one tool. It is a question you have to answer honestly: what does my data actually do?&lt;/p&gt;
&lt;h2 id=&quot;what-i-now-check-before-i-trust-an-interval&quot;&gt;What I now check before I trust an interval&lt;a class=&quot;heading-anchor&quot; href=&quot;#what-i-now-check-before-i-trust-an-interval&quot; aria-label=&quot;Link to this section&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I still bootstrap everything. But I no longer read a tight interval as good news, and I no longer reach for the default resampler on data that has an order.&lt;/p&gt;






























&lt;div class=&quot;table-scroll&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;what I read as true&lt;/th&gt;&lt;th&gt;what was actually true&lt;/th&gt;&lt;th&gt;the rule it became&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;a tight interval means a precise estimate&lt;/td&gt;&lt;td&gt;on autocorrelated data, a tight interval means the resampler deleted the dependence&lt;/td&gt;&lt;td&gt;narrowness is a red flag on a time series, not a comfort&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;the bootstrap is assumption-free&lt;/td&gt;&lt;td&gt;the ordinary bootstrap assumes your observations are interchangeable&lt;/td&gt;&lt;td&gt;name the assumption before you resample, because the default has one&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;a 90% interval covers the truth 90% of the time&lt;/td&gt;&lt;td&gt;this one covered it 49.6% of the time&lt;/td&gt;&lt;td&gt;test coverage against a known truth before you trust a method on an unknown one&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;the block bootstrap fixes it&lt;/td&gt;&lt;td&gt;it recovered coverage to 79.7%, not 90%&lt;/td&gt;&lt;td&gt;the right tool can still undercover; honesty about the residual gap is part of the fix&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;The interval I opened with, &lt;code&gt;[-0.51, -0.19]&lt;/code&gt;, still sits in my terminal history. It is a perfectly ordinary-looking result: a signed effect, a tight band, ninety percent confidence. It is also a statement about data with a mean of zero that the mean is not zero. Nothing about the number looks like a lie, which is why the ordinary bootstrap gets away with telling it. Change one argument (resample the blocks, not the points) and, on this series, the truth climbs back inside the interval, where it was the whole time.&lt;/p&gt;
&lt;section class=&quot;faq&quot; aria-label=&quot;Frequently asked questions&quot; data-astro-cid-z6gx6xcw&gt; &lt;h2 data-astro-cid-z6gx6xcw&gt;Frequently asked questions&lt;/h2&gt; &lt;div class=&quot;faq-list&quot; data-astro-cid-z6gx6xcw&gt; &lt;details class=&quot;faq-item&quot; open data-astro-cid-z6gx6xcw&gt; &lt;summary data-astro-cid-z6gx6xcw&gt;What is tsbootstrap?&lt;/summary&gt; &lt;div class=&quot;faq-a&quot; data-astro-cid-z6gx6xcw&gt;tsbootstrap is a time series bootstrap library for Python. It resamples a series while preserving the temporal dependence that an ordinary bootstrap destroys, using the methods the statistics literature recommends (block, residual, sieve, and wild resampling) plus a conformal layer for prediction intervals. The public API is one &lt;code data-astro-cid-z6gx6xcw&gt;bootstrap&lt;/code&gt; call configured with a typed method spec, and a &lt;code data-astro-cid-z6gx6xcw&gt;conf_int&lt;/code&gt; helper that runs the bootstrap and reads the interval in one call.&lt;/div&gt; &lt;/details&gt;&lt;details class=&quot;faq-item&quot; open data-astro-cid-z6gx6xcw&gt; &lt;summary data-astro-cid-z6gx6xcw&gt;Why does the ordinary bootstrap fail on time series data?&lt;/summary&gt; &lt;div class=&quot;faq-a&quot; data-astro-cid-z6gx6xcw&gt;The ordinary (i.i.d.) bootstrap resamples observations independently, which assumes they carry no information about each other. A time series violates that: consecutive values are correlated. Resampling single points at random destroys the autocorrelation, so the resampled series looks more random than the real one and the bootstrap reports a standard error that is too small. On an AR(1) series with autocorrelation 0.7, the i.i.d. standard error of the mean comes out about 2.4 times too small.&lt;/div&gt; &lt;/details&gt;&lt;details class=&quot;faq-item&quot; open data-astro-cid-z6gx6xcw&gt; &lt;summary data-astro-cid-z6gx6xcw&gt;What is a block bootstrap and how does it fix this?&lt;/summary&gt; &lt;div class=&quot;faq-a&quot; data-astro-cid-z6gx6xcw&gt;A block bootstrap resamples contiguous chunks (blocks) of consecutive observations instead of single points. Because each block is a run of real, adjacent data, it carries the local dependence with it, so the resampled series keeps the autocorrelation of the original. That gives a standard error and confidence interval that reflect the real, reduced information content of dependent data. In tsbootstrap you select it by passing &lt;code data-astro-cid-z6gx6xcw&gt;method=MovingBlock(block_length=&amp;quot;auto&amp;quot;)&lt;/code&gt; to &lt;code data-astro-cid-z6gx6xcw&gt;bootstrap&lt;/code&gt; or &lt;code data-astro-cid-z6gx6xcw&gt;conf_int&lt;/code&gt;; the &lt;code data-astro-cid-z6gx6xcw&gt;&amp;quot;auto&amp;quot;&lt;/code&gt; length comes from Politis and White&amp;#39;s spectral plug-in estimator, the textbook default rule.&lt;/div&gt; &lt;/details&gt;&lt;details class=&quot;faq-item&quot; open data-astro-cid-z6gx6xcw&gt; &lt;summary data-astro-cid-z6gx6xcw&gt;Does the block bootstrap give perfectly correct confidence intervals?&lt;/summary&gt; &lt;div class=&quot;faq-a&quot; data-astro-cid-z6gx6xcw&gt;No, and it should not be sold as if it does. In a 2,000-run coverage study on AR(1) data (*phi* = 0.7, *n* = 200), the moving-block bootstrap&amp;#39;s nominal 90% interval covered the true mean 79.7% of the time, versus 49.6% for the i.i.d. bootstrap. It recovers most of the gap but still undercovers at short series lengths. The block bootstrap is the right tool, an honest improvement that falls short of exact coverage.&lt;/div&gt; &lt;/details&gt; &lt;/div&gt; &lt;script type=&quot;application/ld+json&quot;&gt;{&quot;@context&quot;:&quot;https://schema.org&quot;,&quot;@type&quot;:&quot;FAQPage&quot;,&quot;mainEntity&quot;:[{&quot;@type&quot;:&quot;Question&quot;,&quot;name&quot;:&quot;What is tsbootstrap?&quot;,&quot;acceptedAnswer&quot;:{&quot;@type&quot;:&quot;Answer&quot;,&quot;text&quot;:&quot;tsbootstrap is a time series bootstrap library for Python. It resamples a series while preserving the temporal dependence that an ordinary bootstrap destroys, using the methods the statistics literature recommends (block, residual, sieve, and wild resampling) plus a conformal layer for prediction intervals. The public API is one bootstrap call configured with a typed method spec, and a conf_int helper that runs the bootstrap and reads the interval in one call.&quot;}},{&quot;@type&quot;:&quot;Question&quot;,&quot;name&quot;:&quot;Why does the ordinary bootstrap fail on time series data?&quot;,&quot;acceptedAnswer&quot;:{&quot;@type&quot;:&quot;Answer&quot;,&quot;text&quot;:&quot;The ordinary (i.i.d.) bootstrap resamples observations independently, which assumes they carry no information about each other. A time series violates that: consecutive values are correlated. Resampling single points at random destroys the autocorrelation, so the resampled series looks more random than the real one and the bootstrap reports a standard error that is too small. On an AR(1) series with autocorrelation 0.7, the i.i.d. standard error of the mean comes out about 2.4 times too small.&quot;}},{&quot;@type&quot;:&quot;Question&quot;,&quot;name&quot;:&quot;What is a block bootstrap and how does it fix this?&quot;,&quot;acceptedAnswer&quot;:{&quot;@type&quot;:&quot;Answer&quot;,&quot;text&quot;:&quot;A block bootstrap resamples contiguous chunks (blocks) of consecutive observations instead of single points. Because each block is a run of real, adjacent data, it carries the local dependence with it, so the resampled series keeps the autocorrelation of the original. That gives a standard error and confidence interval that reflect the real, reduced information content of dependent data. In tsbootstrap you select it by passing method=MovingBlock(block_length=\&quot;auto\&quot;) to bootstrap or conf_int; the \&quot;auto\&quot; length comes from Politis and White&apos;s spectral plug-in estimator, the textbook default rule.&quot;}},{&quot;@type&quot;:&quot;Question&quot;,&quot;name&quot;:&quot;Does the block bootstrap give perfectly correct confidence intervals?&quot;,&quot;acceptedAnswer&quot;:{&quot;@type&quot;:&quot;Answer&quot;,&quot;text&quot;:&quot;No, and it should not be sold as if it does. In a 2,000-run coverage study on AR(1) data (*phi* = 0.7, *n* = 200), the moving-block bootstrap&apos;s nominal 90% interval covered the true mean 79.7% of the time, versus 49.6% for the i.i.d. bootstrap. It recovers most of the gap but still undercovers at short series lengths. The block bootstrap is the right tool, an honest improvement that falls short of exact coverage.&quot;}}]}&lt;/script&gt; &lt;/section&gt; &lt;!-- Mobile collapse (UX audit F-40): each Q/A pair is a &lt;details&gt;, server-rendered
     OPEN so the answers are visible with no JS, in print, on desktop, and to crawlers
     (the full text is always in the DOM; the FAQPage JSON-LD above is untouched).
     At phone widths this script collapses the pairs so the questions are scannable
     and an answer expands on tap; widening the viewport re-opens everything (which
     also repairs any keyboard-toggled state before the desktop pointer-events lock
     makes it unreachable). astro:page-load covers view-transition navigations. --&gt; &lt;script type=&quot;module&quot; src=&quot;https://thepragmaticquant.com/vercel/path0/src/components/Faq.astro?astro&amp;type=script&amp;index=0&amp;lang.ts&quot;&gt;&lt;/script&gt;
&lt;p&gt;The ordinary bootstrap, pointed at a time series, breaks the coverage promise by a wide margin and without a warning. The next piece takes a different broken assumption (errors whose variance shifts over time) and the resampler built to respect it.&lt;/p&gt;</content:encoded><category>tsbootstrap</category><category>time-series</category><category>bootstrap</category><category>statistics</category></item><item><title>When your errors aren’t equal</title><link>https://thepragmaticquant.com/when-your-errors-arent-equal/</link><guid isPermaLink="true">https://thepragmaticquant.com/when-your-errors-arent-equal/</guid><description>The residual bootstrap assumes your model’s errors all come from the same distribution. Feed it a series whose noise grows over time and it quietly shuffles the loud errors in among the quiet ones, averaging the variance away, and hands back a standard error at three-quarters of the truth. Here is the failure on real numbers, and the wild bootstrap: a fix so simple it sounds like a joke. Keep every residual exactly where it is. Just flip its sign at random.</description><pubDate>Mon, 06 Jul 2026 00:00:00 GMT</pubDate><content:encoded>
&lt;div class=&quot;tldr&quot;&gt;&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: The residual bootstrap resamples your model’s errors by shuffling them across time, which silently assumes every error was drawn from the same distribution. When the error variance shifts over time (larger in some regimes than others) that shuffle averages the variance profile away, and the price is a standard error that is too small exactly where it matters. On a heteroskedastic autoregression I built, the shuffle recovered on average only &lt;strong&gt;78%&lt;/strong&gt; of the true standard error of the slope, and its nominal 90% confidence interval covered the truth &lt;strong&gt;79.1%&lt;/strong&gt; of the time.&lt;/p&gt;&lt;p&gt;The wild bootstrap (keep each residual at its own time position, multiply it by a random sign) recovered &lt;strong&gt;100%&lt;/strong&gt; of the true standard error and lifted coverage to &lt;strong&gt;88.8%&lt;/strong&gt;. Same model and data; one argument changed.&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;I built a time series whose errors I controlled completely, because I wrote the noise myself: an AR(1) with slope 0.5 (each value is half the previous value plus a fresh random shock, so the 0.5 is a slope you can fit like any regression), six hundred points long, where the shocks in the second half are three times louder than in the first, nine times the variance. Then I fit the model, asked a residual bootstrap for the standard error of that slope (the typical miss between the fitted 0.5 and the truth) and compared it to the truth, which I can compute to four decimal places by brute force because I own the data-generating process. The truth is 0.0453. The bootstrap said 0.034.&lt;/p&gt;
&lt;p&gt;That is not a rounding disagreement. It is a quarter of the uncertainty, gone, on a series where nothing was misspecified and the bootstrap did exactly what it was designed to do. In the &lt;a href=&quot;https://thepragmaticquant.com/your-bootstrap-is-lying-to-you/&quot;&gt;first piece in this series&lt;/a&gt;, the ordinary bootstrap lied by shredding autocorrelation, and the block bootstrap fixed it by resampling contiguous chunks. This is the second failure mode, and it lives one layer deeper: not in how you resample the &lt;em&gt;observations&lt;/em&gt;, but in how you resample the model’s &lt;em&gt;errors&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-bootstrap-under-the-bootstrap&quot;&gt;The bootstrap under the bootstrap&lt;a class=&quot;heading-anchor&quot; href=&quot;#the-bootstrap-under-the-bootstrap&quot; aria-label=&quot;Link to this section&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The block methods from the first article resample the observed series directly. There is a second family, the &lt;em&gt;residual bootstrap&lt;/em&gt;, that goes through a model instead: fit the model, collect the leftover errors it could not explain (the &lt;em&gt;residuals&lt;/em&gt;), resample those, and rebuild synthetic series by running the fitted model forward on the resampled errors. It is the natural choice when you trust the model’s structure and want uncertainty on its parameters, which is precisely the situation of anyone bootstrapping a regression slope, an autoregression coefficient, or a fitted forecast.&lt;/p&gt;
&lt;p&gt;And how does it resample the residuals? The default answer is the same default as always: independently and uniformly, with replacement. Pick a residual at random from anywhere in the series, put it back, pick another. Which is a mathematical statement that the residuals are &lt;em&gt;exchangeable&lt;/em&gt;, that the error the model made at time 12 could just as well have happened at time 580, because they all came from one common distribution.&lt;/p&gt;
&lt;p&gt;There is a name for the property that assumption requires: &lt;em&gt;homoskedasticity&lt;/em&gt;, from the Greek for “same scatter”: the error variance is constant over the whole series. Its violation, &lt;em&gt;heteroskedasticity&lt;/em&gt; (“different scatter”), shows up everywhere: financial returns in calm and turbulent regimes, sensor noise at different temperatures, forecast errors between weekdays and holidays. If your data was collected over any interesting stretch of time, the odds are good its noise level did not hold still. The check is cheap: plot the squared or absolute residuals in time order and look for a level that drifts or steps.&lt;/p&gt;
&lt;h2 id=&quot;the-tight-number-i-believed&quot;&gt;The tight number I believed&lt;a class=&quot;heading-anchor&quot; href=&quot;#the-tight-number-i-believed&quot; aria-label=&quot;Link to this section&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I did not go looking for this failure. It turned up in a mean-reversion estimate I once made on a spread whose noise regime changed partway through the sample: a venue migration, roughly doubling the tick-to-tick noise from that date on. I knew better than to trust a textbook formula, so I bootstrapped the reversion coefficient’s standard error from the fitted model’s residuals and got a satisfyingly tight number. What I did not register was that my resampler was lifting residuals from the loud months and planting them in the quiet months, and vice versa, building synthetic histories in which the noise regime never changed at all. The tight standard error was a measurement of those counterfeit series. The strategy sized off that estimate was, in hindsight, sized off roughly three quarters of the real uncertainty; it survived, but by luck rather than arithmetic, and I only worked out why long after the trade was closed.&lt;/p&gt;
&lt;p&gt;As in the first article, nothing looked wrong: a residual bootstrap on a fitted model is the &lt;em&gt;responsible&lt;/em&gt; choice. The failure has no error message.&lt;/p&gt;
&lt;h2 id=&quot;shuffling-averages-the-variance-away&quot;&gt;Shuffling averages the variance away&lt;a class=&quot;heading-anchor&quot; href=&quot;#shuffling-averages-the-variance-away&quot; aria-label=&quot;Link to this section&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The mechanism fits in one sentence: &lt;strong&gt;shuffling residuals averages the variance away; flipping their signs keeps it in place.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In my built series, the second-half residuals are three times larger than the first-half ones, and, this is the load-bearing detail, the second half is also where the series itself swings widest, since louder shocks push the process further from its mean. The uncertainty of a regression slope is dominated by the errors that sit on the extreme values of the regressor (the input on the x-axis of the fit, which for an AR(1) is simply yesterday’s value). A big error on a big swing tilts the fitted line hard. Heteroskedasticity that is &lt;em&gt;correlated with the regressor level&lt;/em&gt; concentrates the largest errors exactly where they do the most damage, and an honest standard error has to account for that.&lt;/p&gt;
&lt;p&gt;The i.i.d. shuffle (independent and identically distributed) destroys the correlation. It takes the loud residuals and scatters them uniformly across time, so in the synthetic series a big error is no likelier to land on a big swing than a quiet one is. Averaged over replicates, every time position experiences the &lt;em&gt;average&lt;/em&gt; error variance: the profile is flattened and the slope wobbles less than it truly would. The bootstrap then reports that reduced wobble as your standard error. On my series: 0.034 reported, 0.0453 true.&lt;/p&gt;
&lt;figure class=&quot;full&quot; data-astro-cid-bj3fsypb&gt; &lt;video autoplay muted loop playsinline preload=&quot;none&quot; poster=&quot;/assets/terminal/tsb-wb-signflip.frame1.png&quot; aria-label=&quot;An animated loop that returns to this labelled still. Top panel: the residual bars of a fitted AR(1) in time order, visibly quiet in the first half and loud in the second. Per replicate, each bar flips sign in place at random (magnitudes and positions never move), drawn in blue and labelled &apos;wild: flip in place&apos;. A small orange inset labelled &apos;i.i.d.: shuffle&apos; shows the same bars scattered across time, the loud-half profile flattened into a uniform band. Bottom panel: a translucent envelope of refitted slope lines accumulates replicate by replicate; a running standard-error readout converges to 0.045 in blue, beside the collapsed i.i.d. readout at 0.034 in orange, against a grey Monte-Carlo-truth rule at 0.0453.&quot; class=&quot;has-portrait&quot; data-poster-portrait=&quot;/assets/terminal/tsb-wb-signflip.portrait.frame1.png&quot; data-astro-cid-bj3fsypb&gt; &lt;source src=&quot;https://thepragmaticquant.com/assets/terminal/tsb-wb-signflip.portrait.webm&quot; type=&quot;video/webm&quot; media=&quot;(max-width: 620px)&quot; data-astro-cid-bj3fsypb&gt; &lt;source src=&quot;https://thepragmaticquant.com/assets/terminal/tsb-wb-signflip.portrait.mp4&quot; type=&quot;video/mp4&quot; media=&quot;(max-width: 620px)&quot; data-astro-cid-bj3fsypb&gt; &lt;source src=&quot;https://thepragmaticquant.com/assets/terminal/tsb-wb-signflip.webm&quot; type=&quot;video/webm&quot; data-astro-cid-bj3fsypb&gt; &lt;source src=&quot;https://thepragmaticquant.com/assets/terminal/tsb-wb-signflip.mp4&quot; type=&quot;video/mp4&quot; data-astro-cid-bj3fsypb&gt; &lt;/video&gt; &lt;figcaption data-astro-cid-bj3fsypb&gt;The same fitted residuals, resampled two ways. The wild bootstrap keeps every residual at its own time position and only randomizes its sign, so the loud half of the series stays loud in every replicate, and the refitted slopes spread out to the honest width. The i.i.d. shuffle relocates the residuals, flattening the variance profile, and reports a standard error a quarter too small.&lt;/figcaption&gt; &lt;details class=&quot;data-table&quot; data-astro-cid-bj3fsypb&gt; &lt;summary data-astro-cid-bj3fsypb&gt;data table&lt;/summary&gt;  &lt;div class=&quot;data-table-scroll&quot; data-astro-cid-bj3fsypb&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;quantity&lt;/th&gt;&lt;th&gt;SE of the slope&lt;/th&gt;&lt;th&gt;reads as&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;i.i.d.-residual shuffle&lt;/td&gt;&lt;td&gt;0.034&lt;/td&gt;&lt;td&gt;the collapse (variance profile averaged away)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;wild (Rademacher flips)&lt;/td&gt;&lt;td&gt;0.045&lt;/td&gt;&lt;td&gt;variance kept where it lives&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Monte-Carlo truth (200k draws)&lt;/td&gt;&lt;td&gt;0.0453&lt;/td&gt;&lt;td&gt;the yardstick&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt; &lt;/details&gt; &lt;/figure&gt; &lt;script type=&quot;module&quot; src=&quot;https://thepragmaticquant.com/vercel/path0/src/components/Figure.astro?astro&amp;type=script&amp;index=0&amp;lang.ts&quot;&gt;&lt;/script&gt;
&lt;h2 id=&quot;flip-the-signs-instead&quot;&gt;Flip the signs instead&lt;a class=&quot;heading-anchor&quot; href=&quot;#flip-the-signs-instead&quot; aria-label=&quot;Link to this section&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now the second half of the sentence. The &lt;em&gt;wild bootstrap&lt;/em&gt; refuses to move anything. Each synthetic error is the original residual, at its original time position, multiplied by a fresh random draw:&lt;/p&gt;
&lt;div class=&quot;codeblock&quot;&gt;&lt;div class=&quot;codeblock-head&quot;&gt;&lt;span class=&quot;lang&quot;&gt;math&lt;/span&gt;&lt;button type=&quot;button&quot; class=&quot;copy-btn&quot; data-copy aria-label=&quot;Copy code&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect width=&quot;14&quot; height=&quot;14&quot; x=&quot;8&quot; y=&quot;8&quot; rx=&quot;2&quot; ry=&quot;2&quot;&gt;&lt;/rect&gt;&lt;path d=&quot;M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span class=&quot;copy-label&quot;&gt;Copy&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msubsup&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo&gt;∗&lt;/mo&gt;&lt;/msubsup&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/msub&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;msub&gt;&lt;mover accent=&quot;true&quot;&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo&gt;^&lt;/mo&gt;&lt;/mover&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;e_t^* = v_t \, \hat{e}_t&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.9857em;vertical-align:-0.247em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7387em&quot;&gt;&lt;span style=&quot;top:-2.453em;margin-left:0em;margin-right:0.05em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mbin mtight&quot;&gt;∗&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.247em&quot;&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=&quot;mspace&quot; style=&quot;margin-right:0.2778em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8444em;vertical-align:-0.15em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2806em&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0359em;margin-right:0.05em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em&quot;&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=&quot;mspace&quot; style=&quot;margin-right:0.1667em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord accent&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6944em&quot;&gt;&lt;span style=&quot;top:-3em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;accent-body&quot; style=&quot;left:-0.1944em&quot;&gt;&lt;span class=&quot;mord&quot;&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=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2806em&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em&quot;&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&gt;&lt;/div&gt;
&lt;p&gt;where the multiplier &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;v_t&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.5806em;vertical-align:-0.15em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2806em&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0359em;margin-right:0.05em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em&quot;&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; is drawn independently at each &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;t&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6151em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; from a distribution satisfying two moment conditions:&lt;/p&gt;
&lt;div class=&quot;codeblock&quot;&gt;&lt;div class=&quot;codeblock-head&quot;&gt;&lt;span class=&quot;lang&quot;&gt;math&lt;/span&gt;&lt;button type=&quot;button&quot; class=&quot;copy-btn&quot; data-copy aria-label=&quot;Copy code&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect width=&quot;14&quot; height=&quot;14&quot; x=&quot;8&quot; y=&quot;8&quot; rx=&quot;2&quot; ry=&quot;2&quot;&gt;&lt;/rect&gt;&lt;path d=&quot;M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span class=&quot;copy-label&quot;&gt;Copy&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;double-struck&quot;&gt;E&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mspace width=&quot;2em&quot;&gt;&lt;/mspace&gt;&lt;mi mathvariant=&quot;double-struck&quot;&gt;E&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;1.&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbb{E}[v] = 0, \qquad \mathbb{E}[v^2] = 1 .&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathbb&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.1141em;vertical-align:-0.25em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:2em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathbb&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8641em&quot;&gt;&lt;span style=&quot;top:-3.113em;margin-right:0.05em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&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=&quot;mclose&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;Mean zero makes the synthetic errors centered, like errors should be. Variance one is the trick: it means &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msubsup&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo&gt;∗&lt;/mo&gt;&lt;/msubsup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;e_t^*&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.9357em;vertical-align:-0.247em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6887em&quot;&gt;&lt;span style=&quot;top:-2.453em;margin-left:0em;margin-right:0.05em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mbin mtight&quot;&gt;∗&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.247em&quot;&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; has &lt;em&gt;exactly&lt;/em&gt; the variance of &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mover accent=&quot;true&quot;&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo&gt;^&lt;/mo&gt;&lt;/mover&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\hat{e}_t&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8444em;vertical-align:-0.15em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord accent&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6944em&quot;&gt;&lt;span style=&quot;top:-3em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;accent-body&quot; style=&quot;left:-0.1944em&quot;&gt;&lt;span class=&quot;mord&quot;&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=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2806em&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em&quot;&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;, at every single &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;t&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6151em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; (the multiplier is drawn independently of the residual, so &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;Var&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/msub&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;msub&gt;&lt;mover accent=&quot;true&quot;&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo&gt;^&lt;/mo&gt;&lt;/mover&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi mathvariant=&quot;double-struck&quot;&gt;E&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;msubsup&gt;&lt;mover accent=&quot;true&quot;&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo&gt;^&lt;/mo&gt;&lt;/mover&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msubsup&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msubsup&gt;&lt;mover accent=&quot;true&quot;&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo&gt;^&lt;/mo&gt;&lt;/mover&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msubsup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\operatorname{Var}(v_t \, \hat{e}_t) = \mathbb{E}[v^2] \, \hat{e}_t^2 = \hat{e}_t^2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;&lt;span class=&quot;mord mathrm&quot;&gt;Var&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2806em&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0359em;margin-right:0.05em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em&quot;&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=&quot;mspace&quot; style=&quot;margin-right:0.1667em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord accent&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6944em&quot;&gt;&lt;span style=&quot;top:-3em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;accent-body&quot; style=&quot;left:-0.1944em&quot;&gt;&lt;span class=&quot;mord&quot;&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=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2806em&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em&quot;&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=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.0641em;vertical-align:-0.25em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathbb&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&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=&quot;mclose&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord accent&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6944em&quot;&gt;&lt;span style=&quot;top:-3em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;accent-body&quot; style=&quot;left:-0.1944em&quot;&gt;&lt;span class=&quot;mord&quot;&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=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em&quot;&gt;&lt;span style=&quot;top:-2.453em;margin-left:0em;margin-right:0.05em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.247em&quot;&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=&quot;mspace&quot; style=&quot;margin-right:0.2778em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.0611em;vertical-align:-0.247em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord accent&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.6944em&quot;&gt;&lt;span style=&quot;top:-3em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:3em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;accent-body&quot; style=&quot;left:-0.1944em&quot;&gt;&lt;span class=&quot;mord&quot;&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=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em&quot;&gt;&lt;span style=&quot;top:-2.453em;margin-left:0em;margin-right:0.05em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.247em&quot;&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;). A loud residual stays loud, a quiet one stays quiet, and the whole variance profile, whatever shape it has, known or unknown, is preserved by construction. You never estimate the heteroskedasticity; you just decline to destroy it.&lt;/p&gt;
&lt;p&gt;The simplest distribution meeting both conditions is the &lt;em&gt;Rademacher&lt;/em&gt;: &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;v = +1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.4306em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7278em;vertical-align:-0.0833em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; or &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;-1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7278em;vertical-align:-0.0833em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, a fair coin. Under it, the wild bootstrap literally just flips residual signs, which sounds too crude to work, except that a sign flip is exactly as much randomness as a resampler needs: the refit cares only about which way each error pushes the line and how hard, and the flip randomizes the direction while the residual keeps the how-hard. Some multipliers add a third condition, &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;double-struck&quot;&gt;E&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathbb{E}[v^3] = 1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.0641em;vertical-align:-0.25em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathbb&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141em&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;3&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=&quot;mclose&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, which additionally preserves each residual’s &lt;em&gt;skewness&lt;/em&gt; (the asymmetry of the errors, not just their size). That is why the Mammen two-point distribution exists, with its odd-looking golden-ratio values: it is the two-point law that satisfies all three conditions at once. The working answer: use the coin, and reach for Mammen only when the errors are strongly skewed and the asymmetry of the interval matters.&lt;/p&gt;
&lt;span class=&quot;marginnote&quot; role=&quot;note&quot;&gt;The coin flip is the actual literature recommendation, crude as it looks. Davidson and Flachaire (2008) found the Rademacher version generally performs best in practice even on skewed errors, which is why it is the default here and in most implementations. Mammen (1993) supplied the theory for the skewness-preserving alternative.&lt;/span&gt;
&lt;figure class data-astro-cid-bj3fsypb&gt; &lt;div class=&quot;svgfig svgfig-chart&quot; role=&quot;img&quot; aria-label=&quot;Three stacked panels, one per row, each on its own identical horizontal axis. Rademacher: two point masses at minus 1 and plus 1, each probability one half. Mammen: two point masses at minus 0.618 with probability 0.724 and plus 1.618 with probability 0.276, annotated E[v cubed] equals 1. Gaussian: the standard normal curve. All three annotated E[v] equals 0 and E[v squared] equals 1.&quot; data-astro-cid-bj3fsypb&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; width=&quot;736&quot; id=&quot;fig-tsb-wb-multipliers&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 736 1130&quot; role=&quot;img&quot; aria-label=&quot;Three stacked panels, one per row, each on its own identical horizontal v axis. Rademacher: two point masses at minus 1 and plus 1, each probability one half. Mammen: two point masses at minus 0.618 with probability 0.724 and plus 1.618 with probability 0.276, annotated E of v cubed equals 1, skewness kept. Gaussian: the standard normal curve. All three annotated E of v equals 0 and E of v squared equals 1.&quot;&gt;&lt;style&gt;#fig-tsb-wb-multipliers [fill=&quot;#1a1d23&quot; i]{fill:var(--bg)}#fig-tsb-wb-multipliers [stroke=&quot;#1a1d23&quot; i]{stroke:var(--bg)}#fig-tsb-wb-multipliers [fill=&quot;#18181b&quot; i]{fill:var(--bg-panel)}#fig-tsb-wb-multipliers [stroke=&quot;#18181b&quot; i]{stroke:var(--bg-panel)}#fig-tsb-wb-multipliers [fill=&quot;#2c2f37&quot; i]{fill:var(--current-line)}#fig-tsb-wb-multipliers [stroke=&quot;#2c2f37&quot; i]{stroke:var(--current-line)}#fig-tsb-wb-multipliers [fill=&quot;#f4f5f7&quot; i]{fill:var(--fg)}#fig-tsb-wb-multipliers [stroke=&quot;#f4f5f7&quot; i]{stroke:var(--fg)}#fig-tsb-wb-multipliers [fill=&quot;#8a8f98&quot; i]{fill:var(--comment)}#fig-tsb-wb-multipliers [stroke=&quot;#8a8f98&quot; i]{stroke:var(--comment)}&lt;/style&gt;
&lt;rect width=&quot;736&quot; height=&quot;1130&quot; fill=&quot;#1a1d23&quot;/&gt;
&lt;style&gt;
    :where(#wmu-root) text { font-family: var(--mono); fill: var(--fg); }
    .wmu-title { font-size: 22px; font-weight: bold; }
    .wmu-sub { font-size: 18px; fill: var(--comment); }
    .wmu-ptitle { font-size: 20px; font-weight: bold; text-anchor: middle; }
    .wmu-psub { font-size: 18px; fill: var(--comment); text-anchor: middle; }
    .wmu-axis { stroke: var(--comment); stroke-width: 1; }
    .wmu-tick { font-size: 18px; fill: var(--comment); text-anchor: middle; }
    .wmu-mass { font-size: 18px; fill: #56b4e9; font-weight: bold; }
    .wmu-mom { font-size: 18px; fill: var(--comment); text-anchor: middle; }
    .wmu-mom3 { font-size: 18px; fill: #56b4e9; font-weight: bold; text-anchor: middle; }
    .wmu-foot { font-size: 18px; fill: var(--comment); text-anchor: middle; }
  &lt;/style&gt;
&lt;g id=&quot;wmu-root&quot;&gt;
&lt;text class=&quot;wmu-title&quot; x=&quot;24&quot; y=&quot;38&quot;&gt;The multiplier v: three legal draws&lt;/text&gt;
&lt;text class=&quot;wmu-sub&quot; x=&quot;24&quot; y=&quot;66&quot;&gt;mass height &amp;#8733; probability (two-point panels)&lt;/text&gt;
&lt;text class=&quot;wmu-sub&quot; x=&quot;24&quot; y=&quot;90&quot;&gt;two shared moments, one optional third&lt;/text&gt;

&lt;text class=&quot;wmu-ptitle&quot; x=&quot;368&quot; y=&quot;132&quot;&gt;Rademacher&lt;/text&gt;
&lt;text class=&quot;wmu-psub&quot; x=&quot;368&quot; y=&quot;158&quot;&gt;fair sign flip&lt;/text&gt;
&lt;line class=&quot;wmu-axis&quot; x1=&quot;82&quot; y1=&quot;308&quot; x2=&quot;654&quot; y2=&quot;308&quot;/&gt;
&lt;line class=&quot;wmu-axis&quot; x1=&quot;108&quot; y1=&quot;308&quot; x2=&quot;108&quot; y2=&quot;314&quot;/&gt;
&lt;text class=&quot;wmu-tick&quot; x=&quot;108&quot; y=&quot;336&quot;&gt;&amp;#8722;2&lt;/text&gt;
&lt;line class=&quot;wmu-axis&quot; x1=&quot;238&quot; y1=&quot;308&quot; x2=&quot;238&quot; y2=&quot;314&quot;/&gt;
&lt;text class=&quot;wmu-tick&quot; x=&quot;238&quot; y=&quot;336&quot;&gt;&amp;#8722;1&lt;/text&gt;
&lt;line class=&quot;wmu-axis&quot; x1=&quot;368&quot; y1=&quot;308&quot; x2=&quot;368&quot; y2=&quot;314&quot;/&gt;
&lt;text class=&quot;wmu-tick&quot; x=&quot;368&quot; y=&quot;336&quot;&gt;0&lt;/text&gt;
&lt;line class=&quot;wmu-axis&quot; x1=&quot;498&quot; y1=&quot;308&quot; x2=&quot;498&quot; y2=&quot;314&quot;/&gt;
&lt;text class=&quot;wmu-tick&quot; x=&quot;498&quot; y=&quot;336&quot;&gt;1&lt;/text&gt;
&lt;line class=&quot;wmu-axis&quot; x1=&quot;628&quot; y1=&quot;308&quot; x2=&quot;628&quot; y2=&quot;314&quot;/&gt;
&lt;text class=&quot;wmu-tick&quot; x=&quot;628&quot; y=&quot;336&quot;&gt;2&lt;/text&gt;
&lt;line x1=&quot;238&quot; y1=&quot;308&quot; x2=&quot;238&quot; y2=&quot;233&quot; stroke=&quot;#56b4e9&quot; stroke-width=&quot;4&quot;/&gt;
&lt;circle cx=&quot;238&quot; cy=&quot;233&quot; r=&quot;7&quot; fill=&quot;#56b4e9&quot;/&gt;
&lt;text class=&quot;wmu-mass&quot; text-anchor=&quot;middle&quot; x=&quot;238&quot; y=&quot;217&quot;&gt;p = 1/2&lt;/text&gt;
&lt;line x1=&quot;498&quot; y1=&quot;308&quot; x2=&quot;498&quot; y2=&quot;233&quot; stroke=&quot;#56b4e9&quot; stroke-width=&quot;4&quot;/&gt;
&lt;circle cx=&quot;498&quot; cy=&quot;233&quot; r=&quot;7&quot; fill=&quot;#56b4e9&quot;/&gt;
&lt;text class=&quot;wmu-mass&quot; text-anchor=&quot;middle&quot; x=&quot;498&quot; y=&quot;217&quot;&gt;p = 1/2&lt;/text&gt;
&lt;text class=&quot;wmu-mom&quot; x=&quot;368&quot; y=&quot;368&quot;&gt;E[v] = 0 &amp;#183; E[v&amp;#178;] = 1&lt;/text&gt;
&lt;text class=&quot;wmu-mom&quot; x=&quot;368&quot; y=&quot;394&quot;&gt;E[v&amp;#179;] = 0&lt;/text&gt;

&lt;text class=&quot;wmu-ptitle&quot; x=&quot;368&quot; y=&quot;450&quot;&gt;Mammen&lt;/text&gt;
&lt;text class=&quot;wmu-psub&quot; x=&quot;368&quot; y=&quot;476&quot;&gt;golden-ratio two-point&lt;/text&gt;
&lt;line class=&quot;wmu-axis&quot; x1=&quot;82&quot; y1=&quot;666&quot; x2=&quot;654&quot; y2=&quot;666&quot;/&gt;
&lt;line class=&quot;wmu-axis&quot; x1=&quot;108&quot; y1=&quot;666&quot; x2=&quot;108&quot; y2=&quot;672&quot;/&gt;
&lt;text class=&quot;wmu-tick&quot; x=&quot;108&quot; y=&quot;694&quot;&gt;&amp;#8722;2&lt;/text&gt;
&lt;line class=&quot;wmu-axis&quot; x1=&quot;238&quot; y1=&quot;666&quot; x2=&quot;238&quot; y2=&quot;672&quot;/&gt;
&lt;text class=&quot;wmu-tick&quot; x=&quot;238&quot; y=&quot;694&quot;&gt;&amp;#8722;1&lt;/text&gt;
&lt;line class=&quot;wmu-axis&quot; x1=&quot;368&quot; y1=&quot;666&quot; x2=&quot;368&quot; y2=&quot;672&quot;/&gt;
&lt;text class=&quot;wmu-tick&quot; x=&quot;368&quot; y=&quot;694&quot;&gt;0&lt;/text&gt;
&lt;line class=&quot;wmu-axis&quot; x1=&quot;498&quot; y1=&quot;666&quot; x2=&quot;498&quot; y2=&quot;672&quot;/&gt;
&lt;text class=&quot;wmu-tick&quot; x=&quot;498&quot; y=&quot;694&quot;&gt;1&lt;/text&gt;
&lt;line class=&quot;wmu-axis&quot; x1=&quot;628&quot; y1=&quot;666&quot; x2=&quot;628&quot; y2=&quot;672&quot;/&gt;
&lt;text class=&quot;wmu-tick&quot; x=&quot;628&quot; y=&quot;694&quot;&gt;2&lt;/text&gt;
&lt;line x1=&quot;287.66&quot; y1=&quot;666&quot; x2=&quot;287.66&quot; y2=&quot;557.4&quot; stroke=&quot;#56b4e9&quot; stroke-width=&quot;4&quot;/&gt;
&lt;circle cx=&quot;287.66&quot; cy=&quot;557.4&quot; r=&quot;7&quot; fill=&quot;#56b4e9&quot;/&gt;
&lt;text class=&quot;wmu-mass&quot; text-anchor=&quot;middle&quot; x=&quot;287.66&quot; y=&quot;541.4&quot;&gt;p = 0.724&lt;/text&gt;
&lt;text class=&quot;wmu-mass&quot; text-anchor=&quot;middle&quot; x=&quot;287.66&quot; y=&quot;517.4&quot;&gt;&amp;#8722;0.618&lt;/text&gt;
&lt;line x1=&quot;578.34&quot; y1=&quot;666&quot; x2=&quot;578.34&quot; y2=&quot;624.6&quot; stroke=&quot;#56b4e9&quot; stroke-width=&quot;4&quot;/&gt;
&lt;circle cx=&quot;578.34&quot; cy=&quot;624.6&quot; r=&quot;7&quot; fill=&quot;#56b4e9&quot;/&gt;
&lt;text class=&quot;wmu-mass&quot; text-anchor=&quot;middle&quot; x=&quot;578.34&quot; y=&quot;608.6&quot;&gt;p = 0.276&lt;/text&gt;
&lt;text class=&quot;wmu-mass&quot; text-anchor=&quot;middle&quot; x=&quot;578.34&quot; y=&quot;584.6&quot;&gt;+1.618&lt;/text&gt;
&lt;text class=&quot;wmu-mom&quot; x=&quot;368&quot; y=&quot;726&quot;&gt;E[v] = 0 &amp;#183; E[v&amp;#178;] = 1&lt;/text&gt;
&lt;text class=&quot;wmu-mom3&quot; x=&quot;368&quot; y=&quot;752&quot;&gt;E[v&amp;#179;] = 1 &amp;#183; skewness kept&lt;/text&gt;
&lt;text class=&quot;wmu-foot&quot; x=&quot;368&quot; y=&quot;778&quot;&gt;points: 1/2 &amp;#177; &amp;#8730;5/2 &amp;#8212; the golden ratio&lt;/text&gt;

&lt;text class=&quot;wmu-ptitle&quot; x=&quot;368&quot; y=&quot;834&quot;&gt;Gaussian&lt;/text&gt;
&lt;text class=&quot;wmu-psub&quot; x=&quot;368&quot; y=&quot;860&quot;&gt;N(0, 1)&lt;/text&gt;
&lt;line class=&quot;wmu-axis&quot; x1=&quot;82&quot; y1=&quot;1010&quot; x2=&quot;654&quot; y2=&quot;1010&quot;/&gt;
&lt;line class=&quot;wmu-axis&quot; x1=&quot;108&quot; y1=&quot;1010&quot; x2=&quot;108&quot; y2=&quot;1016&quot;/&gt;
&lt;text class=&quot;wmu-tick&quot; x=&quot;108&quot; y=&quot;1038&quot;&gt;&amp;#8722;2&lt;/text&gt;
&lt;line class=&quot;wmu-axis&quot; x1=&quot;238&quot; y1=&quot;1010&quot; x2=&quot;238&quot; y2=&quot;1016&quot;/&gt;
&lt;text class=&quot;wmu-tick&quot; x=&quot;238&quot; y=&quot;1038&quot;&gt;&amp;#8722;1&lt;/text&gt;
&lt;line class=&quot;wmu-axis&quot; x1=&quot;368&quot; y1=&quot;1010&quot; x2=&quot;368&quot; y2=&quot;1016&quot;/&gt;
&lt;text class=&quot;wmu-tick&quot; x=&quot;368&quot; y=&quot;1038&quot;&gt;0&lt;/text&gt;
&lt;line class=&quot;wmu-axis&quot; x1=&quot;498&quot; y1=&quot;1010&quot; x2=&quot;498&quot; y2=&quot;1016&quot;/&gt;
&lt;text class=&quot;wmu-tick&quot; x=&quot;498&quot; y=&quot;1038&quot;&gt;1&lt;/text&gt;
&lt;line class=&quot;wmu-axis&quot; x1=&quot;628&quot; y1=&quot;1010&quot; x2=&quot;628&quot; y2=&quot;1016&quot;/&gt;
&lt;text class=&quot;wmu-tick&quot; x=&quot;628&quot; y=&quot;1038&quot;&gt;2&lt;/text&gt;
&lt;polyline points=&quot;95.0,997.9 108.0,995.1 121.0,991.9 134.0,988.2 147.0,984.1 160.0,979.4 173.0,974.3 186.0,968.7 199.0,962.7 212.0,956.5 225.0,949.9 238.0,943.3 251.0,936.6 264.0,930.1 277.0,923.9 290.0,918.1 303.0,912.9 316.0,908.5 329.0,904.8 342.0,902.2 355.0,900.5 368.0,900.0 381.0,900.5 394.0,902.2 407.0,904.8 420.0,908.5 433.0,912.9 446.0,918.1 459.0,923.9 472.0,930.1 485.0,936.6 498.0,943.3 511.0,949.9 524.0,956.5 537.0,962.7 550.0,968.7 563.0,974.3 576.0,979.4 589.0,984.1 602.0,988.2 615.0,991.9 628.0,995.1 641.0,997.9&quot; fill=&quot;none&quot; stroke=&quot;#56b4e9&quot; stroke-width=&quot;3&quot;/&gt;
&lt;text class=&quot;wmu-mom&quot; x=&quot;368&quot; y=&quot;1070&quot;&gt;E[v] = 0 &amp;#183; E[v&amp;#178;] = 1&lt;/text&gt;
&lt;text class=&quot;wmu-mom&quot; x=&quot;368&quot; y=&quot;1096&quot;&gt;E[v&amp;#179;] = 0&lt;/text&gt;
&lt;/g&gt;&lt;/svg&gt;
&lt;/div&gt; &lt;figcaption data-astro-cid-bj3fsypb&gt;Three multiplier distributions, one contract. All satisfy the two moment conditions; Mammen alone adds the third, preserving skewness. On this article’s data all three are statistically indistinguishable, so read this as a glossary of mechanisms; on this data there is no leaderboard.&lt;/figcaption&gt; &lt;details class=&quot;data-table&quot; data-astro-cid-bj3fsypb&gt; &lt;summary data-astro-cid-bj3fsypb&gt;data table&lt;/summary&gt;  &lt;div class=&quot;data-table-scroll&quot; data-astro-cid-bj3fsypb&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;distribution&lt;/th&gt;&lt;th&gt;values&lt;/th&gt;&lt;th&gt;probabilities&lt;/th&gt;&lt;th&gt;E[&lt;em&gt;v&lt;/em&gt;]&lt;/th&gt;&lt;th&gt;E[&lt;em&gt;v&lt;/em&gt;²]&lt;/th&gt;&lt;th&gt;E[&lt;em&gt;v&lt;/em&gt;³]&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Rademacher&lt;/td&gt;&lt;td&gt;−1, +1&lt;/td&gt;&lt;td&gt;1/2, 1/2&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Mammen&lt;/td&gt;&lt;td&gt;−0.618, +1.618&lt;/td&gt;&lt;td&gt;0.724, 0.276&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Gaussian&lt;/td&gt;&lt;td&gt;N(0,1)&lt;/td&gt;&lt;td&gt;n/a&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt; &lt;/details&gt; &lt;/figure&gt; 
&lt;h2 id=&quot;five-hundred-series-one-verdict&quot;&gt;Five hundred series, one verdict&lt;a class=&quot;heading-anchor&quot; href=&quot;#five-hundred-series-one-verdict&quot; aria-label=&quot;Link to this section&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One series proves nothing, so here is the experiment in full, self-contained enough to check. Generate 500 fresh series from the heteroskedastic AR(1) above (slope 0.5, &lt;em&gt;n&lt;/em&gt; = 600, error variance 9x larger in the second half). For each, fit the model and bootstrap the standard error of the lag-1 slope four ways (the i.i.d.-residual shuffle and the wild bootstrap under each of the three multipliers) with 999 replicates each. Divide every bootstrap standard error by the true one, 0.045326, computed from 200,000 independent Monte-Carlo draws of the process. A perfect resampler averages 1.0. All of it ran on tsbootstrap 0.6.1 on one 8-core Linux workstation, measured 2026-07-06.&lt;/p&gt;
&lt;p&gt;The i.i.d.-residual bootstrap recovered on average &lt;strong&gt;78% of the true standard error&lt;/strong&gt; (mean ratio 0.783). The wild bootstrap with Rademacher multipliers recovered &lt;strong&gt;100%&lt;/strong&gt; (mean ratio 1.001); Mammen and Gaussian multipliers landed at 0.997 and 0.990. And the miss was unanimous: the i.i.d. standard error came out below the wild one in 500 of 500 series: the wild estimate ran 1.28x larger on average, and the gap is exactly the uncertainty the shuffle deleted.&lt;/p&gt;
&lt;figure class=&quot;full&quot; data-astro-cid-bj3fsypb&gt; &lt;div class=&quot;svgfig svgfig-chart&quot; role=&quot;img&quot; aria-label=&quot;Horizontal bar chart of mean recovered fraction of the true standard error across 500 series. The i.i.d.-residual bar at 0.783 is drawn in orange with a vermillion label &apos;78%, collapsed&apos;. Three wild bars cluster at the top in blue: Gaussian 0.990, Mammen 0.997, Rademacher 1.001. A grey vertical reference rule at 1.000 is labelled &apos;truth&apos;. The wild bars sit on the rule; the i.i.d. bar falls far short of it.&quot; data-astro-cid-bj3fsypb&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; width=&quot;928&quot; id=&quot;fig-tsb-wb-se-recovery&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 928 410&quot; role=&quot;img&quot; aria-label=&quot;Horizontal bar chart of mean recovered fraction of the true standard error across 500 series. Three wild bars cluster at the top in blue: Rademacher 1.001, Mammen 0.997, Gaussian 0.990, all sitting on a grey vertical truth rule at 1.000. The i.i.d.-residual bar at the bottom, 0.783, is drawn in orange and labelled 78% collapsed; it falls far short of the rule.&quot;&gt;&lt;style&gt;#fig-tsb-wb-se-recovery [fill=&quot;#1a1d23&quot; i]{fill:var(--bg)}#fig-tsb-wb-se-recovery [stroke=&quot;#1a1d23&quot; i]{stroke:var(--bg)}#fig-tsb-wb-se-recovery [fill=&quot;#18181b&quot; i]{fill:var(--bg-panel)}#fig-tsb-wb-se-recovery [stroke=&quot;#18181b&quot; i]{stroke:var(--bg-panel)}#fig-tsb-wb-se-recovery [fill=&quot;#2c2f37&quot; i]{fill:var(--current-line)}#fig-tsb-wb-se-recovery [stroke=&quot;#2c2f37&quot; i]{stroke:var(--current-line)}#fig-tsb-wb-se-recovery [fill=&quot;#f4f5f7&quot; i]{fill:var(--fg)}#fig-tsb-wb-se-recovery [stroke=&quot;#f4f5f7&quot; i]{stroke:var(--fg)}#fig-tsb-wb-se-recovery [fill=&quot;#8a8f98&quot; i]{fill:var(--comment)}#fig-tsb-wb-se-recovery [stroke=&quot;#8a8f98&quot; i]{stroke:var(--comment)}&lt;/style&gt;
&lt;rect width=&quot;928&quot; height=&quot;410&quot; fill=&quot;#1a1d23&quot;/&gt;
&lt;style&gt;
    :where(#wsr-root) text { font-family: var(--mono); fill: var(--fg); }
    .wsr-title { font-size: 21px; font-weight: bold; }
    .wsr-sub { font-size: 16px; fill: var(--comment); }
    .wsr-grid { stroke: var(--current-line); stroke-width: 1; }
    .wsr-axis { stroke: var(--comment); stroke-width: 1; }
    .wsr-tick { font-size: 16px; fill: var(--comment); text-anchor: middle; }
    .wsr-atitle { font-size: 16px; fill: var(--fg); font-weight: bold; text-anchor: middle; }
    .wsr-row { font-size: 16px; text-anchor: end; dominant-baseline: middle; }
    .wsr-rowsub { font-size: 16px; fill: var(--comment); text-anchor: end; dominant-baseline: middle; }
    .wsr-valb { font-size: 16px; fill: #56b4e9; font-weight: bold; dominant-baseline: middle; }
    .wsr-valo { font-size: 16px; fill: #e69f00; font-weight: bold; dominant-baseline: middle; }
    .wsr-flag { font-size: 16px; fill: #d55e00; font-weight: bold; dominant-baseline: middle; }
    .wsr-reflab { font-size: 16px; fill: var(--comment); font-weight: bold; text-anchor: middle; }
  &lt;/style&gt;
&lt;g id=&quot;wsr-root&quot;&gt;
&lt;text class=&quot;wsr-title&quot; x=&quot;24&quot; y=&quot;34&quot;&gt;How much of the true standard error each resampler recovers&lt;/text&gt;
&lt;text class=&quot;wsr-sub&quot; x=&quot;24&quot; y=&quot;58&quot;&gt;500 heteroskedastic AR(1) series &amp;#183; B = 999 &amp;#183; truth = 0.045326 &amp;#183; bars start at zero&lt;/text&gt;
&lt;line class=&quot;wsr-grid&quot; x1=&quot;200&quot; y1=&quot;96&quot; x2=&quot;200&quot; y2=&quot;344&quot;/&gt;
&lt;text class=&quot;wsr-tick&quot; x=&quot;200&quot; y=&quot;366&quot;&gt;0.00&lt;/text&gt;
&lt;line class=&quot;wsr-grid&quot; x1=&quot;340&quot; y1=&quot;96&quot; x2=&quot;340&quot; y2=&quot;344&quot;/&gt;
&lt;text class=&quot;wsr-tick&quot; x=&quot;340&quot; y=&quot;366&quot;&gt;0.25&lt;/text&gt;
&lt;line class=&quot;wsr-grid&quot; x1=&quot;480&quot; y1=&quot;96&quot; x2=&quot;480&quot; y2=&quot;344&quot;/&gt;
&lt;text class=&quot;wsr-tick&quot; x=&quot;480&quot; y=&quot;366&quot;&gt;0.50&lt;/text&gt;
&lt;line class=&quot;wsr-grid&quot; x1=&quot;620&quot; y1=&quot;96&quot; x2=&quot;620&quot; y2=&quot;344&quot;/&gt;
&lt;text class=&quot;wsr-tick&quot; x=&quot;620&quot; y=&quot;366&quot;&gt;0.75&lt;/text&gt;
&lt;line class=&quot;wsr-grid&quot; x1=&quot;760&quot; y1=&quot;96&quot; x2=&quot;760&quot; y2=&quot;344&quot;/&gt;
&lt;text class=&quot;wsr-tick&quot; x=&quot;760&quot; y=&quot;366&quot;&gt;1.00&lt;/text&gt;
&lt;line class=&quot;wsr-axis&quot; x1=&quot;200&quot; y1=&quot;344&quot; x2=&quot;800&quot; y2=&quot;344&quot;/&gt;
&lt;line class=&quot;wsr-axis&quot; x1=&quot;200&quot; y1=&quot;96&quot; x2=&quot;200&quot; y2=&quot;344&quot;/&gt;
&lt;text class=&quot;wsr-atitle&quot; x=&quot;500&quot; y=&quot;390&quot;&gt;mean bootstrap SE / true SE&lt;/text&gt;
&lt;line x1=&quot;760&quot; y1=&quot;90&quot; x2=&quot;760&quot; y2=&quot;344&quot; stroke=&quot;#8a8f98&quot; stroke-width=&quot;2&quot; stroke-dasharray=&quot;6 4&quot;/&gt;
&lt;rect x=&quot;655&quot; y=&quot;73&quot; width=&quot;210&quot; height=&quot;20&quot; fill=&quot;#1a1d23&quot;/&gt;
&lt;text class=&quot;wsr-reflab&quot; x=&quot;760&quot; y=&quot;87&quot;&gt;truth = 1.000&lt;/text&gt;
&lt;text class=&quot;wsr-row&quot; x=&quot;192&quot; y=&quot;115&quot;&gt;Rademacher&lt;/text&gt;
&lt;text class=&quot;wsr-rowsub&quot; x=&quot;192&quot; y=&quot;133&quot;&gt;wild&lt;/text&gt;
&lt;rect x=&quot;200&quot; y=&quot;106&quot; width=&quot;560.6&quot; height=&quot;36&quot; fill=&quot;#56b4e9&quot;/&gt;
&lt;rect x=&quot;766&quot; y=&quot;113&quot; width=&quot;58&quot; height=&quot;22&quot; fill=&quot;#1a1d23&quot;/&gt;
&lt;text class=&quot;wsr-valb&quot; x=&quot;770&quot; y=&quot;124&quot;&gt;1.001&lt;/text&gt;
&lt;text class=&quot;wsr-row&quot; x=&quot;192&quot; y=&quot;173&quot;&gt;Mammen&lt;/text&gt;
&lt;text class=&quot;wsr-rowsub&quot; x=&quot;192&quot; y=&quot;191&quot;&gt;wild&lt;/text&gt;
&lt;rect x=&quot;200&quot; y=&quot;164&quot; width=&quot;558.3&quot; height=&quot;36&quot; fill=&quot;#56b4e9&quot;/&gt;
&lt;rect x=&quot;766&quot; y=&quot;171&quot; width=&quot;58&quot; height=&quot;22&quot; fill=&quot;#1a1d23&quot;/&gt;
&lt;text class=&quot;wsr-valb&quot; x=&quot;770&quot; y=&quot;182&quot;&gt;0.997&lt;/text&gt;
&lt;text class=&quot;wsr-row&quot; x=&quot;192&quot; y=&quot;231&quot;&gt;Gaussian&lt;/text&gt;
&lt;text class=&quot;wsr-rowsub&quot; x=&quot;192&quot; y=&quot;249&quot;&gt;wild&lt;/text&gt;
&lt;rect x=&quot;200&quot; y=&quot;222&quot; width=&quot;554.4&quot; height=&quot;36&quot; fill=&quot;#56b4e9&quot;/&gt;
&lt;rect x=&quot;766&quot; y=&quot;229&quot; width=&quot;58&quot; height=&quot;22&quot; fill=&quot;#1a1d23&quot;/&gt;
&lt;text class=&quot;wsr-valb&quot; x=&quot;770&quot; y=&quot;240&quot;&gt;0.990&lt;/text&gt;
&lt;text class=&quot;wsr-row&quot; x=&quot;192&quot; y=&quot;289&quot;&gt;i.i.d.&lt;/text&gt;
&lt;text class=&quot;wsr-rowsub&quot; x=&quot;192&quot; y=&quot;307&quot;&gt;(naive baseline)&lt;/text&gt;
&lt;rect x=&quot;200&quot; y=&quot;280&quot; width=&quot;438.5&quot; height=&quot;36&quot; fill=&quot;#e69f00&quot;/&gt;
&lt;rect x=&quot;642.5&quot; y=&quot;287&quot; width=&quot;58&quot; height=&quot;22&quot; fill=&quot;#1a1d23&quot;/&gt;
&lt;text class=&quot;wsr-valo&quot; x=&quot;646.5&quot; y=&quot;298&quot;&gt;0.783&lt;/text&gt;
&lt;rect x=&quot;698.5&quot; y=&quot;286&quot; width=&quot;182&quot; height=&quot;24&quot; fill=&quot;#1a1d23&quot;/&gt;
&lt;text class=&quot;wsr-flag&quot; x=&quot;702.5&quot; y=&quot;298&quot;&gt;&amp;#9664; 78% &amp;#8212; collapsed&lt;/text&gt;
&lt;/g&gt;&lt;/svg&gt;
&lt;/div&gt; &lt;figcaption data-astro-cid-bj3fsypb&gt;Mean recovered fraction of the true slope standard error, 500 heteroskedastic AR(1) series, 999 replicates each. The i.i.d.-residual shuffle (orange) stalls at 78% of the truth; every wild variant (blue) sits at the grey truth line. The three multipliers are indistinguishable here; the whole gap sits between shuffling and flipping.&lt;/figcaption&gt; &lt;details class=&quot;data-table&quot; data-astro-cid-bj3fsypb&gt; &lt;summary data-astro-cid-bj3fsypb&gt;data table&lt;/summary&gt;  &lt;div class=&quot;data-table-scroll&quot; data-astro-cid-bj3fsypb&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;residual resampler&lt;/th&gt;&lt;th&gt;mean SE / truth&lt;/th&gt;&lt;th&gt;reads as&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;i.i.d.-residual (naive baseline)&lt;/td&gt;&lt;td&gt;0.783&lt;/td&gt;&lt;td&gt;78%, collapsed&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;wild, Rademacher&lt;/td&gt;&lt;td&gt;1.001&lt;/td&gt;&lt;td&gt;100%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;wild, Mammen&lt;/td&gt;&lt;td&gt;0.997&lt;/td&gt;&lt;td&gt;100%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;wild, Gaussian&lt;/td&gt;&lt;td&gt;0.990&lt;/td&gt;&lt;td&gt;99%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Monte-Carlo truth (200k draws)&lt;/td&gt;&lt;td&gt;1.000&lt;/td&gt;&lt;td&gt;reference&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt; &lt;/details&gt; &lt;/figure&gt; 
&lt;p&gt;Two scope notes. The 78% belongs to &lt;em&gt;this&lt;/em&gt; process, where the loud errors sit on the big regressor values; heteroskedasticity that is uncorrelated with the regressor bites far less. And on a genuinely homoskedastic, well-specified model the i.i.d.-residual bootstrap is fine: the shuffle only lies when there is a variance profile to flatten. The wild bootstrap removes the question: flipping works whether or not the shuffle would have failed.&lt;/p&gt;
&lt;h2 id=&quot;what-a-collapsed-standard-error-costs-you-downstream&quot;&gt;What a collapsed standard error costs you downstream&lt;a class=&quot;heading-anchor&quot; href=&quot;#what-a-collapsed-standard-error-costs-you-downstream&quot; aria-label=&quot;Link to this section&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A standard error is an intermediate quantity; the thing you act on is the interval. So: 2,000 more fresh series from the same process, a nominal 90% percentile confidence interval (read straight off the replicates’ percentiles) for the slope from each method, 999 replicates, and a count of how often the interval contains the true 0.5.&lt;/p&gt;
&lt;p&gt;The i.i.d.-residual intervals covered the truth 79.1% of the time. The wild (Rademacher) intervals covered 88.8%, running 1.27x wider on average, width the shuffle had been withholding.&lt;/p&gt;
&lt;p&gt;And no, 88.8% is not 90%. Part of the residual gap has nothing to do with variance at all: the least-squares slope of an AR(1) is biased slightly downward in finite samples (across the 200,000 truth draws it averaged 0.4947 against a true 0.5), and percentile intervals at 999 replicates carry their own small-sample wobble. Both leftovers belong to the estimator and the percentile rule, not to the resampling. The wild bootstrap recovers the standard error and most of the coverage; it does not repair the estimator it is wrapped around. If the first article taught suspicion of intervals that are too tight, the habit worth keeping from both is asking which assumption each resampler restores, and checking coverage when the answer matters.&lt;/p&gt;
&lt;h2 id=&quot;the-fix-is-one-argument&quot;&gt;The fix is one argument&lt;a class=&quot;heading-anchor&quot; href=&quot;#the-fix-is-one-argument&quot; aria-label=&quot;Link to this section&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In tsbootstrap the residual bootstrap is a method spec, and how the residuals are resampled is its &lt;code&gt;innovation&lt;/code&gt;, a typed argument:&lt;/p&gt;
&lt;div class=&quot;codeblock&quot;&gt;&lt;div class=&quot;codeblock-head&quot;&gt;&lt;span class=&quot;lang&quot;&gt;python&lt;/span&gt;&lt;button type=&quot;button&quot; class=&quot;copy-btn&quot; data-copy aria-label=&quot;Copy code&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect width=&quot;14&quot; height=&quot;14&quot; x=&quot;8&quot; y=&quot;8&quot; rx=&quot;2&quot; ry=&quot;2&quot;&gt;&lt;/rect&gt;&lt;path d=&quot;M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span class=&quot;copy-label&quot;&gt;Copy&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre class=&quot;astro-code astro-code-themes github-light github-dark-default&quot; style=&quot;--shiki-light:#24292e;--shiki-dark:#e6edf3;--shiki-light-bg:#fff;--shiki-dark-bg:#0d1117;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; numpy &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; np&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; tsbootstrap &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;    AR&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;IID&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;, Wild,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;    ResidualBootstrap, bootstrap)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#8B949E&quot;&gt;# hetero AR(1): slope 0.5, n=600,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#8B949E&quot;&gt;# shock sd 1 then 3 (9x variance)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#D2A8FF&quot;&gt; hetero_ar1&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;(n, phi, seed):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;    rng &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; np.random.default_rng(seed)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;    z &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; rng.standard_normal(n)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;    late &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; np.arange(n) &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; n &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;    sd &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; np.where(late, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;3.0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;    x &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; np.empty(n)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;    x[&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; z[&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;np.sqrt(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; phi&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;**&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; t &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;, n):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;        x[t] &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; phi&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;x[t&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;sd[t]&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;z[t]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; x&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;x &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; hetero_ar1(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;600&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;0.5&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;seed&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;42&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#D2A8FF&quot;&gt; slope_se&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;(paths):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#8B949E&quot;&gt;    # refit the slope per replicate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;    slopes &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;      np.polyfit(p[:&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;], p[&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;:], &lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;)[&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;      for&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; p &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; paths]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; np.std(slopes, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;ddof&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#8B949E&quot;&gt;# the lie: shuffle residuals in time&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;res &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; bootstrap(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;    x,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;    method&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;ResidualBootstrap(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;        model&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;AR(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;order&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;        innovation&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;IID()),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;    n_bootstraps&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;999&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;    random_state&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;se &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; slope_se(res.values())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;print&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;round&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;(se, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#8B949E&quot;&gt;# slope SE: 0.034   (truth 0.0453)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#8B949E&quot;&gt;# the fix: keep each residual in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#8B949E&quot;&gt;# place, flip its sign at random&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;res &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; bootstrap(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;    x,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;    method&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;ResidualBootstrap(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;        model&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;AR(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;order&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;        innovation&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;Wild()),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;    n_bootstraps&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;999&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#E36209;--shiki-dark:#FFA657&quot;&gt;    random_state&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;se &lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#FF7B72&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt; slope_se(res.values())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;print&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;round&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;(se, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79C0FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E6EDF3&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#8B949E&quot;&gt;# slope SE: 0.045   (truth 0.0453)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Wild()&lt;/code&gt; defaults to Rademacher multipliers; &lt;code&gt;Wild(distribution=&amp;quot;mammen&amp;quot;)&lt;/code&gt; and &lt;code&gt;&amp;quot;gaussian&amp;quot;&lt;/code&gt; are one keyword away. Everything else (model, data, replicate count, seed) is identical between the lie and the fix. As of this writing (July 2026), none of arch, darts, MAPIE, or TorchCP ships a wild-bootstrap innovation spec or a block-wild variant as a first-class resampling option.&lt;/p&gt;
&lt;h2 id=&quot;when-the-residuals-themselves-are-dependent&quot;&gt;When the residuals themselves are dependent&lt;a class=&quot;heading-anchor&quot; href=&quot;#when-the-residuals-themselves-are-dependent&quot; aria-label=&quot;Link to this section&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One assumption is still hiding in the wild bootstrap: drawing each &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;v_t&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.5806em;vertical-align:-0.15em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2806em&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0359em;margin-right:0.05em&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em&quot;&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; independently asserts that the residuals, whatever their variances, are at least &lt;em&gt;uncorrelated with each other&lt;/em&gt;. For a well-specified model that is what residuals should be. But when the model is a little wrong (an underfit autoregression, structure at a horizon the model does not see) the leftover errors are themselves locally dependent, and independent sign flips would shred that dependence the same way the i.i.d. bootstrap shredded the wave in the first article. The concrete picture: fit an AR(1) to a series that is truly AR(3), and the two lags the model never sees leave ripples behind: each residual is correlated with its own recent past, and the residual autocorrelations show it at short lags.&lt;/p&gt;
&lt;p&gt;The extension is the &lt;em&gt;block-wild bootstrap&lt;/em&gt;: partition the time axis into contiguous blocks and give every residual in a block the &lt;em&gt;same&lt;/em&gt; multiplier. Within a block, relative signs (and therefore local correlation) are preserved exactly; across blocks, the flips are independent. You can measure the machinery doing its job directly, on the multiplier process itself: at block length 10, neighboring multipliers correlate at 0.904, multipliers five steps apart at 0.513, and twelve steps apart (past the block edge) at 0.007, indistinguishable from zero. The measured points sit on the triangular law &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;max&lt;/mi&gt;&lt;mo&gt;⁡&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mtext&gt; &lt;/mtext&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\max(0,\, 1 - h/L)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mop&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; (correlation at lag h for block length L) that the block construction implies.&lt;/p&gt;
&lt;span class=&quot;marginnote&quot; role=&quot;note&quot;&gt;This block-constant scheme is the piecewise-constant case of Shao’s (2010) dependent wild bootstrap, and the same construction as the wild cluster bootstrap of Cameron, Gelbach and Miller (2008), with time blocks playing the role of clusters.&lt;/span&gt;
&lt;figure class=&quot;full&quot; data-astro-cid-bj3fsypb&gt; &lt;div class=&quot;svgfig svgfig-chart&quot; role=&quot;img&quot; aria-label=&quot;Correlation of the block-wild multiplier process against lag, block length 10. Measured points in blue: 0.904 at lag 1, 0.513 at lag 5, 0.007 at lag 12. A grey triangular theory rule, one minus h over 10, descends from 1 to hit zero at lag 10. The measured points sit on the rule.&quot; data-astro-cid-bj3fsypb&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; width=&quot;928&quot; id=&quot;fig-tsb-wb-blockwild-acf&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 928 440&quot; role=&quot;img&quot; aria-label=&quot;Correlation of the block-wild multiplier process against lag, block length 10. Measured points in blue: 0.904 at lag 1, 0.513 at lag 5, 0.007 at lag 12. A grey dashed triangular theory rule, one minus h over 10, descends from 1 to hit zero at the block edge at lag 10, then runs flat. The measured points sit on the rule.&quot;&gt;&lt;style&gt;#fig-tsb-wb-blockwild-acf [fill=&quot;#1a1d23&quot; i]{fill:var(--bg)}#fig-tsb-wb-blockwild-acf [stroke=&quot;#1a1d23&quot; i]{stroke:var(--bg)}#fig-tsb-wb-blockwild-acf [fill=&quot;#18181b&quot; i]{fill:var(--bg-panel)}#fig-tsb-wb-blockwild-acf [stroke=&quot;#18181b&quot; i]{stroke:var(--bg-panel)}#fig-tsb-wb-blockwild-acf [fill=&quot;#2c2f37&quot; i]{fill:var(--current-line)}#fig-tsb-wb-blockwild-acf [stroke=&quot;#2c2f37&quot; i]{stroke:var(--current-line)}#fig-tsb-wb-blockwild-acf [fill=&quot;#f4f5f7&quot; i]{fill:var(--fg)}#fig-tsb-wb-blockwild-acf [stroke=&quot;#f4f5f7&quot; i]{stroke:var(--fg)}#fig-tsb-wb-blockwild-acf [fill=&quot;#8a8f98&quot; i]{fill:var(--comment)}#fig-tsb-wb-blockwild-acf [stroke=&quot;#8a8f98&quot; i]{stroke:var(--comment)}&lt;/style&gt;
&lt;rect width=&quot;928&quot; height=&quot;440&quot; fill=&quot;#1a1d23&quot;/&gt;
&lt;style&gt;
    :where(#wbw-root) text { font-family: var(--mono); fill: var(--fg); }
    .wbw-title { font-size: 21px; font-weight: bold; }
    .wbw-sub { font-size: 16px; fill: var(--comment); }
    .wbw-grid { stroke: var(--current-line); stroke-width: 1; }
    .wbw-axis { stroke: var(--comment); stroke-width: 1; }
    .wbw-tick { font-size: 16px; fill: var(--comment); text-anchor: middle; }
    .wbw-ytick { font-size: 16px; fill: var(--comment); text-anchor: end; }
    .wbw-ylab { font-size: 16px; fill: var(--comment); font-weight: bold; text-anchor: end; }
    .wbw-atitle { font-size: 16px; fill: var(--fg); font-weight: bold; text-anchor: middle; }
    .wbw-edge { font-size: 16px; fill: var(--comment); }
    .wbw-theory { font-size: 16px; fill: var(--comment); font-weight: bold; }
    .wbw-val { font-size: 17px; fill: #56b4e9; font-weight: bold; }
    .wbw-leg { font-size: 16px; fill: #56b4e9; font-weight: bold; text-anchor: end; }
  &lt;/style&gt;
&lt;g id=&quot;wbw-root&quot;&gt;
&lt;text class=&quot;wbw-title&quot; x=&quot;24&quot; y=&quot;34&quot;&gt;The multiplier process carries the block structure&lt;/text&gt;
&lt;text class=&quot;wbw-sub&quot; x=&quot;24&quot; y=&quot;58&quot;&gt;autocorrelation of the multiplier process &amp;#183; the same flip for every residual in a block&lt;/text&gt;
&lt;line class=&quot;wbw-grid&quot; x1=&quot;120&quot; y1=&quot;350&quot; x2=&quot;874&quot; y2=&quot;350&quot;/&gt;
&lt;text class=&quot;wbw-ytick&quot; x=&quot;108&quot; y=&quot;355&quot;&gt;0.0&lt;/text&gt;
&lt;line class=&quot;wbw-grid&quot; x1=&quot;120&quot; y1=&quot;230&quot; x2=&quot;874&quot; y2=&quot;230&quot;/&gt;
&lt;text class=&quot;wbw-ytick&quot; x=&quot;108&quot; y=&quot;235&quot;&gt;0.5&lt;/text&gt;
&lt;line class=&quot;wbw-grid&quot; x1=&quot;120&quot; y1=&quot;110&quot; x2=&quot;874&quot; y2=&quot;110&quot;/&gt;
&lt;text class=&quot;wbw-ytick&quot; x=&quot;108&quot; y=&quot;115&quot;&gt;1.0&lt;/text&gt;
&lt;text class=&quot;wbw-ylab&quot; x=&quot;108&quot; y=&quot;88&quot;&gt;corr(h)&lt;/text&gt;
&lt;line class=&quot;wbw-axis&quot; x1=&quot;120&quot; y1=&quot;350&quot; x2=&quot;874&quot; y2=&quot;350&quot;/&gt;
&lt;line class=&quot;wbw-axis&quot; x1=&quot;120&quot; y1=&quot;110&quot; x2=&quot;120&quot; y2=&quot;350&quot;/&gt;
&lt;line class=&quot;wbw-axis&quot; x1=&quot;120&quot; y1=&quot;350&quot; x2=&quot;120&quot; y2=&quot;356&quot;/&gt;
&lt;text class=&quot;wbw-tick&quot; x=&quot;120&quot; y=&quot;376&quot;&gt;0&lt;/text&gt;
&lt;line class=&quot;wbw-axis&quot; x1=&quot;178&quot; y1=&quot;350&quot; x2=&quot;178&quot; y2=&quot;356&quot;/&gt;
&lt;text class=&quot;wbw-tick&quot; x=&quot;178&quot; y=&quot;376&quot;&gt;1&lt;/text&gt;
&lt;line class=&quot;wbw-axis&quot; x1=&quot;410&quot; y1=&quot;350&quot; x2=&quot;410&quot; y2=&quot;356&quot;/&gt;
&lt;text class=&quot;wbw-tick&quot; x=&quot;410&quot; y=&quot;376&quot;&gt;5&lt;/text&gt;
&lt;line class=&quot;wbw-axis&quot; x1=&quot;700&quot; y1=&quot;350&quot; x2=&quot;700&quot; y2=&quot;356&quot;/&gt;
&lt;text class=&quot;wbw-tick&quot; x=&quot;700&quot; y=&quot;376&quot;&gt;10&lt;/text&gt;
&lt;line class=&quot;wbw-axis&quot; x1=&quot;816&quot; y1=&quot;350&quot; x2=&quot;816&quot; y2=&quot;356&quot;/&gt;
&lt;text class=&quot;wbw-tick&quot; x=&quot;816&quot; y=&quot;376&quot;&gt;12&lt;/text&gt;
&lt;text class=&quot;wbw-atitle&quot; x=&quot;497&quot; y=&quot;408&quot;&gt;lag h (time steps apart)&lt;/text&gt;
&lt;line x1=&quot;700&quot; y1=&quot;110&quot; x2=&quot;700&quot; y2=&quot;350&quot; stroke=&quot;#2c2f37&quot; stroke-width=&quot;1.5&quot; stroke-dasharray=&quot;3 5&quot;/&gt;
&lt;text class=&quot;wbw-edge&quot; text-anchor=&quot;end&quot; x=&quot;690&quot; y=&quot;132&quot;&gt;block edge (L = 10)&lt;/text&gt;
&lt;polyline points=&quot;120,110 700,350 874,350&quot; fill=&quot;none&quot; stroke=&quot;#8a8f98&quot; stroke-width=&quot;2.5&quot; stroke-dasharray=&quot;7 5&quot;/&gt;
&lt;rect x=&quot;632&quot; y=&quot;278&quot; width=&quot;244&quot; height=&quot;24&quot; fill=&quot;#1a1d23&quot;/&gt;
&lt;text class=&quot;wbw-theory&quot; x=&quot;636&quot; y=&quot;295&quot;&gt;theory: max(0, 1 &amp;#8722; h/10)&lt;/text&gt;
&lt;circle cx=&quot;178&quot; cy=&quot;133&quot; r=&quot;7&quot; fill=&quot;#56b4e9&quot;/&gt;
&lt;rect x=&quot;192&quot; y=&quot;111&quot; width=&quot;58&quot; height=&quot;22&quot; fill=&quot;#1a1d23&quot;/&gt;
&lt;text class=&quot;wbw-val&quot; text-anchor=&quot;start&quot; x=&quot;196&quot; y=&quot;126&quot;&gt;0.904&lt;/text&gt;
&lt;circle cx=&quot;410&quot; cy=&quot;226.9&quot; r=&quot;7&quot; fill=&quot;#56b4e9&quot;/&gt;
&lt;rect x=&quot;424&quot; y=&quot;190&quot; width=&quot;58&quot; height=&quot;22&quot; fill=&quot;#1a1d23&quot;/&gt;
&lt;text class=&quot;wbw-val&quot; text-anchor=&quot;start&quot; x=&quot;428&quot; y=&quot;205&quot;&gt;0.513&lt;/text&gt;
&lt;circle cx=&quot;816&quot; cy=&quot;348.3&quot; r=&quot;7&quot; fill=&quot;#56b4e9&quot;/&gt;
&lt;rect x=&quot;787&quot; y=&quot;307&quot; width=&quot;58&quot; height=&quot;22&quot; fill=&quot;#1a1d23&quot;/&gt;
&lt;text class=&quot;wbw-val&quot; text-anchor=&quot;middle&quot; x=&quot;816&quot; y=&quot;322&quot;&gt;0.007&lt;/text&gt;
&lt;text class=&quot;wbw-leg&quot; x=&quot;874&quot; y=&quot;88&quot;&gt;&amp;#9679; measured&lt;/text&gt;
&lt;/g&gt;&lt;/svg&gt;
&lt;/div&gt; &lt;figcaption data-astro-cid-bj3fsypb&gt;What a block multiplier preserves. With block length 10 (Rademacher multipliers, 2,000 replicates), the sign flips applied to nearby residuals are almost perfectly correlated (0.904 at lag 1), half-correlated at lag 5, and independent past the block edge; the measured correlations track the triangular law from the construction. This is what lets block-wild keep local residual dependence that independent flips would destroy.&lt;/figcaption&gt; &lt;details class=&quot;data-table&quot; data-astro-cid-bj3fsypb&gt; &lt;summary data-astro-cid-bj3fsypb&gt;data table&lt;/summary&gt;  &lt;div class=&quot;data-table-scroll&quot; data-astro-cid-bj3fsypb&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;lag h&lt;/th&gt;&lt;th&gt;measured correlation&lt;/th&gt;&lt;th&gt;theory 1 − h/10&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;0.904&lt;/td&gt;&lt;td&gt;0.9&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;0.513&lt;/td&gt;&lt;td&gt;0.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;0.007&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt; &lt;/details&gt; &lt;/figure&gt; 
&lt;p&gt;Block-wild is not a free upgrade over plain wild, though. On this article’s process the residuals are independent by construction, so there is no local dependence to preserve, and block-wild duly buys nothing. Its automatic block-length rule resolved to a length of 2 on my showcase series, and its standard-error recovery there, 0.856 of the truth, actually sat &lt;em&gt;below&lt;/em&gt; plain wild’s. Blocking the multipliers spends resampling variety to protect a structure, so when the structure is absent it costs variety for no gain. So the order of operations is explicit. First, fix the model: dependent residuals are a misspecification symptom before they are a resampling problem, and a refit that absorbs the missing lags beats any bootstrap patch. When you cannot refit, block-wild is the patch that respects what the residuals still carry. And when the residuals pass the checks (no drift in their spread, no short-lag correlation) plain wild is all you need.&lt;/p&gt;
&lt;h2 id=&quot;which-resampler-then&quot;&gt;Which resampler, then?&lt;a class=&quot;heading-anchor&quot; href=&quot;#which-resampler-then&quot; aria-label=&quot;Link to this section&quot;&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The decision this piece adds to the last one’s, in one table:&lt;/p&gt;






























&lt;div class=&quot;table-scroll&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;your data’s situation&lt;/th&gt;&lt;th&gt;the assumption at risk&lt;/th&gt;&lt;th&gt;reach for&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;dependent observations, no model you trust&lt;/td&gt;&lt;td&gt;independence of observations&lt;/td&gt;&lt;td&gt;block bootstrap (moving, circular, stationary)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;trusted model, steady error variance&lt;/td&gt;&lt;td&gt;none (defaults hold)&lt;/td&gt;&lt;td&gt;i.i.d.-residual bootstrap&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;trusted model, error variance shifts over time&lt;/td&gt;&lt;td&gt;homoskedasticity of errors&lt;/td&gt;&lt;td&gt;wild bootstrap, Rademacher default&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;shaky model, residuals locally dependent&lt;/td&gt;&lt;td&gt;independence of errors&lt;/td&gt;&lt;td&gt;block-wild, then question the model&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;The first article’s thesis holds here unchanged: match the resampler to the assumption your data violates. Only the assumption moved. That failure lived in the observations; this one lives in the errors of a model you already trusted, which is a more dangerous address, because trusting the model is what made the analysis feel careful. My tight little 0.034 came from a fitted model and 999 replicates of honest-looking work. The truth, 0.0453, was never hidden. It was flattened, averaged into the quiet half of a history that never happened. The wild bootstrap’s whole contribution is refusing to build that history: every residual stays home, and the only randomness is a sign.&lt;/p&gt;
&lt;section class=&quot;faq&quot; aria-label=&quot;Frequently asked questions&quot; data-astro-cid-z6gx6xcw&gt; &lt;h2 data-astro-cid-z6gx6xcw&gt;Frequently asked questions&lt;/h2&gt; &lt;div class=&quot;faq-list&quot; data-astro-cid-z6gx6xcw&gt; &lt;details class=&quot;faq-item&quot; open data-astro-cid-z6gx6xcw&gt; &lt;summary data-astro-cid-z6gx6xcw&gt;What is the wild bootstrap?&lt;/summary&gt; &lt;div class=&quot;faq-a&quot; data-astro-cid-z6gx6xcw&gt;The wild bootstrap is a resampling method for regression and time series models with heteroskedastic errors, meaning error variance that shifts over the sample. Instead of shuffling the fitted residuals across time, it keeps each residual at its own position and multiplies it by an independent random draw with mean zero and variance one (by default a Rademacher sign flip: +1 or −1 with equal probability). That preserves each residual’s variance and position exactly, so the bootstrap reproduces the true variance profile without ever estimating it. In tsbootstrap you select it by passing innovation=Wild() to ResidualBootstrap.&lt;/div&gt; &lt;/details&gt;&lt;details class=&quot;faq-item&quot; open data-astro-cid-z6gx6xcw&gt; &lt;summary data-astro-cid-z6gx6xcw&gt;When does the ordinary residual bootstrap fail?&lt;/summary&gt; &lt;div class=&quot;faq-a&quot; data-astro-cid-z6gx6xcw&gt;When the errors are heteroskedastic (their variance shifts over time), and especially when the loud errors coincide with extreme regressor values. Shuffling residuals across time averages the variance profile away, so the bootstrap understates the uncertainty. On a heteroskedastic AR(1) (slope 0.5, *n* = 600, error variance 9x larger in the second half), the i.i.d.-residual bootstrap recovered on average only 78% of the true standard error of the slope across 500 simulated series, and its nominal 90% interval covered the truth 79.1% of the time (tsbootstrap 0.6.1, 999 replicates per bootstrap, measured 2026-07-06). The wild bootstrap recovered 100% of the true standard error on the same series, with 88.8% coverage.&lt;/div&gt; &lt;/details&gt;&lt;details class=&quot;faq-item&quot; open data-astro-cid-z6gx6xcw&gt; &lt;summary data-astro-cid-z6gx6xcw&gt;Which wild bootstrap multiplier should I use: Rademacher, Mammen, or Gaussian?&lt;/summary&gt; &lt;div class=&quot;faq-a&quot; data-astro-cid-z6gx6xcw&gt;Rademacher (random sign flips) is the standard default, following Davidson and Flachaire (2008), who found it generally performs best in practice. Mammen’s two-point distribution additionally preserves the skewness of each residual (its third moment equals 1), which theory favors for strongly asymmetric errors; the Gaussian multiplier is a smooth alternative. In the measured experiment here all three recovered 99 to 100% of the true standard error; the choice that matters is wild versus shuffle, not the multiplier.&lt;/div&gt; &lt;/details&gt;&lt;details class=&quot;faq-item&quot; open data-astro-cid-z6gx6xcw&gt; &lt;summary data-astro-cid-z6gx6xcw&gt;What is the block-wild bootstrap and when is it needed?&lt;/summary&gt; &lt;div class=&quot;faq-a&quot; data-astro-cid-z6gx6xcw&gt;The block-wild bootstrap gives every residual within a contiguous time block the same multiplier, preserving local correlation among residuals, useful when the model is misspecified enough that its residuals are still dependent. It is the piecewise-constant case of Shao’s (2010) dependent wild bootstrap. It is not a free upgrade: on a well-specified model with independent residuals, plain wild is the better choice, and in tsbootstrap BlockWild(block_length=&amp;quot;auto&amp;quot;) will resolve to a very short block in that case.&lt;/div&gt; &lt;/details&gt; &lt;/div&gt; &lt;script type=&quot;application/ld+json&quot;&gt;{&quot;@context&quot;:&quot;https://schema.org&quot;,&quot;@type&quot;:&quot;FAQPage&quot;,&quot;mainEntity&quot;:[{&quot;@type&quot;:&quot;Question&quot;,&quot;name&quot;:&quot;What is the wild bootstrap?&quot;,&quot;acceptedAnswer&quot;:{&quot;@type&quot;:&quot;Answer&quot;,&quot;text&quot;:&quot;The wild bootstrap is a resampling method for regression and time series models with heteroskedastic errors, meaning error variance that shifts over the sample. Instead of shuffling the fitted residuals across time, it keeps each residual at its own position and multiplies it by an independent random draw with mean zero and variance one (by default a Rademacher sign flip: +1 or −1 with equal probability). That preserves each residual’s variance and position exactly, so the bootstrap reproduces the true variance profile without ever estimating it. In tsbootstrap you select it by passing innovation=Wild() to ResidualBootstrap.&quot;}},{&quot;@type&quot;:&quot;Question&quot;,&quot;name&quot;:&quot;When does the ordinary residual bootstrap fail?&quot;,&quot;acceptedAnswer&quot;:{&quot;@type&quot;:&quot;Answer&quot;,&quot;text&quot;:&quot;When the errors are heteroskedastic (their variance shifts over time), and especially when the loud errors coincide with extreme regressor values. Shuffling residuals across time averages the variance profile away, so the bootstrap understates the uncertainty. On a heteroskedastic AR(1) (slope 0.5, *n* = 600, error variance 9x larger in the second half), the i.i.d.-residual bootstrap recovered on average only 78% of the true standard error of the slope across 500 simulated series, and its nominal 90% interval covered the truth 79.1% of the time (tsbootstrap 0.6.1, 999 replicates per bootstrap, measured 2026-07-06). The wild bootstrap recovered 100% of the true standard error on the same series, with 88.8% coverage.&quot;}},{&quot;@type&quot;:&quot;Question&quot;,&quot;name&quot;:&quot;Which wild bootstrap multiplier should I use: Rademacher, Mammen, or Gaussian?&quot;,&quot;acceptedAnswer&quot;:{&quot;@type&quot;:&quot;Answer&quot;,&quot;text&quot;:&quot;Rademacher (random sign flips) is the standard default, following Davidson and Flachaire (2008), who found it generally performs best in practice. Mammen’s two-point distribution additionally preserves the skewness of each residual (its third moment equals 1), which theory favors for strongly asymmetric errors; the Gaussian multiplier is a smooth alternative. In the measured experiment here all three recovered 99 to 100% of the true standard error; the choice that matters is wild versus shuffle, not the multiplier.&quot;}},{&quot;@type&quot;:&quot;Question&quot;,&quot;name&quot;:&quot;What is the block-wild bootstrap and when is it needed?&quot;,&quot;acceptedAnswer&quot;:{&quot;@type&quot;:&quot;Answer&quot;,&quot;text&quot;:&quot;The block-wild bootstrap gives every residual within a contiguous time block the same multiplier, preserving local correlation among residuals, useful when the model is misspecified enough that its residuals are still dependent. It is the piecewise-constant case of Shao’s (2010) dependent wild bootstrap. It is not a free upgrade: on a well-specified model with independent residuals, plain wild is the better choice, and in tsbootstrap BlockWild(block_length=\&quot;auto\&quot;) will resolve to a very short block in that case.&quot;}}]}&lt;/script&gt; &lt;/section&gt; &lt;!-- Mobile collapse (UX audit F-40): each Q/A pair is a &lt;details&gt;, server-rendered
     OPEN so the answers are visible with no JS, in print, on desktop, and to crawlers
     (the full text is always in the DOM; the FAQPage JSON-LD above is untouched).
     At phone widths this script collapses the pairs so the questions are scannable
     and an answer expands on tap; widening the viewport re-opens everything (which
     also repairs any keyboard-toggled state before the desktop pointer-events lock
     makes it unreachable). astro:page-load covers view-transition navigations. --&gt; &lt;script type=&quot;module&quot; src=&quot;https://thepragmaticquant.com/vercel/path0/src/components/Faq.astro?astro&amp;type=script&amp;index=0&amp;lang.ts&quot;&gt;&lt;/script&gt;
&lt;p&gt;The next failure in this series has nothing to do with statistics: when you need a million replicates, you have to be able to build them at all.&lt;/p&gt;</content:encoded><category>tsbootstrap</category><category>time-series</category><category>bootstrap</category><category>heteroskedasticity</category></item></channel></rss>