/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.engine.marketdata.manipulator.function;
import org.fudgemsg.FudgeMsg;
import org.fudgemsg.MutableFudgeMsg;
import org.fudgemsg.mapping.FudgeDeserializer;
import org.fudgemsg.mapping.FudgeSerializer;
import com.opengamma.engine.function.FunctionExecutionContext;
import com.opengamma.engine.value.ValueSpecification;
import com.opengamma.util.ArgumentChecker;
public class MarketDataPointRandomizingManipulator implements StructureManipulator<Double> {
/**
* The lower bound of the scaling to be applied to the market data value.
*/
private final double _lowerBound;
/**
* The upper bound of the scaling to be applied to the market data value.
*/
private final double _upperBound;
/**
* The precalculated range provided by the 2 bounds.
*/
private final double _rangeSize;
/**
* Creates a randomizing manipulator where the actual market value is shifted by a random
* factor between the provided lower and upper bounds. Values produced will be shifted by
* a value greater than or equal to the lower bound, and strictly less than the upper
* bound. The reason for this is simplicity as it is in line with {@link Math#random()}.
*
* The following would create a manipulator such that if the original value is x, the
* produced value, y, would satisfy 0.9x <= y < 1.1x (i.e. y is within 10% of x).
*
* <code>
* new MarketDataPointRandomizingManipulator(0.9, 1.1);
* </code>
*
* @param lowerBound the lower bound of the scaling to be applied to the market data value
* @param upperBound the upper bound of the scaling to be applied to the market data value
*/
public MarketDataPointRandomizingManipulator(Double lowerBound, Double upperBound) {
ArgumentChecker.notNull(lowerBound, "lowerBound");
ArgumentChecker.notNull(upperBound, "upperBound");
ArgumentChecker.notNegative(lowerBound, "lowerBound");
ArgumentChecker.isTrue(lowerBound < upperBound, "Lower bound must be less than the upper bound");
_lowerBound = lowerBound;
_upperBound = upperBound;
_rangeSize = upperBound - lowerBound;
}
@Override
public Double execute(Double structure,
ValueSpecification valueSpecification,
FunctionExecutionContext executionContext) {
return structure * randomFactor();
}
@Override
public Class<Double> getExpectedType() {
return Double.class;
}
private double randomFactor() {
return Math.random() * _rangeSize + _lowerBound;
}
public MutableFudgeMsg toFudgeMsg(final FudgeSerializer serializer) {
final MutableFudgeMsg msg = serializer.newMessage();
msg.add("lowerBound", _lowerBound);
msg.add("upperBound", _upperBound);
return msg;
}
public static MarketDataPointRandomizingManipulator fromFudgeMsg(final FudgeDeserializer deserializer, final FudgeMsg msg) {
return new MarketDataPointRandomizingManipulator(msg.getDouble("lowerBound"), msg.getDouble("upperBound"));
}
}