/*
Copyright (C) 2007 Richard Gomes
This source code is release under the BSD License.
This file is part of JQuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://jquantlib.org/
JQuantLib is free software: you can redistribute it and/or modify it
under the terms of the JQuantLib license. You should have received a
copy of the license along with this program; if not, please email
. The license is also available online at
.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
JQuantLib is based on QuantLib. http://quantlib.org/
When applicable, the original copyright notice follows this notice.
*/
/*
Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
Copyright (C) 2003, 2004, 2005, 2006, 2007 StatPro Italia srl
This file is part of QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/
QuantLib is free software: you can redistribute it and/or modify it
under the terms of the QuantLib license. You should have received a
copy of the license along with this program; if not, please email
. The license is also available online at
.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
*/
package org.jquantlib.instruments;
import java.util.HashMap;
import java.util.Map;
import org.jquantlib.QL;
import org.jquantlib.lang.annotation.QualityAssurance;
import org.jquantlib.lang.annotation.QualityAssurance.Quality;
import org.jquantlib.lang.annotation.QualityAssurance.Version;
import org.jquantlib.lang.exceptions.LibraryException;
import org.jquantlib.lang.reflect.ReflectConstants;
import org.jquantlib.pricingengines.PricingEngine;
import org.jquantlib.util.LazyObject;
/**
* This is an abstract {@link Instrument} class which is able to use a {@link PricingEngine} implemented
* internally or externally to it.
*
* @see PricingEngine
* @see QuantLib: Financial Instruments
*
* @author Richard Gomes
*/
@QualityAssurance(quality = Quality.Q3_DOCUMENTATION, version = Version.V097, reviewers = { "Femi Anthony" })
public abstract class Instrument extends LazyObject {
//
// private static final fields
//
private static final String SHOULD_DEFINE_PRICING_ENGINE = "Should define pricing engine";
private static final String SETUP_ARGUMENTS_NOT_IMPLEMENTED = "Instrument#setupArguments() not implemented";
//
// protected fields
//
/**
* The value of this attribute and any other that derived classes might declare must be set during calculation.
*
* @see PricingEngine
*/
protected PricingEngine engine;
/**
* Represents the net present value of the instrument.
*/
protected /*@Real*/ double NPV;
/**
* Represents the error estimate on the NPV when available.
*/
protected /*@Real*/ double errorEstimate;
//
// public abstract methods
//
/**
* @return true if the instrument is still tradeable.
*/
public abstract boolean isExpired();
/**
* Passes arguments to be used by a {@link PricingEngine}.
* When a derived argument structure is defined for an instrument, this method should be overridden to fill it.
*
* @param arguments keeps values to be used by the external {@link PricingEngine}
*
* @see Arguments
* @see PricingEngine
*/
protected void setupArguments(final PricingEngine.Arguments a) /* @ReadOnly */ {
throw new LibraryException(SETUP_ARGUMENTS_NOT_IMPLEMENTED);
}
//
// protected constructors
//
protected Instrument() {
this.NPV = Double.NaN;
this.errorEstimate = 0.0;
}
//
// public final methods
//
/**
* This method defines an external {@link PricingEngine} to be used for a new-style {@link Instrument}.
*
* @param engine is the external {@link PricingEngine} to be used
*
* @see PricingEngine
*/
public final void setPricingEngine(final PricingEngine engine) {
if (this.engine != null)
this.engine.deleteObserver(this);
this.engine = engine;
if (this.engine != null)
this.engine.addObserver(this);
//XXX:OBS update(this, null);
update();
}
/**
* returns the net present value of the instrument.
*/
public final/*@Real*/double NPV() /*@ReadOnly*/{
calculate();
QL.require(!Double.isNaN(this.NPV) , "NPV not provided"); // TODO: message
return NPV;
}
/**
* returns the error estimate on the NPV when available.
*/
public final/*@Real*/double errorEstimate() /*@ReadOnly*/{
calculate();
QL.require(!Double.isNaN(this.errorEstimate) , "error estimate not provided"); // TODO: message
return errorEstimate;
}
//
// protected methods
//
/**
* Obtains the {@link Results} populated by a {@link PricingEngine}.
* When a derived result structure is defined for an instrument, this method should be overridden to read from it.
*
* @param results contains the {@link Results} object populated by a {@link PricingEngine}
*
* @see Results
* @see PricingEngine
*/
protected void fetchResults(final PricingEngine.Results r) /* @ReadOnly */ {
QL.require(PricingEngine.Results.class.isAssignableFrom(r.getClass()), ReflectConstants.WRONG_ARGUMENT_TYPE); // QA:[RG]::verified
final Instrument.ResultsImpl results = (Instrument.ResultsImpl)r;
NPV = results.value;
errorEstimate = results.errorEstimate;
}
/**
* This method must leave the instrument in a consistent
* state when the expiration condition is met.
*/
protected void setupExpired() /*@ReadOnly*/{
NPV = 0.0;
errorEstimate = 0.0;
}
//
// overrides LazyObject
//
/**
* This method performs the actual calculations and set any needed results.
*
* @see LazyObject#performCalculations
*/
@Override
protected void performCalculations() /*@ReadOnly*/ {
QL.require(engine != null, SHOULD_DEFINE_PRICING_ENGINE); // QA:[RG]::verified
engine.reset();
setupArguments(engine.getArguments());
engine.getArguments().validate();
engine.calculate();
fetchResults(engine.getResults());
}
@Override
protected void calculate() /*@ReadOnly*/ {
if (isExpired()) {
setupExpired();
calculated = true;
} else
super.calculate();
}
//
// ????? inner interfaces
//
/**
* basic instrument arguments
*
* @author Richard Gomes
*/
public interface Arguments extends PricingEngine.Arguments { /* marking interface */ }
/**
* Results from instrument calculation
*
* @author Richard Gomes
*/
public interface Results extends PricingEngine.Results { /* marking interface */ }
//
// ????? inner classes
//
/**
* Results are used by {@link PricingEngine}s in order to store results of calculations
* relative to new-style {@link Instrument}s
*
* @note Public fields as this class works pretty much as Data Transfer Objects
*
* @see Instrument
* @see PricingEngine
* @see Arguments
*
* @author Richard Gomes
*/
static public class ResultsImpl implements Instrument.Results {
//
// public fields
//
/**
* Represents the calculated value of an {@link Instrument}
*
* @see Instrument
*/
public /*@Real*/ double value;
/**
* Contains the estimated error due to floating point error
*/
public /*@Real*/ double errorEstimate;
//TODO: Code review
private final Map additionalResults = new HashMap();
//
// public methods
//
/**
* returns any additional result returned by the pricing engine.
*/
public Object result(final String key) /* @ReadOnly */ {
return this.additionalResults.get(key);
}
/**
* returns all additional result returned by the pricing engine.
*/
public Map additionalResults() /* @ReadOnly */ {
return this.additionalResults;
}
//
// Overrides PriceEngine.Results
//
/**
* Clean up results of calculations
*
* Notice that values are undefined after reset.
*/
@Override
public void reset() {
value = errorEstimate = Double.NaN;
additionalResults.clear();
}
}
}
Ads help maintain this website.