Package com.opengamma.integration.marketdata.manipulator.dsl

Source Code of com.opengamma.integration.marketdata.manipulator.dsl.Simulation

/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.integration.marketdata.manipulator.dsl;

import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threeten.bp.Instant;
import org.threeten.bp.ZonedDateTime;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.opengamma.engine.function.EmptyFunctionParameters;
import com.opengamma.engine.function.FunctionParameters;
import com.opengamma.engine.marketdata.manipulator.CompositeMarketDataSelector;
import com.opengamma.engine.marketdata.manipulator.DistinctMarketDataSelector;
import com.opengamma.engine.marketdata.manipulator.ScenarioDefinition;
import com.opengamma.engine.marketdata.spec.MarketDataSpecification;
import com.opengamma.engine.view.ViewProcessor;
import com.opengamma.engine.view.client.ViewClient;
import com.opengamma.engine.view.execution.ArbitraryViewCycleExecutionSequence;
import com.opengamma.engine.view.execution.ExecutionFlags;
import com.opengamma.engine.view.execution.ExecutionOptions;
import com.opengamma.engine.view.execution.ViewCycleExecutionOptions;
import com.opengamma.engine.view.execution.ViewCycleExecutionSequence;
import com.opengamma.engine.view.execution.ViewExecutionFlags;
import com.opengamma.engine.view.execution.ViewExecutionOptions;
import com.opengamma.engine.view.listener.ViewResultListener;
import com.opengamma.id.UniqueId;
import com.opengamma.id.VersionCorrection;
import com.opengamma.livedata.UserPrincipal;
import com.opengamma.util.ArgumentChecker;

/**
* A collection of {@link Scenario}s, each of which modifies the market data in a single calculation cycle.
*/
public class Simulation {

  private static final Logger s_logger = LoggerFactory.getLogger(Simulation.class);

  /** The simulation name. */
  private final String _name; // TODO this needs to be passed to the results somehow
  /** The scenarios in this simulation, keyed by name. */
  private final Map<String, Scenario> _scenarios = Maps.newLinkedHashMap();

  /** The default calculation configuration name for scenarios. */
  private Set<String> _calcConfigNames;
  /** The default valuation time for scenarios. */
  private Instant _valuationTime;
  /** The default resolver version correction for scenarios. */
  private VersionCorrection _resolverVersionCorrection;

  /** The name of the base scenario (i.e. containing no transformations) */
  private String _baseScenarioName;

  /**
   * Creates a new simulation with a calculation configuration name of "Default", valuation time of {@code Instant.now()}
   * and resolver version correction of {@link VersionCorrection#LATEST}.
   * @param name The simulation name
   */
  public Simulation(String name) {
    ArgumentChecker.notEmpty(name, "name");
    _name = name;
  }

  /**
   * Creates a new simulation, specifying the default values to use for its scenarios
   * @param name The simulation name
   * @param calcConfigNames The default calculation configuration name for scenarios
   * @param valuationTime The default valuation time for scenarios
   * @param resolverVersionCorrection The default resolver version correction for scenarios
   */
  public Simulation(String name, Instant valuationTime, VersionCorrection resolverVersionCorrection, String... calcConfigNames) {
    ArgumentChecker.notEmpty(name, "name");
    ArgumentChecker.notNull(valuationTime, "valuationTime");
    ArgumentChecker.notNull(resolverVersionCorrection, "resolverVersionCorrection");
    _name = name;
    if (calcConfigNames.length > 0) {
      _calcConfigNames = ImmutableSet.copyOf(calcConfigNames);
    } else {
      _calcConfigNames = null;
    }
    _valuationTime = valuationTime;
    _resolverVersionCorrection = resolverVersionCorrection;
  }

  /* package */ Set<DistinctMarketDataSelector> allSelectors() {
    // TODO check for empty scenarios
    Set<DistinctMarketDataSelector> selectors = Sets.newHashSet();
    for (Scenario scenario : _scenarios.values()) {
      selectors.addAll(scenario.createDefinition().getDefinitionMap().keySet());
    }
    return Collections.unmodifiableSet(selectors);
  }

  /**
   * Builds cycle execution options for each scenario in this simulation.
   * @param baseOptions Base set of options
   * @param allSelectors This simulation's selectors
   * @return Execution options for each scenario in this simulation
   */
  /* package */ List<ViewCycleExecutionOptions> cycleExecutionOptions(ViewCycleExecutionOptions baseOptions,
                                                                      Set<DistinctMarketDataSelector> allSelectors) {
    List<ViewCycleExecutionOptions> options = Lists.newArrayListWithCapacity(_scenarios.size());
    for (Scenario scenario : _scenarios.values()) {
      ScenarioDefinition definition = scenario.createDefinition();
      Map<DistinctMarketDataSelector, FunctionParameters> scenarioParams = definition.getDefinitionMap();
      Map<DistinctMarketDataSelector, FunctionParameters> params = Maps.newHashMap();
      params.putAll(scenarioParams);
      // if a selector isn't used by a particular scenario then it needs to have a no-op manipulator. if it didn't
      // then the manipulator from the previous scenario would be used
      Set<DistinctMarketDataSelector> unusedSelectors = Sets.difference(allSelectors, params.keySet());
      for (DistinctMarketDataSelector unusedSelector : unusedSelectors) {
        params.put(unusedSelector, EmptyFunctionParameters.INSTANCE);
      }
      ViewCycleExecutionOptions scenarioOptions = baseOptions.copy()
          .setFunctionParameters(params)
          .setValuationTime(scenario.getValuationTime())
          .setResolverVersionCorrection(scenario.getResolverVersionCorrection())
          .create();
      options.add(scenarioOptions);
    }
    return options;
  }

  /**
   * Returns the scenario with the given name. If no scenario exists with the specified name it is created and
   * initialized with default the simulation's default values for calculation configuration, valuation time and
   * resolver version correction.
   * @param name The scenario name
   * @return The scenario.
   * TODO check the name isn't the base scenario name and throw IAE
   */
  public Scenario scenario(String name) {
    ArgumentChecker.notEmpty(name, "name");
    if (name.equals(_baseScenarioName)) {
      throw new IllegalArgumentException("Can't add scenario named " + name + ", a base scenario exists with " +
                                             "that name");
    }
    if (_scenarios.containsKey(name)) {
      return _scenarios.get(name);
    } else {
      Scenario scenario = new Scenario(this, name);
      _scenarios.put(name, scenario);
      return scenario;
    }
  }

  /**
   * Creates a base scenario with the given name. A base scenario has no transformations defined.
   * @param name The name of the base scenario
   * @return This simulation
   * @throws IllegalStateException If the base scenario name has already been set
   * @throws IllegalArgumentException If there is already a non-base scenario with the specified name
   */
  public Simulation baseScenarioName(String name) {
    ArgumentChecker.notEmpty(name, "name");
    if (_baseScenarioName != null) {
      throw new IllegalStateException("Base scenario already defined with name " + _baseScenarioName);
    }
    if (_scenarios.containsKey(name)) {
      throw new IllegalArgumentException("Cannot add a base scenario named " + name + ", a scenario already exists " +
                                             "with that name");
    }
    Scenario base = new Scenario(this, name);
    _scenarios.put(name, base);
    _baseScenarioName = name;
    return this;
  }

  /**
   * Sets the calculation configuration name to which the scenarios will apply.
   * @param calcConfigNames The calculation configuration name to which the scenarios will apply
   * @return This simulation
   * @throws IllegalStateException If the calculation configuration names have already been set
   */
  public Simulation calculationConfigurations(String... calcConfigNames) {
    ArgumentChecker.notEmpty(calcConfigNames, "calcConfigNames");
    if (_calcConfigNames != null) {
      throw new IllegalStateException("Calculation configuration names are already set");
    }
    _calcConfigNames = ImmutableSet.copyOf(calcConfigNames);
    return this;
  }

  /**
   * Sets the {@link VersionCorrection} used when resolving positions and portfolios
   * @param versionCorrection The version/correction used when resolving positions and portfolios
   * @return This simulation
   */
  public Simulation resolverVersionCorrection(VersionCorrection versionCorrection) {
    ArgumentChecker.notNull(versionCorrection, "versionCorrection");
    if (_resolverVersionCorrection != null) {
      throw new IllegalStateException("Resolver version correction has already been set");
    }
    _resolverVersionCorrection = versionCorrection;
    return this;
  }

  /**
   * Sets the valuation time used in the calculations
   * @param valuationTime The valuation time used in the calculations
   * @return This simulation
   * @throws IllegalStateException If the valuation time has already been set
   */
  public Simulation valuationTime(Instant valuationTime) {
    ArgumentChecker.notNull(valuationTime, "valuationTime");
    if (_valuationTime != null) {
      throw new IllegalStateException("Valuation time has already been set");
    }
    _valuationTime = valuationTime;
    return this;
  }

  /**
   * Sets the valuation time used in the calculations
   * @param valuationTime The valuation time used in the calculations
   * @return This simulation
   * @throws IllegalStateException If the valuation time has already been set
   */
  public Simulation valuationTime(ZonedDateTime valuationTime) {
    ArgumentChecker.notNull(valuationTime, "valuationTime");
    return valuationTime(valuationTime.toInstant());
  }

  /**
   * Executes this simulation on a running server.
   * @param viewDefId The ID of the view definition to use
   * @param marketDataSpecs The market data to use when running the view
   * @param batchMode Whether to run the simulation using batch mode
   * @param listener Listener that is notified as the simulation runs
   * @param viewProcessor View process that will be used to execute the simulation
   */
  public void run(UniqueId viewDefId,
                  List<MarketDataSpecification> marketDataSpecs,
                  boolean batchMode,
                  ViewResultListener listener,
                  ViewProcessor viewProcessor) {
    ViewClient viewClient = viewProcessor.createViewClient(UserPrincipal.getTestUser());
    try {
      Set<DistinctMarketDataSelector> allSelectors = allSelectors();
      ViewCycleExecutionOptions baseOptions =
          ViewCycleExecutionOptions
              .builder()
              .setMarketDataSpecifications(marketDataSpecs)
              .setMarketDataSelector(CompositeMarketDataSelector.of(allSelectors))
              .create();
      List<ViewCycleExecutionOptions> cycleOptions = cycleExecutionOptions(baseOptions, allSelectors);
      ViewCycleExecutionSequence sequence = new ArbitraryViewCycleExecutionSequence(cycleOptions);
      EnumSet<ViewExecutionFlags> executionFlags = ExecutionFlags.none().awaitMarketData().runAsFastAsPossible().get();
      ViewExecutionOptions executionOptions;
      if (listener != null) {
        viewClient.setResultListener(listener);
      }
      if (batchMode) {
        executionOptions = ExecutionOptions.batch(sequence, baseOptions);
      } else if (listener != null) {
        executionOptions = ExecutionOptions.of(sequence, executionFlags);
      } else {
        s_logger.warn("Not running in batch mode and no listener specified, the results would be ignored. Exiting.");
        return;
      }
      s_logger.info("Attaching to view process, view def ID {}, execution options {}", viewDefId, executionOptions);
      viewClient.attachToViewProcess(viewDefId, executionOptions, true);
      try {
        viewClient.waitForCompletion();
      } catch (InterruptedException e) {
        s_logger.warn("Interrupted waiting for ViewClient to complete", e);
      }
    } finally {
      viewClient.shutdown();
    }
  }

  /* package */ Set<String> getCalcConfigNames() {
    return _calcConfigNames;
  }

  /* package */ Instant getValuationTime() {
    return _valuationTime;
  }

  /* package */ VersionCorrection getResolverVersionCorrection() {
    return _resolverVersionCorrection;
  }

  /* package */ Map<String, Scenario> getScenarios() {
    return Collections.unmodifiableMap(_scenarios);
  }

  @Override
  public int hashCode() {
    return Objects.hash(_name, _scenarios, _calcConfigNames, _valuationTime, _resolverVersionCorrection, _baseScenarioName);
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj == null || getClass() != obj.getClass()) {
      return false;
    }
    final Simulation other = (Simulation) obj;
    return Objects.equals(this._name, other._name) &&
        Objects.equals(this._scenarios, other._scenarios) &&
        Objects.equals(this._calcConfigNames, other._calcConfigNames) &&
        Objects.equals(this._valuationTime, other._valuationTime) &&
        Objects.equals(this._resolverVersionCorrection, other._resolverVersionCorrection) &&
        Objects.equals(this._baseScenarioName, other._baseScenarioName);
  }

  @Override
  public String toString() {
    return "Simulation [" +
        "_scenarios=" + _scenarios +
        ", _calcConfigNames=" + _calcConfigNames +
        ", _valuationTime=" + _valuationTime +
        ", _resolverVersionCorrection=" + _resolverVersionCorrection +
        "]";
  }
}
TOP

Related Classes of com.opengamma.integration.marketdata.manipulator.dsl.Simulation

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.