QuantLib C# / .Net binding
QuantLib .Net/‘C#’ Bindings
The original unmodified QuantLib financial analytics library can be used from the .Net/CLR (Common Language Runtime) family of languages through a wrapper interface. The C# interface has been a feature of QuantLib since 2005.
This interface is generated automatically using the SWIG and allows safe and efficient use of the underlying C++ code. The same underlying C++ code and the same interface files are used for all languages including the Python binding and the Java binding which means a level of consistency between the bindings.
At BN Algorithms we have substantial experience with delivering such wrappers to clients which include Exchanges, third party software providers and fund management companies. If you’d like us to help you with integration of QauntLib in your .Net application, contact us at webs@bnikolic.co.uk.
If you are looking for an alternative to Java binding to QuantLib, we offer ready-to-license wrapping of QuantLib and other libraries via REST interface, suitable for fast and durable development of applications: see following dedicated website and this blog post
Try as interactive Jupyter notebooks on MyBinder
You can try QuantLib-Net as Net Interactive Jupyter with binderhub. Current examples all from QuantLib-SWIG C# examples directory with minor adaptation to the notebook format:
Bermudan Swaption binder notebook
Equity Option binder notebook
Finite Difference Methods Comparison binder notebook
Builds of QuantLib for ‘C#’
Builds of QuantLib for the CLR/.Net/C# ecosystem are available on nuget at https://www.nuget.org/packages/QuantLib/ .
Example of using QuantLib from ‘C#’
Below is an example from the QuantLib-SWIG repository. You can find the other public examples at https://github.com/lballabio/QuantLib-SWIG/tree/master/CSharp/examples :
/*
Copyright (C) 2005 Dominic Thuillier
This file is part of QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/
QuantLib is free software: you can redistribute it and/or modify it
under the terms of the QuantLib license. You should have received a
copy of the license along with this program; if not, please email
<quantlib-dev@lists.sf.net>. The license is also available online at
<http://quantlib.org/license.shtml>.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
*/
using System;
using QuantLib;
namespace BermudanSwaption
{
class Run
{
private const int numRows = 5;
private const int numCols = 5;
private static int[] swapLengths = { 1, 2, 3, 4, 5 };
private static double[] swaptionVols = {
0.1490, 0.1340, 0.1228, 0.1189, 0.1148,
0.1290, 0.1201, 0.1146, 0.1108, 0.1040,
0.1149, 0.1112, 0.1070, 0.1010, 0.0957,
0.1047, 0.1021, 0.0980, 0.0951, 0.1270,
0.1000, 0.0950, 0.0900, 0.1230, 0.1160 };
private static void calibrateModel(
,
ShortRateModel model,
CalibrationHelperVector helpersdouble lambda )
{
= new Simplex( lambda );
Simplex om .calibrate(helpers, om,
modelnew EndCriteria(1000, 250, 1e-7, 1e-7, 1e-7));
// Output the implied Black volatilities
for (int i=0; i<numRows; i++)
{
int j = numCols - i -1; // 1x5, 2x4, 3x3, 4x2, 5x1
int k = i*numCols + j;
double npv =
.as_black_helper(helpers[i]).modelValue();
NQuantLibcdouble implied =
.as_black_helper(helpers[i]).impliedVolatility(
NQuantLibc,
npv1e-4,
1000,
0.05,
0.50 );
double diff = implied - swaptionVols[k];
.WriteLine( "{0}x{1}: model {2}, market {3} ({4})",
Console+1, swapLengths[j], implied, swaptionVols[k], diff );
i}
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
= DateTime.Now;
DateTime startTime
= new Date(15, Month.February, 2002);
Date todaysDate = new TARGET();
Calendar calendar = new Date(19, Month.February, 2002);
Date settlementDate .instance().setEvaluationDate( todaysDate );
Settings
// flat yield term structure impling 1x5 swap at 5%
= new SimpleQuote(0.04875825);
Quote flatRate = new FlatForward(
FlatForward myTermStructure ,
settlementDatenew QuoteHandle( flatRate ),
new Actual365Fixed() );
=
RelinkableYieldTermStructureHandle rhTermStructure new RelinkableYieldTermStructureHandle();
.linkTo( myTermStructure );
rhTermStructure
// Define the ATM/OTM/ITM swaps
= new Period(1,TimeUnit.Years);
Period fixedLegTenor =
BusinessDayConvention fixedLegConvention .Unadjusted;
BusinessDayConvention=
BusinessDayConvention floatingLegConvention .ModifiedFollowing;
BusinessDayConvention=
DayCounter fixedLegDayCounter new Thirty360( Thirty360.Convention.European );
= new Period(6,TimeUnit.Months);
Period floatingLegTenor double dummyFixedRate = 0.03;
= new Euribor6M( rhTermStructure );
IborIndex indexSixMonths
= calendar.advance(settlementDate,1,TimeUnit.Years,
Date startDate );
floatingLegConvention= calendar.advance(startDate,5,TimeUnit.Years,
Date maturity );
floatingLegConvention= new Schedule(startDate,maturity,
Schedule fixedSchedule ,calendar,fixedLegConvention,fixedLegConvention,
fixedLegTenor.Rule.Forward,false);
DateGeneration= new Schedule(startDate,maturity,
Schedule floatSchedule ,calendar,floatingLegConvention,
floatingLegTenor,DateGeneration.Rule.Forward,false);
floatingLegConvention= new VanillaSwap(
VanillaSwap swap .Type.Payer, 1000.0,
Swap, dummyFixedRate, fixedLegDayCounter,
fixedSchedule, indexSixMonths, 0.0,
floatSchedule.dayCounter());
indexSixMonths=
DiscountingSwapEngine swapEngine new DiscountingSwapEngine(rhTermStructure);
.setPricingEngine(swapEngine);
swapdouble fixedATMRate = swap.fairRate();
double fixedOTMRate = fixedATMRate * 1.2;
double fixedITMRate = fixedATMRate * 0.8;
= new VanillaSwap(
VanillaSwap atmSwap .Type.Payer, 1000.0,
Swap, fixedATMRate, fixedLegDayCounter,
fixedSchedule, indexSixMonths, 0.0,
floatSchedule.dayCounter() );
indexSixMonths= new VanillaSwap(
VanillaSwap otmSwap .Type.Payer, 1000.0,
Swap, fixedOTMRate, fixedLegDayCounter,
fixedSchedule, indexSixMonths, 0.0,
floatSchedule.dayCounter());
indexSixMonths= new VanillaSwap(
VanillaSwap itmSwap .Type.Payer, 1000.0,
Swap, fixedITMRate, fixedLegDayCounter,
fixedSchedule, indexSixMonths, 0.0,
floatSchedule.dayCounter());
indexSixMonths.setPricingEngine(swapEngine);
atmSwap.setPricingEngine(swapEngine);
otmSwap.setPricingEngine(swapEngine);
itmSwap
// defining the swaptions to be used in model calibration
= new PeriodVector();
PeriodVector swaptionMaturities .Add( new Period(1, TimeUnit.Years) );
swaptionMaturities.Add( new Period(2, TimeUnit.Years) );
swaptionMaturities.Add( new Period(3, TimeUnit.Years) );
swaptionMaturities.Add( new Period(4, TimeUnit.Years) );
swaptionMaturities.Add( new Period(5, TimeUnit.Years) );
swaptionMaturities
= new CalibrationHelperVector();
CalibrationHelperVector swaptions
// List of times that have to be included in the timegrid
= new DoubleVector();
DoubleVector times
for ( int i=0; i<numRows; i++) {
int j = numCols - i -1; // 1x5, 2x4, 3x3, 4x2, 5x1
int k = i*numCols + j;
= new SimpleQuote( swaptionVols[k] );
Quote vol = new SwaptionHelper(
SwaptionHelper helper [i],
swaptionMaturitiesnew Period(swapLengths[j], TimeUnit.Years),
new QuoteHandle(vol),
,
indexSixMonths.tenor(),
indexSixMonths.dayCounter(),
indexSixMonths.dayCounter(),
indexSixMonths);
rhTermStructure .Add( helper );
swaptions.AddRange( helper.times() );
times}
// Building time-grid
= new TimeGrid( times, 30);
TimeGrid grid
// defining the models
// G2 modelG2 = new G2(rhTermStructure));
= new HullWhite( rhTermStructure );
HullWhite modelHW = new HullWhite( rhTermStructure );
HullWhite modelHW2 = new BlackKarasinski( rhTermStructure );
BlackKarasinski modelBK
// model calibrations
// Console.WriteLine( "G2 (analytic formulae) calibration" );
// for (int i=0; i<swaptions.Count; i++)
// NQuantLibc.as_black_helper(swaptions[i]).setPricingEngine(
// new G2SwaptionEngine( modelG2, 6.0, 16 ) );
//
// calibrateModel( modelG2, swaptions, 0.05);
// Console.WriteLine( "calibrated to:" );
// Console.WriteLine( "a = " + modelG2.parameters()[0] );
// Console.WriteLine( "sigma = " + modelG2.parameters()[1] );
// Console.WriteLine( "b = " + modelG2.parameters()[2] );
// Console.WriteLine( "eta = " + modelG2.parameters()[3] );
// Console.WriteLine( "rho = " + modelG2.parameters()[4] );
.WriteLine( "Hull-White (analytic formulae) calibration" );
Consolefor (int i=0; i<swaptions.Count; i++)
.as_black_helper(swaptions[i]).setPricingEngine(
NQuantLibcnew JamshidianSwaptionEngine(modelHW));
calibrateModel( modelHW, swaptions, 0.05);
// Console.WriteLine( "calibrated to:" );
// Console.WriteLine( "a = " + modelHW.parameters()[0] );
// Console.WriteLine( "sigma = " + modelHW.parameters()[1] );
.WriteLine( "Hull-White (numerical) calibration" );
Consolefor (int i=0; i<swaptions.Count; i++)
.as_black_helper(swaptions[i]).setPricingEngine(
NQuantLibcnew TreeSwaptionEngine(modelHW2,grid));
calibrateModel(modelHW2, swaptions, 0.05);
// std::cout << "calibrated to:\n"
// << "a = " << modelHW2->params()[0] << ", "
// << "sigma = " << modelHW2->params()[1]
// << std::endl << std::endl;
.WriteLine( "Black-Karasinski (numerical) calibration" );
Consolefor (int i=0; i<swaptions.Count; i++)
.as_black_helper(swaptions[i]).setPricingEngine(
NQuantLibcnew TreeSwaptionEngine(modelBK,grid));
calibrateModel(modelBK, swaptions, 0.05);
// std::cout << "calibrated to:\n"
// << "a = " << modelBK->params()[0] << ", "
// << "sigma = " << modelBK->params()[1]
// << std::endl << std::endl;
// ATM Bermudan swaption pricing
.WriteLine( "Payer bermudan swaption struck at {0} (ATM)",
Console);
fixedATMRate
= new DateVector();
DateVector bermudanDates = new Schedule(startDate,maturity,
Schedule schedule new Period(3,TimeUnit.Months),calendar,
.Following,
BusinessDayConvention.Following,
BusinessDayConvention.Rule.Forward,false);
DateGeneration
for (uint i=0; i<schedule.size(); i++)
.Add( schedule.date( i ) );
bermudanDates= new BermudanExercise( bermudanDates );
Exercise bermudaExercise
=
Swaption bermudanSwaption new Swaption( atmSwap, bermudaExercise);
.setPricingEngine(
bermudanSwaptionnew TreeSwaptionEngine(modelHW, 50));
.WriteLine( "HW: " + bermudanSwaption.NPV() );
Console
.setPricingEngine(
bermudanSwaptionnew TreeSwaptionEngine(modelHW2, 50));
.WriteLine( "HW (num): " + bermudanSwaption.NPV() );
Console
.setPricingEngine(
bermudanSwaptionnew TreeSwaptionEngine(modelBK, 50));
.WriteLine( "BK (num): " + bermudanSwaption.NPV() );
Console
= DateTime.Now;
DateTime endTime = endTime - startTime;
TimeSpan delta .WriteLine();
Console.WriteLine("Run completed in {0} s", delta.TotalSeconds);
Console.WriteLine();
Console}
}
}
Copyright and published by: BN Algorihtms Ltd 2024. For general information only. Not to be relied for any purpose. Not advice about investment. No warranty of any kind. No liability for any use of this information accepted. Contact: webs@bnikolic.co.uk