Bollinger Bands: an average with a margin that breathes

On this page
  1. Three lines from twenty closes
  2. The width is the volatility
  3. Where the close sits in the band
  4. What the books say it means, and what SPY did
  5. Traps
  6. The code
  7. Summary
  8. References

The indicators post used one number from the Bollinger Bands, the distance of the price from its average in units of standard deviation, and left the bands themselves for later. This is later. The bands are the most common way a chart shows “the price is unusually far from normal”, and the reason they work on a $40 stock and a $400 one alike is the part worth understanding. The post builds them on SPY’s closes from 2019 to 2023, works one day by hand, and checks the books’ claims about them against what the data does.

Three lines from twenty closes

Take the last twenty closing prices. Their mean is the middle band, an ordinary 20-day simple moving average. Their standard deviation (the usual measure of how spread out they are) sets the other two: the upper band is the mean plus two standard deviations, the lower band is the mean minus two. Achelis reports John Bollinger’s own settings: twenty periods, a simple average, two standard deviations, and a warning that averages under ten periods “do not work very well”. The StockCharts page writes the same three lines and adds why the middle band is a simple average: the standard deviation is computed over the same window, so the two agree about which days count.

U, L, the upper and lower bandsσ, the standard deviation of the last 20 closes

Mt=120∑i=019Pt−iUt=Mt+2 σt,Lt=Mt−2 σt\begin{aligned} M_t &= \tfrac{1}{20}\textstyle\sum_{i=0}^{19} P_{t-i} \\[10pt] \key{U_t} &= M_t + 2\,\risk{\sigma_t}, \qquad \key{L_t} = M_t - 2\,\risk{\sigma_t} \end{aligned}

On 2020-03-16, the Monday SPY fell eleven percent in a day, the twenty closes ending that day had a mean of 272.88 and a standard deviation of 25.62\risk{25.62}. Two standard deviations is 51.25, so the upper band sat at 324.13\key{324.13} and the lower band at 221.63\key{221.63}. The close was 218.09: below the lower band by $3.54. That is the same day the indicators post gave a position of −1.07 bands below the average, and the two statements are one fact in two units.

The bands are the average plus and minus a margin, and the margin is the price’s own recent spread. Everything the bands do that a fixed percentage envelope cannot comes from that one choice.

The width is the volatility

Murphy and Achelis both introduce the bands by contrast with envelopes, two lines a fixed percentage above and below an average. An envelope five percent wide is five percent wide in a crash and in a calm. Bollinger Bands “expand and contract based on the last 20 days’ volatility”, in Murphy’s words, so the same rule, “the price is outside the band”, fires at a sensible distance in both. Kirkpatrick and Dahlquist add why the fixed version fails in practice: volatility usually falls in a sideways market and expands when a trend begins, so an envelope wide enough for the quiet stretch gives false signals exactly when the move starts, and the percentage itself “must be determined through experiment”. The width is easy to read off: the upper band minus the lower, divided by the middle, is four standard deviations as a fraction of the price.

DayWhat was happeningBand width (fraction of the price)
2019-07-31the calmest month of the five years2.1%
2020-02-19the high before the crash6.2%
2020-03-16the eleven-percent day37.6%
2020-03-23the low, and the widest bands of the five years44.4%
2020-08-31the recovery, back to its old range7.0%

The bands were six times wider at the low than at the high five weeks earlier, and back to normal by the end of summer. Both books read something into the narrow end. Achelis quotes Bollinger: “sharp price changes tend to occur after the bands tighten, as volatility lessens”. Murphy says that when the bands have “narrowed too far, that is often a sign that a market may be about to initiate a new trend”. Kirkpatrick and Dahlquist agree that the tightening “is often followed by a sharp price move”. None of the three gives a number for “too far”, and the February 2020 width of 6.2% was not unusual; the squeeze is a pattern the books describe, not a threshold they test.

{"panels":[{"x0":54.44,"x1":564.73,"y0":29.16,"y1":223.28,"title":"1. The bands open in the March crash and close again by summer","xlabel":"Date (2020)","ylabel":"Price (dollars)","xlog":false},{"x0":54.44,"x1":564.73,"y0":311.96,"y1":506.08,"title":"2. Where the close sits inside the band, day by day","xlabel":"Date (2020)","ylabel":"%B (fraction of the band)","xlog":false}],"series":[{"panel":0,"label":"SPY close","color":"var(--chart-maroon, #b6262c)","x":["2020-01-02","2020-01-03","2020-01-06","2020-01-07","2020-01-08","2020-01-09","2020-01-10","2020-01-13","2020-01-14","2020-01-15","2020-01-16","2020-01-17","2020-01-21","2020-01-22","2020-01-23","2020-01-24","2020-01-27","2020-01-28","2020-01-29","2020-01-30","2020-01-31","2020-02-03","2020-02-04","2020-02-05","2020-02-06","2020-02-07","2020-02-10","2020-02-11","2020-02-12","2020-02-13","2020-02-14","2020-02-18","2020-02-19","2020-02-20","2020-02-21","2020-02-24","2020-02-25","2020-02-26","2020-02-27","2020-02-28","2020-03-02","2020-03-03","2020-03-04","2020-03-05","2020-03-06","2020-03-09","2020-03-10","2020-03-11","2020-03-12","2020-03-13","2020-03-16","2020-03-17","2020-03-18","2020-03-19","2020-03-20","2020-03-23","2020-03-24","2020-03-25","2020-03-26","2020-03-27","2020-03-30","2020-03-31","2020-04-01","2020-04-02","2020-04-03","2020-04-06","2020-04-07","2020-04-08","2020-04-09","2020-04-13","2020-04-14","2020-04-15","2020-04-16","2020-04-17","2020-04-20","2020-04-21","2020-04-22","2020-04-23","2020-04-24","2020-04-27","2020-04-28","2020-04-29","2020-04-30","2020-05-01","2020-05-04","2020-05-05","2020-05-06","2020-05-07","2020-05-08","2020-05-11","2020-05-12","2020-05-13","2020-05-14","2020-05-15","2020-05-18","2020-05-19","2020-05-20","2020-05-21","2020-05-22","2020-05-26","2020-05-27","2020-05-28","2020-05-29","2020-06-01","2020-06-02","2020-06-03","2020-06-04","2020-06-05","2020-06-08","2020-06-09","2020-06-10","2020-06-11","2020-06-12","2020-06-15","2020-06-16","2020-06-17","2020-06-18","2020-06-19","2020-06-22","2020-06-23","2020-06-24","2020-06-25","2020-06-26","2020-06-29","2020-06-30","2020-07-01","2020-07-02","2020-07-06","2020-07-07","2020-07-08","2020-07-09","2020-07-10","2020-07-13","2020-07-14","2020-07-15","2020-07-16","2020-07-17","2020-07-20","2020-07-21","2020-07-22","2020-07-23","2020-07-24","2020-07-27","2020-07-28","2020-07-29","2020-07-30","2020-07-31","2020-08-03","2020-08-04","2020-08-05","2020-08-06","2020-08-07","2020-08-10","2020-08-11","2020-08-12","2020-08-13","2020-08-14","2020-08-17","2020-08-18","2020-08-19","2020-08-20","2020-08-21","2020-08-24","2020-08-25","2020-08-26","2020-08-27","2020-08-28","2020-08-31"],"y":[295.392,293.155,294.273,293.446,295.01,297.01,296.156,298.192,297.738,298.411,300.893,301.829,301.238,301.275,301.62,298.938,294.146,297.228,296.983,297.947,292.537,294.71,299.202,302.657,303.675,302.057,304.312,304.839,306.803,306.476,306.967,306.176,307.639,306.376,303.221,293.164,284.281,283.235,270.514,269.378,281.044,272.997,284.471,275.015,270.469,249.347,262.249,249.465,225.597,244.882,218.086,229.861,218.223,218.686,209.262,203.912,222.387,225.716,238.896,231.78,239.307,235.74,225.131,230.326,226.997,242.243,242.49,250.63,254.444,252.121,259.557,254.042,255.267,262.163,257.545,249.725,255.267,255.249,258.807,262.538,261.331,268.172,265.675,258.642,259.355,261.752,259.977,263.115,267.468,267.523,262.191,257.554,260.636,261.834,269.809,267.038,271.575,269.7,270.212,273.541,277.611,277.099,278.334,279.459,281.772,285.522,284.772,292.071,295.601,293.397,291.76,274.94,278.233,280.83,286.236,285.047,285.156,283.527,285.346,286.659,279.347,282.342,275.636,279.687,283.27,285.254,286.825,291.253,288.249,290.453,288.8,291.749,289.222,292.971,295.662,294.688,295.543,297.931,298.565,300.264,296.682,294.771,296.921,295.037,298.666,297.6,299.952,302.037,303.204,305.087,307.127,307.347,308.266,305.721,309.983,309.423,309.432,310.415,311.086,309.791,310.755,311.858,315.017,316.12,319.289,319.987,322.054,320.888],"sx":[77.64,79.55,85.31,87.22,89.14,91.06,92.97,98.72,100.64,102.56,104.47,106.39,114.06,115.98,117.89,119.81,125.56,127.48,129.4,131.31,133.23,138.98,140.9,142.81,144.73,146.65,152.4,154.32,156.23,158.15,160.07,167.73,169.65,171.57,173.48,179.24,181.15,183.07,184.99,186.9,192.65,194.57,196.49,198.41,200.32,206.07,207.99,209.91,211.82,213.74,219.49,221.41,223.33,225.24,227.16,232.91,234.83,236.74,238.66,240.58,246.33,248.25,250.16,252.08,254.0,259.75,261.66,263.58,265.5,273.17,275.08,277.0,278.92,280.83,286.58,288.5,290.42,292.34,294.25,300.0,301.92,303.84,305.75,307.67,313.42,315.34,317.26,319.17,321.09,326.84,328.76,330.67,332.59,334.51,340.26,342.18,344.09,346.01,347.93,355.59,357.51,359.43,361.35,367.1,369.01,370.93,372.85,374.76,380.52,382.43,384.35,386.27,388.18,393.93,395.85,397.77,399.68,401.6,407.35,409.27,411.19,413.1,415.02,420.77,422.69,424.61,426.52,434.19,436.11,438.02,439.94,441.86,447.61,449.53,451.44,453.36,455.28,461.03,462.94,464.86,466.78,468.69,474.45,476.36,478.28,480.2,482.11,487.86,489.78,491.7,493.62,495.53,501.28,503.2,505.12,507.03,508.95,514.7,516.62,518.54,520.45,522.37,528.12,530.04,531.95,533.87,535.79,541.54],"sy":[77.97,80.9,79.43,80.52,78.47,75.85,76.97,74.3,74.9,74.02,70.77,69.54,70.31,70.27,69.81,73.33,79.6,75.56,75.89,74.62,81.71,78.86,72.98,68.46,67.12,69.24,66.29,65.6,63.03,63.46,62.81,63.85,61.93,63.59,67.72,80.89,92.52,93.89,110.54,112.03,96.76,107.29,92.27,104.65,110.6,138.26,121.36,138.1,169.35,144.1,179.19,163.77,179.01,178.4,190.74,197.74,173.55,169.2,151.94,161.26,151.4,156.07,169.96,163.16,167.52,147.56,147.23,136.58,131.58,134.62,124.89,132.11,130.5,121.48,127.52,137.76,130.5,130.53,125.87,120.98,122.57,113.61,116.88,126.09,125.15,122.01,124.34,120.23,114.53,114.46,121.44,127.51,123.48,121.91,111.46,115.09,109.15,111.61,110.94,106.58,101.25,101.92,100.3,98.83,95.8,90.89,91.87,82.32,77.69,80.58,82.72,104.75,100.44,97.03,89.96,91.51,91.37,93.5,91.12,89.4,98.98,95.06,103.84,98.53,93.84,91.24,89.19,83.39,87.32,84.44,86.6,82.74,86.05,81.14,77.62,78.89,77.77,74.64,73.81,71.59,76.28,78.78,75.97,78.43,73.68,75.08,72.0,69.27,67.74,65.28,62.6,62.32,61.11,64.45,58.86,59.6,59.59,58.3,57.42,59.12,57.85,56.41,52.27,50.83,46.68,45.77,43.06,44.59]},{"panel":0,"label":"20-day average (middle band)","color":"var(--chart-blue, #3b6ea5)","x":["2020-01-02","2020-01-03","2020-01-06","2020-01-07","2020-01-08","2020-01-09","2020-01-10","2020-01-13","2020-01-14","2020-01-15","2020-01-16","2020-01-17","2020-01-21","2020-01-22","2020-01-23","2020-01-24","2020-01-27","2020-01-28","2020-01-29","2020-01-30","2020-01-31","2020-02-03","2020-02-04","2020-02-05","2020-02-06","2020-02-07","2020-02-10","2020-02-11","2020-02-12","2020-02-13","2020-02-14","2020-02-18","2020-02-19","2020-02-20","2020-02-21","2020-02-24","2020-02-25","2020-02-26","2020-02-27","2020-02-28","2020-03-02","2020-03-03","2020-03-04","2020-03-05","2020-03-06","2020-03-09","2020-03-10","2020-03-11","2020-03-12","2020-03-13","2020-03-16","2020-03-17","2020-03-18","2020-03-19","2020-03-20","2020-03-23","2020-03-24","2020-03-25","2020-03-26","2020-03-27","2020-03-30","2020-03-31","2020-04-01","2020-04-02","2020-04-03","2020-04-06","2020-04-07","2020-04-08","2020-04-09","2020-04-13","2020-04-14","2020-04-15","2020-04-16","2020-04-17","2020-04-20","2020-04-21","2020-04-22","2020-04-23","2020-04-24","2020-04-27","2020-04-28","2020-04-29","2020-04-30","2020-05-01","2020-05-04","2020-05-05","2020-05-06","2020-05-07","2020-05-08","2020-05-11","2020-05-12","2020-05-13","2020-05-14","2020-05-15","2020-05-18","2020-05-19","2020-05-20","2020-05-21","2020-05-22","2020-05-26","2020-05-27","2020-05-28","2020-05-29","2020-06-01","2020-06-02","2020-06-03","2020-06-04","2020-06-05","2020-06-08","2020-06-09","2020-06-10","2020-06-11","2020-06-12","2020-06-15","2020-06-16","2020-06-17","2020-06-18","2020-06-19","2020-06-22","2020-06-23","2020-06-24","2020-06-25","2020-06-26","2020-06-29","2020-06-30","2020-07-01","2020-07-02","2020-07-06","2020-07-07","2020-07-08","2020-07-09","2020-07-10","2020-07-13","2020-07-14","2020-07-15","2020-07-16","2020-07-17","2020-07-20","2020-07-21","2020-07-22","2020-07-23","2020-07-24","2020-07-27","2020-07-28","2020-07-29","2020-07-30","2020-07-31","2020-08-03","2020-08-04","2020-08-05","2020-08-06","2020-08-07","2020-08-10","2020-08-11","2020-08-12","2020-08-13","2020-08-14","2020-08-17","2020-08-18","2020-08-19","2020-08-20","2020-08-21","2020-08-24","2020-08-25","2020-08-26","2020-08-27","2020-08-28","2020-08-31"],"y":[288.8,289.367,289.965,290.393,290.943,291.609,292.192,292.755,293.286,293.752,294.339,294.972,295.516,295.999,296.476,296.819,296.844,297.028,297.279,297.544,297.401,297.479,297.725,298.186,298.619,298.872,299.279,299.612,300.065,300.468,300.772,300.989,301.309,301.564,301.644,301.356,300.862,300.163,298.839,297.411,296.836,295.751,295.014,293.632,291.972,289.336,287.233,284.464,280.404,277.324,272.88,269.065,264.594,260.209,255.511,251.049,247.954,245.078,243.497,241.617,239.53,237.668,234.701,232.466,230.293,229.937,228.949,229.008,230.45,230.812,232.885,234.094,235.947,238.121,240.535,242.825,244.469,245.946,246.941,248.479,249.581,251.202,253.229,254.645,256.263,257.239,258.113,258.737,259.388,260.158,260.29,260.466,260.734,260.718,261.331,262.197,263.012,263.735,264.305,264.855,265.669,266.115,266.748,267.789,268.91,270.098,271.338,272.786,274.193,275.486,276.965,277.834,278.714,279.664,280.485,281.386,282.065,282.756,283.513,284.169,284.255,284.518,284.383,284.394,284.469,284.456,284.558,284.517,284.15,284.002,283.854,284.695,285.244,285.851,286.323,286.805,287.324,288.044,288.705,289.385,290.252,290.874,291.938,292.705,293.475,294.093,294.749,295.288,296.036,296.768,297.684,298.464,299.416,300.054,300.77,301.506,302.201,302.825,303.451,303.927,304.631,305.485,306.39,307.444,308.476,309.595,310.7,311.643],"sx":[77.64,79.55,85.31,87.22,89.14,91.06,92.97,98.72,100.64,102.56,104.47,106.39,114.06,115.98,117.89,119.81,125.56,127.48,129.4,131.31,133.23,138.98,140.9,142.81,144.73,146.65,152.4,154.32,156.23,158.15,160.07,167.73,169.65,171.57,173.48,179.24,181.15,183.07,184.99,186.9,192.65,194.57,196.49,198.41,200.32,206.07,207.99,209.91,211.82,213.74,219.49,221.41,223.33,225.24,227.16,232.91,234.83,236.74,238.66,240.58,246.33,248.25,250.16,252.08,254.0,259.75,261.66,263.58,265.5,273.17,275.08,277.0,278.92,280.83,286.58,288.5,290.42,292.34,294.25,300.0,301.92,303.84,305.75,307.67,313.42,315.34,317.26,319.17,321.09,326.84,328.76,330.67,332.59,334.51,340.26,342.18,344.09,346.01,347.93,355.59,357.51,359.43,361.35,367.1,369.01,370.93,372.85,374.76,380.52,382.43,384.35,386.27,388.18,393.93,395.85,397.77,399.68,401.6,407.35,409.27,411.19,413.1,415.02,420.77,422.69,424.61,426.52,434.19,436.11,438.02,439.94,441.86,447.61,449.53,451.44,453.36,455.28,461.03,462.94,464.86,466.78,468.69,474.45,476.36,478.28,480.2,482.11,487.86,489.78,491.7,493.62,495.53,501.28,503.2,505.12,507.03,508.95,514.7,516.62,518.54,520.45,522.37,528.12,530.04,531.95,533.87,535.79,541.54],"sy":[86.6,85.86,85.07,84.51,83.79,82.92,82.16,81.42,80.73,80.12,79.35,78.52,77.81,77.17,76.55,76.1,76.07,75.83,75.5,75.15,75.34,75.24,74.91,74.31,73.74,73.41,72.88,72.44,71.85,71.32,70.93,70.64,70.22,69.89,69.78,70.16,70.81,71.72,73.46,75.33,76.08,77.5,78.46,80.27,82.45,85.9,88.65,92.28,97.59,101.63,107.44,112.44,118.29,124.03,130.18,136.03,140.08,143.85,145.92,148.38,151.11,153.55,157.43,160.36,163.2,163.67,164.96,164.89,163.0,162.52,159.81,158.23,155.8,152.95,149.79,146.79,144.64,142.71,141.41,139.39,137.95,135.83,133.17,131.32,129.2,127.92,126.78,125.96,125.11,124.1,123.93,123.7,123.35,123.37,122.57,121.43,120.36,119.42,118.67,117.95,116.89,116.3,115.47,114.11,112.64,111.09,109.46,107.57,105.73,104.03,102.1,100.96,99.81,98.56,97.49,96.31,95.42,94.51,93.52,92.66,92.55,92.21,92.38,92.37,92.27,92.29,92.15,92.21,92.69,92.88,93.08,91.97,91.26,90.46,89.84,89.21,88.53,87.59,86.72,85.83,84.7,83.88,82.49,81.49,80.48,79.67,78.81,78.1,77.13,76.17,74.97,73.95,72.7,71.87,70.93,69.96,69.05,68.24,67.42,66.79,65.87,64.75,63.57,62.19,60.84,59.37,57.93,56.69]},{"panel":0,"label":"upper band (average + 2 sd)","color":"var(--chart-grey, #a3a19c)","x":["2020-01-02","2020-01-03","2020-01-06","2020-01-07","2020-01-08","2020-01-09","2020-01-10","2020-01-13","2020-01-14","2020-01-15","2020-01-16","2020-01-17","2020-01-21","2020-01-22","2020-01-23","2020-01-24","2020-01-27","2020-01-28","2020-01-29","2020-01-30","2020-01-31","2020-02-03","2020-02-04","2020-02-05","2020-02-06","2020-02-07","2020-02-10","2020-02-11","2020-02-12","2020-02-13","2020-02-14","2020-02-18","2020-02-19","2020-02-20","2020-02-21","2020-02-24","2020-02-25","2020-02-26","2020-02-27","2020-02-28","2020-03-02","2020-03-03","2020-03-04","2020-03-05","2020-03-06","2020-03-09","2020-03-10","2020-03-11","2020-03-12","2020-03-13","2020-03-16","2020-03-17","2020-03-18","2020-03-19","2020-03-20","2020-03-23","2020-03-24","2020-03-25","2020-03-26","2020-03-27","2020-03-30","2020-03-31","2020-04-01","2020-04-02","2020-04-03","2020-04-06","2020-04-07","2020-04-08","2020-04-09","2020-04-13","2020-04-14","2020-04-15","2020-04-16","2020-04-17","2020-04-20","2020-04-21","2020-04-22","2020-04-23","2020-04-24","2020-04-27","2020-04-28","2020-04-29","2020-04-30","2020-05-01","2020-05-04","2020-05-05","2020-05-06","2020-05-07","2020-05-08","2020-05-11","2020-05-12","2020-05-13","2020-05-14","2020-05-15","2020-05-18","2020-05-19","2020-05-20","2020-05-21","2020-05-22","2020-05-26","2020-05-27","2020-05-28","2020-05-29","2020-06-01","2020-06-02","2020-06-03","2020-06-04","2020-06-05","2020-06-08","2020-06-09","2020-06-10","2020-06-11","2020-06-12","2020-06-15","2020-06-16","2020-06-17","2020-06-18","2020-06-19","2020-06-22","2020-06-23","2020-06-24","2020-06-25","2020-06-26","2020-06-29","2020-06-30","2020-07-01","2020-07-02","2020-07-06","2020-07-07","2020-07-08","2020-07-09","2020-07-10","2020-07-13","2020-07-14","2020-07-15","2020-07-16","2020-07-17","2020-07-20","2020-07-21","2020-07-22","2020-07-23","2020-07-24","2020-07-27","2020-07-28","2020-07-29","2020-07-30","2020-07-31","2020-08-03","2020-08-04","2020-08-05","2020-08-06","2020-08-07","2020-08-10","2020-08-11","2020-08-12","2020-08-13","2020-08-14","2020-08-17","2020-08-18","2020-08-19","2020-08-20","2020-08-21","2020-08-24","2020-08-25","2020-08-26","2020-08-27","2020-08-28","2020-08-31"],"y":[297.092,297.185,297.329,297.506,297.667,297.934,297.872,298.474,298.768,299.316,300.321,301.319,302.059,302.753,303.41,303.512,303.49,303.492,303.286,303.146,303.368,303.25,303.338,303.832,304.561,304.953,305.679,306.449,307.551,308.432,309.251,309.799,310.608,311.135,311.244,311.622,313.305,314.839,318.612,321.179,321.634,322.744,322.412,322.171,321.882,324.357,323.497,323.424,325.933,323.752,324.126,321.228,318.146,313.717,309.614,306.774,302.776,298.113,295.208,292.085,286.461,281.885,273.301,266.094,258.809,257.619,252.94,253.213,257.113,258.477,262.67,265.292,267.572,270.713,271.223,268.421,268.726,268.96,270.39,271.775,273.131,275.202,274.67,273.273,269.669,269.099,267.769,267.961,269.158,269.945,270.113,269.938,269.884,269.858,271.192,270.717,271.855,272.263,272.97,274.4,276.621,278.169,279.977,281.596,283.454,286.001,287.775,291.16,294.999,297.716,299.403,298.373,297.591,296.796,297.198,296.949,296.998,296.513,295.967,295.764,295.669,295.47,295.716,295.707,295.729,295.71,295.863,295.713,294.241,293.599,293.03,293.504,293.721,294.727,296.226,297.363,298.542,300.057,301.521,303.153,303.533,303.753,302.889,302.079,302.083,301.957,302.242,303.259,304.032,305.274,306.519,307.831,308.699,309.223,310.7,311.72,312.594,313.63,314.66,315.373,315.931,316.216,317.132,317.618,319.074,320.086,321.564,322.612],"sx":[77.64,79.55,85.31,87.22,89.14,91.06,92.97,98.72,100.64,102.56,104.47,106.39,114.06,115.98,117.89,119.81,125.56,127.48,129.4,131.31,133.23,138.98,140.9,142.81,144.73,146.65,152.4,154.32,156.23,158.15,160.07,167.73,169.65,171.57,173.48,179.24,181.15,183.07,184.99,186.9,192.65,194.57,196.49,198.41,200.32,206.07,207.99,209.91,211.82,213.74,219.49,221.41,223.33,225.24,227.16,232.91,234.83,236.74,238.66,240.58,246.33,248.25,250.16,252.08,254.0,259.75,261.66,263.58,265.5,273.17,275.08,277.0,278.92,280.83,286.58,288.5,290.42,292.34,294.25,300.0,301.92,303.84,305.75,307.67,313.42,315.34,317.26,319.17,321.09,326.84,328.76,330.67,332.59,334.51,340.26,342.18,344.09,346.01,347.93,355.59,357.51,359.43,361.35,367.1,369.01,370.93,372.85,374.76,380.52,382.43,384.35,386.27,388.18,393.93,395.85,397.77,399.68,401.6,407.35,409.27,411.19,413.1,415.02,420.77,422.69,424.61,426.52,434.19,436.11,438.02,439.94,441.86,447.61,449.53,451.44,453.36,455.28,461.03,462.94,464.86,466.78,468.69,474.45,476.36,478.28,480.2,482.11,487.86,489.78,491.7,493.62,495.53,501.28,503.2,505.12,507.03,508.95,514.7,516.62,518.54,520.45,522.37,528.12,530.04,531.95,533.87,535.79,541.54],"sy":[75.74,75.62,75.43,75.2,74.99,74.64,74.72,73.93,73.55,72.83,71.52,70.21,69.24,68.33,67.47,67.34,67.37,67.36,67.63,67.82,67.53,67.68,67.56,66.92,65.96,65.45,64.5,63.49,62.05,60.9,59.82,59.11,58.05,57.36,57.21,56.72,54.52,52.51,47.57,44.21,43.61,42.16,42.59,42.91,43.29,40.05,41.17,41.27,37.98,40.84,40.35,44.14,48.18,53.98,59.35,63.07,68.3,74.41,78.21,82.3,89.66,95.65,106.89,116.33,125.87,127.42,133.55,133.19,128.09,126.3,120.81,117.38,114.39,110.28,109.61,113.28,112.88,112.58,110.7,108.89,107.11,104.4,105.1,106.93,111.65,112.39,114.14,113.89,112.32,111.29,111.07,111.3,111.37,111.4,109.65,110.28,108.79,108.25,107.33,105.45,102.55,100.52,98.15,96.03,93.6,90.26,87.94,83.51,78.48,74.93,72.72,74.07,75.09,76.13,75.6,75.93,75.87,76.5,77.22,77.48,77.61,77.87,77.54,77.56,77.53,77.55,77.35,77.55,79.48,80.32,81.06,80.44,80.16,78.84,76.88,75.39,73.84,71.86,69.94,67.81,67.31,67.02,68.15,69.21,69.21,69.37,69.0,67.67,66.66,65.03,63.4,61.68,60.55,59.86,57.93,56.59,55.45,54.09,52.74,51.81,51.08,50.7,49.51,48.87,46.96,45.64,43.7,42.33]},{"panel":0,"label":"lower band (average - 2 sd)","color":"var(--chart-grey, #a3a19c)","x":["2020-01-02","2020-01-03","2020-01-06","2020-01-07","2020-01-08","2020-01-09","2020-01-10","2020-01-13","2020-01-14","2020-01-15","2020-01-16","2020-01-17","2020-01-21","2020-01-22","2020-01-23","2020-01-24","2020-01-27","2020-01-28","2020-01-29","2020-01-30","2020-01-31","2020-02-03","2020-02-04","2020-02-05","2020-02-06","2020-02-07","2020-02-10","2020-02-11","2020-02-12","2020-02-13","2020-02-14","2020-02-18","2020-02-19","2020-02-20","2020-02-21","2020-02-24","2020-02-25","2020-02-26","2020-02-27","2020-02-28","2020-03-02","2020-03-03","2020-03-04","2020-03-05","2020-03-06","2020-03-09","2020-03-10","2020-03-11","2020-03-12","2020-03-13","2020-03-16","2020-03-17","2020-03-18","2020-03-19","2020-03-20","2020-03-23","2020-03-24","2020-03-25","2020-03-26","2020-03-27","2020-03-30","2020-03-31","2020-04-01","2020-04-02","2020-04-03","2020-04-06","2020-04-07","2020-04-08","2020-04-09","2020-04-13","2020-04-14","2020-04-15","2020-04-16","2020-04-17","2020-04-20","2020-04-21","2020-04-22","2020-04-23","2020-04-24","2020-04-27","2020-04-28","2020-04-29","2020-04-30","2020-05-01","2020-05-04","2020-05-05","2020-05-06","2020-05-07","2020-05-08","2020-05-11","2020-05-12","2020-05-13","2020-05-14","2020-05-15","2020-05-18","2020-05-19","2020-05-20","2020-05-21","2020-05-22","2020-05-26","2020-05-27","2020-05-28","2020-05-29","2020-06-01","2020-06-02","2020-06-03","2020-06-04","2020-06-05","2020-06-08","2020-06-09","2020-06-10","2020-06-11","2020-06-12","2020-06-15","2020-06-16","2020-06-17","2020-06-18","2020-06-19","2020-06-22","2020-06-23","2020-06-24","2020-06-25","2020-06-26","2020-06-29","2020-06-30","2020-07-01","2020-07-02","2020-07-06","2020-07-07","2020-07-08","2020-07-09","2020-07-10","2020-07-13","2020-07-14","2020-07-15","2020-07-16","2020-07-17","2020-07-20","2020-07-21","2020-07-22","2020-07-23","2020-07-24","2020-07-27","2020-07-28","2020-07-29","2020-07-30","2020-07-31","2020-08-03","2020-08-04","2020-08-05","2020-08-06","2020-08-07","2020-08-10","2020-08-11","2020-08-12","2020-08-13","2020-08-14","2020-08-17","2020-08-18","2020-08-19","2020-08-20","2020-08-21","2020-08-24","2020-08-25","2020-08-26","2020-08-27","2020-08-28","2020-08-31"],"y":[280.508,281.55,282.602,283.279,284.219,285.284,286.512,287.036,287.804,288.188,288.357,288.625,288.973,289.244,289.542,290.126,290.199,290.563,291.272,291.942,291.435,291.708,292.112,292.54,292.677,292.79,292.879,292.774,292.579,292.504,292.293,292.18,292.01,291.993,292.045,291.089,288.42,285.487,279.067,273.643,272.039,268.757,267.616,265.092,262.062,254.315,250.969,245.505,234.875,230.897,221.634,216.901,211.042,206.702,201.409,195.324,193.132,192.044,191.787,191.15,192.6,193.451,196.1,198.838,201.776,202.255,204.959,204.802,203.787,203.147,203.101,202.897,204.321,205.528,209.846,217.23,220.212,222.932,223.493,225.184,226.03,227.202,231.789,236.017,242.857,245.378,248.457,249.514,249.618,250.372,250.467,250.994,251.584,251.577,251.47,253.677,254.169,255.207,255.64,255.31,254.717,254.061,253.519,253.983,254.366,254.196,254.901,254.412,253.386,253.257,254.526,257.296,259.837,262.532,263.773,265.823,267.132,268.999,271.058,272.573,272.842,273.565,273.049,273.081,273.21,273.201,273.254,273.322,274.059,274.406,274.679,275.886,276.768,276.976,276.42,276.246,276.106,276.031,275.89,275.618,276.972,277.995,280.987,283.332,284.867,286.228,287.256,287.318,288.04,288.261,288.849,289.097,290.133,290.884,290.839,291.293,291.808,292.02,292.242,292.482,293.331,294.755,295.649,297.271,297.877,299.104,299.836,300.673],"sx":[77.64,79.55,85.31,87.22,89.14,91.06,92.97,98.72,100.64,102.56,104.47,106.39,114.06,115.98,117.89,119.81,125.56,127.48,129.4,131.31,133.23,138.98,140.9,142.81,144.73,146.65,152.4,154.32,156.23,158.15,160.07,167.73,169.65,171.57,173.48,179.24,181.15,183.07,184.99,186.9,192.65,194.57,196.49,198.41,200.32,206.07,207.99,209.91,211.82,213.74,219.49,221.41,223.33,225.24,227.16,232.91,234.83,236.74,238.66,240.58,246.33,248.25,250.16,252.08,254.0,259.75,261.66,263.58,265.5,273.17,275.08,277.0,278.92,280.83,286.58,288.5,290.42,292.34,294.25,300.0,301.92,303.84,305.75,307.67,313.42,315.34,317.26,319.17,321.09,326.84,328.76,330.67,332.59,334.51,340.26,342.18,344.09,346.01,347.93,355.59,357.51,359.43,361.35,367.1,369.01,370.93,372.85,374.76,380.52,382.43,384.35,386.27,388.18,393.93,395.85,397.77,399.68,401.6,407.35,409.27,411.19,413.1,415.02,420.77,422.69,424.61,426.52,434.19,436.11,438.02,439.94,441.86,447.61,449.53,451.44,453.36,455.28,461.03,462.94,464.86,466.78,468.69,474.45,476.36,478.28,480.2,482.11,487.86,489.78,491.7,493.62,495.53,501.28,503.2,505.12,507.03,508.95,514.7,516.62,518.54,520.45,522.37,528.12,530.04,531.95,533.87,535.79,541.54],"sy":[97.46,96.09,94.72,93.83,92.6,91.2,89.6,88.91,87.9,87.4,87.18,86.83,86.37,86.02,85.63,84.86,84.77,84.29,83.36,82.49,83.15,82.79,82.26,81.7,81.52,81.38,81.26,81.4,81.65,81.75,82.03,82.17,82.4,82.42,82.35,83.6,87.1,90.94,99.34,106.45,108.55,112.84,114.34,117.64,121.61,131.75,136.13,143.29,157.2,162.41,174.54,180.74,188.41,194.09,201.02,208.99,211.86,213.28,213.62,214.45,212.56,211.44,207.97,204.39,200.54,199.91,196.37,196.58,197.91,198.75,198.81,199.07,197.21,195.63,189.98,180.31,176.4,172.84,172.11,169.89,168.79,167.25,161.25,155.71,146.75,143.45,139.42,138.04,137.9,136.91,136.79,136.1,135.33,135.34,135.48,132.59,131.94,130.58,130.02,130.45,131.23,132.08,132.79,132.19,131.68,131.91,130.98,131.62,132.97,133.14,131.47,127.85,124.52,120.99,119.37,116.68,114.97,112.52,109.83,107.85,107.49,106.55,107.22,107.18,107.01,107.02,106.95,106.87,105.9,105.45,105.09,103.51,102.35,102.08,102.81,103.04,103.22,103.32,103.5,103.86,102.09,100.75,96.83,93.76,91.75,89.97,88.62,88.54,87.6,87.31,86.54,86.21,84.85,83.87,83.93,83.34,82.66,82.38,82.09,81.78,80.67,78.8,77.63,75.51,74.72,73.11,72.15,71.05]},{"panel":1,"label":"%B (0 = lower band, 1 = upper band)","color":"var(--chart-maroon, #b6262c)","x":["2020-01-02","2020-01-03","2020-01-06","2020-01-07","2020-01-08","2020-01-09","2020-01-10","2020-01-13","2020-01-14","2020-01-15","2020-01-16","2020-01-17","2020-01-21","2020-01-22","2020-01-23","2020-01-24","2020-01-27","2020-01-28","2020-01-29","2020-01-30","2020-01-31","2020-02-03","2020-02-04","2020-02-05","2020-02-06","2020-02-07","2020-02-10","2020-02-11","2020-02-12","2020-02-13","2020-02-14","2020-02-18","2020-02-19","2020-02-20","2020-02-21","2020-02-24","2020-02-25","2020-02-26","2020-02-27","2020-02-28","2020-03-02","2020-03-03","2020-03-04","2020-03-05","2020-03-06","2020-03-09","2020-03-10","2020-03-11","2020-03-12","2020-03-13","2020-03-16","2020-03-17","2020-03-18","2020-03-19","2020-03-20","2020-03-23","2020-03-24","2020-03-25","2020-03-26","2020-03-27","2020-03-30","2020-03-31","2020-04-01","2020-04-02","2020-04-03","2020-04-06","2020-04-07","2020-04-08","2020-04-09","2020-04-13","2020-04-14","2020-04-15","2020-04-16","2020-04-17","2020-04-20","2020-04-21","2020-04-22","2020-04-23","2020-04-24","2020-04-27","2020-04-28","2020-04-29","2020-04-30","2020-05-01","2020-05-04","2020-05-05","2020-05-06","2020-05-07","2020-05-08","2020-05-11","2020-05-12","2020-05-13","2020-05-14","2020-05-15","2020-05-18","2020-05-19","2020-05-20","2020-05-21","2020-05-22","2020-05-26","2020-05-27","2020-05-28","2020-05-29","2020-06-01","2020-06-02","2020-06-03","2020-06-04","2020-06-05","2020-06-08","2020-06-09","2020-06-10","2020-06-11","2020-06-12","2020-06-15","2020-06-16","2020-06-17","2020-06-18","2020-06-19","2020-06-22","2020-06-23","2020-06-24","2020-06-25","2020-06-26","2020-06-29","2020-06-30","2020-07-01","2020-07-02","2020-07-06","2020-07-07","2020-07-08","2020-07-09","2020-07-10","2020-07-13","2020-07-14","2020-07-15","2020-07-16","2020-07-17","2020-07-20","2020-07-21","2020-07-22","2020-07-23","2020-07-24","2020-07-27","2020-07-28","2020-07-29","2020-07-30","2020-07-31","2020-08-03","2020-08-04","2020-08-05","2020-08-06","2020-08-07","2020-08-10","2020-08-11","2020-08-12","2020-08-13","2020-08-14","2020-08-17","2020-08-18","2020-08-19","2020-08-20","2020-08-21","2020-08-24","2020-08-25","2020-08-26","2020-08-27","2020-08-28","2020-08-31"],"y":[0.89746,0.742241,0.792534,0.714632,0.802414,0.926952,0.84887,0.975378,0.906035,0.918639,1.04779,1.04022,0.937262,0.890537,0.870952,0.658303,0.296989,0.515545,0.475329,0.535945,0.092343,0.260073,0.631498,0.895923,0.925455,0.761885,0.893158,0.882249,0.950067,0.87716,0.865312,0.794368,0.840371,0.751351,0.582101,0.101048,-0.166346,-0.0767152,-0.216281,-0.0897221,0.181572,0.078532,0.307603,0.173843,0.140544,-0.0709373,0.155528,0.0508251,-0.101888,0.150619,-0.0346162,0.12423,0.0670483,0.11199,0.0725798,0.0770595,0.266815,0.317459,0.455507,0.402538,0.497621,0.478206,0.37604,0.468176,0.44221,0.72227,0.782206,0.946647,0.949956,0.885123,0.947737,0.819695,0.805458,0.868844,0.777134,0.634776,0.722572,0.702114,0.753008,0.80175,0.749472,0.853541,0.790241,0.607282,0.615333,0.690262,0.596546,0.737295,0.913492,0.876271,0.596741,0.346275,0.494633,0.561065,0.929874,0.78412,0.984148,0.849732,0.840863,0.955009,1.04517,0.955592,0.937883,0.922608,0.942204,0.984958,0.908654,1.02478,1.01447,0.902865,0.829684,0.429553,0.487259,0.534049,0.672042,0.617622,0.603523,0.528021,0.573589,0.6074,0.284971,0.400672,0.114104,0.291954,0.446741,0.535464,0.600252,0.800815,0.703095,0.836087,0.769494,0.900366,0.734644,0.901068,0.971552,0.873336,0.866308,0.911506,0.884673,0.895094,0.742066,0.651305,0.727503,0.624393,0.801495,0.723012,0.847206,0.923385,0.948229,0.988993,1.03439,0.974181,0.976681,0.809046,0.963911,0.887569,0.847893,0.851241,0.840562,0.756126,0.770983,0.796921,0.901591,0.926393,1.01015,0.995321,1.02258,0.921401],"sx":[77.64,79.55,85.31,87.22,89.14,91.06,92.97,98.72,100.64,102.56,104.47,106.39,114.06,115.98,117.89,119.81,125.56,127.48,129.4,131.31,133.23,138.98,140.9,142.81,144.73,146.65,152.4,154.32,156.23,158.15,160.07,167.73,169.65,171.57,173.48,179.24,181.15,183.07,184.99,186.9,192.65,194.57,196.49,198.41,200.32,206.07,207.99,209.91,211.82,213.74,219.49,221.41,223.33,225.24,227.16,232.91,234.83,236.74,238.66,240.58,246.33,248.25,250.16,252.08,254.0,259.75,261.66,263.58,265.5,273.17,275.08,277.0,278.92,280.83,286.58,288.5,290.42,292.34,294.25,300.0,301.92,303.84,305.75,307.67,313.42,315.34,317.26,319.17,321.09,326.84,328.76,330.67,332.59,334.51,340.26,342.18,344.09,346.01,347.93,355.59,357.51,359.43,361.35,367.1,369.01,370.93,372.85,374.76,380.52,382.43,384.35,386.27,388.18,393.93,395.85,397.77,399.68,401.6,407.35,409.27,411.19,413.1,415.02,420.77,422.69,424.61,426.52,434.19,436.11,438.02,439.94,441.86,447.61,449.53,451.44,453.36,455.28,461.03,462.94,464.86,466.78,468.69,474.45,476.36,478.28,480.2,482.11,487.86,489.78,491.7,493.62,495.53,501.28,503.2,505.12,507.03,508.95,514.7,516.62,518.54,520.45,522.37,528.12,530.04,531.95,533.87,535.79,541.54],"sy":[341.77,363.44,356.42,367.29,355.04,337.65,348.55,330.89,340.57,338.81,320.78,321.84,336.21,342.73,345.47,375.16,425.6,395.09,400.7,392.24,454.17,430.75,378.9,341.98,337.86,360.7,342.37,343.89,334.42,344.6,346.26,356.16,349.74,362.17,385.79,452.95,490.28,477.77,497.25,479.59,441.71,456.1,424.12,442.79,447.44,476.96,445.35,459.96,481.28,446.03,471.89,449.72,457.7,451.43,456.93,456.3,429.81,422.74,403.47,410.86,397.59,400.3,414.56,401.7,405.32,366.23,357.86,334.9,334.44,343.49,334.75,352.63,354.61,345.76,358.57,378.44,366.18,369.04,361.93,355.13,362.43,347.9,356.74,382.28,381.16,370.69,383.78,364.13,339.53,344.73,383.75,418.72,398.01,388.73,337.24,357.59,329.67,348.43,349.67,333.73,321.15,333.65,336.13,338.26,335.52,329.55,340.21,323.99,325.43,341.01,351.23,407.09,399.04,392.5,373.24,380.84,382.8,393.34,386.98,382.26,427.28,411.12,451.13,426.3,404.69,392.31,383.26,355.26,368.9,350.34,359.63,341.36,364.5,341.26,331.42,345.14,346.12,339.81,343.55,342.1,363.46,376.13,365.5,379.89,355.17,366.12,348.78,338.15,334.68,328.99,322.65,331.06,330.71,354.11,332.49,343.15,348.69,348.22,349.71,361.5,359.43,355.8,341.19,337.73,326.04,328.11,324.3,338.43]}]} 2026-10-27T02:45:15.659202 image/svg+xml Matplotlib v3.11.2, https://matplotlib.org/ 2020-01 2020-02 2020-03 2020-04 2020-05 2020-06 2020-07 2020-08 2020-09 Date (2020) 200 220 240 260 280 300 320 Price (dollars) 1. The bands open in the March crash and close again by summer SPY close 20-day average (middle band) upper band (average + 2 sd) lower band (average - 2 sd) 2020-01 2020-02 2020-03 2020-04 2020-05 2020-06 2020-07 2020-08 2020-09 Date (2020) −0.2 0.0 0.2 0.4 0.6 0.8 1.0 %B (fraction of the band) 2. Where the close sits inside the band, day by day %B (0 = lower band, 1 = upper band)

Where the close sits in the band

Charts show the bands on the price; a model wants a single number. The usual one is the close’s position between the two bands, zero at the lower band and one at the upper, called %B. It is the earlier post’s “position in two-standard-deviation units” shifted and halved: a position of bb gives a %B of (b+1)/2(b + 1)/2. On the eleven-percent day the position was −1.07 and %B was −0.035\key{-0.035}, a little below the lower band. The second panel of the chart shows %B through 2020: it goes below zero twice, in late February and mid March, and spends the summer near one.

Both numbers say the same thing and both are comparable across stocks and across years, because the standard deviation in the denominator puts every stock on its own scale. A %B of 1.1 on SPY in 2020 and a %B of 1.1 on a small stock in a quiet year are both “a little above the upper band”, which a dollar gap from the average never is.

What the books say it means, and what SPY did

The books agree on the construction and disagree on the reading. Murphy: prices “are considered to be overextended on the upside (overbought) when they touch the upper band”, and oversold at the lower one. Achelis, quoting Bollinger: “when prices move outside the bands, a continuation of the current trend is implied”. One says a touch is a stretch that should give back; the other says it is strength that should go on. StockCharts settles it the only safe way: a touch is a “tag”, not a signal, and “relatively high” is not the same as “sell”.

Kirkpatrick and Dahlquist come down on Achelis’s side, and give reasons. Trading between the bands, selling at the upper one and buying at the lower one, fails for three reasons they list: the bands contract in a dull market and leave no room to pay costs, a new trend keeps the price pressed against one band and throws off false exits, and widening bands mean volatility has arrived and a position that bet on calm is stopped out. So in their account bands “have become methods of determining the beginnings of trends”: the empirical entry is in the direction of a break outside a band that held about 90% of the past prices, and the middle band becomes the trailing stop. That is a rule, and a tested one, but it is still a rule laid on top of the indicator. The band says where the price is. What to do about it is a rule, with a threshold and a position, and the indicators post is about why those are separate decisions.

One claim can be checked. Murphy writes that two standard deviations “ensures that 95% of the price data will fall between the two trading bands”. Kirkpatrick and Dahlquist explain why it does not: 95% is what two standard deviations contain under the bell curve the formula comes from, and “price action is nonstationary and nonrandom”, so it “does not follow the statistical properties of the standard deviation calculation precisely”. The bands hold “the majority of price action” and no particular share of it. StockCharts quotes Bollinger himself at “about 88-89%”. SPY from 2019 to 2023 lands between the two:

Where the close wasDaysShare of 1,239 days
above the upper band514.1%
inside the bands1,13491.5%
below the lower band544.4%

So the bands held the close about nine days in ten, and a close outside them happened about once every two or three weeks, roughly as often on each side. That is a useful fact about the indicator: “outside the band” is uncommon but not rare, and a rule that fires on every tag fires twenty times a year.

Sample or population standard deviation

pandas divides by 19 when it computes the standard deviation of twenty numbers (the sample version); most charting software divides by 20 (the population version). On 2020-03-16 that is 25.62 against 24.97, and the bands move by about $1.30 each. The ratio is always the square root of 19 over 20, about 0.975, so neither choice changes what a day looks like. The series’ earlier posts use the pandas default and so does this one.

Traps

People thinkActually
A close above the upper band is a sellMurphy reads it as overbought; Achelis and Kirkpatrick and Dahlquist read it as a trend starting; the band says “unusually high”, the rule is yours
Sell at the upper band, buy at the lower oneKirkpatrick and Dahlquist give three reasons that fails: narrow bands in calm markets, the price riding one band in a trend, widening bands stopping out the bet on calm
The bands contain 95% of pricesthat is the bell-curve figure; Bollinger says about 88-89%, SPY gave 91.5%
Wide bands mean the price will fallwide bands mean the last twenty days moved a lot; the direction is not in the width
A narrow band is a signalthe books describe the squeeze; they give no threshold and the post found none
The bands can be read in dollarsthe gap to the band depends on the stock’s price and spread; use %B or the position

The code

The snippet reproduces the bands on 2020-03-16 and the share of days inside them. Variables:

VariableHolds
pxSPY’s adjusted close, one row per trading day
wthe twenty closes ending on 2020-03-16
mid, sdthe 20-day mean and standard deviation, one value per day
pct_b%B: the close’s position between the bands, 0 at the lower band and 1 at the upper
import pandas as pd

url = "https://raw.githubusercontent.com/ankurtrapasiya/examples/main/data/prices.csv"
px = pd.read_csv(url, index_col="date", parse_dates=True)["SPY"]

w = px.loc[:"2020-03-16"].iloc[-20:]               # the twenty closes ending that day
mid, sd = w.mean(), w.std()
print(f"middle {mid:.2f}  upper {mid + 2 * sd:.2f}  lower {mid - 2 * sd:.2f}  close {w.iloc[-1]:.2f}")

mid, sd = px.rolling(20).mean(), px.rolling(20).std()  # the same, for every day
upper, lower = mid + 2 * sd, mid - 2 * sd
pct_b = ((px - lower) / (upper - lower)).dropna()  # 0 at the lower band, 1 at the upper
print(f"%B on 2020-03-16: {pct_b['2020-03-16']:.3f}")
print(f"inside the bands: {100 * pct_b.between(0, 1).mean():.1f}% of {len(pct_b)} days")

It prints a middle band of 272.88, an upper band of 324.13, a lower band of 221.63 and a close of 218.09, then a %B of −0.035 and 91.5% of 1,239 days inside the bands.

The script behind the real numbers

The tables and the chart come from examples/bollinger-bands/bollinger.py, which runs on the blog’s five tickers. To run it yourself, clone the examples repo: its README has a three-command Docker setup, or run uv run bollinger-bands/bollinger.py.

Summary

IdeaIn one lineOn SPY, 2019 to 2023
Three lines from twenty closesthe mean, and the mean plus and minus two standard deviations272.88, 324.13 and 221.63 on 2020-03-16
The width is the volatilitythe bands open when the price moves a lot and close when it calms6.2% wide before the crash, 44.4% at the low
%B is the close’s place in the band0 at the lower band, 1 at the upper; comparable across stocks−0.035 on the eleven-percent day
A tag is not a signalthe books read a touch two ways, and the tested reading is the breakout; the rule is still a separate decisionoutside the bands on 8.5% of days

References

  • Steven B. Achelis, Technical Analysis from A to Z, 2nd edition (McGraw-Hill, 2001). The “Bollinger Bands” entry for the construction, Bollinger’s recommended settings and his four observations, including the tightening and the continuation reading.
  • John J. Murphy, Technical Analysis of the Financial Markets (New York Institute of Finance, 1999). Chapter 9, “Moving Averages”, for the bands against envelopes, the overbought and oversold reading, the 95% claim and the band width as volatility.
  • Charles D. Kirkpatrick and Julie R. Dahlquist, Technical Analysis: The Complete Resource for Financial Market Technicians (FT Press, 2007). Chapter 14, “Moving Averages”, for percentage envelopes and why fixed ones fail, the construction of the bands, why 95% does not hold, the three reasons range trading between bands fails, the breakout reading and the middle band as a trailing stop.
  • StockCharts ChartSchool, Bollinger Bands. The three formulas, why the middle band is a simple average, Bollinger’s 88-89% figure, and tags as distinct from signals.
  • Romero and Balch, What Hedge Funds Really Do (Business Expert Press, 2014). Chapter 11 for the band as a range around the mean and a strategy built on it.