-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHJM_Swaption_Blocking.cpp
145 lines (120 loc) · 5.21 KB
/
HJM_Swaption_Blocking.cpp
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
//HJM_Swaption_Blocking.cpp
//Routines to compute various security prices using HJM framework (via Simulation).
//Authors: Mark Broadie, Jatin Dewanwala
//Collaborator: Mikhail Smelyanskiy, Intel, Jike Chong (Berkeley)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "nr_routines.h"
#include "HJM_Securities.h"
#include "HJM.h"
#include "HJM_type.h"
int HJM_Swaption_Blocking(FTYPE *pdSwaptionPrice, //Output vector that will store simulation results in the form:
//Swaption Price
//Swaption Standard Error
//Swaption Parameters
FTYPE dStrike,
FTYPE dCompounding, //Compounding convention used for quoting the strike (0 => continuous,
//0.5 => semi-annual, 1 => annual).
FTYPE dMaturity, //Maturity of the swaption (time to expiration)
FTYPE dTenor, //Tenor of the swap
FTYPE dPaymentInterval, //frequency of swap payments e.g. dPaymentInterval = 0.5 implies a swap payment every half
//year
//HJM Framework Parameters (please refer HJM.cpp for explanation of variables and functions)
int iN,
int iFactors,
FTYPE dYears,
FTYPE *pdYield,
FTYPE *ppdFactors,
//Simulation Parameters
long iRndSeed,
long lTrials,
int BLOCKSIZE, int tid,
FTYPE *ppdHJMPath, FTYPE *pdForward, FTYPE *ppdDrifts, FTYPE *pdTotalDrift,
FTYPE *pdDiscountingRatePath, FTYPE *pdPayoffDiscountFactors, FTYPE *pdSwapRatePath, FTYPE *pdSwapDiscountFactors, FTYPE *pdSwapPayoffs,
FTYPE *pdZ, FTYPE *randZ,
FTYPE *pdexpRes)
{
int iSuccess = 0;
int i;
int b; //block looping variable
long l; //looping variables
FTYPE ddelt = (FTYPE)(dYears/iN);
int iFreqRatio = (int)(dPaymentInterval/ddelt + 0.5);
FTYPE dStrikeCont;
dStrikeCont = dCompounding == 0 ? dStrike: (1 / dCompounding) * log(1 + dStrike * dCompounding);
int iSwapVectorLength = (int)(iN - dMaturity / ddelt + 0.5);
int iSwapStartTimeIndex;
int iSwapTimePoints;
FTYPE dSwapVectorYears;
FTYPE dSwaptionPayoff;
FTYPE dDiscSwaptionPayoff;
FTYPE dFixedLegValue;
// Accumulators
FTYPE dSumSimSwaptionPrice;
FTYPE dSumSquareSimSwaptionPrice;
// Final returned results
FTYPE dSimSwaptionMeanPrice;
FTYPE dSimSwaptionStdError;
iSwapStartTimeIndex = (int)(dMaturity/ddelt + 0.5); //Swap starts at swaption maturity
iSwapTimePoints = (int)(dTenor/ddelt + 0.5); //Total HJM time points corresponding to the swap's tenor
dSwapVectorYears = (FTYPE)(iSwapVectorLength*ddelt);
for (i = 0; i < iSwapVectorLength; i++) pdSwapPayoffs[i] = 0.0;
for (i = iFreqRatio; i <= iSwapTimePoints; i += iFreqRatio) {
if(i != iSwapTimePoints)
pdSwapPayoffs[i] = exp(dStrikeCont * dPaymentInterval) - 1;
else
pdSwapPayoffs[i] = exp(dStrikeCont * dPaymentInterval);
}
//generating forward curve at t=0 from supplied yield curve
iSuccess = HJM_Yield_to_Forward(pdForward, iN, pdYield);
if(iSuccess != 1) return iSuccess;
//computation of drifts from factor volatilities
iSuccess = HJM_Drifts(pdTotalDrift, ppdDrifts, iN, iFactors, dYears, ppdFactors);
if(iSuccess != 1) return iSuccess;
dSumSimSwaptionPrice = 0.0;
dSumSquareSimSwaptionPrice = 0.0;
//Simulations begin:
for(l = 0; l < lTrials; l += BLOCKSIZE) {
//For each trial a new HJM Path is generated
/* GC: 51% of the time goes here */
iSuccess = HJM_SimPath_Forward_Blocking(ppdHJMPath, iN, iFactors, dYears, pdForward, pdTotalDrift, ppdFactors, &iRndSeed, BLOCKSIZE, pdZ, randZ);
if(iSuccess != 1) return iSuccess;
//now we compute the discount factor vector
for(i = 0; i < iN; i++){
for(b = 0; b < BLOCKSIZE; b++){
pdDiscountingRatePath[BLOCKSIZE*i + b] = ppdHJMPath[i * iN * BLOCKSIZE + b];
}
}
/* 15% of the time goes here */
iSuccess = Discount_Factors_Blocking(pdPayoffDiscountFactors, iN, dYears, pdDiscountingRatePath, BLOCKSIZE, pdexpRes);
if(iSuccess != 1) return iSuccess;
//now we compute discount factors along the swap path
for(i = 0; i < iSwapVectorLength; i++){
for(b = 0; b < BLOCKSIZE; b++){
pdSwapRatePath[i * BLOCKSIZE + b] = ppdHJMPath[iSwapStartTimeIndex * iN * BLOCKSIZE + i * BLOCKSIZE + b];
}
}
iSuccess = Discount_Factors_Blocking(pdSwapDiscountFactors, iSwapVectorLength, dSwapVectorYears, pdSwapRatePath, BLOCKSIZE, pdexpRes);
if(iSuccess != 1) return iSuccess;
// Simulation
for(b = 0; b < BLOCKSIZE; b++){
dFixedLegValue = 0.0;
for(i = 0; i < iSwapVectorLength; i++) dFixedLegValue += pdSwapPayoffs[i] * pdSwapDiscountFactors[i*BLOCKSIZE + b];
dSwaptionPayoff = dMax(dFixedLegValue - 1.0, 0);
dDiscSwaptionPayoff = dSwaptionPayoff * pdPayoffDiscountFactors[iSwapStartTimeIndex*BLOCKSIZE + b];
// end simulation
// accumulate into the aggregating variables
dSumSimSwaptionPrice += dDiscSwaptionPayoff;
dSumSquareSimSwaptionPrice += dDiscSwaptionPayoff*dDiscSwaptionPayoff;
}
}
// Simulation Results Stored
dSimSwaptionMeanPrice = dSumSimSwaptionPrice / lTrials;
dSimSwaptionStdError = sqrt((dSumSquareSimSwaptionPrice-dSumSimSwaptionPrice*dSumSimSwaptionPrice/lTrials)/
(lTrials-1.0))/sqrt((FTYPE)lTrials);
//results returned
pdSwaptionPrice[0] = dSimSwaptionMeanPrice;
pdSwaptionPrice[1] = dSimSwaptionStdError;
return 1;
}