Package org.jquantlib.time

Source Code of org.jquantlib.time.TimeGrid

/*
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
<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.time;

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

import org.jquantlib.QL;
import org.jquantlib.lang.annotation.NonNegative;
import org.jquantlib.lang.annotation.Time;
import org.jquantlib.lang.iterators.Iterables;
import org.jquantlib.math.Closeness;
import org.jquantlib.math.matrixutilities.Array;


/**
* TimeGrid class.
*
* @author Dominik Holenstein
*/
// TODO: Taken over from QuantLib: What was the rationale for limiting the grid to positive times?
// Investigate and see whether we can use it for negative ones as well.
public class TimeGrid {

    //
    // private fields
    //
    private final Array times;
    private final Array dt;
    private final Array mandatoryTimes;



    //
    // Constructors
    //

    public TimeGrid() {
        this.times = null; //XXX  new Array();
        this.dt = null; //XXX: new Array();
        this.mandatoryTimes = null; //XXX: new Array();
    }

    /**
     * Regularly spaced time-grid
     *
     * @param end
     * @param steps
     */
    public TimeGrid(@Time @NonNegative final double end, @NonNegative final int steps) {

        // THIS COMMENT COMES FROM QuantLib/C++ code
        //
        // We seem to assume that the grid begins at 0.
        // Let's enforce the assumption for the time being
        // (even though I'm not sure that I agree.)
        QL.require(end > 0.0 , "negative times not allowed"); // QA:[RG]::verified // FIXME: message

        /*@Time*/ final double dt = end/steps;
        this.times = new Array(steps+1);
        for (int i=0; i<=steps; i++) {
            times.set(i, dt*i);
        }
        this.mandatoryTimes = new Array(1).fill(end);
        this.dt = new Array(steps).fill(dt);
    }


    /**
     * Time grid with mandatory time points.
     * <p>
     * Mandatory points are guaranteed to belong to the grid. No additional points are added.
     *
     * @note This constructor is not available yet
     *
     * @param list
     */
    public TimeGrid(@Time @NonNegative final Array mandatoryTimes) {

        if (System.getProperty("EXPERIMENTAL")==null)
            throw new UnsupportedOperationException("This constructor is not available yet");

        //XXX this.mandatoryTimes = mandatoryTimes.clone();
        this.mandatoryTimes = mandatoryTimes;
        this.mandatoryTimes.sort();

        // THIS COMMENT COMES FROM QuantLib/C++ code
        //
        // We seem to assume that the grid begins at 0.
        // Let's enforce the assumption for the time being
        // (even though I'm not sure that I agree.)
        QL.require(mandatoryTimes.first() < 0.0 , "negative times not allowed"); // QA:[RG]::verified // TODO: message

        final List<Double> unique = new ArrayList<Double>();
        double prev = this.mandatoryTimes.get(0);
        unique.add(prev);
        for (int i=1; i<this.mandatoryTimes.size(); i++) {
            final double curr = this.mandatoryTimes.get(i);
            if (! Closeness.isCloseEnough(prev, curr)) {
                unique.add(curr);
            }
            prev = curr;
        }

        this.times = new Array(unique.size());
        int i=0;
        for (final double d : Iterables.unmodifiableIterable(unique.iterator())) {
            this.times.set(i, d);
            i++;
        }
        this.dt = this.times.adjacentDifference();
    }



    /**
     * Time grid with mandatory time points
     * <p>
     * Mandatory points are guaranteed to belong to the grid.
     * Additional points are then added with regular spacing between pairs of mandatory times in order
     * to reach the desired number of steps.
     *
     * @note This constructor is not available yet - fix adjacent_difference before using
     */
    //TODO: needs code review
//    template <class Iterator>
//    TimeGrid(Iterator begin, Iterator end, Size steps)
//    : mandatoryTimes_(begin, end) {
//        std::sort(mandatoryTimes_.begin(),mandatoryTimes_.end());
//        // We seem to assume that the grid begins at 0.
//        // Let's enforce the assumption for the time being
//        // (even though I'm not sure that I agree.)
//        QL_REQUIRE(mandatoryTimes_.front() >= 0.0,
//                   "negative times not allowed");
//        std::vector<Time>::iterator e =
//            std::unique(mandatoryTimes_.begin(),mandatoryTimes_.end(),
//                        std::ptr_fun(close_enough));
//        mandatoryTimes_.resize(e - mandatoryTimes_.begin());
//
//        Time last = mandatoryTimes_.back();
//        Time dtMax;
//        // The resulting timegrid have points at times listed in the input
//        // list. Between these points, there are inner-points which are
//        // regularly spaced.
//        if (steps == 0) {
//            std::vector<Time> diff;
//            std::adjacent_difference(mandatoryTimes_.begin(),
//                                     mandatoryTimes_.end(),
//                                     std::back_inserter(diff));
//            if (diff.front()==0.0)
//                diff.erase(diff.begin());
//            dtMax = *(std::min_element(diff.begin(), diff.end()));
//        } else {
//            dtMax = last/steps;
//        }
//
//        Time periodBegin = 0.0;
//        times_.push_back(periodBegin);
//        for (std::vector<Time>::const_iterator t=mandatoryTimes_.begin();
//                                               t<mandatoryTimes_.end();
//                                               t++) {
//            Time periodEnd = *t;
//            if (periodEnd != 0.0) {
//                // the nearest integer
//                Size nSteps = Size((periodEnd - periodBegin)/dtMax+0.5);
//                // at least one time step!
//                nSteps = (nSteps!=0 ? nSteps : 1);
//                Time dt = (periodEnd - periodBegin)/nSteps;
//                times_.reserve(nSteps);
//                for (Size n=1; n<=nSteps; ++n)
//                    times_.push_back(periodBegin + n*dt);
//            }
//            periodBegin = periodEnd;
//        }
//
//        std::adjacent_difference(times_.begin()+1,times_.end(),
//                                 std::back_inserter(dt_));
//    }


    public @NonNegative int index(@Time @NonNegative final double t) /* @ReadOnly */ {
        final @NonNegative int i = closestIndex(t);
        if (Closeness.isCloseEnough(t, times.get(i)))
            return i;
        else if (t < front())
            throw new IllegalArgumentException(
                    "using inadequate time grid: all nodes are later than the required time t = "
                    + t + " (earliest node is t1 = " + times.first() + ")" );
        else if (t > back())
            throw new IllegalArgumentException(
                    "using inadequate time grid: all nodes are earlier than the required time t = "
                    + t + " (latest node is t1 = " + back() + ")" );
        else {
            /*@NonNegative*/ int j, k;
            if (t > times.get(i)) {
                j = i;
                k = i+1;
            } else {
                j = i-1;
                k = i;
            }
            throw new IllegalArgumentException(
                    "using inadequate time grid: the nodes closest to the required time t = "
                    + t + " are t1 = " + times.get(j) + " and t2 = " + times.get(k) );
        }
    }


    public @NonNegative int closestIndex(@Time @NonNegative final double t) /* @ReadOnly */ {
        final int size = times.size();
        final int result = times.lowerBound(t);

        if (result == 0)
            return 0;
        else if (result == size)
            return size-1;
        else {
            final @Time double dt1 = times.get(result) - t;
            final @Time double dt2 = t - times.get(result-1);
            if (dt1 < dt2)
                return result;
            else
                return result-1;
        }
    }

    /**
     * @return the time on the grid closest to the given t
     */
    public @Time double closestTime (@Time @NonNegative final double t) /*@Readonly*/ {
        return times.get(closestIndex(t));
    }

    public final Array mandatoryTimes() /*@Readonly*/ {
        // TODO: code review :: use of clone()
        return mandatoryTimes.clone();
    }

    public double dt (final int i) /*@Readonly*/ {
        return dt.get(i);
    }

    public double get(final int i) /*@Readonly*/ {
        return times.get(i);
    }

    public double at(final int i) /*@Readonly*/ {
        return times.get(i);
    }

    public int size() /*@Readonly*/ {
        return times.size();
    }

    public boolean empty() /*@Readonly*/ {
        return times.size() == 0;
    }

    public double begin() /*@Readonly*/ {
        return times.first();
    }

    public double end() /*@Readonly*/ {
        return times.last();
    }

    public double front() /*@Readonly*/ {
        return times.first();
    }

    public double back() /*@Readonly*/ {
        return times.last();
    }

}
TOP

Related Classes of org.jquantlib.time.TimeGrid

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.