/*
 Copyright (C) 2010 Zahid Hussain

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

 JQuantLib is based on QuantLib. http://quantlib.org/
 When applicable, the original copyright notice follows this notice.
 */
/*
 Copyright (C) 2005, 2006 Theo Boafo
 Copyright (C) 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.pricingengines.hybrid;

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

import org.jquantlib.QL;
import org.jquantlib.cashflow.Callability;
import org.jquantlib.cashflow.Dividend;
import org.jquantlib.daycounters.DayCounter;
import org.jquantlib.exercise.Exercise;
import org.jquantlib.instruments.DiscretizedAsset;
import org.jquantlib.instruments.bonds.ConvertibleBondOption;
import org.jquantlib.lang.annotation.QualityAssurance;
import org.jquantlib.lang.annotation.QualityAssurance.Quality;
import org.jquantlib.lang.annotation.QualityAssurance.Version;
import org.jquantlib.math.Closeness;
import org.jquantlib.math.Constants;
import org.jquantlib.math.matrixutilities.Array;
import org.jquantlib.processes.GeneralizedBlackScholesProcess;
import org.jquantlib.termstructures.Compounding;
import org.jquantlib.time.Date;
import org.jquantlib.time.Frequency;
import org.jquantlib.time.TimeGrid;
import org.jquantlib.util.Std;

/**
 * Discretized Convertible
 * 
 * @author Zahid Hussain
 *
 */
@QualityAssurance(quality=Quality.Q3_DOCUMENTATION, version=Version.V097, reviewers="Richard Gomes")
public class DiscretizedConvertible extends DiscretizedAsset {

    //
    // protected fields
    //
    
    protected Array conversionProbability;
    protected Array spreadAdjustedRate;
    protected Array dividendValues;

    //
    // private fields
    //
    
    private final ConvertibleBondOption.ArgumentsImpl arguments;
    private final GeneralizedBlackScholesProcess process;
    private final List< /* @Time */ Double > stoppingTimes;
    private final List< /* @Time */ Double > callabilityTimes;
    private final List< /* @Time */ Double > couponTimes;
    private final List< /* @Time */ Double > dividendTimes;


    //
    // public constructors
    //
    
    public DiscretizedConvertible(final ConvertibleBondOption.ArgumentsImpl arguments,
                                  final GeneralizedBlackScholesProcess process,
                                  final TimeGrid grid) {
        this.arguments = arguments;
        this.process = process; 

       dividendValues = new Array(this.arguments.dividends.size()).fill(0.0);

       final Date settlementDate = this.process.riskFreeRate().currentLink().referenceDate();
       for (int i=0; i(this.arguments.exercise.dates().size());
       for (int i=0; i(this.arguments.callabilityDates.size());
       for (int i=0; i(this.arguments.couponDates.size());
       for (int i=0; i(this.arguments.dividendDates.size());
       for (int i=0; i mandatoryTimes() {
        
        final List result = new ArrayList();
        Std.copy(stoppingTimes, 0, stoppingTimes.size(), result);
        Std.copy(callabilityTimes, 0, callabilityTimes.size(),result);
        Std.copy(couponTimes, 0, couponTimes.size(), result);
        return result;
    }

    public void applyConvertibility() {
        final Array grid = adjustedGrid();
        for (int j=0; j= trigger) {
                        // ...and might trigger conversion
                        values_.set(j, 
                            Math.min(Math.max(this.arguments.callabilityPrices.get(i),
                                              this.arguments.conversionRatio*grid.get(j)),
                                     values_.get(j)));
                    }
                }
            } else if (convertible) {
                for (j=0; j= t || Closeness.isCloseEnough(dividendTime,t)) {
               final Dividend d = this.arguments.dividends.get(i);
                for (int j=0; jamount(grid[j]);
                }
            }
        }
        return grid;
    }

    
    //
    // overrides DiscretizedAsset
    //
    
    /**
     * This method should initialize the asset values to an {@link Array} of the
     * given size and with values depending on the particular asset.
     */
    @Override
    public void reset(final int size) {
            // Set to bond redemption values
            values_ = new Array(size).fill(this.arguments.redemption);

            // coupon amounts should be added when adjusting
            // values_ = Array(size, this.arguments.cashFlows.back()->amount());

            conversionProbability = new Array(size).fill(0.0);
            spreadAdjustedRate = new Array(size).fill(0.0);

            final DayCounter rfdc  = this.process.riskFreeRate().currentLink().dayCounter();

            // this takes care of convertibility and conversion probabilities
            adjustValues();

            final double creditSpread = this.arguments.creditSpread.currentLink().value();

            final Date exercise = this.arguments.exercise.lastDate();

            final double riskFreeRate =
                this.process.riskFreeRate().currentLink().zeroRate(exercise, rfdc,
                                                   Compounding.Continuous, Frequency.NoFrequency).rate();

            // Calculate blended discount rate to be used on roll back.
            for (int j=0; j= stoppingTimes.get(0))
                convertible = true;
            break;
          case European:
            if (isOnTime(stoppingTimes.get(0)))
                convertible = true;
            break;
          case Bermudan:
            for (int i=0; i 

Ads help maintain this website.