/*
 Copyright (C) 2008 Richard Gomes
 Copyright (C) 2010 Neel Sheyal

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

package org.jquantlib.termstructures.yieldcurves;

import org.jquantlib.QL;
import org.jquantlib.daycounters.DayCounter;
import org.jquantlib.indexes.IborIndex;
import org.jquantlib.quotes.Handle;
import org.jquantlib.quotes.Quote;
import org.jquantlib.quotes.SimpleQuote;
import org.jquantlib.termstructures.RateHelper;
import org.jquantlib.time.BusinessDayConvention;
import org.jquantlib.time.Calendar;
import org.jquantlib.time.Date;
import org.jquantlib.time.IMM;
import org.jquantlib.time.Period;
import org.jquantlib.time.TimeUnit;

/**
 * FuturesRateHelper
 * 
 * @author Srinivas Hasti
 * @author Neel Sheyal
 * 
 * Rate helper for bootstrapping over IborIndex futures prices
 * {@link } {@link }
 */


public class FuturesRateHelper extends RateHelper {
     
   private static final String NOT_A_VALID_IMM_DATE = "not a valid IMM date"; 
   private static final String TERMSTRUCT_NOT_SET = "term structure not set";
    //
    // private fields
    // 
    private final double yearFraction;
    private Handle convAdj;

	//
	// public constructors
	//
	/**
	 * @param Handle
	 *             price
	 * @param Date
	 *            immDate
	 * @param int lengthInMonths
	 * @param Calendar
	 *            calendar
	 * @param BusinessDayConvention
	 *            convention
	 * @param boolean endOfMonth
	 * @param DayCounter
	 *            dayCounter
	 */
	public FuturesRateHelper(final Handle price, 
			                  final Date immDate,
			                  final/* Natural */int lengthInMonths, 
			                  final Calendar calendar,
			                  final BusinessDayConvention convention, 
			                  final boolean endOfMonth,
			                  final DayCounter dayCounter) {
		this(price, immDate, lengthInMonths, calendar, convention, endOfMonth,
				dayCounter, new Handle());
	}
    
	/**
	 * @param Handle
	 *             price
	 * @param Date
	 *            immDate
	 * @param int lengthInMonths
	 * @param Calendar
	 *            calendar
	 * @param BusinessDayConvention
	 *            convention
	 * @param boolean endOfMonth
	 * @param DayCounter
	 *            dayCounter
	 * @param Handle
	 *             convAdj
	 */
	public FuturesRateHelper(final Handle price, 
			                  final Date immDate,
			                  final/* Natural */int lengthInMonths, 
			                  final Calendar calendar,
			                  final BusinessDayConvention convention, 
			                  final boolean endOfMonth,
			                  final DayCounter dayCounter, 
			                  final Handle convAdj) {
		super(price);
		this.convAdj = convAdj;

		QL.require(new IMM().isIMMdate(immDate, false), NOT_A_VALID_IMM_DATE);

		earliestDate = immDate;
		latestDate = calendar.advance(immDate, new Period(lengthInMonths,
				TimeUnit.Months), convention, endOfMonth);
		yearFraction = dayCounter.yearFraction(earliestDate, latestDate);

		convAdj.addObserver(this); 
	}    
    

	/**
	 * @param Handle
	 *             price
	 * @param Date
	 *            immDate
	 * @param int lengthInMonths
	 * @param Calendar
	 *            calendar
	 * @param BusinessDayConvention
	 *            convention
	 * @param boolean endOfMonth
	 * @param DayCounter
	 *            dayCounter
	 */
	public FuturesRateHelper(final/* Real */double price, 
			                  final Date immDate,
			                  final/* Natural */ int lengthInMonths, 
			                  final Calendar calendar,
			                  final BusinessDayConvention convention, 
			                  final boolean endOfMonth,
			                  final DayCounter dayCounter) {
		this(price, immDate, lengthInMonths, calendar, convention, endOfMonth,
				dayCounter, 0.0);
	}
	
	/**
	 * @param double price
	 * @param Date
	 *            immDate
	 * @param int lengthInMonths
	 * @param Calendar
	 *            calendar
	 * @param BusinessDayConvention
	 *            convention
	 * @param boolean endOfMonth
	 * @param DayCounter
	 *            dayCounter
	 *  @param double  convAdj         
	 */
	public FuturesRateHelper(final/* Real */double price, 
			                  final Date immDate,
			                  final/* Natural */int lengthInMonths, 
			                  final Calendar calendar,
			                  final BusinessDayConvention convention, 
			                  final boolean endOfMonth,
			                  final DayCounter dayCounter, 
			                  final/* Rate */double convAdj) {
		super(price);
		this.convAdj = new Handle(new SimpleQuote(convAdj));

		QL.require(new IMM().isIMMdate(immDate, false), NOT_A_VALID_IMM_DATE);

		earliestDate = immDate;
		latestDate = calendar.advance(immDate, new Period(lengthInMonths,
				TimeUnit.Months), convention, endOfMonth);
		yearFraction = dayCounter.yearFraction(earliestDate, latestDate);
	}

	/**
	 * @param Handle
	 *             price
	 * @param Date
	 *            immDate
	 * @param IborIndex
	 *            index
	 */
	public FuturesRateHelper(final Handle price, 
			                  final Date immDate,
			                  final IborIndex i) {
		this(price, immDate, i, new Handle());
	}

	/**
	 * @param Handle
	 *             price
	 * @param Date
	 *            immDate
	 * @param IborIndex
	 *            index
	 * @param Handle
	 *             convAdj
	 */
	public FuturesRateHelper(final Handle price, 
			                  final Date immDate,
		                      final IborIndex i, 
		                      final Handle convAdj) {

		super(price);
		this.convAdj = convAdj;

		QL.require(new IMM().isIMMdate(immDate, false), NOT_A_VALID_IMM_DATE);

		this.earliestDate = immDate;
		this.latestDate = i.fixingCalendar().advance(immDate, i.tenor(),
				i.businessDayConvention());
		this.yearFraction = i.dayCounter().yearFraction(this.earliestDate,
				this.latestDate);

		convAdj.addObserver(this); 
	}
 

	/**
	 * @param double price
	 * @param Date
	 *            immDate
	 * @param IborIndex
	 *            index
	 */
	public FuturesRateHelper(final /* Real */ double price, 
			                  final Date immDate,
			                  final IborIndex i) {
		this(price, immDate, i, 0.0);
	}
        
	/**
	 * @param double price
	 * @param Date
	 *            immDate
	 * @param IborIndex
	 *            index
	 * @param double convAdj
	 * 
	 */  
    public FuturesRateHelper(final /* Real */ double price,
                              final Date immDate,
                              final IborIndex i,
                              final /* Rate */ double convAdj) {
        super(price);   
        this.convAdj = new Handle(new SimpleQuote(convAdj));
        
        QL.require(new IMM().isIMMdate(immDate, false) , NOT_A_VALID_IMM_DATE); 
        
        earliestDate = immDate;
        final Calendar cal = i.fixingCalendar();
        latestDate = cal.advance(immDate, i.tenor(), i.businessDayConvention());
        yearFraction = i.dayCounter().yearFraction(earliestDate, latestDate);
    }


    /**
    /* Implements the abstract method defined in {@link }
     * Returns the futures value of the instrument  
     *
     * @return double   
     */
	@Override
	public/* Real */double impliedQuote() {

		QL.require(termStructure != null, TERMSTRUCT_NOT_SET);
		final/* Rate */double forwardRate = termStructure.discount(earliestDate)
				/ (termStructure.discount(latestDate) - 1.0) / yearFraction;
		final/* Rate */double convA = this.convAdj.empty() ? 0.0 : this.convAdj
				.currentLink().value();
		QL.ensure(convA >= 0.0, "Negative (" + convAdj
				+ ") futures convexity adjustment");
		final/* Rate */double futureRate = forwardRate + convA;
		return 100.0 * (1.0 - futureRate);
	}

    //
    // public methods
    //
	/**
	 * @return double value of the adjusted convexity
	 */
    public /* Real */ double getConvexityAdjustment() {
        return convAdj.empty() ? 0.0 : convAdj.currentLink().value();
    }

}

 

Ads help maintain this website.