/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.sesame.function.scenarios.marketdata;
import static com.opengamma.sesame.config.ConfigBuilder.config;
import static com.opengamma.sesame.config.ConfigBuilder.implementations;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import org.testng.annotations.Test;
import org.threeten.bp.ZonedDateTime;
import com.opengamma.core.security.Security;
import com.opengamma.financial.security.cashflow.CashFlowSecurity;
import com.opengamma.id.ExternalIdBundle;
import com.opengamma.sesame.Environment;
import com.opengamma.sesame.SimpleEnvironment;
import com.opengamma.sesame.config.FunctionModelConfig;
import com.opengamma.sesame.function.Output;
import com.opengamma.sesame.function.scenarios.FilteredScenarioDefinition;
import com.opengamma.sesame.graph.FunctionModel;
import com.opengamma.sesame.marketdata.DefaultMarketDataFn;
import com.opengamma.sesame.marketdata.MapMarketDataBundle;
import com.opengamma.sesame.marketdata.MarketDataBundle;
import com.opengamma.sesame.marketdata.MarketDataEnvironmentBuilder;
import com.opengamma.sesame.marketdata.MarketDataFn;
import com.opengamma.sesame.marketdata.SecurityId;
import com.opengamma.util.money.Currency;
import com.opengamma.util.result.Result;
import com.opengamma.util.test.TestGroup;
@SuppressWarnings("unchecked")
@Test(groups = TestGroup.UNIT)
public class MarketDataShockDecoratorTest {
private static final String SCHEME = "scheme";
private static final String VALUE1 = "value1";
private static final String VALUE2 = "value2";
// TODO these need to be securities to conform to the new MarketDataFn API
private static final Security SEC1 = createSecurity(SCHEME, VALUE1);
private static final Security SEC2 = createSecurity(SCHEME, VALUE2);
private static final FunctionModelConfig CONFIG =
config(implementations(Fn.class, Impl.class, MarketDataFn.class, DefaultMarketDataFn.class));
private static final MarketDataMatcher MATCHER1 = MarketDataMatcher.idEquals(SCHEME, VALUE1);
private static final MarketDataMatcher MATCHER2 = MarketDataMatcher.idEquals(SCHEME, VALUE2);
private static final FunctionModelConfig DECORATED_CONFIG = CONFIG.decoratedWith(MarketDataShockDecorator.class);
private static final MarketDataBundle MARKET_DATA_BUNDLE =
new MapMarketDataBundle(new MarketDataEnvironmentBuilder()
.add(SecurityId.of(SEC1.getExternalIdBundle()), 1.0)
.add(SecurityId.of(SEC2.getExternalIdBundle()), 2.0)
.valuationTime(ZonedDateTime.now())
.build());
private static final Fn FN = FunctionModel.build(Fn.class, DECORATED_CONFIG);
private static final double DELTA = 1e-8;
private static Security createSecurity(String idScheme, String idValue) {
CashFlowSecurity security = new CashFlowSecurity(Currency.GBP, ZonedDateTime.now(), 123.45);
security.setExternalIdBundle(ExternalIdBundle.of(idScheme, idValue));
return security;
}
/**
* apply a single shock to one piece of market data but not another
*/
@SuppressWarnings("unchecked")
@Test
public void singleShock() {
MarketDataShock shock = MarketDataShock.relativeShift(0.5, MATCHER1);
FilteredScenarioDefinition scenarioDef = new FilteredScenarioDefinition(shock);
SimpleEnvironment env = new SimpleEnvironment(ZonedDateTime.now(), MARKET_DATA_BUNDLE, scenarioDef);
assertEquals(1.5, FN.foo(env, SEC1).getValue(), DELTA);
assertEquals(2d, FN.foo(env, SEC2).getValue(), DELTA);
}
/**
* apply a shock to one piece of data and a different shock to another
*/
@Test
public void multipleSeparateShocks() {
MarketDataShock relativeShift = MarketDataShock.relativeShift(0.5, MATCHER1);
MarketDataShock absoluteShift = MarketDataShock.absoluteShift(0.1, MATCHER2);
FilteredScenarioDefinition scenarioDef = new FilteredScenarioDefinition(absoluteShift, relativeShift);
SimpleEnvironment env = new SimpleEnvironment(ZonedDateTime.now(), MARKET_DATA_BUNDLE, scenarioDef);
assertEquals(1.5, FN.foo(env, SEC1).getValue(), DELTA);
assertEquals(2.1, FN.foo(env, SEC2).getValue(), DELTA);
}
/**
* apply two shocks to the same piece of data
*/
@Test
public void multipleShocksOnSameData() {
MarketDataShock absoluteShift = MarketDataShock.absoluteShift(0.1, MATCHER1);
MarketDataShock relativeShift = MarketDataShock.relativeShift(0.5, MATCHER1);
FilteredScenarioDefinition scenarioDef = new FilteredScenarioDefinition(absoluteShift, relativeShift);
SimpleEnvironment env = new SimpleEnvironment(ZonedDateTime.now(), MARKET_DATA_BUNDLE, scenarioDef);
assertEquals(1.65, FN.foo(env, SEC1).getValue(), DELTA);
assertEquals(2d, FN.foo(env, SEC2).getValue(), DELTA);
}
/**
* apply two shocks to the same piece of data
*/
@Test
public void multipleShocksOnSameDataReversed() {
MarketDataShock relativeShift = MarketDataShock.relativeShift(0.5, MATCHER1);
MarketDataShock absoluteShift = MarketDataShock.absoluteShift(0.1, MATCHER1);
FilteredScenarioDefinition scenarioDef = new FilteredScenarioDefinition(relativeShift, absoluteShift);
SimpleEnvironment env = new SimpleEnvironment(ZonedDateTime.now(), MARKET_DATA_BUNDLE, scenarioDef);
assertEquals(1.6, FN.foo(env, SEC1).getValue(), DELTA);
assertEquals(2d, FN.foo(env, SEC2).getValue(), DELTA);
}
/**
* try (and fail) to shock a piece of market data that isn't a double
*/
public void dataNotDouble() {
MarketDataBundle marketDataBundle = new MapMarketDataBundle(
new MarketDataEnvironmentBuilder()
.add(SecurityId.of(SEC1.getExternalIdBundle()), "not a double")
.add(SecurityId.of(SEC2.getExternalIdBundle()), 2.0)
.valuationTime(ZonedDateTime.now())
.build());
MarketDataShock shock = MarketDataShock.relativeShift(0.5, MATCHER1);
FilteredScenarioDefinition scenarioDef = new FilteredScenarioDefinition(shock);
SimpleEnvironment env = new SimpleEnvironment(ZonedDateTime.now(), marketDataBundle, scenarioDef);
assertFalse(FN.foo(env, SEC1).isSuccess());
assertEquals(2d, FN.foo(env, SEC2).getValue(), DELTA);
}
public interface Fn {
@Output("Foo")
Result<Double> foo(Environment env, Security security);
}
public static class Impl implements Fn {
private final MarketDataFn _marketDataFn;
public Impl(MarketDataFn marketDataFn) {
_marketDataFn = marketDataFn;
}
@Override
public Result<Double> foo(Environment env, Security security) {
return _marketDataFn.getMarketValue(env, security);
}
}
}