/*
* (c) Copyright Christian P. Fries, Germany. All rights reserved. Contact: email@christianfries.com.
*
* Created on 17.08.2013
*/
package net.finmath.montecarlo.products;
import java.util.Arrays;
import java.util.Vector;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import net.finmath.exception.CalculationException;
import net.finmath.montecarlo.AbstractMonteCarloProduct;
import net.finmath.montecarlo.MonteCarloSimulationInterface;
import net.finmath.stochastic.RandomVariableInterface;
/**
* A portfolio of products, each product being of AbstractMonteCarloProduct type.
* The valuation is performed multi-threaded over the portfolio of products.
*
* @author Christian Fries
*/
public class PortfolioMonteCarloProduct extends AbstractMonteCarloProduct {
private AbstractMonteCarloProduct[] products;
private double weights[];
/**
* Create a portfolio of products, each product being of AbstractMonteCarloProduct type.
*
* @param products An array of products.
*/
public PortfolioMonteCarloProduct(
AbstractMonteCarloProduct[] products) {
this(products, weightsOfOne(products.length));
}
/**
* Create a portfolio of products, each product being of AbstractMonteCarloProduct type
* and weighted with a given weight.
*
* @param products An array of products.
* @param weights An array of weights.
*/
public PortfolioMonteCarloProduct(
AbstractMonteCarloProduct[] products,
double[] weights) {
super();
this.products = products;
this.weights = weights;
}
/**
* Helper returns an array of 1.0's with given length.
*
* @param length Length of the array.
* @return Array of double with given length, each entry being 1.0.
*/
private static double[] weightsOfOne(int length) {
double[] weightsOfOne = new double[length];
Arrays.fill(weightsOfOne, 1.0);
return weightsOfOne;
}
/* (non-Javadoc)
* @see net.finmath.montecarlo.AbstractMonteCarloProduct#getValue(double, net.finmath.montecarlo.MonteCarloSimulationInterface)
*/
@Override
public RandomVariableInterface getValue(final double evaluationTime,
final MonteCarloSimulationInterface model) throws CalculationException {
if(products == null || products.length == 0) return null;
// We do not allocate more threads the twice the number of processors.
int numberOfThreads = Math.min(Math.max(2 * Runtime.getRuntime().availableProcessors(),1),products.length);
ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
RandomVariableInterface value = null;
try {
// Start calculation threads for each product
Vector> values = new Vector>(products.length);
for(int i=0; i worker = new Callable() {
public RandomVariableInterface call() throws CalculationException {
return product.getValue(evaluationTime, model).mult(weight);
}
};
executor.submit(worker);
}
// Collect and sum results
value = values.get(0).get();
for(int i=1; i
Ads help maintain this website.