https://www.python.org/ftp/python/2.7.13/python-2.7.13.msi
2. Download required python packages and dependencies from
http://www.lfd.uci.edu/~gohlke/pythonlibs/#quantlib
QuantLib_Python‑1.9‑cp27‑cp27m‑win32.whl
Dependencies for matplotlib and others (win32)
six‑1.10.0‑py2.py3‑none‑any.whl
pyparsing‑2.2.0‑py2.py3‑none‑any.whl
packaging‑16.8‑py2.py3‑none‑any.whl
appdirs-1.4.3-py2.py3-none-any.whl
python_dateutil‑2.6.0‑py2.py3‑none‑any.whl
pytz‑2016.10‑py2.py3‑none‑any.whl
cycler‑0.10.0‑py2.py3‑none‑any.whl
setuptools‑34.3.3‑py2.py3‑none‑any.whl
numpy‑1.11.3+mkl‑cp27‑cp27m‑win32.whl
matplotlib‑1.5.3‑cp27‑cp27m‑win32.whl
xlrd-1.0.0-py2.py3-none-any.whl
pandas-0.19.2-cp27-cp27m-win32.whl
scipy‑0.19.0‑cp27‑cp27m‑win32.whl
3. Copy the above Installers and Packages to destination machine for offline installation
4. Install Python 2.7 and add Environment Variable PATH
SET PATH=C:\Python27;C:\Python27\Scripts;%PATH%
To be persistence, use sysdm.cpl to edit Advanced -> Environment Variables -> Path
or use py -2 to run python script under Windows OS without setting PATH
py -2 chap06.py
5. Install each and every the python packages above using pip
For example
pip install QuantLib_Python‑1.9‑cp27‑cp27m‑win32.whl
or if have python2 and python3 co-exist
py -2 -m pip install QuantLib_Python‑1.9‑cp27‑cp27m‑win32.whl
6. Microsoft Visual Studio not required
and no need to build your own QuantLib-Python library
However, a code editor like Microsoft VS Code is recommended.
https://code.visualstudio.com/download
(requirement : .NET Framework 4.5.2 for Windows 7)
Offline VS code extension for python can be downloaded from
https://donjayamanne.gallery.vsassets.io/_apis/public/gallery/publisher/donjayamanne/extension/python/0.6.0/assetbyname/Microsoft.VisualStudio.Services.VSIXPackage
see stack overflow discussion here http://stackoverflow.com/questions/37071388/how-to-install-vscode-extensions-offline
or NotePad ++
https://notepad-plus-plus.org/download/
7. Test
The code is borrowed from QuantLib Python Cookbook chapter 06 (requires QuantLib-Python, matplotlib)
- chap06.py Select all
#! python2
#!/usr/bin/env python
# pylint: disable-msg=C0103
# Interest-rate Curves
# Chapter 6 EONIA curve bootstrapping
# Everything You Always Wanted to Know About Multiple Interest Rate Curve Bootstrapping but Were Afraid to Ask
# In[1]
import math
# In[2]
from QuantLib import *
print ("\nOut[1]:")
print ("QuantLib version", QuantLib.__version__)
# In[3]
# setup evaluationDate
today = Date(11, December,2012)
Settings.instance().evaluationDate = today
# In[4]
# setup DepositRateHelper for 0-2 days
helpers = [ DepositRateHelper(QuoteHandle(SimpleQuote(rate/100)),
Period(1,Days), fixingDays,
TARGET(), Following, False, Actual360())
for rate, fixingDays in [(0.04, 0), (0.04, 1), (0.04, 2)] ]
# DepositRateHelper (const Handle< Quote > &rate,
# const Period &tenor,
# Natural fixingDays,
# const Calendar &calendar,
# BusinessDayConvention convention,
# bool endOfMonth,
# const DayCounter &dayCounter)
# DepositRateHelper (Rate rate,
# const Period &tenor,
# Natural fixingDays,
# const Calendar &calendar,
# BusinessDayConvention convention,
# bool endOfMonth,
# const DayCounter &dayCounter)
# In[5]
"""
Eonia(const Handle< YieldTermStructure > &h=Handle< YieldTermStructure >())
Eonia (Euro Overnight Index Average) rate fixed by the ECB
HKDHibor(const Period &tenor, const Handle< YieldTermStructure > &h=Handle< YieldTermStructure >())
"""
eonia = Eonia()
"""
http://quant.stackexchange.com/questions/32345/quantlib-python-dual-curve-bootstrapping-example
swap-rate helpers used to bootstrap the LIBOR curve can take a discount curve to use.
In the old single-curve examples, a SwapRateHelper instance would be created as
helper = SwapRateHelper(quoted_rate, tenor, calendar,
fixedLegFrequency, fixedLegAdjustment,
fixedLegDayCounter, Euribor6M())
and use the curve being bootstrapped for both forecast and discounting.
To use dual-curve bootstrapping, instead, you'll have to build it as
helper = SwapRateHelper(quoted_rate, tenor, calendar,
fixedLegFrequency, fixedLegAdjustment,
fixedLegDayCounter, Euribor6M(),
QuoteHandle(), Period(0,Days), # needed as default value
discountCurve) # the discountCurve argument would be a handle to the OIS curve that you bootstrapped previously
SwapRateHelper (Rate rate,
const Period &tenor,
const Calendar &calendar,
Frequency fixedFrequency,
BusinessDayConvention fixedConvention,
const DayCounter &fixedDayCount,
const boost::shared_ptr< IborIndex > &iborIndex,
const Handle< Quote < &spread=Handle< Quote >(),
const Period &fwdStart=0 *Days,
const Handle< YieldTermStructure > &discountingCurve=Handle< YieldTermStructure >())
In the above, the additional QuoteHandle() and Period(0,Days) arguments are,
unfortunately, needed because the SWIG wrappers don't support keyword arguments
for this constructor; and the discountCurve argument would be a handle to the
OIS curve that you bootstrapped previously. When the swap-rate helpers are
instantiated as above, they will use the LIBOR curve being bootstrapped for forecast
and the OIS curve for discounting.
"""
# In[6]
# Overnight Index Swap rate
# setup OISRateHelper for 1,2,3 weeks and 1 month
helpers += [ OISRateHelper(2, Period(*tenor), QuoteHandle(SimpleQuote(rate/100)), eonia)
for rate, tenor in [(0.070, (1,Weeks)), (0.069, (2,Weeks)),
(0.078, (3,Weeks)), (0.074, (1,Months))] ]
# In[7]
"""
DatedOISRateHelper(const Date &startDate,
const Date &endDate,
const Handle< Quote > &fixedRate,
const boost::shared_ptr< OvernightIndex > &overnightIndex)
"""
# setup DatedOISRateHelper
helpers += [ DatedOISRateHelper(start_date, end_date, QuoteHandle(SimpleQuote(rate/100)), eonia)
for rate, start_date, end_date in [(0.046, Date(16,January,2013), Date(13,February,2013)),
(0.016, Date(13,February,2013), Date(13,March,2013)),
(-0.007, Date(13,March,2013), Date(10,April,2013)),
(-0.013, Date(10,April,2013), Date(8,May,2013)),
(-0.014, Date(8,May,2013), Date(12,June,2013))] ]
# In[8]
"""
Overnight Index Swap rate
OISRateHelper(Natural settlementDays,
const Period &tenor,
const Handle< Quote > &fixedRate,
const boost::shared_ptr< OvernightIndex > &overnightIndex)
"""
# setup OISRateHelper from 15 months to 30 years
helpers += [ OISRateHelper(2, Period(*tenor), QuoteHandle(SimpleQuote(rate/100)), eonia)
for rate, tenor in [(0.002, (15,Months)), (0.008, (18,Months)),
(0.021, (21,Months)), (0.036, (2,Years)),
(0.127, (3,Years)), (0.274, (4,Years)),
(0.456, (5,Years)), (0.647, (6,Years)),
(0.827, (7,Years)), (0.996, (8,Years)),
(1.147, (9,Years)), (1.280, (10,Years)),
(1.404, (11,Years)), (1.516, (12,Years)),
(1.764, (15,Years)), (1.939, (20,Years)),
(2.003, (25,Years)), (2.038, (30,Years))] ]
# In[9]
eonia_curve_c = PiecewiseLogCubicDiscount(0, TARGET(),
helpers, Actual365Fixed())
"""
# QuantLib-SWIG/SWIG/piecewiseyieldcurve.i
%define export_piecewise_curve(Name, Base, Interpolator)
export_piecewise_curve(PiecewiseLogCubicDiscount, Discount, MonotonicLogCubic);
PiecewiseYieldCurve<Base,Interpolator>(
settlementDays, # Integer settlementDays,
calendar, # const Calendar& calendar,
instruments, # const std::vector<boost::shared_ptr<RateHelper> >& instruments,
dayCounter, # const DayCounter& dayCounter,
jumps, # const std::vector<Handle<Quote> >& jumps=std::vector<Handle<Quote> >(),
jumpDates, # const std::vector<Date>& jumpDates = std::vector<Date>(),
accuracy, # Real accuracy = 1.0e-12,
i # const Interpolator& i = Interpolator()
)
"""
eonia_curve_c.enableExtrapolation()
# In[10]
today = eonia_curve_c.referenceDate()
end = today+Period(2,Years)
dates = [ Date(serial) for serial in range(today.serialNumber(),
end.serialNumber()+1) ]
rates_c = [ eonia_curve_c.forwardRate(d, TARGET().advance(d, 1, Days),
Actual360(), Simple).rate()*100
for d in dates ]
# In[11]
import matplotlib.pyplot as plt
plt.title("Multiple Interest Rate Curve Bootstrapping")
plt.plot(rates_c, '-')
plt.ylabel('Rates')
plt.show()
# get spot rates
spots = []
tenors = []
today = eonia_curve_c.referenceDate()
end = today+Period(2,Years)
dates = [ Date(serial) for serial in range(today.serialNumber(),
end.serialNumber()+1) ]
#for d in eonia_curve_c.dates(): # return boost::dynamic_pointer_cast<Name>(*self)->dates();
for d in dates:
day_count = Actual360()
yrs = day_count.yearFraction(today, d)
compounding = Simple
freq = Annual
zero_rate = eonia_curve_c.zeroRate(yrs, compounding, freq)
tenors.append(yrs)
eq_rate = zero_rate.equivalentRate(day_count,
compounding,
freq,
today,
d).rate()
spots.append(100*eq_rate)
plt.title('Discount Curve')
plt.plot(tenors[1::], spots[1::], linewidth=2.0)
plt.xlabel('tenor (Y)')
plt.ylabel('spot (%)')
plt.show()
8. Test2, requires QuantLib, numpy, scipy, matplotlib
The code is borrowed from QuantLib Python Cookbook chapter 13
- chap13.py Select all
#! python2
#!/usr/bin/env python
# pylint: disable-msg=C0103
# Interest-rate Models
# Chapter 13 Thoughts on the Convergence of Hull-White Model Monte-Carlo Simulations
# In[1]
import QuantLib as ql
print ("\nOut[1]:")
print ("QuantLib version", ql.__version__)
import matplotlib.pyplot as plt
import numpy as np
from scipy.integrate import simps, cumtrapz, romb
# % matplotlib inline
import math
todays_date = ql.Date(15, 1, 2015)
ql.Settings.instance().evaluationDate = todays_date
# In[2]
# <!-- collapse=True -->
def get_path_generator(timestep, hw_process, length,
low_discrepancy=False, brownian_bridge=True):
"""
Returns a path generator
The `get_path_generator` function creates the a path generator. This function takes various inputs such as
"""
if low_discrepancy:
usg = ql.UniformLowDiscrepancySequenceGenerator(timestep)
rng = ql.GaussianLowDiscrepancySequenceGenerator(usg)
seq = ql.GaussianSobolPathGenerator(
hw_process, length, timestep, rng,brownian_bridge)
else:
usg = ql.UniformRandomSequenceGenerator(timestep, ql.UniformRandomGenerator())
rng = ql.GaussianRandomSequenceGenerator(usg)
seq = ql.GaussianPathGenerator(
hw_process, length, timestep, rng, brownian_bridge)
return seq
# In[3]
# <!-- collapse=True -->
def generate_paths(num_paths, timestep, seq):
"""
The `generate_paths` function uses the generic path generator produced by the
`get_path_generator` function to return a tuple of the array of the points in
the time grid and a matrix of the short rates generated."
"""
arr = np.zeros((num_paths, timestep+1))
for i in range(num_paths):
sample_path = seq.next()
path = sample_path.value()
time = [path.time(j) for j in range(len(path))]
value = [path[j] for j in range(len(path))]
arr[i, :] = np.array(value)
return np.array(time), arr
# In[4]
# <!-- collapse=True -->
def generate_paths_zero_price(spot_curve_handle, a, sigma, timestep, length,
num_paths, avg_grid_array, low_discrepancy=False,
brownian_bridge=True):
"""
This function returns a tuple (T_array, F_array), where T_array is the array
of points in the time grid, and F_array is the array of the average of zero
prices observed from the simulation.
The `generate_paths_zero_price` essentially is a wrapper around
`generate_path_generator` and `generate_paths` taking all the required raw
inputs. This function returns the average of zero prices from all the paths
for different points in time. I wrote this out so that I can conveniently
change all the required inputs and easily plot the results."
"""
hw_process = ql.HullWhiteProcess(spot_curve_handle, a, sigma)
seq = get_path_generator(
timestep, hw_process, length, low_discrepancy, brownian_bridge
)
time, paths = generate_paths(num_paths, timestep, seq)
avgs = [(time[j], (np.mean([math.exp(-simps(paths[i][0:j], time[0:j]))
for i in range(num_paths)])))
for j in avg_grid_array
]
return zip(*avgs)
def generate_paths_discount_factors(spot_curve_handle, a, sigma, timestep, length,
num_paths, avg_grid_array, low_discrepancy=False,
brownian_bridge=True):
"""
This function returns a tuple (T_array, S_matrix), where T_array is the array
of points in the time grid, and S_matrix is the matrix of the spot rates for
each path in the different points in the time grid.
"""
hw_process = ql.HullWhiteProcess(spot_curve_handle, a, sigma)
seq = get_path_generator(
timestep, hw_process, length, low_discrepancy, brownian_bridge
)
time, paths = generate_paths(num_paths, timestep, seq)
arr = np.zeros((num_paths, len(avg_grid_array)))
for i in range(num_paths):
arr[i, :] = [np.exp(-simps(paths[i][0:j], time[0:j])) for j in avg_grid_array ]
t_array = [time[j] for j in avg_grid_array]
return t_array, arr
def V(t,T, a, sigma):
""" Variance of the integral of short rates, used below """
return sigma*sigma/a/a*(T-t + 2.0/a*math.exp(-a*(T-t)) -
1.0/(2.0*a)*math.exp(-2.0*a*(T-t)) - 3.0/(2.0*a) )
# In[5]
# <!-- collapse=True -->
# Here we vary sigma with fixed a and observe the error epsilon
# define constants
num_paths = 500
sigma_array = np.arange(0.01,0.1,0.03)
a = 0.1
timestep = 180
length = 15 # in years
forward_rate = 0.05
day_count = ql.Thirty360()
avg_grid_array = np.arange(12, timestep+1, 12)
# generate spot curve
spot_curve = ql.FlatForward(
todays_date,
ql.QuoteHandle(ql.SimpleQuote(forward_rate)), day_count
)
spot_curve_handle = ql.YieldTermStructureHandle(spot_curve)
#initialize plots
figure, axis = plt.subplots()
plots = []
zero_price_theory = np.array([spot_curve.discount(j*float(length)/float(timestep))
for j in avg_grid_array])
for sigma in sigma_array:
term, zero_price_empirical = generate_paths_zero_price(
spot_curve_handle, a, sigma, timestep, length, num_paths,
avg_grid_array
)
plots += axis.plot(
term, np.abs(zero_price_theory - np.array(zero_price_empirical)),
lw=2, alpha=0.6,
label="$\sigma=$"+str(sigma)
)
# plot legend
labels = [p.get_label() for p in plots]
legend =axis.legend(plots,labels, loc=0)#, loc=0, bbox_to_anchor=(1.1,0.4))
axis.set_xlabel("T (years)", size=12)
axis.set_ylabel("|$\epsilon(T)$|", size=12)
axis.set_title("Out[5]:Discount Factor Error for $a=$%0.2f and Varying $\sigma$"%a, size=14)
plt.show()
# In[6]
# <!-- collapse=True -->
# Here we vary a with fixed sigma and observe the error epsilon
# define constants
num_paths = 500
sigma = 0.1
a_array = np.arange(0.1, 0.51, 0.1)
timestep = 180
length = 15 # in years
forward_rate = 0.05
day_count = ql.Thirty360()
avg_grid_array = np.arange(12, timestep+1, 12)
# generate spot curve
spot_curve = ql.FlatForward(
todays_date,
ql.QuoteHandle(ql.SimpleQuote(forward_rate)), day_count
)
spot_curve_handle = ql.YieldTermStructureHandle(spot_curve)
#initialize plots
figure, axis = plt.subplots()
plots = []
zero_price_theory = np.array([spot_curve.discount(j*float(length)/float(timestep))
for j in avg_grid_array])
for a in a_array:
term, zero_price_empirical = generate_paths_zero_price(
spot_curve_handle, a, sigma, timestep, length, num_paths,
avg_grid_array
)
plots += axis.plot(
term,np.abs(zero_price_theory - np.array(zero_price_empirical)),
lw=2, alpha=0.6,
label="a="+str(a)
)
# plot legend
labels = [p.get_label() for p in plots]
legend =axis.legend(plots,labels, loc=0)#, loc=0, bbox_to_anchor=(1.1,0.4))
axis.set_xlabel("T (years)", size=12)
axis.set_ylabel("|$\\epsilon(T)$|", size=12)
axis.set_title("Out[6]:Discount Factor Error for $\sigma$=%0.2f and Varying $a$"%sigma, size=14)
plt.show()
# In[7]
# <!-- collapse=True -->
#define constants
num_paths = 500
sigma = 0.02
a = 0.1
timestep = 180
length = 15 # in years
forward_rate = 0.05
day_count = ql.Thirty360()
avg_grid_array = np.arange(1, timestep+1, 12)
# generate spot curve
spot_curve = ql.FlatForward(
todays_date,
ql.QuoteHandle(ql.SimpleQuote(forward_rate)), day_count
)
spot_curve_handle = ql.YieldTermStructureHandle(spot_curve)
term, discount_factor_matrix = generate_paths_discount_factors(
spot_curve_handle, a, sigma, timestep, length, num_paths,
avg_grid_array
)
vol = [np.var(discount_factor_matrix[:, i]) for i in range(len(term))]
l1 = plt.plot(term, 100*np.sqrt(vol),"b", lw=2, alpha=0.6, label="Empirical")
vol_theory = [100*np.sqrt(math.exp(V(0,T,a, sigma))-1.0) *
spot_curve_handle.discount(T) for T in term]
l2 = plt.plot(term, vol_theory,"r--", lw=2, alpha=0.6, label="Theory")
plots = l1+l2
labels = [p.get_label() for p in plots]
legend =plt.legend(plots,labels, loc=0)
plt.xlabel("Time (Years)", size=12)
plt.ylabel("$\sigma_D(0,T)$ (%)", size=12)
plt.title("Out[7]:Standard Deviation of Discount Factors "
"(a=%0.2f, $\sigma$=%0.2f)"%(a, sigma), size=14)
plt.show()
9. Test3, requires QuantLib, numpy, panda, xlrd
The code is using QuantLib, numpy, panda and xlrd to read xls data
- testreadxls.py Select all
#! python2
#!/usr/bin/env python
# pylint: disable-msg=C0103
# pylint: disable-msg=C0301
# testreadxls.py
import os
import pandas
import numpy as np
import QuantLib as ql
xls_file = os.path.dirname(os.path.realpath(__file__)) + '/usd_market_data_2016-07-13.xls'
#alternate way to mount google drive and read xlsx file data
#import os
#from google.colab import drive
#drive.mount('/content/drive')
#xls_file = '/content/drive/My Drive/usd_market_data_2016-07-13.xlsx'
# if the file is in csv format
#csv_file = '/content/drive/My Drive/usd_market_data_2016-07-13.csv'
#csv = pandas.read_csv(csv_file)
#print("\nCSV data\n")
#print(csv)
#print (csv.loc[:, 'dates'])
#print (csv.iloc[0:, 1])
#discounts_csv = np.array(csv.iloc[0:,1].tolist())
#print(discounts_csv)
xl = pandas.ExcelFile(xls_file)
print (xl.sheet_names)
#df = xl.parse("usdstd")
#df = xl.parse(0) # alternate way to read first worksheet
filename = xls_file
sheetname = 'usdois'
sheet = pandas.read_excel(filename, sheetname) # Read an Excel table into a pandas DataFrame
#sheet = pandas.read_excel(filename, 0) # alternate way to read first worksheet instead of name
print (sheet.columns)
#tenors = np.array([Date.from_timestamp(d).t for d in sheet['dates']])
today = ql.Date(21,3,2016)
act365 = ql.Actual365Fixed()
dates = np.array([ql.Date(d.day, d.month, d.year) for d in sheet['dates']])
#dates = np.array([ql.Date(d.day, d.month, d.year) for d in df.iloc[0:,0]]) # use iloc to read first column, all rows
print ("\nusd_market_data_2016-07-13.xls dates column")
print (dates)
tenors = np.array([act365.yearFraction(today,ql.Date(d.day, d.month, d.year)) for d in sheet['dates']])
print ("\nusd_market_data_2016-07-13.xls dates column convert to tenor")
print (tenors)
print ("\nusd_market_data_2016-07-13.xls discounts column")
discounts = np.array(sheet['discounts'].tolist())
#discounts = np.array(df.iloc[0:,1].tolist()) # use iloc to read second column, all rows
print (discounts)
Assume the usd_market_data_2016-07-13.xls sheet usdois (first worksheet) has the following data
https://mega.nz/#!m4Bh2TJD!KVZbvAn4D_sSR8-FYJtNASkiWvY2TWZ1LokJ-vcw-u4
10. Test3, requires QuantLib, pandas, matplotlib
The code demonstrates the download of Interest Rate xml market data from markit.com and Bootstrapping IR Curve in QuantLib
- test_xml_download.py Select all
#!python2
#!/usr/bin/env python
# pylint: disable-msg=C0103
# pylint: disable-msg=C0301
# test_xml_download.py
from QuantLib import *
print ("\nQuantLib version", QuantLib.__version__)
import urllib
import zipfile
import xml.etree.ElementTree as ET
import pandas as pd
import datetime as dt
from matplotlib.dates import YearLocator, MonthLocator, DateFormatter
from matplotlib.ticker import FuncFormatter
import sys
if sys.version_info[0] >= 3:
from urllib.request import urlretrieve
else: # Not Python 3 - today, it is most likely to be Python 2
# But note that this might need an update when Python 4
# might be around one day
from urllib import urlretrieve
def to_datetime(d):
"""
to_datetime
"""
return dt.datetime(d.year(), d.month(), d.dayOfMonth())
def format_rate(r, p=2):
"""
format_rate
"""
return '{0:.{prec}f}%'.format(r*100.00, prec=p)
period_dict = {str(k)+'M': (k, Months) for k in range(1, 12, 1)}
d2 = {str(k)+'Y': (k, Years) for k in range(1, 50, 1)}
period_dict.update(d2)
(ir_currency, ir_date) = ('USD', '20170331')
url = 'https://www.markit.com/news/InterestRates_%s_%s.zip' % (ir_currency, ir_date)
#filehandle, _ = urllib.urlretrieve(url)
filehandle, _ = urlretrieve(url)
zip_file_object = zipfile.ZipFile(filehandle, 'r')
interest_rate_file = zip_file_object.open(zip_file_object.namelist()[1])
content = interest_rate_file.read()
#print (content)
root = ET.fromstring(content)
print ("\nInfo on InterestRates_%s_%s" % (ir_currency, ir_date))
for a in [root.find(b) for b in ['./currency',
'./effectiveasof',
'./deposits/daycountconvention',
'./deposits/snaptime',
'./deposits/spotdate',
'./swaps/fixeddaycountconvention',
'./swaps/floatingdaycountconvention',
'./swaps/snaptime',
'./swaps/spotdate']]:
print (a.tag, a.text)
effectiveasof = root.find('./effectiveasof').text
currency = root.find('./currency').text
today = DateParser.parseFormatted(effectiveasof, '%Y-%m-%d')
Settings.instance().evaluationDate = today
print ("\nDeposit Rates")
deposits_maturitydates = [a.text for a in root.findall('.//deposits/curvepoint/maturitydate')]
deposits_parrates_text = [a.text for a in root.findall('.//deposits/curvepoint/parrate')]
deposits_tenors = [a.text for a in root.findall('.//deposits/curvepoint/tenor')]
deposits_periods = [period_dict[a] for a in deposits_tenors]
print (pd.DataFrame(zip(deposits_tenors, deposits_maturitydates, map(float, deposits_parrates_text)), columns=('Tenor', 'Maturity', 'Parrate')))
maturity_dict = {}
for t, m in zip(deposits_tenors, deposits_maturitydates):
d = {t: m}
maturity_dict.update(d)
print ("\nSwap Rates")
swaps_maturitydates = [a.text for a in root.findall('.//swaps/curvepoint/maturitydate')]
swaps_parrates_text = [a.text for a in root.findall('.//swaps/curvepoint/parrate')]
swaps_tenors = [a.text for a in root.findall('.//swaps/curvepoint/tenor')]
swaps_periods = [period_dict[a] for a in swaps_tenors]
print (pd.DataFrame(zip(swaps_tenors, swaps_maturitydates, map(float, swaps_parrates_text)), columns=('Tenor', 'Maturity', 'Parrate')))
for t, m in zip(swaps_tenors, swaps_maturitydates):
d = {t: m}
maturity_dict.update(d)
#print (maturity_dict)
euribor6m = Euribor6M()
helpers = [DepositRateHelper(rate,
Period(*tenor), 2,
TARGET(), Following, False, Actual360())
for tenor, rate in zip(deposits_periods, map(float, deposits_parrates_text))]
helpers += [SwapRateHelper(rate,
Period(*tenor), TARGET(),
Semiannual, Unadjusted,
Thirty360(),
euribor6m)
for tenor, rate in zip(swaps_periods, map(float, swaps_parrates_text))]
curve = PiecewiseLogCubicDiscount(2, TARGET(), helpers,
Actual360())
curve.enableExtrapolation()
spot = curve.referenceDate()
#dates = [spot+Period(i,Months) for i in range(0, 30*12+1)]
dates = [spot+Period(i, Years) for i in range(0, 30)]
rates = [curve.forwardRate(d, euribor6m.maturityDate(d),
Actual360(), Simple).rate()
for d in dates]
valid_dates = [d for d in dates if d >= spot]
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
fig.autofmt_xdate()
ax.plot_date([to_datetime(d) for d in valid_dates], rates, '-')
ax.set_xlim(to_datetime(min(dates)), to_datetime(max(dates)))
ax.xaxis.set_major_locator(YearLocator(2, month=today.month(), day=today.dayOfMonth()))
ax.xaxis.set_major_formatter(DateFormatter("%Y"))
ax.xaxis.grid(True, 'major')
ax.xaxis.grid(False, 'minor')
ax.yaxis.set_major_formatter(FuncFormatter(lambda r, pos: format_rate(r)))
plt.title("%s Interest Rate Curve Bootstrapping, effective %s" % (currency, effectiveasof))
plt.xlabel('Year')
plt.ylabel('Rates')
plt.show()
11. Compile QuantLib Python 1.10 for Mac
- script.sh Select all
# install Xcode and HomeBrew
# ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
# install boost
brew install boost
# Download QuantLib-1.10
cd $(HOME)/Downloads
wget --no-check-certificate https://jaist.dl.sourceforge.net/project/quantlib/test/QuantLib-1.10.tar.gz
tar xzvf QuantLib-1.10.tar.gz
# Compile QuantLib 1.10
cd QuantLib-1.10
./configure --prefix=/usr/local/ CXXFLAGS='-O2 -stdlib=libstdc++ -mmacosx-version-min=10.6' LDFLAGS='-stdlib=libstdc++ -mmacosx-version-min=10.6'
make && sudo make install
# test compile c++
g++ Bonds.cpp -std=c++11 -stdlib=libstdc++ -o Bonds -lQuantLib
./Bonds
# Download QuantLib-SWIG 1.10
cd $(HOME)/Downloads
wget --no-check-certificate https://jaist.dl.sourceforge.net/project/quantlib/test/QuantLib-SWIG-1.10.tar.gz
tar xzvf QuantLib-SWIG-1.10.tar.gz
# Compile QuantLib Python
cd QuantLib-SWIG-1.10
./configure CXXFLAGS='-O2 -stdlib=libstdc++ -mmacosx-version-min=10.6'
make -C Python
make -C Python check
sudo make -C Python install
# Package wheel file
sudo -H python pip install setuptools wheel
cd $(HOME)/Downloads/QuantLib-SWIG-1.10/Python
# Modify setup.py and replace
from distutils.core import setup, Extension
# By
try:
from setuptools import setup, Extension
except:
from distutils.core import setup, Extension
# python 2 wheel file
python setup.py bdist_wheel
ls dist/
# python 3 wheel file
LDFLAGS="-arch x86_64 -bundle -flat_namespace -undefined suppress" CFLAGS="-fno-strict-aliasing -Wsign-compare -fno-common -static -arch x86_64 -Wno-shorten-64-to-32" python3 setup.py bdist_wheel
ls dist/
QuantLib_Python-1.10-cp27-cp27m-macosx_10_10_intel.whl download
QuantLib_Python-1.10-cp36-cp36m-macosx_10_6_intel.whl download
For Python3, have to install libQuantLib to /usr/local/lib
cd /usr/local/lib
sudo tar xzvf ~/Download/libQuantLib.tgz
Download libQuantLib.tgz here https://mega.nz/#!rpJg0B6T!NlG3Ijgo0weNOi_CVOkCzpGCMRqHZkWSeF3S0sAR12o
12. For Windows 64-bit, Regeneration of python SWIG interface method
If you need to edit the SWIG interface file and add functionality in QuantLib Python, you need to regenerate.
- script.cmd Select all
# First, compile QuantLib using Visual Studio 2015.
# Select 21 projects and right click select Property -> All Configurations Add C:\local\boost_1_59_0; to the Property Pages : VC++ Include directories to win32 platform and Add C:\local\boost_1_59_0\lib32-msvc-14.0; to the VC++ Libs directories to win32 platform
# Select All Configurations Add C:\local\boost_1_59_0_64; to the Property Pages : VC++ Include directories to x64 platform and Add C:\local\boost_1_59_0_64\lib64-msvc-14.0; to the VC++ Libs directories to x64 platform
# Add /wd4819 to Command Line : Additional Options to disable C4819 warnings when compiling Quantlib to both win32 and x64 platform
# Build Release x64 Solution or Release win32 Solution.
# setting of QuantLib Project directory, e.g.
SET QL_DIR=C:\local\QuantLib-1.10\QuantLib-1.10
# or alternatively, edit the setup.py
# QL_INSTALL_DIR = r'C:\local\QuantLib-1.10\QuantLib-1.10'
# setting of compiled libraries location for QuantLib ('QuantLib-vc140-x64-mt.lib') and Boost, e.g. for x64 platform
SET LIB=C:\local\boost_1_59_0_64\lib64-msvc-14.0
# setting of Boost Project directory, e.g.
SET INCLUDE=C:\local\boost_1_59_0_64
# setting of SWIGWIN.exe PATH, e.g.
SET PATH=C:\local\swigwin-3.0.12;%PATH%
# setting of VISUAL STUDIO 2015 (Version 14)
SET VS90COMNTOOLS=%VS140COMNTOOLS%
# Edit SWIG interface file if any
C:\local\QuantLib-1.10\QuantLib-SWIG-1.10\SWIG\*.i
# e.g. edit piecewiseyieldcurve.i and add at the end
# export_piecewise_curve(PiecewiseLogLinearDiscount,Discount,LogLinear);
# Wrap the edited interface file again after edit
py -2 setup.py wrap
# compile using msvc
# need to edit setup.py to add ,'/wd4819' to the extra_compile_args to disable warnings
py -2 setup.py build --compiler=msvc
# must use Administrator Command Prompt to install
py -2 -m setup.py install --skip-build
# generation of wheel file is same as above that is modify setup.py first
# need to install setuptools and wheel
py -2 -m pip install setuptools wheel
py -2 setup.py test
py -2 setup.py bdist_wheel
dir dist
Visual Studio 2015 setup https://mega.nz/#!70ZwyARa!z4et3sKwguU16tEbCYTdwBC1VEkNJTTakryrDRBSKM8