forked from asavine/CompFinance
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ivs.h
179 lines (146 loc) · 4.58 KB
/
ivs.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/*
Written by Antoine Savine in 2018
This code is the strict IP of Antoine Savine
License to use and alter this code for personal and commercial applications
is freely granted to any person or company who purchased a copy of the book
Modern Computational Finance: AAD and Parallel Simulations
Antoine Savine
Wiley, 2018
As long as this comment is preserved at the top of the file
*/
#pragma once
#include "mcBase.h"
#include "matrix.h"
#include "analytics.h"
// Implied Volatility Surfaces and Risk Views,
// See chapter 13
// Risk view
template <class T>
class RiskView
{
bool myEmpty;
vector<double> myStrikes;
vector<Time> myMats;
matrix<T> mySpreads;
public:
// Default constructor, empty view
RiskView() : myEmpty(true) {}
// Intializes risk view AND put on tape
// Sets all spreads to 0
RiskView(const vector<double>& strikes, const vector<Time>& mats) :
myEmpty(false),
myStrikes(strikes),
myMats(mats),
mySpreads(strikes.size(), mats.size())
{
for (auto& spr : mySpreads) spr = T(0.0);
}
// Get spread
T spread(const double strike, const Time mat) const
{
return myEmpty
? T(0.0)
: interp2D<true>(myStrikes, myMats, mySpreads, strike, mat);
}
// Accessors by const ref
bool empty() const { return myEmpty; }
size_t rows() const { return myStrikes.size(); }
size_t cols() const { return myMats.size(); }
const vector<double>& strikes() const { return myStrikes; }
const vector<Time>& mats() const { return myMats; }
const matrix<T>& risks() const { return mySpreads; }
// Iterators
typedef typename matrix<T>::iterator iterator;
typedef typename matrix<T>::const_iterator const_iterator;
iterator begin() { return mySpreads.begin(); }
iterator end() { return mySpreads.end(); }
const_iterator begin() const { return mySpreads.begin(); }
const_iterator end() const { return mySpreads.end(); }
// For bump risk
void bump(const size_t i, const size_t j, const double bumpBy)
{
mySpreads[i][j] += bumpBy;
}
};
// Base IVS
class IVS
{
// To avoid reference to a linear market
double mySpot;
public:
IVS(const double spot) : mySpot(spot) {}
// Read access to spot
double spot() const
{
return mySpot;
}
// Raw implied vol
virtual double impliedVol(const double strike, const Time mat) const = 0;
// Call price
template<class T = double>
T call(
const double strike,
const Time mat,
const RiskView<T>* risk = nullptr) const
{
// blackScholes is defined in analytics.h, templated
return blackScholes<T>(
mySpot,
strike,
impliedVol(strike, mat)
+ (risk ? risk->spread(strike, mat) : T(0.0)),
mat);
}
// Local vol, dupire's formula
template<class T = double>
T localVol(
const double strike,
const double mat,
const RiskView<T>* risk = nullptr) const
{
// Derivative to time
const T c00 = call(strike, mat, risk);
const T c01 = call(strike, mat - 1.0e-04, risk);
const T c02 = call(strike, mat + 1.0e-04, risk);
const T ct = (c02 - c01) * 0.5e04;
// Second derivative to strike = density
const T c10 = call(strike - 1.0e-04, mat, risk);
const T c20 = call(strike + 1.0e-04, mat, risk);
const T ckk = (c10 + c20 - 2.0 * c00) * 1.0e08;
// Dupire's formula
return sqrt(2.0 * ct / ckk) / strike;
}
// Virtual destructor needed for polymorphic class
virtual ~IVS() {}
};
// Concrete IVS just override (raw) call prices
// Merton IVS
class MertonIVS : public IVS
{
double myVol;
double myIntensity, myAverageJmp, myJmpStd;
public:
MertonIVS(const double spot, const double vol,
const double intens, const double aveJmp, const double stdJmp)
: IVS(spot),
myVol(vol),
myIntensity(intens),
myAverageJmp(aveJmp),
myJmpStd(stdJmp)
{}
double impliedVol(const double strike, const Time mat) const override
{
// Merton's formula is defined in analytics.h
const double call
= merton(
spot(),
strike,
myVol,
mat,
myIntensity,
myAverageJmp,
myJmpStd);
// Implied volatility from price, also in analytics.h
return blackScholesIvol(spot(), strike, call, mat);
}
};