Wednesday, March 29, 2017

How to install QuantLib Python for Windows 32 in offline installation

1. Download Python 2.7 Windows x86 MSI installer from

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


No comments: