Coverage Report

Created: 2025-10-14 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/experimental/catbonds/catrisk.cpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2012, 2013 Grzegorz Andruszkiewicz
5
6
 This file is part of QuantLib, a free-software/open-source library
7
 for financial quantitative analysts and developers - http://quantlib.org/
8
9
 QuantLib is free software: you can redistribute it and/or modify it
10
 under the terms of the QuantLib license.  You should have received a
11
 copy of the license along with this program; if not, please email
12
 <quantlib-dev@lists.sf.net>. The license is also available online at
13
 <https://www.quantlib.org/license.shtml>.
14
15
 This program is distributed in the hope that it will be useful, but WITHOUT
16
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17
 FOR A PARTICULAR PURPOSE.  See the license for more details.
18
*/
19
20
#include <ql/experimental/catbonds/catrisk.hpp>
21
#include <ql/time/daycounters/actualactual.hpp>
22
#include <random>
23
#include <utility>
24
25
namespace QuantLib {
26
27
28
    EventSetSimulation::EventSetSimulation(
29
        ext::shared_ptr<std::vector<std::pair<Date, Real> > > events,
30
        Date eventsStart,
31
        Date eventsEnd,
32
        Date start,
33
        Date end)
34
0
    : CatSimulation(start, end), events_(std::move(events)), eventsStart_(eventsStart),
35
0
      eventsEnd_(eventsEnd) {
36
0
        years_ = end_.year()-start_.year();
37
0
        if(eventsStart_.month()<start_.month() 
38
0
                            || (eventsStart_.month()==start_.month() 
39
0
                                && eventsStart_.dayOfMonth()<=start_.dayOfMonth())) {
40
0
            periodStart_ = Date(start_.dayOfMonth(), start_.month(), eventsStart_.year());
41
0
        } else {
42
0
            periodStart_ = Date(start_.dayOfMonth(), start_.month(), eventsStart_.year()+1);
43
0
        }
44
0
        periodEnd_ = Date(end_.dayOfMonth(), end_.month(), periodStart_.year()+years_);
45
0
        while(i_<events_->size() && (*events_)[i_].first<periodStart_) ++i_; //i points to the first element after the start of the relevant period.
46
0
    }
47
48
0
    bool EventSetSimulation::nextPath(std::vector< std::pair< Date, Real > >& path) {
49
0
        path.resize(0);
50
0
        if(periodEnd_>eventsEnd_) //Ran out of event data 
51
0
            return false;
52
53
0
        while(i_<events_->size() && (*events_)[i_].first<periodStart_) {
54
0
            ++i_; //skip the elements between the previous period and this period
55
0
        }
56
0
        while(i_<events_->size()  && (*events_)[i_].first<=periodEnd_){
57
0
            std::pair<Date, Real> e(events_->at(i_).first+(start_.year() - periodStart_.year())*Years, events_->at(i_).second);
58
0
            path.push_back(e);
59
0
            ++i_; //i points to the first element after the start of the relevant period.
60
0
        }
61
0
        if(start_+years_*Years<end_) {
62
0
            periodStart_+=(years_+1)*Years;
63
0
            periodEnd_+=(years_+1)*Years;
64
0
        } else {
65
0
            periodStart_+=years_*Years;
66
0
            periodEnd_+=years_*Years;
67
0
        }
68
0
        return true;
69
0
    }
70
71
    EventSet::EventSet(ext::shared_ptr<std::vector<std::pair<Date, Real> > > events,
72
                       Date eventsStart,
73
                       Date eventsEnd)
74
0
    : events_(std::move(events)), eventsStart_(eventsStart), eventsEnd_(eventsEnd) {}
75
76
0
    ext::shared_ptr<CatSimulation> EventSet::newSimulation(const Date& start, const Date& end) const{
77
0
        return ext::make_shared<EventSetSimulation>(events_, eventsStart_, eventsEnd_, start, end);
78
0
    }
79
80
    BetaRiskSimulation::BetaRiskSimulation(Date start, Date end, Real maxLoss, Real lambda, Real alpha, Real beta) 
81
0
              : CatSimulation(start, end), 
82
0
                maxLoss_(maxLoss), 
83
0
                exponential_(lambda),
84
0
                gammaAlpha_(alpha),
85
0
                gammaBeta_(beta)
86
0
    {
87
0
        DayCounter dayCounter = ActualActual(ActualActual::ISDA);
88
0
        dayCount_ = dayCounter.dayCount(start, end);
89
0
        yearFraction_ = dayCounter.yearFraction(start, end);
90
0
    }
91
92
    Real BetaRiskSimulation::generateBeta()
93
0
    {
94
0
        Real X = gammaAlpha_(rng_);
95
0
        Real Y = gammaBeta_(rng_);
96
0
        return X*maxLoss_/(X+Y);
97
0
    }
98
99
    bool BetaRiskSimulation::nextPath(std::vector<std::pair<Date, Real> > &path)
100
0
    {        
101
0
        path.resize(0);
102
0
        Real eventFraction = exponential_(rng_);
103
0
        while(eventFraction<=yearFraction_)
104
0
        {
105
0
            auto days =
106
0
                static_cast<Integer>(std::lround(eventFraction * dayCount_ / yearFraction_));
107
0
            Date eventDate = start_ + days*Days;
108
0
            if(eventDate<=end_)
109
0
            {
110
0
                path.emplace_back(eventDate, generateBeta());
111
0
            }
112
0
            else break;
113
0
            eventFraction = exponential_(rng_);
114
0
        }
115
0
        return true;
116
0
    }
117
118
    BetaRisk::BetaRisk(Real maxLoss, 
119
                 Real years, 
120
                 Real mean, 
121
                 Real stdDev) 
122
0
    : maxLoss_(maxLoss), lambda_(1.0/years) {
123
0
        QL_REQUIRE(mean<maxLoss, "Mean "<<mean<<"of the loss distribution must be less than the maximum loss "<<maxLoss);
124
0
        Real normalizedMean = mean/maxLoss;
125
0
        Real normalizedVar = stdDev*stdDev/(maxLoss*maxLoss);
126
0
        QL_REQUIRE(normalizedVar<normalizedMean*(1.0-normalizedMean), "Standard deviation of "<<stdDev<<" is impossible to achieve in gamma distribution with mean "<<mean);
127
0
        Real nu = normalizedMean*(1.0-normalizedMean)/normalizedVar - 1.0;
128
0
        alpha_=normalizedMean*nu;
129
0
        beta_=(1.0-normalizedMean)*nu;
130
0
    }
131
132
0
    ext::shared_ptr<CatSimulation> BetaRisk::newSimulation(const Date& start, const Date& end) const {
133
0
        return ext::make_shared<BetaRiskSimulation>(start, end, maxLoss_, lambda_, alpha_, beta_);
134
0
    }
135
}