Skip to content

Commit e87e05e

Browse files
authored
Update sabr.cpp
1 parent 0794505 commit e87e05e

File tree

1 file changed

+41
-4
lines changed

1 file changed

+41
-4
lines changed

SABRModel/sabr.cpp

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ namespace plt = matplotlibcpp;
1414

1515
using namespace boost::property_tree;
1616

17+
// Financial Modeling Prep API address
1718
std::string fmp_address(std::string ticker){
1819
std::string url = "https://financialmodelingprep.com";
1920
std::string key = "";
@@ -56,8 +57,11 @@ std::string Request(const std::string& url) {
5657
return readBuffer;
5758
}
5859

60+
// Pulls stock data on an inputted ticker
5961
std::vector<double> PullStockData(std::string ticker){
6062
std::vector<double> close;
63+
64+
// Fetches stock price data and parses it as JSON using Boost
6165
std::string response = Request(fmp_address(ticker));
6266
std::stringstream ss(response);
6367
ptree dataset;
@@ -67,29 +71,36 @@ std::vector<double> PullStockData(std::string ticker){
6771
for(ptree::const_iterator jt = it->second.begin(); jt != it->second.end(); ++jt){
6872
for(ptree::const_iterator kt = jt->second.begin(); kt != jt->second.end(); ++kt){
6973
if(kt->first == "adjClose"){
74+
// Pulls adjusted close data into a single vector
7075
close.push_back(kt->second.get_value<double>());
7176
}
7277
}
7378
}
7479
}
7580
}
81+
// Get the oldest price first and newest price last
7682
std::reverse(close.begin(), close.end());
7783
return close;
7884
}
7985

86+
// Fetches latest stock price
8087
double stockPrice(std::vector<double> close){
8188
return close[close.size() - 1];
8289
}
8390

91+
// Generates parameters for SABR model with inuptted close prices
8492
std::map<std::string, double> Parameters(std::vector<double> close){
93+
94+
// Computes the average value of a given vector
8595
auto mean = [](std::vector<double> x){
8696
double average = 0;
8797
for(auto & i : x){
8898
average += i;
8999
}
90100
return average / (double) x.size();
91101
};
92-
102+
103+
// Computes the standard deviation of a given vector
93104
auto stdev = [&](std::vector<double> x){
94105
double mu = mean(x);
95106
double volatility = 0;
@@ -98,49 +109,62 @@ std::map<std::string, double> Parameters(std::vector<double> close){
98109
}
99110
return pow(volatility / ((double) x.size() - 1), 0.5);
100111
};
112+
113+
// Calculates the rate of returns
101114
std::map<std::string, double> result;
102115
std::vector<double> ror;
103116
for(int i = 1; i < close.size(); ++i){
104117
ror.push_back(close[i]/close[i-1] - 1.0);
105118
}
119+
120+
// Calculates the volatilty of the entire returns vector
106121
double ivol = stdev(ror);
122+
123+
// Calculates the rolling volatility of the returns
107124
double window = 100;
108125
std::vector<double> store_vol;
109126
for(int i = window; i < ror.size(); ++i){
110127
std::vector<double> hold = {ror.begin()+i-window, ror.begin()+i};
111128
store_vol.push_back(stdev(hold));
112129
}
130+
131+
// Computes the volatility of the volatility
113132
double vvol = stdev(store_vol);
114133
result["iv"] = ivol;
115134
result["sv"] = vvol;
116135
return result;
117136
}
118137

138+
// Generates 3D grid based on the Strike Price, Forward Price, and Time till Expiration
119139
std::map<std::string, std::vector<std::vector<double>>> GRID(std::vector<double> x, std::vector<double> y, std::vector<double> T){
120140
std::map<std::string, std::vector<std::vector<double>>> result;
121141
for(int i = 0; i < x.size(); ++i){
122142
std::vector<double> tempx;
123143
std::vector<double> tempy;
124144
std::vector<double> tempz;
125145
for(int j = 0; j < y.size(); ++j){
146+
// Build row grid
126147
tempx.push_back(x[i]);
127148
tempy.push_back(y[j]);
128149
tempz.push_back(T[j]);
129150
}
151+
// Build matrix
130152
result["Strikes"].push_back(tempx);
131153
result["Forward"].push_back(tempy);
132154
result["Expiry"].push_back(tempz);
133155
}
134156
return result;
135157
}
136158

159+
// Calculates the implied volatility at each point
137160
double ImpliedVol(double iv, double vvol, double rho, double Ft, double K, double beta){
138161
double z = (vvol/iv)*pow(Ft*K, (1 - beta)/2.0)*log(Ft/K);
139162
double xz = log((pow(1 - 2.0*rho*z + pow(z, 2), 0.5) + z - rho)/(1 - rho));
140163
double adj = (pow(1 - beta, 2)/24.0)*(pow(iv, 2)/pow(Ft*K, 1-beta))+(rho*beta*iv*vvol)/(4.0*pow(Ft*K, (1-beta)/2.0))+(pow(vvol, 2)*(2 - 3*pow(rho, 2)))/24.0;
141164
return (iv/pow(Ft*K, (1 - beta)/2.0))*(z/xz)*(1+adj);
142165
}
143166

167+
// Computes the implied volatility surface based on the strike prices and forward prices and the beta (the beta defines curvature or linear)
144168
std::vector<std::vector<double>> VolSurface(std::map<std::string, std::vector<std::vector<double>>> xy, double iv, double vvol, double rho, double beta){
145169
std::vector<std::vector<double>> vs;
146170
std::vector<double> ts;
@@ -154,6 +178,7 @@ std::vector<std::vector<double>> VolSurface(std::map<std::string, std::vector<st
154178
return vs;
155179
}
156180

181+
// Generaes a line of points between a and b for n size
157182
std::vector<double> linspace(double a, double b, int n){
158183
std::vector<double> result;
159184
double dx = (b - a)/(n - 1);
@@ -165,35 +190,44 @@ std::vector<double> linspace(double a, double b, int n){
165190

166191
int main()
167192
{
193+
// Declare stocks and 3D plots
168194
std::vector<std::string> tickers = {"MSFT","AAPL","AMZN","IBM","NVDA","GOOGL"};
169195
std::vector<PyObject*> bx;
170196
for(auto & num : {231, 232, 233, 234, 235, 236}){
171197
bx.push_back(plt::chart(num));
172198
}
173199

200+
// Define rho and risk-free rate
174201
double rho = -0.9;
175202
double r = 0.044;
176203

177204
for(int k = 0; k < tickers.size(); ++k){
178205
std::string ticker = tickers[k];
179206
PyObject * ax = bx[k];
207+
208+
// Fetch stock price data and grab latest stock price
180209
std::vector<double> close = PullStockData(ticker);
181210
double S = stockPrice(close);
182211

212+
// Generate parameters
183213
std::map<std::string, double> VOL = Parameters(close);
184214

215+
// Calculate the forward prices off of time in the range of 7 days to 2 years
185216
std::vector<double> T = linspace(7/365.0, 2.0, 100);
186217
std::vector<double> Fr;
187218
for(int t = 0; t < T.size(); ++t){
188219
Fr.push_back(S*exp(r*T[t]));
189220
}
190-
221+
222+
// Set a range for strike prices
191223
std::vector<double> K = linspace(0.5*S, 1.5*S, 100);
192-
224+
225+
// Set a beta and return the Implied Volatility Surface stored in ZVol
193226
double beta = 0.3;
194227
std::map<std::string, std::vector<std::vector<double>>> grid = GRID(K, Fr, T);
195228
std::vector<std::vector<double>> ZVol = VolSurface(grid, VOL["iv"], VOL["sv"], rho, beta);
196229

230+
// Plot the Volatility surface for each stock in their respective 3D chart
197231
plt::PlotTitle(ax, ticker);
198232
plt::surface3DMap(ax, grid["Strikes"], grid["Expiry"], ZVol, "jet", 0.8);
199233
plt::Chart3DAxesNames(ax, "Strike Price", "Expiry", "Implied Volatility");
@@ -205,6 +239,9 @@ int main()
205239
}
206240

207241
/* PART ONE
242+
243+
This is the animated version where the beta is changed and the vol surface reacts to the change
244+
208245
int main()
209246
{
210247
std::string ticker = "MSFT";
@@ -238,4 +275,4 @@ int main()
238275
239276
return 0;
240277
}
241-
*/
278+
*/

0 commit comments

Comments
 (0)