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; // Bands collected as tickers gettable TickerSequence upperBand = new TickerSequence("Upper Bollinger Band"); gettable TickerSequence lowerBand = new TickerSequence("Lower Bollinger Band"); 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)); upperBand?.addIfPriceChanged(range.end(), candle.endTime().toLong()); lowerBand?.addIfPriceChanged(range.start(), candle.endTime().toLong()); change(); } }); } L bandsAsTickers(L candles) { feed(candles); ret ll(upperBand, lowerBand); } DoubleRange value() { ret range(); } }