Package org.jquantlib.math.statistics

Source Code of org.jquantlib.math.statistics.GenericRiskStatistics

/*
Copyright (C) 2009 Ueli Hofstetter

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
<jquant-devel@lists.sourceforge.net>. The license is also available online at
<http://www.jquantlib.org/index.php/LICENSE.TXT>.

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.
*/
package org.jquantlib.math.statistics;

import java.util.ArrayList;
import java.util.List;

import org.jquantlib.QL;
import org.jquantlib.math.Ops;
import org.jquantlib.math.functions.Bind1st;
import org.jquantlib.math.functions.Bind1stPredicate;
import org.jquantlib.math.functions.Bind2nd;
import org.jquantlib.math.functions.Bind2ndPredicate;
import org.jquantlib.math.functions.Clipped;
import org.jquantlib.math.functions.Constant;
import org.jquantlib.math.functions.Expression;
import org.jquantlib.math.functions.Identity;
import org.jquantlib.math.functions.LessThanPredicate;
import org.jquantlib.math.functions.Minus;
import org.jquantlib.math.functions.Square;
import org.jquantlib.math.functions.TruePredicate;
import org.jquantlib.util.Pair;

// TODO: code review :: license, class comments, comments for access modifiers, comments for @Override
//FIXME: the class hierarchy is wrong :: mimic inheritence using delegate pattern (similar to TimeSeries?)
public class GenericRiskStatistics {

    private static final String no_data_below_the_target = "no data below the target";
    private static final String empty_sample_set = "empty sample set";
    private static final String unsufficient_samples_under_target = "samples under target <=1, unsufficient";

    private Statistics statistics = null;

    public GenericRiskStatistics(final Statistics statistics){
        if (System.getProperty("EXPERIMENTAL") == null)
            throw new UnsupportedOperationException("Work in progress");
        this.statistics = statistics;
    }

    /*! returns the variance of observations below the mean,
        \f[ \frac{N}{N-1}
            \mathrm{E}\left[ (x-\langle x \rangle)^2 \;|\;
                              x < \langle x \rangle \right]. \f]

        See Markowitz (1959).
     */
    public double semiVariance(){
        return regret(statistics.mean());
    }

    /*! returns the semi deviation, defined as the
        square root of the semi variance.
     */
    public double semiDeviation() {
        return Math.sqrt(semiVariance());
    }

    /*! returns the variance of observations below 0.0,
        \f[ \frac{N}{N-1}
            \mathrm{E}\left[ x^2 \;|\; x < 0\right]. \f]
     */
    public double downsideVariance(){
        return regret(0.0);
    }

    /*! returns the downside deviation, defined as the
        square root of the downside variance.
     */
    public double downsideDeviation(){
        return Math.sqrt(downsideVariance());
    }

    /*! returns the variance of observations below target,
        \f[ \frac{N}{N-1}
            \mathrm{E}\left[ (x-t)^2 \;|\;
                              x < t \right]. \f]

        See Dembo and Freeman, "The Rules Of Risk", Wiley (2001).
     */
    public double regret(final double target){
        // average over the range below the target

        final List<Ops.DoubleOp> functions = new ArrayList<Ops.DoubleOp>();
        functions.add(new Square());
        functions.add(new Bind2nd(new Minus(), target));
        final Expression comp = new Expression(functions);
        final Ops.DoublePredicate less = new Bind2ndPredicate(new LessThanPredicate(), target);

        final Pair<Double, Integer> result = statistics.expectationValue(comp, less);
        final double x = result.getFirst();

        // TODO: code review :: please verify against QL/C++ code
        final int n = result.getSecond().intValue();
        QL.require(n >= 2 , unsufficient_samples_under_target); // QA:[RG]::verified
        return (n/(n-1.0))*x;
    }

    //! potential upside (the reciprocal of VAR) at a given percentile
    public double potentialUpside(final double centile){
        QL.require(centile >= 0.9 && centile < 1.0 , "percentile out of range [0.9, 1.0)"); // QA:[RG]::verified // TODO: message
        // potential upside must be a gain, i.e., floored at 0.0
        return Math.max(statistics.percentile(centile), 0.0);
    }

    //! value-at-risk at a given percentile
    public double valueAtRisk(final double centile){
        QL.require(centile >= 0.9 && centile < 1.0 , "percentile out of range [0.9, 1.0)"); // QA:[RG]::verified // TODO: message
        return - Math.min(statistics.percentile(1.0-centile), 0.0);
    }

    //! expected shortfall at a given percentile
    /*! returns the expected loss in case that the loss exceeded
        a VaR threshold,

        \f[ \mathrm{E}\left[ x \;|\; x < \mathrm{VaR}(p) \right], \f]

        that is the average of observations below the
        given percentile \f$ p \f$.
        Also know as conditional value-at-risk.

        See Artzner, Delbaen, Eber and Heath,
        "Coherent measures of risk", Mathematical Finance 9 (1999)
     */
    public double expectedShortfall(final double centile){
        //Require...
        if(centile<0.9 || centile>=1.0)
            throw new IllegalArgumentException("percentile (" + centile + ") out of range [0.9, 1.0)");
        //Ensure...
        // TODO: code review :: please verify against QL/C++ code
        if (statistics.getSampleSize() == 0){
            //not sure whether to throw an exception
            //throw new IllegalArgumentException(empty_sample_set);
        }
        final double target = -valueAtRisk(centile);

        final Ops.DoublePredicate less = new Bind2ndPredicate(new LessThanPredicate(), target);
        final Pair<Double, Integer> result = statistics.expectationValue(new Identity(), less);

        final double x = result.getFirst();
        final Integer N = result.getSecond();

        if(N.intValue() ==  0.0)
            throw new IllegalArgumentException(no_data_below_the_target);
        // must be a loss, i.e., capped at 0.0 and negated
        return -Math.min(x, 0.0);

    }

    /*! probability of missing the given target, defined as
        \f[ \mathrm{E}\left[ \Theta \;|\; (-\infty,\infty) \right] \f]
        where
        \f[ \Theta(x) = \left\{
            \begin{array}{ll}
            1 & x < t \\
            0 & x \geq t
            \end{array}
            \right. \f]
     */
    public double shortfall(final double target){
        if (statistics.getSampleSize()==0)
            throw new IllegalArgumentException(empty_sample_set);

        final Ops.DoublePredicate less = new Bind2ndPredicate(new LessThanPredicate(), target);
        return statistics.expectationValue(new Clipped(less, new Constant(1.0)), new TruePredicate()).getFirst();
    }

    /*! averaged shortfallness, defined as
        \f[ \mathrm{E}\left[ t-x \;|\; x<t \right] \f]
     */
    public double averageShortfall(final double target) {

        final Ops.DoubleOp minus = new Bind1st(target, new Minus());
        final Ops.DoublePredicate less = new Bind1stPredicate(target, new LessThanPredicate());
        final Pair<Double, Integer> result = statistics.expectationValue(minus, less);

        final double x = result.getFirst();
        //mmhh somewhere we have to change N to int
        final Integer N = result.getSecond();
        if(N.intValue()==0)
            throw new IllegalArgumentException(no_data_below_the_target);
        return x;
    }
}
TOP

Related Classes of org.jquantlib.math.statistics.GenericRiskStatistics

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.