The Bollinger Band is another technical trading indicator. It provides a volatility range for a stock price. This is based on the standard deviation from a price's mean. The standard deviation changes as volatility increases and decreases. This translates to a widening of the band when volatility increases and a narrowing of the band when volatility decreases. You can read more about Bollinger Bands at https://en.wikipedia.org/wiki/Bollinger_Bands and http://www.investopedia.com/terms/b/bollingerbands.asp.
The Bollinger Band has upper, lower, and middle bands. For us, the middle band will be the SMA. The upper and lower bands will be two standard deviations from the mean. The standard deviation is the square root of a variance. The variance is the average of the squared differences from the mean. Let's take a closer look at the math. Again, we'll first note down the equation using an algebraic pseudocode:
We're going to similarly work backwards from the data points that we need:
From here, we can take a similar approach of reducing the SMA and calculating the variables that we need. I've included the following completed function as a guide for you to follow. However, see if you can build it on your own, patterning your solution after the first two functions we've completed:
(defn bollinger-band "From a tick-list, generates an accompanying list with upper-band and lower-band Upper Band: K times an N-period standard deviation above the moving average (MA + Kσ) Lower Band: K times an N-period standard deviation below the moving average (MA − Kσ) K: number of standard deviations N: period, or tick-window we are looking at Returns a list, equal in length to the tick-list, but only with slots filled, where preceding tick-list allows. ** This function assumes the latest tick is on the left**" ([tick-window tick-list] (bollinger-band tick-window tick-list (three/simple-moving-average nil tick-window tick-list))) ([tick-window tick-list sma-list] ;; At each step, the Standard Deviation will be: the square root of the variance (average of the squared differences from the Mean) (reduce (fn [rslt ech] (let [;; get the Moving Average ma (:last-trade-price-average ech) ;; work out the mean mean (/ (reduce (fn [rslt ech] (+ (:last-trade-price ech) rslt)) 0 (:population ech)) (count (:population ech))) ;; Then for each number: subtract the mean and square the result (the squared difference) sq-diff-list (map (fn [ech] (let [diff (- mean (:last-trade-price ech))] (* diff diff))) (:population ech)) variance (/ (reduce + sq-diff-list) (count (:population ech))) standard-deviation (. Math sqrt variance)] (lazy-cat rslt [{:last-trade-price (:last-trade-price ech) :last-trade-time (:last-trade-time ech) :upper-band (+ ma (* 2 standard-deviation)) :lower-band (- ma (* 2 standard-deviation))}]))) '() sma-list)))
The timeseries
collection should already be defined, so now we can call our bollinger-band
function in a similar way to the exponential-moving-average
function:
(def bol-band (bollinger-band 20 (take 40 time-series)))
You should see a result that looks something like this:
({:last-trade-price 14.72248400774257, :last-trade-time #inst "2015-09-25T00:59:16.924-00:00", :upper-band 24.882020638795275, :lower-band 9.546205067243378} {:last-trade-price 17.666980809291083, :last-trade-time #inst "2015-09-25T00:59:19.924-00:00", :upper-band 24.882647571351672, :lower-band 9.541527911594255} {:last-trade-price 21.2003769711493, :last-trade-time #inst "2015-09-25T00:59:21.924-00:00", :upper-band 24.87967020977339, :lower-band 9.53964500546127} ...)
Here's a sample graph output (your data may vary):
18.190.156.93