/** * Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.timeseries.util; import static org.testng.AssertJUnit.assertEquals; import org.testng.annotations.Test; import org.threeten.bp.LocalDate; import com.opengamma.timeseries.date.DateDoubleTimeSeries; import com.opengamma.timeseries.date.localdate.LocalDateDoubleTimeSeries; /** * Tests {@link TimeSeriesWeightedVolatilityOperator} */ public class TimeSeriesWeightedVolatilityOperatorTest { private static final LocalDateDoubleTimeSeries TS_1 = TimeSeriesDataSet.timeSeriesGbpLibor3M2014Jan( LocalDate.of(2014, 2, 1)); private static final int NB_DATA_1 = TS_1.size(); private static final double LAMBDA = 0.98; private static final TimeSeriesPercentageChangeOperator OP_REL_1 = new TimeSeriesPercentageChangeOperator(); private static final TimeSeriesWeightedVolatilityOperator OP_EWMA_1 = TimeSeriesWeightedVolatilityOperator.relative(LAMBDA); private static final TimeSeriesPercentageChangeOperator OP_REL_2 = new TimeSeriesPercentageChangeOperator(2); private static final TimeSeriesWeightedVolatilityOperator OP_EWMA_2 = new TimeSeriesWeightedVolatilityOperator(OP_REL_2, LAMBDA, 0); private static final double TOLERANCE_DIFF = 1.0E-10; @Test(expectedExceptions = IllegalArgumentException.class) public void incorrectLambda0Exception() { TimeSeriesWeightedVolatilityOperator.relative(0.0); } @Test(expectedExceptions = IllegalArgumentException.class) public void incorrectLambda1Exception() { TimeSeriesWeightedVolatilityOperator.relative(1.0); } /** Test the EWMA for a relative change with 1 period lag. No seed period. */ @Test public void ewmaRelative1NoSeed() { DateDoubleTimeSeries<?> tsEwma = OP_EWMA_1.evaluate(TS_1); DateDoubleTimeSeries<?> tsRet = OP_REL_1.evaluate(TS_1); assertEquals(NB_DATA_1 - 1, tsEwma.size()); double variancePrevious = tsRet.getValueAtIndex(0) * tsRet.getValueAtIndex(0); double volExpected0 = Math.sqrt(variancePrevious); double volComputed0 = tsEwma.getValueAtIndex(0); assertEquals("TimeSeriesWeightedVolatilityOperator: volatility - " + 0, volExpected0, volComputed0, TOLERANCE_DIFF); for (int i = 1; i < tsEwma.size(); i++) { assertEquals(tsEwma.getTimeAtIndex(i), tsRet.getTimeAtIndex(i)); double varianceExpected = LAMBDA * variancePrevious + (1.0d - LAMBDA) * tsRet.getValueAtIndex(i) * tsRet.getValueAtIndex(i); double volExpected = Math.sqrt(varianceExpected); double volComputed = tsEwma.getValueAtIndex(i); assertEquals("TimeSeriesWeightedVolatilityOperator: volatility - " + i, volExpected, volComputed, TOLERANCE_DIFF); variancePrevious = varianceExpected; } } /** Test the EWMA for a relative change with 2 period lag. No seed period. */ @Test public void ewmaRelative2NoSeed() { DateDoubleTimeSeries<?> tsEwma = OP_EWMA_2.evaluate(TS_1); DateDoubleTimeSeries<?> tsRet = OP_REL_2.evaluate(TS_1); assertEquals(NB_DATA_1 - 2, tsEwma.size()); double variancePrevious = tsRet.getValueAtIndex(0) * tsRet.getValueAtIndex(0); double volExpected0 = Math.sqrt(variancePrevious); double volComputed0 = tsEwma.getValueAtIndex(0); assertEquals("TimeSeriesWeightedVolatilityOperator: volatility - " + 0, volExpected0, volComputed0, TOLERANCE_DIFF); for (int i = 1; i < tsEwma.size(); i++) { assertEquals(tsEwma.getTimeAtIndex(i), tsRet.getTimeAtIndex(i)); double varianceExpected = LAMBDA * variancePrevious + (1.0d - LAMBDA) * tsRet.getValueAtIndex(i) * tsRet.getValueAtIndex(i); double volExpected = Math.sqrt(varianceExpected); double volComputed = tsEwma.getValueAtIndex(i); assertEquals("TimeSeriesWeightedVolatilityOperator: volatility - " + i, volExpected, volComputed, TOLERANCE_DIFF); variancePrevious = varianceExpected; } } /** Test the EWMA for a relative change with 1 period lag and seed period of length 1. Should be equal to no seed. */ @Test public void ewmaRelative1Seed1() { DateDoubleTimeSeries<?> tsEwmaNS = OP_EWMA_1.evaluate(TS_1); TimeSeriesWeightedVolatilityOperator opEwmaS1 = new TimeSeriesWeightedVolatilityOperator(OP_REL_1, LAMBDA, 1); DateDoubleTimeSeries<?> tsEwmaS1 = opEwmaS1.evaluate(TS_1); assertEquals(tsEwmaNS.size(), tsEwmaS1.size()); for (int i = 0; i < tsEwmaNS.size(); i++) { assertEquals(tsEwmaNS.getTimeAtIndex(i), tsEwmaS1.getTimeAtIndex(i)); assertEquals("TimeSeriesWeightedVolatilityOperator: volatility - " + i, tsEwmaNS.getValueAtIndexFast(i), tsEwmaS1.getValueAtIndexFast(i), TOLERANCE_DIFF); } } /** Test the EWMA for a relative change with 1 period lag and seed period of length 10. */ @Test public void ewmaRelative1Seed10() { int seedLength = 10; DateDoubleTimeSeries<?> tsRet = OP_REL_1.evaluate(TS_1); TimeSeriesWeightedVolatilityOperator opEwmaS10 = new TimeSeriesWeightedVolatilityOperator(OP_REL_1, LAMBDA, seedLength); DateDoubleTimeSeries<?> tsEwmaS1 = opEwmaS10.evaluate(TS_1); assertEquals(tsRet.size() - seedLength + 1, tsEwmaS1.size()); int outputLength = tsEwmaS1.size(); // Seed variance double seedVariance = 0.0; for (int i = 0; i < seedLength; i++) { double returnTs = tsRet.getValueAtIndexFast(i); seedVariance += returnTs * returnTs; } seedVariance /= seedLength; assertEquals(tsRet.getTimeAtIndexFast(seedLength - 1), tsEwmaS1.getTimeAtIndexFast(0)); assertEquals(Math.sqrt(seedVariance), tsEwmaS1.getValueAtIndexFast(0), TOLERANCE_DIFF); // EWMA part double varianceEwma = seedVariance; for (int i = 1; i < outputLength; i++) { varianceEwma = LAMBDA * varianceEwma + (1.0d - LAMBDA) * tsRet.getValueAtIndexFast(i + seedLength - 1) * tsRet.getValueAtIndexFast(i + seedLength - 1); assertEquals(tsRet.getTimeAtIndexFast(seedLength - 1 + i), tsEwmaS1.getTimeAtIndexFast(i)); assertEquals("TimeSeriesWeightedVolatilityOperator: volatility - " + i, Math.sqrt(varianceEwma), tsEwmaS1.getValueAtIndexFast(i), TOLERANCE_DIFF); } } /** Test the EWMA for a relative change with 2 period lag and seed period of length 10. */ @Test public void ewmaRelative2Seed10() { int seedLength = 10; DateDoubleTimeSeries<?> tsRet = OP_REL_2.evaluate(TS_1); TimeSeriesWeightedVolatilityOperator opEwmaS10 = new TimeSeriesWeightedVolatilityOperator(OP_REL_2, LAMBDA, seedLength); DateDoubleTimeSeries<?> tsEwmaS1 = opEwmaS10.evaluate(TS_1); assertEquals(tsRet.size() - seedLength + 1, tsEwmaS1.size()); int outputLength = tsEwmaS1.size(); // Seed variance double seedVariance = 0.0; for (int i = 0; i < seedLength; i++) { double returnTs = tsRet.getValueAtIndexFast(i); seedVariance += returnTs * returnTs; } seedVariance /= seedLength; assertEquals(tsRet.getTimeAtIndexFast(seedLength - 1), tsEwmaS1.getTimeAtIndexFast(0)); assertEquals(Math.sqrt(seedVariance), tsEwmaS1.getValueAtIndexFast(0), TOLERANCE_DIFF); // EWMA part double varianceEwma = seedVariance; for (int i = 1; i < outputLength; i++) { varianceEwma = LAMBDA * varianceEwma + (1.0d - LAMBDA) * tsRet.getValueAtIndexFast(i + seedLength - 1) * tsRet.getValueAtIndexFast(i + seedLength - 1); assertEquals(tsRet.getTimeAtIndexFast(seedLength - 1 + i), tsEwmaS1.getTimeAtIndexFast(i)); assertEquals("TimeSeriesWeightedVolatilityOperator: volatility - " + i, Math.sqrt(varianceEwma), tsEwmaS1.getValueAtIndexFast(i), TOLERANCE_DIFF); } } }