-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathutils.py
More file actions
178 lines (152 loc) · 7.1 KB
/
Copy pathutils.py
File metadata and controls
178 lines (152 loc) · 7.1 KB
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
from datetime import datetime
import json
from QuantLib import *
import numpy as Numpy
import boto3
import os
import csv
def clear_output_bucket():
botoSession = boto3.session.Session(region_name='us-east-1')
s3 = botoSession.resource('s3')
bucketname = os.environ['BUCKET_OUT']
bucket = s3.Bucket(bucketname)
objects = bucket.objects.all()
objects.delete()
def ql_to_pydate(d):
return datetime(d.year(), d.month(), d.dayOfMonth())
def str_to_pydate(s):
return datetime.strptime(s, '%m/%d/%Y')
def py_to_qldate(d):
return Date(d.day, d.month,d.year)
# Builds a QuantLib swap object from given specification
def makeSwap(today, start, maturity, nominal, fixedRate, index, typ=VanillaSwap.Payer):
calendar = UnitedStates()
fixedLegTenor = Period(6, ql.Months)
floatingLegBDC = ModifiedFollowing
fixedLegDC = Thirty360(ql.Thirty360.BondBasis)
spread = 0.0
settle_date = calendar.advance(start, 2, ql.Days)
end = calendar.advance(settle_date, maturity, floatingLegBDC)
fixedSchedule = ql.Schedule(settle_date,
end,
fixedLegTenor,
calendar,
ql.ModifiedFollowing, ql.ModifiedFollowing,
ql.DateGeneration.Forward, False)
floatSchedule = ql.Schedule(settle_date,
end,
index.tenor(),
index.fixingCalendar(),
index.businessDayConvention(),
index.businessDayConvention(),
ql.DateGeneration.Forward,
False)
swap = ql.VanillaSwap(typ,
nominal,
fixedSchedule,
fixedRate,
fixedLegDC,
floatSchedule,
index,
spread,
index.dayCounter())
#return swap, [index.fixingDate(x) for x in floatSchedule if index.fixingDate(x) >= today][:-1]
return swap
# class for hosting simulation grid (dates, times)
class Grid:
def __init__(self, startDate, endDate, tenor):
# create date schedule, ignore conventions and calendars
self.schedule = Schedule(startDate, endDate, tenor, NullCalendar(),
Unadjusted, Unadjusted, DateGeneration.Forward, False)
self.dayCounter = Actual365Fixed()
self.tenor = tenor
def GetDates(self):
# get list of scheduled dates
dates = []
[dates.append(self.schedule[i]) for i in range(self.GetSize())]
return dates
def GetTimes(self):
# get list of scheduled times
times = []
[times.append(self.dayCounter.yearFraction(self.schedule[0], self.schedule[i]))
for i in range(self.GetSize())]
return times
def GetMaturity(self):
# get maturity in time units
return self.dayCounter.yearFraction(self.schedule[0], self.schedule[self.GetSteps()])
def GetSteps(self):
# get number of steps in schedule
return self.GetSize() - 1
def GetSize(self):
# get total number of items in schedule
return len(self.schedule)
def GetTimeGrid(self):
# get QuantLib TimeGrid object, constructed by using list of scheduled times
return TimeGrid(self.GetTimes(), self.GetSize())
def GetDt(self):
# get constant time step
return self.GetMaturity() / self.GetSteps()
def GetTenor(self):
# get grid tenor
return self.tenor
# term A(t, T) for analytical Hull-White zero-coupon bond price
def A(curve, a, sigma, t, T):
f = curve.forwardRate(t, t, Continuous, NoFrequency).rate()
value = B(a, t, T) * f - 0.25 * sigma * B(a, t, T) * sigma * B(a, t, T) * B(a, 0.0, 2.0 * t);
return exp(value) * curve.discount(T) / curve.discount(t);
# term B(t, T) for analytical Hull-White zero-coupon bond price
def B(a, t, T):
return (1.0 - exp(-a * (T - t))) / a;
# class for hosting calibration helpers and calibration procedure for a given model
class ModelCalibrator:
def __init__(self, endCriteria):
self.endCriteria = endCriteria
self.helpers = []
def AddCalibrationHelper(self, helper):
self.helpers.append(helper)
def Calibrate(self, model, engine, curve, fixedParameters):
# assign pricing engine to all calibration helpers
for i in range(len(self.helpers)):
self.helpers[i].setPricingEngine(engine)
method = LevenbergMarquardt()
if (len(fixedParameters) == 0):
model.calibrate(self.helpers, method, self.endCriteria)
else:
model.calibrate(self.helpers, method, self.endCriteria,
NoConstraint(), [], fixedParameters)
# load discount curve from S3
def load_discount_curve():
s3 = boto3.client('s3')
bucket = os.environ['BUCKET_IN']
disc_curve_file = os.environ['DISC_CURVE_FILE']
csvfile = s3.get_object(Bucket=bucket, Key=disc_curve_file)
lines = csvfile['Body'].read().decode('utf-8').split()
csv_data = {}
for row in csv.DictReader(lines):
csv_data[row['date']] = row['discount_factor']
termStructureDates = [py_to_qldate(str_to_pydate(x)) for x in csv_data.keys()]
termStructureDiscountFactors = [float(x) for x in csv_data.values()]
# create yield term structure from a given set of discount factors
yieldTermStructure = DiscountCurve(termStructureDates, termStructureDiscountFactors, Actual360(), TARGET())
yieldTermStructure.enableExtrapolation()
return yieldTermStructure
# load simulated fixings
def load_simulated_fixings():
s3 = boto3.client('s3')
bucket = os.environ['BUCKET_OUT']
sim_fixings_file = os.environ['SIMULATED_FIXINGS_FILE']
csvfile = s3.get_object(Bucket=bucket, Key=sim_fixings_file)
lines = csvfile['Body'].read().decode('utf-8').split()
fixingsLookupTable = {}
for row in csv.DictReader(lines):
fixingsLookupTable[py_to_qldate(str_to_pydate(row['date']))] = float(row['fixing'])
return fixingsLookupTable
def CreateSwapTransaction(index):
# create benchmarking IR receiver swap, PV(t = 0) = 0.0
fixedSchedule = Schedule(Date(14, December, 2018), Date(14, December, 2023), Period(1, Years), TARGET(), \
ModifiedFollowing, ModifiedFollowing, DateGeneration.Backward, False)
floatingSchedule = Schedule(Date(14, December, 2018), Date(14, December, 2023), Period(3, Months), TARGET(), \
ModifiedFollowing, ModifiedFollowing, DateGeneration.Backward, False)
swap = VanillaSwap(VanillaSwap.Receiver, 10000000.0, fixedSchedule, 0.03, Actual365Fixed(), \
floatingSchedule, index, 0.001277206920730623, Actual360())
return swap