|
| 1 | +<script setup> |
| 2 | + |
| 3 | +import * as Plot from "@observablehq/plot"; |
| 4 | +import * as d3 from "d3"; |
| 5 | +import {ref} from "vue"; |
| 6 | +import aapl from "../data/aapl.ts"; |
| 7 | + |
| 8 | +const n = ref(20); |
| 9 | +const k = ref(2); |
| 10 | + |
| 11 | +</script> |
| 12 | + |
| 13 | +# Bollinger mark |
| 14 | + |
| 15 | +The **bollinger mark** is a [composite mark](../features/marks.md#marks) consisting of a [line](./line.md) representing a moving average, and an [area](./area.md) representing volatility as a band; the band thickness is proportional to the deviation of nearby values. The bollinger mark is often used to analyze the price of financial instruments such as stocks. |
| 16 | + |
| 17 | +For example, the chart below shows the price of Apple stock from 2013–2018, with window size *n* of {{n}} days and radius *k* of {{k}} standard deviations. |
| 18 | + |
| 19 | +<p> |
| 20 | + <label class="label-input"> |
| 21 | + <span>Window size (n):</span> |
| 22 | + <input type="range" v-model.number="n" min="1" max="100" step="1" /> |
| 23 | + <span style="font-variant-numeric: tabular-nums;">{{n.toLocaleString("en-US")}}</span> |
| 24 | + </label> |
| 25 | + <label class="label-input"> |
| 26 | + <span>Radius (k):</span> |
| 27 | + <input type="range" v-model.number="k" min="0" max="10" step="0.1" /> |
| 28 | + <span style="font-variant-numeric: tabular-nums;">{{k.toLocaleString("en-US")}}</span> |
| 29 | + </label> |
| 30 | +</p> |
| 31 | + |
| 32 | +:::plot hidden |
| 33 | +```js |
| 34 | +Plot.bollingerY(aapl, {x: "Date", y: "Close", n, k}).plot() |
| 35 | +``` |
| 36 | +::: |
| 37 | + |
| 38 | +```js-vue |
| 39 | +Plot.bollingerY(aapl, {x: "Date", y: "Close", n: {{n}}, k: {{k}}}).plot() |
| 40 | +``` |
| 41 | + |
| 42 | +For more control, you can also use the [bollinger map method](#bollinger) directly with the [map transform](../transforms/map.md). |
| 43 | + |
| 44 | +:::plot |
| 45 | +```js |
| 46 | +Plot.plot({ |
| 47 | + marks: [ |
| 48 | + Plot.lineY(aapl, Plot.mapY(Plot.bollinger(20, -2), {x: "Date", y: "Close", stroke: "red"})), |
| 49 | + Plot.lineY(aapl, Plot.mapY(Plot.bollinger(20, 2), {x: "Date", y: "Close", stroke: "green"})), |
| 50 | + Plot.lineY(aapl, Plot.mapY(Plot.bollinger(20, 0), {x: "Date", y: "Close"})) |
| 51 | + ] |
| 52 | +}) |
| 53 | +``` |
| 54 | +::: |
| 55 | + |
| 56 | +The bollinger mark has two constructors: the common [bollingerY](#bollingerY) for when time goes right→ (or ←left); and the rare [bollingerX](#bollingerX) for when time goes up↑ (or down↓). |
| 57 | + |
| 58 | +:::plot |
| 59 | +```js |
| 60 | +Plot.bollingerX(aapl, {y: "Date", x: "Close"}).plot() |
| 61 | +``` |
| 62 | +::: |
| 63 | + |
| 64 | +As [shorthand](../features/shorthand.md), you can pass an array of numbers as data. Below, the *x* axis represents the zero-based index into the data (*i.e.*, trading days since May 13, 2013). |
| 65 | + |
| 66 | +:::plot |
| 67 | +```js |
| 68 | +Plot.bollingerY(aapl.map((d) => d.Close)).plot() |
| 69 | +``` |
| 70 | +::: |
| 71 | + |
| 72 | +## Bollinger options |
| 73 | + |
| 74 | +The bollinger mark is a [composite mark](../features/marks.md#marks) consisting of two marks: |
| 75 | + |
| 76 | +* an [area](../marks/area.md) representing volatility as a band, and |
| 77 | +* a [line](../marks/line.md) representing a moving average |
| 78 | + |
| 79 | +In addition to the standard mark options which are passed through to the underlying area and line, the bollinger mark supports the following options: |
| 80 | + |
| 81 | +* **n** - the window size (corresponding to the window transform’s **k** option), an integer |
| 82 | +* **k** - the band radius, a number representing a multiple of standard deviations |
| 83 | +* **color** - the fill color of the area, and the stroke color of the line; defaults to *currentColor* |
| 84 | +* **opacity** - the fill opacity of the area; defaults to 0.2 |
| 85 | +* **fill** - the fill color of the area; defaults to **color** |
| 86 | +* **fillOpacity** - the fill opacity of the area; defaults to **paocity** |
| 87 | +* **stroke** - the stroke color of the line; defaults to **color** |
| 88 | +* **strokeOpacity** - the stroke opacity of the line; defaults to 1 |
| 89 | +* **strokeWidth** - the stroke width of the line in pixels; defaults to 1.5 |
| 90 | + |
| 91 | +## bollingerX(*data*, *options*) {#bollingerX} |
| 92 | + |
| 93 | +```js |
| 94 | +Plot.bollingerX(aapl, {y: "Date", x: "Close"}) |
| 95 | +``` |
| 96 | + |
| 97 | +Returns a bollinger mark for when time goes up↑ (or down↓). If the **x** option is not specified, it defaults to the identity function, as when *data* is an array of numbers [*x₀*, *x₁*, *x₂*, …]. If the **y** option is not specified, it defaults to [0, 1, 2, …]. |
| 98 | + |
| 99 | +## bollingerY(*data*, *options*) {#bollingerY} |
| 100 | + |
| 101 | +```js |
| 102 | +Plot.bollingerY(aapl, {x: "Date", y: "Close"}) |
| 103 | +``` |
| 104 | + |
| 105 | +Returns a bollinger mark for when time goes right→ (or ←left). If the **y** option is not specified, it defaults to the identity function, as when *data* is an array of numbers [*y₀*, *y₁*, *y₂*, …]. If the **x** option is not specified, it defaults to [0, 1, 2, …]. |
| 106 | + |
| 107 | +TODO Describe the **interval** option inherited from line/area. |
| 108 | + |
| 109 | +## bollinger(*n*, *k*) {#bollinger} |
| 110 | + |
| 111 | +```js |
| 112 | +Plot.lineY(data, Plot.map({y: Plot.bollinger(20, 0)}, {x: "Date", y: "Close"})) |
| 113 | +``` |
| 114 | + |
| 115 | +Returns a bollinger map method for use with the [map transform](../transforms/map.md). |
0 commit comments