persistable sclass ATR extends CandleBasedIndicator { // For first phase new Average initialAverage; // For second phase settable SmoothedMovingAverage sma; // TR value settable double tr = Double.NaN; // ATR value settable double atr = Double.NaN; // ATR values collected as ticker gettable TickerSequence atrHistory = new TickerSequence("ATR"); Double value() { ret atr(); } *(int *length) {} { length = 14; onCandleAdded((IVF1) candle -> { var x = candle.move(); var u = max(x, 0.0); var d = neg(min(x, 0.0)); // Calculate TR if (candles().size() < 2) ret; tr(trueRange(ll(candles().nextToLast(), candles().last()))); if (initialAverage.count() < length()) ret with initialAverage.add(tr); if (sma == null) { sma(new SmoothedMovingAverage(length())); sma().add(initialAverage!); } else sma().add(tr); atr(sma()!); long time = candle.endTime().toLong(); atrHistory?.addIfPriceChanged(atr, time); }); } TickerSequence asTicker(L candles) { feed(candles); ret atrHistory; } void reset :: after { resetFields(this, "initialAverage sma tr atr atrHistory"); } }