/*
* Created on 06.12.2009
*/
package net.finmath.montecarlo.interestrate.products.components;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import net.finmath.concurrency.FutureWrapper;
import net.finmath.exception.CalculationException;
import net.finmath.montecarlo.AbstractMonteCarloProduct;
import net.finmath.montecarlo.interestrate.LIBORModelMonteCarloSimulationInterface;
import net.finmath.stochastic.RandomVariableInterface;
/**
* A collection of product components (like periods, options, etc.) paying the sum of their payouts.
*
* @author Christian Fries
* @version 1.1
*/
public class ProductCollection extends AbstractProductComponent {
/**
*
*/
private static final long serialVersionUID = -3058874897795789705L;
private Collection products;
/**
* Creates a collection of product components paying the sum of their payouts.
*
* @param products Array of AbstractProductComponent objects
*/
public ProductCollection(AbstractProductComponent... products) {
this(Arrays.asList(products));
}
/**
* Creates a collection of product components paying the sum of their payouts.
*
* @param products Collection of AbstractProductComponent objects
*/
public ProductCollection(Collection products) {
super();
this.products = products;
}
@Override
public String getCurrency() {
// @TODO: We report only the currency of the first item.
return products.iterator().next().getCurrency();
}
/**
* Returns the collection containing all products as an unmodifiable collection.
*
* @return the collection containing all products.
*/
public Collection getProducts() {
return Collections.unmodifiableCollection(products);
}
@Override
public Set queryUnderlyings() {
Set underlyingNames = null;
for(AbstractProductComponent product : products) {
Set productUnderlyingNames = product.queryUnderlyings();
if(productUnderlyingNames != null) {
if(underlyingNames == null) underlyingNames = productUnderlyingNames;
else underlyingNames.addAll(productUnderlyingNames);
}
}
return underlyingNames;
}
/**
* This method returns the value random variable of the product within the specified model, evaluated at a given evalutationTime.
* Note: For a lattice this is often the value conditional to evalutationTime, for a Monte-Carlo simulation this is the (sum of) value discounted to evaluation time.
* Cashflows prior evaluationTime are not considered.
*
* @param evaluationTime The time on which this products value should be observed.
* @param model The model used to price the product.
* @return The random variable representing the value of the product discounted to evaluation time
* @throws net.finmath.exception.CalculationException Thrown if the valuation fails, specific cause may be available via the cause() method.
* @see net.finmath.montecarlo.AbstractMonteCarloProduct#getValue(double, net.finmath.montecarlo.MonteCarloSimulationInterface)
*/
@Override
public RandomVariableInterface getValue(final double evaluationTime, final LIBORModelMonteCarloSimulationInterface model) throws CalculationException {
// Ignite asynchronous calculation if possible
ArrayList< Future > results = new ArrayList< Future >();
for(final AbstractMonteCarloProduct product : products) {
Future valueFuture;
try {
valueFuture = executor.submit(
new Callable() {
public RandomVariableInterface call() throws CalculationException {
return product.getValue(evaluationTime, model);
}
}
);
}
catch(RejectedExecutionException e) {
valueFuture = new FutureWrapper(product.getValue(evaluationTime, model));
}
results.add(valueFuture);
}
// Collect results
RandomVariableInterface values = model.getRandomVariableForConstant(0.0);
try {
for(Future valueFuture : results) {
values = values.add(valueFuture.get());
}
} catch (InterruptedException e) {
throw e.getCause() instanceof CalculationException ? (CalculationException)(e.getCause()) : new CalculationException(e.getCause());
} catch (ExecutionException e) {
if(CalculationException.class.isInstance(e.getCause())) {
throw (CalculationException)(e.getCause());
}
else if(RuntimeException.class.isInstance(e.getCause())) {
throw (RuntimeException)(e.getCause());
}
else {
throw new CalculationException(e.getCause());
}
}
// Return values
return values;
}
@Override
public String toString() {
return "ProductCollection [products=" + products + "]";
}
}
Ads help maintain this website.