/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright (C) 2005, 2006 Klaus Spanderen 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. */ #include #include #include #include #include #include #include namespace QuantLib { LiborForwardModelProcess::LiborForwardModelProcess( Size size, const boost::shared_ptr& index) : StochasticProcess(boost::shared_ptr( new EulerDiscretization)), size_ (size), index_ (index), initialValues_ (size_), fixingTimes_ (size_), fixingDates_ (size_), accrualStartTimes_(size), accrualEndTimes_ (size), accrualPeriod_ (size_), m1(size_), m2(size_) { const DayCounter dayCounter = index_->dayCounter(); const Leg flows = cashFlows(); QL_REQUIRE(size_ == flows.size(), "wrong number of cashflows"); const Date settlement = index_->termStructure()->referenceDate(); const Date startDate = boost::dynamic_pointer_cast( flows[0])->fixingDate(); for (Size i = 0; i < size_; ++i) { const boost::shared_ptr coupon = boost::dynamic_pointer_cast(flows[i]); QL_REQUIRE(coupon->date() == coupon->accrualEndDate(), "irregular coupon types are not suppported"); initialValues_[i] = coupon->rate(); accrualPeriod_[i] = coupon->accrualPeriod(); fixingDates_[i] = coupon->fixingDate(); fixingTimes_[i] = dayCounter.yearFraction(startDate, coupon->fixingDate()); accrualStartTimes_[i] = dayCounter.yearFraction(settlement,coupon->accrualStartDate()); accrualEndTimes_[i] = dayCounter.yearFraction(settlement,coupon->accrualEndDate()); } } Disposable LiborForwardModelProcess::drift(Time t, const Array& x) const { Array f(size_, 0.0); Matrix covariance(lfmParam_->covariance(t, x)); const Size m = nextIndexReset(t); for (Size k=m; k LiborForwardModelProcess::diffusion(Time t, const Array& x) const { return lfmParam_->diffusion(t, x); } Disposable LiborForwardModelProcess::covariance( Time t, const Array& x, Time dt) const { return lfmParam_->covariance(t, x)*dt; } Disposable LiborForwardModelProcess::apply( const Array& x0, const Array& dx) const { Array tmp(size_); for (Size k=0; k LiborForwardModelProcess::evolve( Time t0, const Array& x0, Time dt, const Array& dw) const { /* predictor-corrector step to reduce discretization errors. Short - but slow - solution would be Array rnd_0 = stdDeviation(t0, x0, dt)*dw; Array drift_0 = discretization_->drift(*this, t0, x0, dt); return apply(x0, ( drift_0 + discretization_ ->drift(*this,t0,apply(x0, drift_0 + rnd_0),dt) )*0.5 + rnd_0); The following implementation does the same but is faster. */ const Size m = nextIndexReset(t0); const Real sdt = std::sqrt(dt); Array f(x0); Matrix diff = lfmParam_->diffusion(t0, x0); Matrix covariance = lfmParam_->covariance(t0, x0); for (Size k=m; k LiborForwardModelProcess::initialValues() const { Array tmp = initialValues_; return tmp; } void LiborForwardModelProcess::setCovarParam( const boost::shared_ptr & param) { lfmParam_ = param; } boost::shared_ptr LiborForwardModelProcess::covarParam() const { return lfmParam_; } boost::shared_ptr LiborForwardModelProcess::index() const { return index_; } Leg LiborForwardModelProcess::cashFlows(Real amount) const { const Date refDate = index_->termStructure()->referenceDate(); Leg floatingLeg = IborLeg( std::vector(1, amount), Schedule(refDate, refDate + Period(index_->tenor().length()*size_, index_->tenor().units()), index_->tenor(), index_->fixingCalendar(), index_->businessDayConvention(), index_->businessDayConvention(), false, false), index_, index_->dayCounter(), index_->businessDayConvention(), index_->fixingDays()); boost::shared_ptr fictitiousPricer(new BlackIborCouponPricer(Handle())); setCouponPricer(floatingLeg,fictitiousPricer); return floatingLeg; } Size LiborForwardModelProcess::size() const { return size_; } Size LiborForwardModelProcess::factors() const { return lfmParam_->factors(); } const std::vector