package de.invesdwin.util.math.decimal.stream; import javax.annotation.concurrent.NotThreadSafe; import de.invesdwin.util.math.decimal.ADecimal; import de.invesdwin.util.math.decimal.Decimal; @NotThreadSafe public class DecimalStreamGeomAvg<E extends ADecimal<E>> implements IDecimalStreamAlgorithm<E, Void> { private double logSum = 0D; private int count; private final double valueAdjustmentAddition; private final E converter; public DecimalStreamGeomAvg(final E converter) { this.converter = converter; final E valueAdjustmentAddition = getValueAdjustmentAddition(); if (valueAdjustmentAddition == null) { this.valueAdjustmentAddition = 0; } else { this.valueAdjustmentAddition = valueAdjustmentAddition.getDefaultValue().doubleValueRaw(); } } protected E getValueAdjustmentAddition() { return null; } @Override public Void process(final E value) { final double doubleValue = value.getDefaultValue().doubleValueRaw(); final double adjValue = doubleValue + valueAdjustmentAddition; if (adjValue > 0D) { /* * though this is not nice, when trying to calculate the compoundDailyGrowthRate from a detrended equity * curve that goes negative, this is needed */ logSum += Math.log(adjValue); } count++; return null; } public E getGeomAvg() { final double doubleResult; if (count == 0) { doubleResult = 0D; } else { doubleResult = Math.exp(logSum / count); } final Decimal result = new Decimal(doubleResult); if (result.isZero()) { return converter.zero(); } final E geomAvg = converter.fromDefaultValue(result.subtract(new Decimal(valueAdjustmentAddition))); return geomAvg; } }