Here is a demo of how QuantLib c++ code are translated to Python. This included the code for importing of csv file and construction of volatility surface and the timing of MCDiscreteArithmeticAPEngine. Slicing and manipulation of list/array is much easier in Python than that of C++ code. However, C++ is faster.
QuantLib C++ source code, AsianOption.cpp
- AsianOption.cpp Select all
// g++ -std=c++11 AsianOption.cpp -o AsianOption -lQuantLib
#include <ql/quantlib.hpp>
#include <boost/timer.hpp>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/lexical_cast.hpp>
using namespace QuantLib;
using namespace std;
void GetStrikes(string &path, vector<Real> &strikes)
{
std::ifstream file(path);
std::string line;
std::vector<std::string> tokens;
int linecount = 0;
while (std::getline(file, line)) {
std::stringstream stringStream(line);
std::string content;
int item = 0;
if (linecount >= 1)
while (std::getline(stringStream, content, ',')) {
switch (item) {
case 0: // strikes are on first column only
strikes.push_back(boost::lexical_cast<double>(content));
break;
default:
break;
}
item++;
}
linecount++;
}
return;
/* if hardcode csv data
strikes.push_back(0.67263);
strikes.push_back(0.71865);
strikes.push_back(0.7487);
strikes.push_back(0.77129);
strikes.push_back(0.78984);
strikes.push_back(0.80587);
strikes.push_back(0.82034);
strikes.push_back(0.83379);
strikes.push_back(0.84658);
strikes.push_back(0.85792);
strikes.push_back(0.87354);
strikes.push_back(0.89085);
strikes.push_back(0.90904);
strikes.push_back(0.9289);
strikes.push_back(0.95157);
strikes.push_back(0.97862);
strikes.push_back(1.01337);
strikes.push_back(1.06261);
strikes.push_back(1.14631);
*/
}
void GetExpiryDates(string &path, vector<Date> &expirations)
{
std::ifstream file(path);
std::string line;
std::vector<std::string> tokens;
int linecount = 0;
while (std::getline(file, line)) {
std::stringstream stringStream(line);
std::string content;
int item = 0;
if (linecount == 0) // expiration dates are on first row only
while (std::getline(stringStream, content, ',')) {
switch (item) {
case 1:
case 2:
case 3:
case 4:
boost::algorithm::split(tokens, content, boost::algorithm::is_any_of("/"));
expirations.push_back(Date(Day(boost::lexical_cast<int>(tokens.at(1))), Month(boost::lexical_cast<int>(tokens.at(0))), Year(boost::lexical_cast<int>(tokens.at(2)))));
break;
default:
break;
}
item++;
}
linecount++;
}
return;
/* if hardcode csv data
expirations.push_back(Date(27, June, 2017));
expirations.push_back(Date(27, September, 2017));
expirations.push_back(Date(27, December, 2017));
expirations.push_back(Date(27, June, 2018));
*/
}
Matrix GetVolData(string &path, vector<Date> &expirations, vector<Real> &strikes)
{
// Matrix volMatrix(19, 4);
Matrix volMatrix(strikes.size(), expirations.size());
std::ifstream file(path);
std::string line;
std::vector<std::string> tokens;
int linecount = 0;
while (std::getline(file, line)) {
std::stringstream stringStream(line);
std::string content;
int item = 0;
if (linecount >= 1) // vols are on second row onward
while (std::getline(stringStream, content, ',')) {
switch (item) {
case 1:
case 2:
case 3:
case 4:
volMatrix[linecount-1][item-1] = boost::lexical_cast<double>(content);
// vols are on second column onward
break;
default:
break;
}
item++;
}
linecount++;
}
return volMatrix;
/* if hardcode csv data
//0.67263,0.144183920277296,0.139374695503699,0.135526204819277,0.12885
volMatrix[0][0] = 0.144183920277296;
volMatrix[0][1] = 0.139374695503699;
volMatrix[0][2] = 0.135526204819277;
volMatrix[0][3] = 0.12885;
//0.71865,0.133703802426343,0.129893056346044,0.126909006024096,0.12175
volMatrix[1][0] = 0.133703802426343;
volMatrix[1][1] = 0.129893056346044;
volMatrix[1][2] = 0.126909006024096;
volMatrix[1][3] = 0.12175;
//0.7487,0.126860526863085,0.123701764371087,0.121209416342412,0.11695
volMatrix[2][0] = 0.126860526863085;
volMatrix[2][1] = 0.123701764371087;
volMatrix[2][2] = 0.121209416342412;
volMatrix[2][3] = 0.11695;
// 0.77129,0.121720863192182,0.118881707209199,0.116979766476388,0.11381
volMatrix[3][0] = 0.121720863192182;
volMatrix[3][1] = 0.118881707209199;
volMatrix[3][2] = 0.116979766476388;
volMatrix[3][3] = 0.11381;
// 0.78984,0.117581136690647,0.115218428824572,0.113899219047619,0.11163
volMatrix[4][0] = 0.117581136690647;
volMatrix[4][1] = 0.115218428824572;
volMatrix[4][2] = 0.113899219047619;
volMatrix[4][3] = 0.11163;
// 0.80587,0.114363421052632,0.112523118729097,0.111637193240265,0.11019
volMatrix[5][0] = 0.114363421052632;
volMatrix[5][1] = 0.112523118729097;
volMatrix[5][2] = 0.111637193240265;
volMatrix[5][3] = 0.11019;
//0.82034,0.111728795180723,0.110489402985075,0.109987692307692,0.10921
volMatrix[6][0] = 0.111728795180723;
volMatrix[6][1] = 0.110489402985075;
volMatrix[6][2] = 0.109987692307692;
volMatrix[6][3] = 0.10921;
// 0.83379,0.109805703883495,0.109100413723512,0.108870460584588,0.1086
volMatrix[7][0] = 0.109805703883495;
volMatrix[7][1] = 0.109100413723512;
volMatrix[7][2] = 0.108870460584588;
volMatrix[7][3] = 0.1086;
// 0.84658,0.108581646586345,0.108250493273543,0.108197213114754,0.10829
volMatrix[8][0] = 0.108581646586345;
volMatrix[8][1] = 0.108250493273543;
volMatrix[8][2] = 0.108197213114754;
volMatrix[8][3] = 0.10829;
// 0.85792,0.108190964125561,0.107986172506739,0.10796631037213,0.10822
volMatrix[9][0] = 0.108190964125561;
volMatrix[9][1] = 0.107986172506739;
volMatrix[9][2] = 0.10796631037213;
volMatrix[9][3] = 0.10822;
// 0.87354,0.10859510460251,0.108310304612707,0.108232350773766,0.10849
volMatrix[10][0] = 0.10859510460251;
volMatrix[10][1] = 0.108310304612707;
volMatrix[10][2] = 0.108232350773766;
volMatrix[10][3] = 0.10849;
// 0.89085,0.110043016488846,0.109404567049808,0.109102906403941,0.10919
volMatrix[11][0] = 0.110043016488846;
volMatrix[11][1] = 0.109404567049808;
volMatrix[11][2] = 0.109102906403941;
volMatrix[11][3] = 0.10919;
// 0.90904,0.112447321958457,0.111343238289206,0.110615417475728,0.11036
volMatrix[12][0] = 0.112447321958457;
volMatrix[12][1] = 0.111343238289206;
volMatrix[12][2] = 0.110615417475728;
volMatrix[12][3] = 0.11036;
// 0.9289,0.115567066189624,0.113888152866242,0.112830993150685,0.11201
volMatrix[13][0] = 0.115567066189624;
volMatrix[13][1] = 0.113888152866242;
volMatrix[13][2] = 0.112830993150685;
volMatrix[13][3] = 0.11201;
// 0.95157,0.119454321849106,0.117151688909342,0.115569047072331,0.11433
volMatrix[14][0] = 0.119454321849106;
volMatrix[14][1] = 0.117151688909342;
volMatrix[14][2] = 0.115569047072331;
volMatrix[14][3] = 0.11433;
// 0.97862,0.123858310308183,0.121275916334661,0.119199029605263,0.11731
volMatrix[15][0] = 0.123858310308183;
volMatrix[15][1] = 0.121275916334661;
volMatrix[15][2] = 0.119199029605263;
volMatrix[15][3] = 0.11731;
// 1.01337,0.129434558979809,0.126231870274572,0.123929902439024,0.12145
volMatrix[16][0] = 0.129434558979809;
volMatrix[16][1] = 0.126231870274572;
volMatrix[16][2] = 0.123929902439024;
volMatrix[16][3] = 0.12145;
// 1.06261,0.137335982996812,0.133099606048548,0.12994278699187,0.12723
volMatrix[17][0] = 0.137335982996812;
volMatrix[17][1] = 0.133099606048548;
volMatrix[17][2] = 0.12994278699187;
volMatrix[17][3] = 0.12723;
// 1.14631,0.150767120085016,0.144773641066454,0.140163713821138,0.13547
volMatrix[18][0] = 0.150767120085016;
volMatrix[18][1] = 0.144773641066454;
volMatrix[18][2] = 0.140163713821138;
volMatrix[18][3] = 0.13547;
return volMatrix;
*/
}
void asian()
{
// Calendar set up
Calendar calendar = TARGET();
Date todaysDate(4, April, 2017);
Settings::instance().evaluationDate() = todaysDate;
DayCounter dayCounter = Actual360();
// Option parameters Asian FX
Option::Type optionType(Option::Call);
Average::Type averageType = Average::Arithmetic;
Date maturity(4, April, 2018);
Real strike = 0.74;
Volatility volatility = 0.07053702474;
Date obsStart(4, March, 2018);
Real runningSum = 0;
Size pastFixings = 0;
vector<Date> fixingDates;
for (Date incrementedDate = obsStart; incrementedDate <= maturity; incrementedDate += 1)
{
if (calendar.isBusinessDay(incrementedDate))
{
fixingDates.push_back(incrementedDate);
}
}
// Option parameters
// European Exercise
boost::shared_ptr<Exercise> europeanExercise(
new EuropeanExercise(maturity));
// Payoff
boost::shared_ptr<StrikedTypePayoff> payoffAsianOption(
new PlainVanillaPayoff(Option::Type(optionType), strike));
// Model parameters
Real underlying = 0.748571186;
Spread dividendYield = 0.04125;
Rate riskFreeRate = 0.0225377;
// Market Data
// Quote handling
Handle<Quote> underlyingH(
boost::shared_ptr<Quote>(new SimpleQuote(underlying)));
// Yield term structure handling
Handle<YieldTermStructure> flatTermStructure(
boost::shared_ptr<YieldTermStructure>(new FlatForward(todaysDate, dividendYield, dayCounter)));
// Dividend term structure handling
Handle<YieldTermStructure> flatDividendTermStructure(
boost::shared_ptr<YieldTermStructure>(new FlatForward(todaysDate, riskFreeRate, dayCounter)));
// Volatility structure handling: constant volatility
Handle<BlackVolTermStructure> flatVolTermStructure(
boost::shared_ptr<BlackVolTermStructure>(new BlackConstantVol(todaysDate, calendar, volatility, dayCounter)));
// Read csv file
string path = "./VolMatrixA.csv";
vector<Real> strikes = {};
GetStrikes(path, strikes);
vector<Date> expirations = {};
GetExpiryDates(path, expirations);
cout << "strikes.size() " << strikes.size() << endl;
cout << "expirations.size() " << expirations.size() << endl;
// assert csv data
BOOST_ASSERT_MSG(strikes.size() > 0, static_cast<std::stringstream&>(std::stringstream() << "No valid strikes.size() found! It is " << strikes.size()).str().c_str());
BOOST_ASSERT_MSG(expirations.size() > 0, static_cast<std::stringstream&>(std::stringstream() << "No valid expirations.size() found! It is " << expirations.size()).str().c_str());
Matrix volMatrix = GetVolData(path, expirations, strikes);
// Volatility Surface
BlackVarianceSurface volatilitySurface(Settings::instance().evaluationDate(),
calendar, expirations, strikes, volMatrix, dayCounter);
volatilitySurface.setInterpolation<Bicubic>();
volatilitySurface.enableExtrapolation(true);
const boost::shared_ptr<BlackVarianceSurface> volatilitySurfaceH(
new BlackVarianceSurface(volatilitySurface));
Handle<BlackVolTermStructure> volTermStructure(volatilitySurfaceH);
// the BS equation behind
boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(
new BlackScholesMertonProcess(underlyingH, flatDividendTermStructure, flatTermStructure, volTermStructure));
// Options
DiscreteAveragingAsianOption discreteArithmeticAsianAverageOption(
averageType,
runningSum,
pastFixings,
fixingDates,
payoffAsianOption,
europeanExercise);
// Outputting on the screen
cout << "Option type = " << optionType << endl;
cout << "Option maturity = " << maturity << endl;
cout << "Underlying = " << underlying << endl;
cout << "Strike = " << strike << endl;
cout << "Risk-free interest rate = " << setprecision(4) << io::rate(riskFreeRate) << endl;
cout << "Dividend yield = " << setprecision(4) << io::rate(dividendYield) << endl;
cout << "Volatility = " << setprecision(4) << io::volatility(volatility) << endl;
cout << "Time-length between successive fixings = weekly time step" << endl;
cout << "Previous fixings = " << pastFixings << endl;
cout << setprecision(10) << endl;
boost::timer timer;
// Pricing engine
discreteArithmeticAsianAverageOption.setPricingEngine(
boost::shared_ptr<PricingEngine>(
MakeMCDiscreteArithmeticAPEngine<LowDiscrepancy>(bsmProcess)
.withSamples(1500)));
// Timer
timer.restart();
try
{
cout << "Discrete ArithMC Price: " << discreteArithmeticAsianAverageOption.NPV() << endl;
}
catch (exception const& e) { cout << "Erreur: " << e.what() << endl; }
cout << " in " << timer.elapsed() << " s" << endl;
timer.restart();
}
int main(int, char* []) {
asian();
}
QuantLib Python source code, AsianOption.py
- AsianOption.py Select all
#!python2
#!/usr/bin/env python
# AsianOption.py
from QuantLib import *
import csv
import time
# Calendar set up
calendar = TARGET()
todaysDate = Date(4, April, 2017)
Settings.instance().evaluationDate = todaysDate
dayCounter = Actual360()
# Option parameters Asian FX
optionType = Option.Call
averageType = Average.Arithmetic
maturity = Date(4, April, 2018)
strike = 0.74
volatility = 0.07053702474
obsStart = Date(4, March, 2018)
runningSum = 0
pastFixings = 0
fixingDates = [ Date(serial) for serial in
range(obsStart.serialNumber(), maturity.serialNumber())
if calendar.isBusinessDay(Date(serial)) ]
# Model parameters
underlying = 0.748571186
dividendYield = 0.04125
riskFreeRate = 0.0225377
#settlementDate = todaysDate
# Option parameters
# European Exercise
europeanExercise = EuropeanExercise(maturity)
# Payoff
payoffAsianOption = PlainVanillaPayoff(optionType, strike)
# Market Data
# Quote handling
underlyingH = QuoteHandle(SimpleQuote(underlying))
# Yield term structure handling
flatTermStructure = YieldTermStructureHandle(FlatForward(todaysDate, dividendYield, dayCounter))
# Dividend term structure handling
flatDividendTermStructure = YieldTermStructureHandle(FlatForward(todaysDate, riskFreeRate, dayCounter))
# Volatility structure handling: constant volatility
flatVolTermStructure = BlackVolTermStructureHandle(BlackConstantVol(Settings.instance().evaluationDate, calendar, volatility, dayCounter))
# Read csv file
with open('VolMatrixA.csv', 'rb') as f:
reader = csv.reader(f)
csv_list = list(reader)
expirations = [ Date(int(col.split("/")[1]), int(col.split("/")[0]), int(col.split("/")[2]))
for col in csv_list[0][1:] ] # expirations are on first row[0] and for second column[1:] onward
strikes = [ float(row[0]) for row in csv_list[1:] ] # strikes are for second row [1:] onward and on first column [0]
"""
# if hardcode csv data
expirations = [Date(27, June, 2017), Date(27, September, 2017), Date(27, December, 2017), Date(27, June, 2018)]
strikes = [0.67263, 0.71865, 0.7487, 0.77129,
0.78984, 0.80587, 0.82034, 0.83379,
0.84658, 0.85792, 0.87354, 0.89085,
0.90904, 0.9289, 0.95157, 0.97862,
1.01337, 1.06261, 1.14631]
volMatrix = [ [0.144183920277296,0.139374695503699,0.135526204819277,0.12885],
[0.133703802426343,0.129893056346044,0.126909006024096,0.12175],
[0.126860526863085,0.123701764371087,0.121209416342412,0.11695],
[0.121720863192182,0.118881707209199,0.116979766476388,0.11381],
[0.117581136690647,0.115218428824572,0.113899219047619,0.11163],
[0.114363421052632,0.112523118729097,0.111637193240265,0.11019],
[0.111728795180723,0.110489402985075,0.109987692307692,0.10921],
[0.109805703883495,0.109100413723512,0.108870460584588,0.1086],
[0.108581646586345,0.108250493273543,0.108197213114754,0.10829],
[0.108190964125561,0.107986172506739,0.10796631037213,0.10822],
[0.10859510460251,0.108310304612707,0.108232350773766,0.10849],
[0.110043016488846,0.109404567049808,0.109102906403941,0.10919],
[0.112447321958457,0.111343238289206,0.110615417475728,0.11036],
[0.115567066189624,0.113888152866242,0.112830993150685,0.11201],
[0.119454321849106,0.117151688909342,0.115569047072331,0.11433],
[0.123858310308183,0.121275916334661,0.119199029605263,0.11731],
[0.129434558979809,0.126231870274572,0.123929902439024,0.12145],
[0.137335982996812,0.133099606048548,0.12994278699187,0.12723],
[0.150767120085016,0.144773641066454,0.140163713821138,0.13547] ]
"""
# assert csv data
assert len(strikes) > 0, "No valid len(strikes) found ! It is " + str(len(strikes))
assert len(expirations) > 0, "No valid len(expirations) found ! It is " + str(len(expirations))
#volMatrix = Matrix(len(strikes), len(expirations))
volMatrix = [[float(y) for y in x[1:]] for x in csv_list[1:]] # vols are for second row [1:] and for second column [1:] onward
print "len(strikes) ", len(strikes)
print "len(expirations) ", len(expirations)
# Volatility Surface
volatilitySurface = BlackVarianceSurface(Settings.instance().evaluationDate, calendar, expirations,
strikes, volMatrix, dayCounter)
volatilitySurface.setInterpolation("Bicubic")
volatilitySurface.enableExtrapolation()
volTermStructure = BlackVolTermStructureHandle(volatilitySurface)
# the BS equation behind
bsmProcess = BlackScholesMertonProcess(underlyingH, flatDividendTermStructure, flatTermStructure, volTermStructure)
# Options
discreteArithmeticAsianAverageOption = DiscreteAveragingAsianOption(averageType,
runningSum,
pastFixings,
fixingDates,
payoffAsianOption,
europeanExercise)
# Outputting on the screen
optionTypeKeyName = dict((v,k) for k, v in vars(Option).iteritems() if v == optionType)
print "Option type = ", optionTypeKeyName[optionType]
print "Option maturity = ", maturity
print "Underlying = ", underlying
print "Strike = ", strike
print "Risk-free interest rate = ", '{0:.{prec}f}%'.format(riskFreeRate*100.00, prec=4)
print "Dividend yield = ", '{0:.{prec}f}%'.format(dividendYield*100.00, prec=4)
print "Volatility = ", '{0:.{prec}f}%'.format(volatility*100.00, prec=4)
print "Time-length between successive fixings = weekly time step"
print "Previous fixings = ", pastFixings
print ""
# Pricing engine
engine = MCDiscreteArithmeticAPEngine(bsmProcess, "LowDiscrepancy", requiredSamples=1500)
discreteArithmeticAsianAverageOption.setPricingEngine(engine)
# Timer
start = time.time()
print "Discrete ArithMC Price: ", discreteArithmeticAsianAverageOption.NPV()
print ' in ' + '{0:.2f}'.format(time.time() - start), 's\n'
VolMatrixA.csv file is the data source of the Volatility Surface
- VolMatrixA.csv Select all
Strike ,6/27/2017,9/27/2017,12/27/2017,6/27/2018
0.67263,0.144183920277296,0.139374695503699,0.135526204819277,0.12885
0.71865,0.133703802426343,0.129893056346044,0.126909006024096,0.12175
0.7487,0.126860526863085,0.123701764371087,0.121209416342412,0.11695
0.77129,0.121720863192182,0.118881707209199,0.116979766476388,0.11381
0.78984,0.117581136690647,0.115218428824572,0.113899219047619,0.11163
0.80587,0.114363421052632,0.112523118729097,0.111637193240265,0.11019
0.82034,0.111728795180723,0.110489402985075,0.109987692307692,0.10921
0.83379,0.109805703883495,0.109100413723512,0.108870460584588,0.1086
0.84658,0.108581646586345,0.108250493273543,0.108197213114754,0.10829
0.85792,0.108190964125561,0.107986172506739,0.10796631037213,0.10822
0.87354,0.10859510460251,0.108310304612707,0.108232350773766,0.10849
0.89085,0.110043016488846,0.109404567049808,0.109102906403941,0.10919
0.90904,0.112447321958457,0.111343238289206,0.110615417475728,0.11036
0.9289,0.115567066189624,0.113888152866242,0.112830993150685,0.11201
0.95157,0.119454321849106,0.117151688909342,0.115569047072331,0.11433
0.97862,0.123858310308183,0.121275916334661,0.119199029605263,0.11731
1.01337,0.129434558979809,0.126231870274572,0.123929902439024,0.12145
1.06261,0.137335982996812,0.133099606048548,0.12994278699187,0.12723
1.14631,0.150767120085016,0.144773641066454,0.140163713821138,0.13547
QuantLib Python source code, Gaussian1dModels.py (Gaussian1dModels.cpp in QuantLib Examples Folder)
- Gaussian1dModels.py Select all
#!python2
#!/usr/bin/env python
#Gaussian1dModels.py
import QuantLib as ql
def printBasket(basket):
print ("%-20s %-20s %-20s %-20s %-20s %-20s" % ("Expiry", "Maturity", "Nominal", "Rate", "MarketVol", "Pay/Rec"))
print ("==================================================================================================================")
for i in range(0, len(basket)):
expiryDate = basket[i].swaptionExpiryDate()
endDate = basket[i].swaptionMaturityDate()
nominal = basket[i].swaptionNominal()
vol = basket[i].volatility().value()
rate = basket[i].swaptionStrike()
#type = basket[i].swaption.type()
print ("%-20s %-20s %-20f %-20f %-20f" % (str(expiryDate), str(endDate), nominal, rate, vol))
print("==================================================================================================================")
def printModelCalibration(basket, volatility):
print ("%-20s %-20s %-20s %-20s %-20s %-20s" % ("Expiry","Model sigma","ModelPrice","MarketPrice","Model impVol","Market impVol"))
print ("=================================================================================================================")
for i in range(0, len(basket)):
expiryDate = basket[i].swaptionExpiryDate()
modelValue = basket[i].modelValue()
marketValue= basket[i].marketValue()
impVol = basket[i].impliedVolatility(modelValue, 1e-6, 1000, 0.0, 2.0)
vol = basket[i].volatility().value()
print ("%-20s %-20f %-20f %-20f %-20f %-20f" % (str(expiryDate), volatility[i], modelValue, marketValue, impVol, vol))
print("==================================================================================================================")
refDate = ql.Date(30, 4, 2014) # Date refDate(30, April, 2014);
ql.Settings.instance().setEvaluationDate(refDate) # Settings::instance().evaluationDate() = refDate;
forward6mQuote = ql.QuoteHandle(ql.SimpleQuote(0.025))
# Handle<Quote> forward6mQuote(boost::make_shared(0.025));
oisQuote = ql.QuoteHandle(ql.SimpleQuote(0.02))
# Handle<Quote> oisQuote(boost::make_shared(0.02));
volQuote = ql.QuoteHandle(ql.SimpleQuote(0.2))
# Handle<Quote> volQuote(boost::make_shared(0.2));
dc = ql.Actual365Fixed()
yts6m = ql.FlatForward(refDate, forward6mQuote, dc)
ytsOis= ql.FlatForward(refDate, oisQuote, dc)
yts6m.enableExtrapolation()
ytsOis.enableExtrapolation()
hyts6m = ql.RelinkableYieldTermStructureHandle(yts6m)
t0_curve = ql.YieldTermStructureHandle(yts6m)
t0_Ois = ql.YieldTermStructureHandle(ytsOis)
euribor6m = ql.Euribor6M(hyts6m)
swaptionVol = ql.ConstantSwaptionVolatility(0, ql.TARGET(), ql.ModifiedFollowing, volQuote, ql.Actual365Fixed())
# Handle<SwaptionVolatilityStructure> swaptionVol(boost::make_shared(0, TARGET(), ModifiedFollowing, volQuote, Actual365Fixed()));
effectiveDate = ql.TARGET().advance(refDate, ql.Period('2D'))
# Date effectiveDate = TARGET().advance(refDate, 2 * Days);
maturityDate = ql.TARGET().advance(effectiveDate, ql.Period('10Y'))
# Date maturityDate = TARGET().advance(effectiveDate, 10 * Years);
fixedSchedule = ql.Schedule(effectiveDate,
maturityDate,
ql.Period('1Y'),
ql.TARGET(),
ql.ModifiedFollowing,
ql.ModifiedFollowing,
ql.DateGeneration.Forward, False)
# Schedule fixedSchedule(effectiveDate, maturityDate, 1 * Years, TARGET(), ModifiedFollowing, ModifiedFollowing, DateGeneration::Forward, false);
floatSchedule = ql.Schedule(effectiveDate,
maturityDate,
ql.Period('6M'),
ql.TARGET(),
ql.ModifiedFollowing,
ql.ModifiedFollowing,
ql.DateGeneration.Forward, False)
# Schedule floatingSchedule(effectiveDate, maturityDate, 6 * Months, TARGET(), ModifiedFollowing, ModifiedFollowing, DateGeneration::Forward, false);
# Vector input for the NonstandardSwap obj
fixedNominal = [1 for x in range(0,len(fixedSchedule)-1)]
floatingNominal = [1 for x in range(0,len(floatSchedule)-1)]
strike = [0.04 for x in range(0,len(fixedSchedule)-1)]
spread = [0 for x in range(0,len(floatSchedule)-1)]
gearing = [1 for x in range(0,len(floatSchedule)-1)]
underlying = ql.NonstandardSwap(ql.VanillaSwap.Payer,
fixedNominal, floatingNominal, fixedSchedule, strike,
ql.Thirty360(), floatSchedule,
euribor6m, gearing, spread, ql.Actual360(), False, False, ql.ModifiedFollowing)
# boost::shared_ptr<NonstandardSwap> underlying = boost::make_shared<NonstandardSwap>(VanillaSwap(VanillaSwap::Payer, 1.0, fixedSchedule, strike, Thirty360(), floatingSchedule, euribor6m, 0.00, Actual360()));
exerciseDates = [ql.TARGET().advance(x, -ql.Period('2D')) for x in fixedSchedule]
exerciseDates = exerciseDates[1:-1]
# std::vector<Date> exerciseDates;
# for (Size i = 1; i < 10; ++i)
# exerciseDates.push_back(TARGET().advance(fixedSchedule[i], -2 * Days));
exercise = ql.BermudanExercise(exerciseDates)
# boost::shared_ptr<Exercise> exercise = boost::make_shared<BermudanExercise>(exerciseDates, false);
swaption = ql.NonstandardSwaption(underlying,exercise,ql.Settlement.Physical)
# boost::shared_ptr<NonstandardSwaption> swaption = boost::make_shared<NonstandardSwaption>(underlying, exercise);
stepDates = exerciseDates[:-1]
# std::vector<Date> stepDates(exerciseDates.begin(), exerciseDates.end() - 1);
sigmas = [ql.QuoteHandle(ql.SimpleQuote(0.01)) for x in range(1, 10)]
# std::vector<Real> sigmas(stepDates.size() + 1, 0.01);
reversion = [ql.QuoteHandle(ql.SimpleQuote(0.01))]
# Real reversion = 0.01;
gsr = ql.Gsr(t0_curve, stepDates, sigmas, reversion)
# boost::shared_ptr<Gsr> gsr = boost::make_shared<Gsr>(yts6m, stepDates, sigmas, reversion);
swaptionEngine = ql.Gaussian1dSwaptionEngine(gsr, 64, 7.0, True, False, t0_Ois)
# boost::shared_ptr<PricingEngine> swaptionEngine = boost::make_shared<Gaussian1dSwaptionEngine>(gsr, 64, 7.0, true, false, ytsOis);
nonstandardSwaptionEngine = ql.Gaussian1dNonstandardSwaptionEngine(gsr, 64, 7.0, True, False, ql.QuoteHandle(ql.SimpleQuote(0)), t0_Ois)
# boost::shared_ptr<PricingEngine> nonstandardSwaptionEngine = boost::make_shared<Gaussian1dNonstandardSwaptionEngine>(gsr, 64, 7.0, true, false, Handle<Quote>(), ytsOis);
swaption.setPricingEngine(nonstandardSwaptionEngine)
# swaption->setPricingEngine(nonstandardSwaptionEngine);
swapBase = ql.EuriborSwapIsdaFixA(ql.Period('10Y'), t0_curve, t0_Ois)
# boost::shared_ptr<SwapIndex> swapBase = boost::make_shared<EuriborSwapIsdaFixA>(10 * Years, yts6m, ytsOis);
basket = swaption.calibrationBasket(swapBase, swaptionVol, 'Naive')
# std::vector<boost::shared_ptr<CalibrationHelper> > basket = swaption->calibrationBasket(swapBase, *swaptionVol, BasketGeneratingEngine::Naive);
for i in range(0, len(basket)):
basket[i].setPricingEngine(swaptionEngine)
# for (Size i = 0; i < basket.size(); ++i) basket[i]->setPricingEngine(swaptionEngine);
method = ql.LevenbergMarquardt()
# LevenbergMarquardt method;
ec = ql.EndCriteria(1000, 10, 1e-8, 1e-8, 1e-8)
# EndCriteria ec(1000, 10, 1E-8, 1E-8, 1E-8);
gsr.calibrateVolatilitiesIterative(basket, method, ec)
# gsr->calibrateVolatilitiesIterative(basket, method, ec);
printBasket(basket)
printModelCalibration(basket, gsr.volatility())
npv = swaption.NPV()
print(npv)
No comments:
Post a Comment