sclass BollingerBands extends CandleBasedIndicator { replace Candle with TradingCandle. // length parameter is in base class // The magic average + standard deviation generator new Welford welford; // Probably wrong word. Defines how many times the standard deviation // we use as the tunnel size (well, twice that, actually) settable double deviation = 2; // result settable DoubleRange range; gettable AverageAndStandardDeviation as; { onCandleAdded(candle -> { if (l(candles()) >= length) { var bCandles = candles().asList(); var prices = mapToDoubleArray(bCandles, ->.endPrice()); as = averageAndStandardDeviation(prices); range = bollingerRange(as, deviation); } }); } L bandsAsTickers(L candles) { var bbSeq1 = new TickerSequence("Upper Bollinger Band"); var bbSeq2 = new TickerSequence("Lower Bollinger Band"); fOr (candle : candles) { feed(candle); var r = range(); if (notNull(r)) { bbSeq1.addIfPriceChanged(r.end(), candle.endTime().toLong()); bbSeq2.addIfPriceChanged(r.start(), candle.endTime().toLong()); } } ret ll(bbSeq1, bbSeq2); } }