package name.abuchen.portfolio.math; import static org.hamcrest.core.Is.is; import static org.hamcrest.number.IsCloseTo.closeTo; import static org.junit.Assert.assertThat; import java.time.LocalDate; import java.util.Arrays; import name.abuchen.portfolio.math.Risk.Drawdown; import name.abuchen.portfolio.math.Risk.Volatility; import org.junit.Test; public class RiskTest { private LocalDate[] getDates(int size) { LocalDate[] dates = new LocalDate[size]; for (int i = 0; i < size; i++) dates[i] = LocalDate.of(2015, 1, i + 1); return dates; } @Test public void testDrawdown() { int size = 10; LocalDate[] dates = getDates(size); double[] values = new double[size]; for (int i = 0; i < size; i++) values[i] = i; Drawdown drawdown = new Drawdown(values, dates); // Every new value is a new peak, so there never is a drawdown and // therefore the magnitude is 0 assertThat(drawdown.getMaxDrawdown(), is(0d)); // Drawdown duration is the longest duration between peaks. Every value // is a peak, so 1 day is every time the duration. The fact that there // is never a drawdown does not negate the duration assertThat(drawdown.getMaxDrawdownDuration().getDays(), is(1l)); drawdown = new Drawdown(new double[] { 1, 1, -0.5, 1, 1, 2, 3, 4, 5, 6 }, dates); // the drawdown is from 2 to 0.5 which is 1.5 or 75% of 2 assertThat(drawdown.getMaxDrawdown(), is(0.75d)); // the first peak is the first 2. The second 2 is not a peak, the next // peak is the 3, which is 5 days later assertThat(drawdown.getMaxDrawdownDuration().getDays(), is(5l)); drawdown = new Drawdown(new double[] { 0, 0.1, 0.2, -1.4 }, getDates(4)); // The drawdown is from 1.2 to -0.4 or 1.6, which is 4/3 from 1.2 assertThat(drawdown.getMaxDrawdown(), closeTo(4d / 3, 0.1e-10)); } @Test public void testVolatility() { double[] delta = new double[] { 0.005, -1 / 300d, -0.005, 0.01, 0.01, -0.005 }; Volatility volatility = new Volatility(delta, index -> true); // calculated reference values with excel assertThat(volatility.getStandardDeviation(), closeTo(0.017736692475, 0.1e-10)); assertThat(volatility.getSemiDeviation(), closeTo(0.012188677034, 0.1e-10)); } @Test public void testVolatilityWithSkip() { double[] delta = new double[] { 0, 0.005, -1 / 300d, -0.005, 0.01, 0.01, -0.005 }; Volatility volatility = new Volatility(delta, index -> index > 0); assertThat(volatility.getStandardDeviation(), closeTo(0.017736692475, 0.1e-10)); assertThat(volatility.getSemiDeviation(), closeTo(0.012188677034, 0.1e-10)); } @Test public void testVolatilityWithConstantReturns() { double[] returns = new double[20]; Arrays.fill(returns, 0.1); Volatility volatility = new Volatility(returns, index -> true); assertThat(volatility.getStandardDeviation(), closeTo(0d, 0.1e-10)); assertThat(volatility.getSemiDeviation(), closeTo(0d, 0.1e-10)); } }