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 <http://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
25namespace 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 : CatSimulation(start, end), events_(std::move(events)), eventsStart_(eventsStart),
35 eventsEnd_(eventsEnd) {
36 years_ = end_.year()-start_.year();
37 if(eventsStart_.month()<start_.month()
38 || (eventsStart_.month()==start_.month()
39 && eventsStart_.dayOfMonth()<=start_.dayOfMonth())) {
40 periodStart_ = Date(start_.dayOfMonth(), start_.month(), eventsStart_.year());
41 } else {
42 periodStart_ = Date(start_.dayOfMonth(), start_.month(), eventsStart_.year()+1);
43 }
44 periodEnd_ = Date(end_.dayOfMonth(), end_.month(), periodStart_.year()+years_);
45 while(i_<events_->size() && (*events_)[i_].first<periodStart_) ++i_; //i points to the first element after the start of the relevant period.
46 }
47
48 bool EventSetSimulation::nextPath(std::vector< std::pair< Date, Real > >& path) {
49 path.resize(new_size: 0);
50 if(periodEnd_>eventsEnd_) //Ran out of event data
51 return false;
52
53 while(i_<events_->size() && (*events_)[i_].first<periodStart_) {
54 ++i_; //skip the elements between the previous period and this period
55 }
56 while(i_<events_->size() && (*events_)[i_].first<=periodEnd_){
57 std::pair<Date, Real> e(events_->at(n: i_).first+(start_.year() - periodStart_.year())*Years, events_->at(n: i_).second);
58 path.push_back(x: e);
59 ++i_; //i points to the first element after the start of the relevant period.
60 }
61 if(start_+years_*Years<end_) {
62 periodStart_+=(years_+1)*Years;
63 periodEnd_+=(years_+1)*Years;
64 } else {
65 periodStart_+=years_*Years;
66 periodEnd_+=years_*Years;
67 }
68 return true;
69 }
70
71 EventSet::EventSet(ext::shared_ptr<std::vector<std::pair<Date, Real> > > events,
72 Date eventsStart,
73 Date eventsEnd)
74 : events_(std::move(events)), eventsStart_(eventsStart), eventsEnd_(eventsEnd) {}
75
76 ext::shared_ptr<CatSimulation> EventSet::newSimulation(const Date& start, const Date& end) const{
77 return ext::make_shared<EventSetSimulation>(args: events_, args: eventsStart_, args: eventsEnd_, args: start, args: end);
78 }
79
80 BetaRiskSimulation::BetaRiskSimulation(Date start, Date end, Real maxLoss, Real lambda, Real alpha, Real beta)
81 : CatSimulation(start, end),
82 maxLoss_(maxLoss),
83 exponential_(lambda),
84 gammaAlpha_(alpha),
85 gammaBeta_(beta)
86 {
87 DayCounter dayCounter = ActualActual(ActualActual::ISDA);
88 dayCount_ = dayCounter.dayCount(d1: start, d2: end);
89 yearFraction_ = dayCounter.yearFraction(d1: start, d2: end);
90 }
91
92 Real BetaRiskSimulation::generateBeta()
93 {
94 Real X = gammaAlpha_(rng_);
95 Real Y = gammaBeta_(rng_);
96 return X*maxLoss_/(X+Y);
97 }
98
99 bool BetaRiskSimulation::nextPath(std::vector<std::pair<Date, Real> > &path)
100 {
101 path.resize(new_size: 0);
102 Real eventFraction = exponential_(rng_);
103 while(eventFraction<=yearFraction_)
104 {
105 auto days =
106 static_cast<Integer>(std::lround(x: eventFraction * dayCount_ / yearFraction_));
107 Date eventDate = start_ + days*Days;
108 if(eventDate<=end_)
109 {
110 path.emplace_back(args&: eventDate, args: generateBeta());
111 }
112 else break;
113 eventFraction = exponential_(rng_);
114 }
115 return true;
116 }
117
118 BetaRisk::BetaRisk(Real maxLoss,
119 Real years,
120 Real mean,
121 Real stdDev)
122 : maxLoss_(maxLoss), lambda_(1.0/years) {
123 QL_REQUIRE(mean<maxLoss, "Mean "<<mean<<"of the loss distribution must be less than the maximum loss "<<maxLoss);
124 Real normalizedMean = mean/maxLoss;
125 Real normalizedVar = stdDev*stdDev/(maxLoss*maxLoss);
126 QL_REQUIRE(normalizedVar<normalizedMean*(1.0-normalizedMean), "Standard deviation of "<<stdDev<<" is impossible to achieve in gamma distribution with mean "<<mean);
127 Real nu = normalizedMean*(1.0-normalizedMean)/normalizedVar - 1.0;
128 alpha_=normalizedMean*nu;
129 beta_=(1.0-normalizedMean)*nu;
130 }
131
132 ext::shared_ptr<CatSimulation> BetaRisk::newSimulation(const Date& start, const Date& end) const {
133 return ext::make_shared<BetaRiskSimulation>(args: start, args: end, args: maxLoss_, args: lambda_, args: alpha_, args: beta_);
134 }
135}
136

source code of quantlib/ql/experimental/catbonds/catrisk.cpp