/*
 Copyright (C) 2009 Ueli Hofstetter
 Copyright (C) 2009 Srinivas Hasti

 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 Joseph Wang
 Copyright (C) 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.vanilla.finitedifferences;


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

import org.jquantlib.QL;
import org.jquantlib.cashflow.Event;
import org.jquantlib.instruments.OneAssetOption;
import org.jquantlib.instruments.Option;
import org.jquantlib.math.SampledCurve;
import org.jquantlib.math.matrixutilities.Array;
import org.jquantlib.methods.finitedifferences.NullCondition;
import org.jquantlib.methods.finitedifferences.StandardFiniteDifferenceModel;
import org.jquantlib.methods.finitedifferences.StepCondition;
import org.jquantlib.pricingengines.PricingEngine.Arguments;
import org.jquantlib.pricingengines.PricingEngine.Results;
import org.jquantlib.processes.GeneralizedBlackScholesProcess;

/**
 * Base engine for options with events happening at specific times
 *
 * @author Richard Gomes
 */
public abstract class FDMultiPeriodEngine extends FDVanillaEngine {


    //
    // protected fields
    //

    protected List events;
    protected List stoppingTimes;
    protected SampledCurve prices;
    protected StepCondition stepCondition;
    protected StandardFiniteDifferenceModel model;


    //
    // final protected fields
    //

    final private int timeStepPerPeriod;


    //
    // public constructors
    //

    public FDMultiPeriodEngine(final GeneralizedBlackScholesProcess process) {
        this(process, 100, 100, false);
    }

    public FDMultiPeriodEngine(final GeneralizedBlackScholesProcess process, final int gridPoints, final int timeSteps, final boolean timeDependent) {
        super(process, gridPoints, timeSteps, timeDependent);
        this.stoppingTimes = new ArrayList();
        this.timeStepPerPeriod = timeSteps;
    }


    //
    // public methods
    //

    public void setupArguments(final Arguments args, final List schedule) {
        super.setupArguments(args);
        events = schedule;
        stoppingTimes.clear();
        final int n = schedule.size();
        for (int i = 0; i();
    }


    //
    // overrides FDVanillaEngine
    //

    @Override
    protected void setupArguments(final Arguments a) {
        super.setupArguments(a);
        final OneAssetOption.ArgumentsImpl args = (OneAssetOption.ArgumentsImpl) a;
        events.clear();
        final int n = args.exercise.size();
        for (int i=0; i 0) {
            QL.require(getDividendTime(0) >= 0, "first date cannot be negative"); // TODO: message
            if (getDividendTime(0) < getResidualTime() * dateTolerance) {
                firstDateIsZero = true;
                firstIndex = 0;
                if (dateNumber >= 2) {
                    firstNonZeroDate = getDividendTime(1);
                }
            }
            if (Math.abs(getDividendTime(lastIndex) - getResidualTime()) < dateTolerance) {
                lastDateIsResTime = true;
                lastIndex = dateNumber - 2;
            }

            if (!firstDateIsZero) {
                firstNonZeroDate = getDividendTime(0);
            }

            if (dateNumber >= 2) {
                for (int j = 1; j < dateNumber; j++) {
                    QL.require(getDividendTime(j - 1) < getDividendTime(j) , "dates must be in strictly increasing order"); // TODO: message
                }
            }
        }

        double dt = getResidualTime() / (timeStepPerPeriod*(dateNumber+1));

        // Ensure that dt is always smaller than the first non-zero date
        if (firstNonZeroDate <= dt) {
            dt = firstNonZeroDate / 2.0;
        }

        setGridLimits();
        initializeInitialCondition();
        initializeOperator();
        initializeBoundaryConditions();
        initializeModel();
        initializeStepCondition();

        prices = intrinsicValues.clone();
        if (lastDateIsResTime) {
            executeIntermediateStep(dateNumber - 1);
        }

        int j = lastIndex;
        do {
            if (j == (dateNumber - 1)) {
                beginDate = getResidualTime();
            } else {
                beginDate = getDividendTime(j + 1);
            }

            if (j >= 0) {
                endDate = getDividendTime(j);
            } else {
                endDate = dt;
            }

            prices.setValues(model.rollback(prices.values(), beginDate, endDate, timeStepPerPeriod, stepCondition));

            if (j >= 0) {
                executeIntermediateStep(j);
            }
        } while (--j >= firstIndex);

        prices.setValues(model.rollback(prices.values(), dt, 0, 1, stepCondition));

        if (firstDateIsZero) {
            executeIntermediateStep(0);
        }

        r.value = prices.valueAtCenter();
        greeks.delta = prices.firstDerivativeAtCenter();
        greeks.gamma = prices.secondDerivativeAtCenter();
        r.additionalResults().put("priceCurve", prices);
    }

}

 

Ads help maintain this website.