=begin
 Copyright (C) 2000, 2001, 2002 RiskMap 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 ferdinando@ametrano.net
 The license is also available online at http://quantlib.org/html/license.html

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

# $Id: piecewise_flat_forward.rb,v 1.5 2002/03/12 11:12:30 lballabio Exp $

require 'QuantLib'
require 'date'
require 'runit/testcase'
require 'runit/testsuite'
require 'runit/cui/testrunner'

def today
    QuantLib::Date.new(Date.today.day,
                       Date.today.month,
                       Date.today.year)
end

def quote(value)
    h = QuantLib::MarketElementHandle.new
    h.linkTo QuantLib::SimpleMarketElement.new(value)
    return h
end

class PiecewiseFlatForwardTest < RUNIT::TestCase
    include QuantLib
    def name
        "Testing piecewise flat forward curve..."
    end
    def test
        euriborHandle = TermStructureHandle.new
        calendar = Calendar.new('TARGET')
        settlementDays = 2
        indexFixingDays = 2

        # deposits

        depositNs    = [     1,      1,       2,       3,       6,       9]
        depositUnits = ['week','month','months','months','months','months']
        depositRates = [ 4.559,  4.581,   4.573,   4.557,   4.496,   4.490]
        rollingConvention = 'ModifiedFollowing'
        dayCounter = DayCounter.new('Act/360')

        deposits = (0...depositNs.length).map { |i|
            DepositRateHelper.new(
                quote(depositRates[i]/100),
                settlementDays,depositNs[i],depositUnits[i],
                calendar, rollingConvention, dayCounter)
        }

        # swaps
        swapYears = [    1,    2,    3,    4,    5,    6,    7,    8,    9,   10,
                        12,   15,   20,   25,   30]
        swapRates = [ 4.54, 4.63, 4.75, 4.86, 4.99, 5.11, 5.23, 5.33, 5.41, 5.47,
                      5.60, 5.75, 5.89, 5.95, 5.96]
        swapRollingConvention = 'modifiedFollowing'
        fixedFrequency = 1
        fixedIsAdjusted = false
        fixedDayCount = DayCounter.new('30/360')
        floatingFrequency = 2

        swaps = (0...swapYears.length).map { |i|
            SwapRateHelper.new(
                quote(swapRates[i]/100),
                settlementDays, swapYears[i], calendar,
                swapRollingConvention, fixedFrequency, fixedIsAdjusted,
                fixedDayCount, floatingFrequency)
        }

        instruments = deposits + swaps

        termStructure = PiecewiseFlatForward.new('EUR',DayCounter.new('Act/360'),
                                                 today,calendar,settlementDays,
                                                 instruments)
        settlement = termStructure.settlementDate

        euriborHandle.linkTo(termStructure)

        # check deposits
        (0...depositRates.length).each { |i|
            index = Euribor.new(depositNs[i], depositUnits[i], euriborHandle)
            estimatedRate = index.fixing(settlement)

            unless (estimatedRate - depositRates[i]/100).abs <= 1.0e-9
                assert_fail(<<-MESSAGE

    #{depositNs[i]} #{depositUnits[i]} deposit:
        estimated rate: #{estimatedRate}
        input rate:     #{depositRates[i]/100}

                    MESSAGE
                )
            end
        }

        # check swaps
        index = Euribor.new(12/floatingFrequency,'Months',euriborHandle)
        (0...swapRates.length).each { |i|
            swap = SimpleSwap.new(true,settlement,swapYears[i],'years',
                calendar,swapRollingConvention,100.0,
                fixedFrequency,0.0,fixedIsAdjusted,
                fixedDayCount,floatingFrequency,index,
                indexFixingDays,0.0,euriborHandle)
            estimatedRate = -swap.NPV/swap.fixedLegBPS

            unless (estimatedRate - swapRates[i]/100).abs <= 1.0e-9
                assert_fail(<<-MESSAGE

    #{swapYears[i]} years swap:
        estimated rate: #{estimatedRate}
        input rate:     #{swapRates[i]/100}

                    MESSAGE
                )
            end
        }
    end
end

if $0 == __FILE__
    RUNIT::CUI::TestRunner.run(PiecewiseFlatForwardTest.suite)
end

