You can subscribe to this list here.
2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
|
Dec
(60) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2001 |
Jan
(18) |
Feb
(4) |
Mar
(6) |
Apr
(2) |
May
|
Jun
(12) |
Jul
(48) |
Aug
(6) |
Sep
(3) |
Oct
(24) |
Nov
(15) |
Dec
(18) |
2002 |
Jan
(39) |
Feb
(12) |
Mar
(80) |
Apr
(72) |
May
(46) |
Jun
(27) |
Jul
(23) |
Aug
(34) |
Sep
(65) |
Oct
(71) |
Nov
(19) |
Dec
(14) |
2003 |
Jan
(44) |
Feb
(59) |
Mar
(18) |
Apr
(62) |
May
(54) |
Jun
(27) |
Jul
(46) |
Aug
(15) |
Sep
(44) |
Oct
(36) |
Nov
(19) |
Dec
(12) |
2004 |
Jan
(26) |
Feb
(33) |
Mar
(47) |
Apr
(63) |
May
(36) |
Jun
(65) |
Jul
(80) |
Aug
(163) |
Sep
(65) |
Oct
(39) |
Nov
(36) |
Dec
(39) |
2005 |
Jan
(97) |
Feb
(78) |
Mar
(64) |
Apr
(64) |
May
(48) |
Jun
(55) |
Jul
(89) |
Aug
(57) |
Sep
(51) |
Oct
(111) |
Nov
(86) |
Dec
(76) |
2006 |
Jan
(84) |
Feb
(103) |
Mar
(143) |
Apr
(92) |
May
(55) |
Jun
(58) |
Jul
(71) |
Aug
(57) |
Sep
(74) |
Oct
(59) |
Nov
(8) |
Dec
(32) |
2007 |
Jan
(60) |
Feb
(40) |
Mar
(50) |
Apr
(26) |
May
(61) |
Jun
(120) |
Jul
(119) |
Aug
(48) |
Sep
(121) |
Oct
(66) |
Nov
(103) |
Dec
(43) |
2008 |
Jan
(60) |
Feb
(109) |
Mar
(92) |
Apr
(106) |
May
(82) |
Jun
(59) |
Jul
(67) |
Aug
(118) |
Sep
(131) |
Oct
(56) |
Nov
(37) |
Dec
(69) |
2009 |
Jan
(75) |
Feb
(76) |
Mar
(103) |
Apr
(78) |
May
(61) |
Jun
(35) |
Jul
(66) |
Aug
(69) |
Sep
(166) |
Oct
(46) |
Nov
(72) |
Dec
(65) |
2010 |
Jan
(48) |
Feb
(57) |
Mar
(93) |
Apr
(85) |
May
(123) |
Jun
(82) |
Jul
(98) |
Aug
(121) |
Sep
(146) |
Oct
(86) |
Nov
(72) |
Dec
(34) |
2011 |
Jan
(96) |
Feb
(55) |
Mar
(73) |
Apr
(57) |
May
(33) |
Jun
(74) |
Jul
(89) |
Aug
(71) |
Sep
(103) |
Oct
(76) |
Nov
(52) |
Dec
(61) |
2012 |
Jan
(48) |
Feb
(54) |
Mar
(78) |
Apr
(60) |
May
(75) |
Jun
(59) |
Jul
(33) |
Aug
(66) |
Sep
(43) |
Oct
(46) |
Nov
(75) |
Dec
(51) |
2013 |
Jan
(112) |
Feb
(72) |
Mar
(49) |
Apr
(48) |
May
(42) |
Jun
(44) |
Jul
(80) |
Aug
(19) |
Sep
(33) |
Oct
(37) |
Nov
(38) |
Dec
(98) |
2014 |
Jan
(113) |
Feb
(93) |
Mar
(49) |
Apr
(106) |
May
(97) |
Jun
(155) |
Jul
(87) |
Aug
(127) |
Sep
(85) |
Oct
(48) |
Nov
(41) |
Dec
(37) |
2015 |
Jan
(34) |
Feb
(50) |
Mar
(104) |
Apr
(80) |
May
(82) |
Jun
(66) |
Jul
(41) |
Aug
(84) |
Sep
(37) |
Oct
(65) |
Nov
(83) |
Dec
(52) |
2016 |
Jan
(68) |
Feb
(35) |
Mar
(42) |
Apr
(35) |
May
(54) |
Jun
(75) |
Jul
(45) |
Aug
(52) |
Sep
(60) |
Oct
(52) |
Nov
(36) |
Dec
(64) |
2017 |
Jan
(92) |
Feb
(59) |
Mar
(35) |
Apr
(53) |
May
(83) |
Jun
(43) |
Jul
(65) |
Aug
(68) |
Sep
(46) |
Oct
(75) |
Nov
(40) |
Dec
(49) |
2018 |
Jan
(68) |
Feb
(54) |
Mar
(48) |
Apr
(58) |
May
(51) |
Jun
(44) |
Jul
(40) |
Aug
(68) |
Sep
(35) |
Oct
(15) |
Nov
(7) |
Dec
(37) |
2019 |
Jan
(43) |
Feb
(7) |
Mar
(22) |
Apr
(21) |
May
(31) |
Jun
(39) |
Jul
(73) |
Aug
(45) |
Sep
(47) |
Oct
(89) |
Nov
(19) |
Dec
(69) |
2020 |
Jan
(52) |
Feb
(63) |
Mar
(45) |
Apr
(59) |
May
(42) |
Jun
(57) |
Jul
(30) |
Aug
(29) |
Sep
(75) |
Oct
(64) |
Nov
(96) |
Dec
(22) |
2021 |
Jan
(14) |
Feb
(24) |
Mar
(35) |
Apr
(58) |
May
(36) |
Jun
(15) |
Jul
(18) |
Aug
(31) |
Sep
(30) |
Oct
(33) |
Nov
(27) |
Dec
(16) |
2022 |
Jan
(35) |
Feb
(22) |
Mar
(14) |
Apr
(20) |
May
(44) |
Jun
(53) |
Jul
(25) |
Aug
(56) |
Sep
(11) |
Oct
(47) |
Nov
(22) |
Dec
(36) |
2023 |
Jan
(30) |
Feb
(17) |
Mar
(31) |
Apr
(48) |
May
(31) |
Jun
(7) |
Jul
(25) |
Aug
(26) |
Sep
(61) |
Oct
(66) |
Nov
(19) |
Dec
(21) |
2024 |
Jan
(37) |
Feb
(29) |
Mar
(26) |
Apr
(26) |
May
(34) |
Jun
(9) |
Jul
(27) |
Aug
(13) |
Sep
(15) |
Oct
(25) |
Nov
(13) |
Dec
(8) |
2025 |
Jan
(13) |
Feb
(1) |
Mar
(16) |
Apr
(17) |
May
(8) |
Jun
(6) |
Jul
(9) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Stats S. <sta...@gm...> - 2025-07-30 11:23:07
|
Thanks, Luigi. Will do. On Fri, Jul 25, 2025 at 7:04 PM Luigi Ballabio <lui...@gm...> wrote: > Hi—it turns out that the rates coming out of the spreaded curve are not as > expected. If you calculate the original rates from the curve and then add > the spread, as you did in your sample code, you get > > >>> zero_rates = [ handle.zeroRate( l.date(), daycount, ql.Compounded, > ql.Monthly ).rate() for ii,l in enumerate(leg) ] > >>> print([r + zspread for r in zero_rates]) > [0.054693695527939915, 0.05243448138456887] > > while if you extract the same rates from the spreaded curve you get > > >>> print([ zspreaded_handle.zeroRate( l.date(), daycount, ql.Compounded, > ql.Monthly ).rate() for ii,l in enumerate(leg) ]) > [0.05502806821107864, 0.05226732979489501] > > The problem seems to be that the curve and the added spread have two > different day counters (act/360 for the curve and 30/360 for the spread) > and somehow ZeroSpreadedTermStructure fails to account for that. If the > two day counters are the same (either both 30/360 or both act/360) the > problem disappears, which is probably why nobody noticed until now. > > May you open an issue on GitHub so someone can pick it up and analyse it > further? Thanks! > > Luigi > > > > On Tue, Jun 10, 2025 at 6:17 AM Stats Student <sta...@gm...> > wrote: > >> Hi - I have been trying to use the spread from ql.CashFlows.zSpread to >> discount cash flows. I am able to use it in ZeroSpreadedTermStructure and >> get the right numbers. >> But I would like to understand how to replicate the same output by hand. >> The NPV I get is very close, but there is still a small difference which I >> suspect will likely get bigger over longer periods. >> >> Does anyone know what is causing this discrepancy? Thanks in advance. >> >> >> >> zspread: 0.009989751634951987 ( from ql.CashFlows.zSpread ) >> >> >> zSpread / ZeroSpreadedTermStructure npv: 198.6780*623718125 (CORRECT)* >> >> >> zSpread manual npv: 198.6780*7379166345* >> >> >> >> ########################################### >> >> >> import QuantLib as ql >> >> daycount = ql.Thirty360(ql.Thirty360.USA) >> >> start = ql.Date(1, 1, 2025) >> >> ql.Settings.instance().evaluationDate = start >> >> rates = ( ['SOFR1D', 4.3564348072], ['SOFR1W', 4.3493027605], ['SOFR1M', >> 4.3238954677], ['SOFR3M', 4.3084328938], ['SOFR6M', 4.2045895664] ) >> >> sofr_index = ql.Sofr() >> >> ois_helpers = [] >> >> for period, rate in rates: >> tenor = period.replace('SOFR','') >> ois_helpers.append( ql.OISRateHelper(0, >> ql.Period ( tenor ), >> >> ql.QuoteHandle(ql.SimpleQuote(rate/100)), >> sofr_index) ) >> >> curve = ql.PiecewiseLogCubicDiscount( start, ois_helpers, ql.Actual360() ) >> >> handle = ql.YieldTermStructureHandle( curve ) >> >> leg = ql.Leg( [ ql.SimpleCashFlow( 100, ql.Date(1,2,2025) ), >> ql.SimpleCashFlow( 100, ql.Date(1,3,2025) ) ] ) >> >> spreaded_npv = 198.6780623718125 >> >> zspread = ql.CashFlows.zSpread(leg, spreaded_npv, curve, daycount, >> ql.Compounded, ql.Monthly, True) >> >> print(f"zspread: {zspread}") # zspread: 0.009989751634951987 >> >> zspread_quote = ql.SimpleQuote( zspread ) >> >> zspreaded_curve = ql.ZeroSpreadedTermStructure( handle, >> ql.QuoteHandle(zspread_quote), ql.Compounded, ql.Monthly, daycount ) >> >> zspreaded_handle = ql.YieldTermStructureHandle( zspreaded_curve ) >> >> zspreaded_npv = ql.CashFlows.npv(leg, zspreaded_handle, True) >> >> print(f"zSpread ZeroSpreadedTermStructure npv: {zspreaded_npv}") # zSpread >> npv: 198.6780623718125 (MATCH) >> >> zero_rates = [ handle.zeroRate( l.date(), daycount, ql.Compounded, >> ql.Monthly ).rate() for ii,l in enumerate(leg) ] >> >> # zero_rates = [ handle.zeroRate( (ii+1)/12, ql.Compounded, ql.Monthly >> ).rate() for ii,l in enumerate(leg) ] # 198.67814955576728 (BIGGER >> DELTA) >> >> zpread_manual_npv = 100 / (1 + (zero_rates[0] + zspread) / 12) + 100 / ( >> 1 + (zero_rates[1] + zspread) / 12 ) ** 2 >> >> print(f"zSpread manual npv: {zpread_manual_npv}\n") # manual zSpread >> npv: 198.67807379166345 (*NO MATCH*) >> >> >> >> _______________________________________________ >> QuantLib-users mailing list >> Qua...@li... >> https://lists.sourceforge.net/lists/listinfo/quantlib-users >> > |
From: Luigi B. <lui...@gm...> - 2025-07-25 15:04:43
|
Hi—it turns out that the rates coming out of the spreaded curve are not as expected. If you calculate the original rates from the curve and then add the spread, as you did in your sample code, you get >>> zero_rates = [ handle.zeroRate( l.date(), daycount, ql.Compounded, ql.Monthly ).rate() for ii,l in enumerate(leg) ] >>> print([r + zspread for r in zero_rates]) [0.054693695527939915, 0.05243448138456887] while if you extract the same rates from the spreaded curve you get >>> print([ zspreaded_handle.zeroRate( l.date(), daycount, ql.Compounded, ql.Monthly ).rate() for ii,l in enumerate(leg) ]) [0.05502806821107864, 0.05226732979489501] The problem seems to be that the curve and the added spread have two different day counters (act/360 for the curve and 30/360 for the spread) and somehow ZeroSpreadedTermStructure fails to account for that. If the two day counters are the same (either both 30/360 or both act/360) the problem disappears, which is probably why nobody noticed until now. May you open an issue on GitHub so someone can pick it up and analyse it further? Thanks! Luigi On Tue, Jun 10, 2025 at 6:17 AM Stats Student <sta...@gm...> wrote: > Hi - I have been trying to use the spread from ql.CashFlows.zSpread to > discount cash flows. I am able to use it in ZeroSpreadedTermStructure and > get the right numbers. > But I would like to understand how to replicate the same output by hand. > The NPV I get is very close, but there is still a small difference which I > suspect will likely get bigger over longer periods. > > Does anyone know what is causing this discrepancy? Thanks in advance. > > > > zspread: 0.009989751634951987 ( from ql.CashFlows.zSpread ) > > > zSpread / ZeroSpreadedTermStructure npv: 198.6780*623718125 (CORRECT)* > > > zSpread manual npv: 198.6780*7379166345* > > > > ########################################### > > > import QuantLib as ql > > daycount = ql.Thirty360(ql.Thirty360.USA) > > start = ql.Date(1, 1, 2025) > > ql.Settings.instance().evaluationDate = start > > rates = ( ['SOFR1D', 4.3564348072], ['SOFR1W', 4.3493027605], ['SOFR1M', > 4.3238954677], ['SOFR3M', 4.3084328938], ['SOFR6M', 4.2045895664] ) > > sofr_index = ql.Sofr() > > ois_helpers = [] > > for period, rate in rates: > tenor = period.replace('SOFR','') > ois_helpers.append( ql.OISRateHelper(0, > ql.Period ( tenor ), > > ql.QuoteHandle(ql.SimpleQuote(rate/100)), > sofr_index) ) > > curve = ql.PiecewiseLogCubicDiscount( start, ois_helpers, ql.Actual360() ) > > handle = ql.YieldTermStructureHandle( curve ) > > leg = ql.Leg( [ ql.SimpleCashFlow( 100, ql.Date(1,2,2025) ), > ql.SimpleCashFlow( 100, ql.Date(1,3,2025) ) ] ) > > spreaded_npv = 198.6780623718125 > > zspread = ql.CashFlows.zSpread(leg, spreaded_npv, curve, daycount, > ql.Compounded, ql.Monthly, True) > > print(f"zspread: {zspread}") # zspread: 0.009989751634951987 > > zspread_quote = ql.SimpleQuote( zspread ) > > zspreaded_curve = ql.ZeroSpreadedTermStructure( handle, > ql.QuoteHandle(zspread_quote), ql.Compounded, ql.Monthly, daycount ) > > zspreaded_handle = ql.YieldTermStructureHandle( zspreaded_curve ) > > zspreaded_npv = ql.CashFlows.npv(leg, zspreaded_handle, True) > > print(f"zSpread ZeroSpreadedTermStructure npv: {zspreaded_npv}") # zSpread > npv: 198.6780623718125 (MATCH) > > zero_rates = [ handle.zeroRate( l.date(), daycount, ql.Compounded, > ql.Monthly ).rate() for ii,l in enumerate(leg) ] > > # zero_rates = [ handle.zeroRate( (ii+1)/12, ql.Compounded, ql.Monthly > ).rate() for ii,l in enumerate(leg) ] # 198.67814955576728 (BIGGER > DELTA) > > zpread_manual_npv = 100 / (1 + (zero_rates[0] + zspread) / 12) + 100 / ( 1 > + (zero_rates[1] + zspread) / 12 ) ** 2 > > print(f"zSpread manual npv: {zpread_manual_npv}\n") # manual zSpread npv: > 198.67807379166345 (*NO MATCH*) > > > > _______________________________________________ > QuantLib-users mailing list > Qua...@li... > https://lists.sourceforge.net/lists/listinfo/quantlib-users > |
From: Luigi B. <lui...@gm...> - 2025-07-23 10:25:18
|
QuantLib 1.39 is available for download at < https://www.quantlib.org/download.shtml>; precompiled binaries are also available from PyPI and NuGet for Python and C# respectively. The list of changes for this release is at < https://www.quantlib.org/reference/history.html>. Note that a few recent versions of the Visual C++ 2022 compiler (from 17.14.2 to 17.14.8) had a known bug that, unfortunately, affected QuantLib heavily and made it basically unusable. A fix was released in version 17.14.9; if you’re compiling QuantLib on Windows, make sure you're using at least that version (or, if you can't upgrade, use the Visual C++ 2019 toolset; you can do that from VC++ 2022, as well). Due to this, Python wheels for Windows are not yet available; they will be shortly, when GitHub action runners upgrade to the latest VC++ version. If you have any problems with this release, please report them here on the QuantLib mailing list (<qua...@li...>) or open a GitHub issue at <https://github.com/lballabio/quantlib/issues>. |
From: Luigi B. <lui...@gm...> - 2025-07-19 20:18:37
|
Hi Aaron, we use Boost 1.86 in our automated builds, as well as the latest 1.88. QuantLib 1.38 builds and tests correctly with both (see https://github.com/lballabio/QuantLib/actions/runs/16391531677/job/46318150792 or https://github.com/lballabio/QuantLib/actions/runs/16391531677/job/46318150804 for a couple of examples on Linux, but we run similar checks for Visual C++). The same goes for the code that will be released shortly as version 1.39. What compiler are you using? Do you get build errors while compiling QuantLib itself, or while compiling some code of yours that uses it? In any case, I'll need to see your compilation log to check what the issue is. Best, Luigi On Sat, Jul 19, 2025 at 1:52 AM Aaron De la Rosa <aar...@gm...> wrote: > Luigi > > There are some issues related to QuantLib and Boost. I can't build a > project using QuantLib 1.38 and Boost 1.86. There's no compatibility. > Boost 1.86 introduced some *template-related breaking changes* (especially > in accumulators), which older QuantLib versions (like 1.38) were not > designed to handle. QuantLib 1.38 is not fully compatible with Boost 1.86 > — errors stem from Boost's accumulators headers and deprecated > SpreadOption usage. > > What about QuantLib 1.39? QuantLib 1.39 could include better > compatibility with newer Boost versions. what do you think? > > Regards > > Aaron > > |
From: Aaron De la R. <aar...@gm...> - 2025-07-18 23:52:38
|
Luigi There are some issues related to QuantLib and Boost. I can't build a project using QuantLib 1.38 and Boost 1.86. There's no compatibility. Boost 1.86 introduced some template-related breaking changes (especially in accumulators), which older QuantLib versions (like 1.38) were not designed to handle. QuantLib 1.38 is not fully compatible with Boost 1.86 — errors stem from Boost's accumulators headers and deprecated SpreadOption usage. What about QuantLib 1.39? QuantLib 1.39 could include better compatibility with newer Boost versions. what do you think? Regards Aaron |
From: Ben W. <ben...@ma...> - 2025-07-15 21:03:26
|
Thanks Luigi, I think we will use a mix of Qantlib and python for this one. Warm Regards *Ben Watson, *CEO *Maroon Analytics Australia* Tel: +61 410 474 984 www.maroonanalytics.com *your edge on complexity* On Wed, 16 July 2025, 12:30 am Luigi Ballabio, <lui...@gm...> wrote: > Hello Ben, > there are a few classes that can be used to build a simulation (I'd > say MCLongstaffSchwartzEngine and LongstaffSchwartzPathPricer) but they're > in C++, not in Python, and I'm not sure if they can be exported as they're > templates and their type would depend on the simulation you're building. > The Hull-White process is available in Python instead. > > Luigi > > > On Wed, Jul 9, 2025 at 9:44 AM Ben Watson <ben...@ma...> > wrote: > >> Hi, >> >> We have the need to implement bermudian puttable bonds, where the bonds >> are resettable. So leaning towards a MC process and thinking about the >> early exit problem. Does Quantlib have the Longstaff-Schwartz American MC >> process implemented in a way we could use it with a Hull and White 1F MC as >> an example? >> >> If so, would that be in the Quantlib Python release? >> >> If not, are there other models that could be used in this use case? >> >> Warm Regards >> >> >> >> *Ben Watson, *CEO >> >> *Maroon Analytics Australia* >> >> Tel: +61 410 474 984 >> >> www.maroonanalytics.com >> >> *your edge on complexity* >> _______________________________________________ >> QuantLib-users mailing list >> Qua...@li... >> https://lists.sourceforge.net/lists/listinfo/quantlib-users >> > |
From: Luigi B. <lui...@gm...> - 2025-07-15 14:30:29
|
Hello Ben, there are a few classes that can be used to build a simulation (I'd say MCLongstaffSchwartzEngine and LongstaffSchwartzPathPricer) but they're in C++, not in Python, and I'm not sure if they can be exported as they're templates and their type would depend on the simulation you're building. The Hull-White process is available in Python instead. Luigi On Wed, Jul 9, 2025 at 9:44 AM Ben Watson <ben...@ma...> wrote: > Hi, > > We have the need to implement bermudian puttable bonds, where the bonds > are resettable. So leaning towards a MC process and thinking about the > early exit problem. Does Quantlib have the Longstaff-Schwartz American MC > process implemented in a way we could use it with a Hull and White 1F MC as > an example? > > If so, would that be in the Quantlib Python release? > > If not, are there other models that could be used in this use case? > > Warm Regards > > > > *Ben Watson, *CEO > > *Maroon Analytics Australia* > > Tel: +61 410 474 984 > > www.maroonanalytics.com > > *your edge on complexity* > _______________________________________________ > QuantLib-users mailing list > Qua...@li... > https://lists.sourceforge.net/lists/listinfo/quantlib-users > |
From: Ben W. <ben...@ma...> - 2025-07-09 07:43:52
|
Hi, We have the need to implement bermudian puttable bonds, where the bonds are resettable. So leaning towards a MC process and thinking about the early exit problem. Does Quantlib have the Longstaff-Schwartz American MC process implemented in a way we could use it with a Hull and White 1F MC as an example? If so, would that be in the Quantlib Python release? If not, are there other models that could be used in this use case? Warm Regards *Ben Watson, *CEO *Maroon Analytics Australia* Tel: +61 410 474 984 www.maroonanalytics.com *your edge on complexity* |
From: Luigi B. <lui...@gm...> - 2025-07-08 13:24:44
|
Hi all, a release candidate for QuantLib 1.39 is available at < https://github.com/lballabio/QuantLib/releases/tag/prerelease%2Fv1.39-rc>. If you have some time, please try it out and report any problems here on the mailing list. Thanks! Luigi |
From: Jonathan S. <sw...@gm...> - 2025-06-11 21:46:17
|
Hi Alex, I would try to add -g and remove -O2 from your CXXFLAGS for debugging. You can also try installing the CMake extension for VSCode and then choose one of the debug build presets. This should enforce consistent build flags between the examples and the library. 2025년 6월 12일 (목) 02:30, Alexandros Fragkiadakis <ale...@gm...>님이 작성: > Hi, > > I am trying to build Quatlib in MacOS and use it in debug mode (i.e I want > to be able to debug the core .cpp files) > > I used the instructions here https://www.quantlib.org/install/macosx.shtml > > I have installed boost using home-brew in: /opt/homebrew/include. I was > able to build using make command and the example of Bermudan swaption works > fine, when I run it from command line. So I assume the installation works. > > Folders: > /Users/alex/local/include/ql/ (containing the .hpp files) > /Users/alex/local/lib (containing libQuantLib.a and libQuantLib.dylib) > > Both have been created > > When I try to open the Quantlib folder with VSCode I was able to debug, > /QuantLib-1.38/Examples/CDS/CDS.cpp. (step into the file) > > > [image: image.png] > > > However, when I try to step into all the .cpp files of Quantlib (example > Date.cpp, TermStructure.cpp etc) I fail. When I put a breakpoint there in > any of the .cpp files inside ql folder I see “Module containing this > breakpoint has not yet loaded” > Also In the /ql folder I can see the .o file for date.cpp has been created. > > Is there another process I need to follow to build the library in a > “Debug” mode? Maybe an extra configuration when doing: > > ./configure --with-boost-include=/usr/local/include/ \ > --prefix=${HOME}/local/ \ > CXXFLAGS='-O2 -stdlib=libstdc++ -mmacosx-version-min=10.6' \ > LDFLAGS='-stdlib=libstdc++ -mmacosx-version-min=10.6' > > I have used the QuantLib in Visual Studio an d windows before and there > after the Build you could step into any file by default/ modify the core > code etc with no issues. > > Thanks, > Alex > _______________________________________________ > QuantLib-users mailing list > Qua...@li... > https://lists.sourceforge.net/lists/listinfo/quantlib-users > |
From: Alexandros F. <ale...@gm...> - 2025-06-11 17:27:27
|
Hi, I am trying to build Quatlib in MacOS and use it in debug mode (i.e I want to be able to debug the core .cpp files) I used the instructions here https://www.quantlib.org/install/macosx.shtml I have installed boost using home-brew in: /opt/homebrew/include. I was able to build using make command and the example of Bermudan swaption works fine, when I run it from command line. So I assume the installation works. Folders: /Users/alex/local/include/ql/ (containing the .hpp files) /Users/alex/local/lib (containing libQuantLib.a and libQuantLib.dylib) Both have been created When I try to open the Quantlib folder with VSCode I was able to debug, /QuantLib-1.38/Examples/CDS/CDS.cpp. (step into the file)  However, when I try to step into all the .cpp files of Quantlib (example Date.cpp, TermStructure.cpp etc) I fail. When I put a breakpoint there in any of the .cpp files inside ql folder I see “Module containing this breakpoint has not yet loaded” Also In the /ql folder I can see the .o file for date.cpp has been created. Is there another process I need to follow to build the library in a “Debug” mode? Maybe an extra configuration when doing: ./configure --with-boost-include=/usr/local/include/ \ --prefix=${HOME}/local/ \ CXXFLAGS='-O2 -stdlib=libstdc++ -mmacosx-version-min=10.6' \ LDFLAGS='-stdlib=libstdc++ -mmacosx-version-min=10.6' I have used the QuantLib in Visual Studio an d windows before and there after the Build you could step into any file by default/ modify the core code etc with no issues. Thanks, Alex |
From: Stats S. <sta...@gm...> - 2025-06-10 04:14:19
|
Hi - I have been trying to use the spread from ql.CashFlows.zSpread to discount cash flows. I am able to use it in ZeroSpreadedTermStructure and get the right numbers. But I would like to understand how to replicate the same output by hand. The NPV I get is very close, but there is still a small difference which I suspect will likely get bigger over longer periods. Does anyone know what is causing this discrepancy? Thanks in advance. zspread: 0.009989751634951987 ( from ql.CashFlows.zSpread ) zSpread / ZeroSpreadedTermStructure npv: 198.6780*623718125 (CORRECT)* zSpread manual npv: 198.6780*7379166345* ########################################### import QuantLib as ql daycount = ql.Thirty360(ql.Thirty360.USA) start = ql.Date(1, 1, 2025) ql.Settings.instance().evaluationDate = start rates = ( ['SOFR1D', 4.3564348072], ['SOFR1W', 4.3493027605], ['SOFR1M', 4.3238954677], ['SOFR3M', 4.3084328938], ['SOFR6M', 4.2045895664] ) sofr_index = ql.Sofr() ois_helpers = [] for period, rate in rates: tenor = period.replace('SOFR','') ois_helpers.append( ql.OISRateHelper(0, ql.Period ( tenor ), ql.QuoteHandle(ql.SimpleQuote(rate/100)), sofr_index) ) curve = ql.PiecewiseLogCubicDiscount( start, ois_helpers, ql.Actual360() ) handle = ql.YieldTermStructureHandle( curve ) leg = ql.Leg( [ ql.SimpleCashFlow( 100, ql.Date(1,2,2025) ), ql.SimpleCashFlow( 100, ql.Date(1,3,2025) ) ] ) spreaded_npv = 198.6780623718125 zspread = ql.CashFlows.zSpread(leg, spreaded_npv, curve, daycount, ql.Compounded, ql.Monthly, True) print(f"zspread: {zspread}") # zspread: 0.009989751634951987 zspread_quote = ql.SimpleQuote( zspread ) zspreaded_curve = ql.ZeroSpreadedTermStructure( handle, ql.QuoteHandle(zspread_quote), ql.Compounded, ql.Monthly, daycount ) zspreaded_handle = ql.YieldTermStructureHandle( zspreaded_curve ) zspreaded_npv = ql.CashFlows.npv(leg, zspreaded_handle, True) print(f"zSpread ZeroSpreadedTermStructure npv: {zspreaded_npv}") # zSpread npv: 198.6780623718125 (MATCH) zero_rates = [ handle.zeroRate( l.date(), daycount, ql.Compounded, ql.Monthly ).rate() for ii,l in enumerate(leg) ] # zero_rates = [ handle.zeroRate( (ii+1)/12, ql.Compounded, ql.Monthly ).rate() for ii,l in enumerate(leg) ] # 198.67814955576728 (BIGGER DELTA) zpread_manual_npv = 100 / (1 + (zero_rates[0] + zspread) / 12) + 100 / ( 1 + (zero_rates[1] + zspread) / 12 ) ** 2 print(f"zSpread manual npv: {zpread_manual_npv}\n") # manual zSpread npv: 198.67807379166345 (*NO MATCH*) |
From: Thomas O. <tho...@gm...> - 2025-06-09 14:06:14
|
Hi Luigi, While repeating the installation process to capture the output, I was not able to reproduce the problem. Everything works perfectly now. It was likely a local and isolated issue, possibly related to a disk write error. Apologies for the disturbance, and thank you for your attention. Best regards, Thomas Oliveira On Mon, Jun 9, 2025 at 12:30 PM Luigi Ballabio <lui...@gm...> wrote: > Hello Thomas, > it looks like all headers are missing in your installation directory, > not just ql/qldefines.hpp. > Can you post what command you used exactly to install, and what the output > was? Thanks! > > Luigi > > > On Fri, Jun 6, 2025 at 5:23 PM Thomas Oliveira <tho...@gm...> > wrote: > >> Dear QuantLib team, >> >> I followed the installation instructions for installing from a Git >> repository, as described here: >> https://www.quantlib.org/install/linux.shtml. >> >> Using the --prefix option with ./configure, I installed QuantLib into >> /home/foo/QuantLib/. The build was done in >> /home/foo/development/quant/QuantLib/. >> >> However, when compiling the BermudanSwaption example using: >> g++ BermudanSwaption.cpp -I/home/foo/QuantLib/include -o BermudanSwaption >> -L/home/foo/QuantLib/lib -lQuantLib >> the compiler could not find ql/qldefines.hpp. >> >> I noticed that qldefines.hpp was generated in >> /home/foo/development/quant/QuantLib/ql/, but it was not installed to >> /home/foo/QuantLib/include/ql/. >> >> In the end, I managed to compile using: >> g++ BermudanSwaption.cpp -I/home/foo/development/quant/QuantLib -o >> BermudanSwaption -L/home/foo/QuantLib/lib -lQuantLib >> >> The contents of both directories >> (/home/foo/development/quant/QuantLib/ql/ and >> /home/foo/QuantLib/include/ql/) are listed in the attached file for >> reference. >> >> Could you please check whether the installation process or Makefile >> should be adjusted to ensure this header is copied? >> >> Best regards, >> Thomas Oliveira >> _______________________________________________ >> QuantLib-users mailing list >> Qua...@li... >> https://lists.sourceforge.net/lists/listinfo/quantlib-users >> > |
From: Luigi B. <lui...@gm...> - 2025-06-09 10:31:00
|
Hello Thomas, it looks like all headers are missing in your installation directory, not just ql/qldefines.hpp. Can you post what command you used exactly to install, and what the output was? Thanks! Luigi On Fri, Jun 6, 2025 at 5:23 PM Thomas Oliveira <tho...@gm...> wrote: > Dear QuantLib team, > > I followed the installation instructions for installing from a Git > repository, as described here: > https://www.quantlib.org/install/linux.shtml. > > Using the --prefix option with ./configure, I installed QuantLib into > /home/foo/QuantLib/. The build was done in > /home/foo/development/quant/QuantLib/. > > However, when compiling the BermudanSwaption example using: > g++ BermudanSwaption.cpp -I/home/foo/QuantLib/include -o BermudanSwaption > -L/home/foo/QuantLib/lib -lQuantLib > the compiler could not find ql/qldefines.hpp. > > I noticed that qldefines.hpp was generated in > /home/foo/development/quant/QuantLib/ql/, but it was not installed to > /home/foo/QuantLib/include/ql/. > > In the end, I managed to compile using: > g++ BermudanSwaption.cpp -I/home/foo/development/quant/QuantLib -o > BermudanSwaption -L/home/foo/QuantLib/lib -lQuantLib > > The contents of both directories (/home/foo/development/quant/QuantLib/ql/ > and /home/foo/QuantLib/include/ql/) are listed in the attached file for > reference. > > Could you please check whether the installation process or Makefile should > be adjusted to ensure this header is copied? > > Best regards, > Thomas Oliveira > _______________________________________________ > QuantLib-users mailing list > Qua...@li... > https://lists.sourceforge.net/lists/listinfo/quantlib-users > |
From: Thomas O. <tho...@gm...> - 2025-06-06 15:23:29
|
Dear QuantLib team, I followed the installation instructions for installing from a Git repository, as described here: https://www.quantlib.org/install/linux.shtml. Using the --prefix option with ./configure, I installed QuantLib into /home/foo/QuantLib/. The build was done in /home/foo/development/quant/QuantLib/. However, when compiling the BermudanSwaption example using: g++ BermudanSwaption.cpp -I/home/foo/QuantLib/include -o BermudanSwaption -L/home/foo/QuantLib/lib -lQuantLib the compiler could not find ql/qldefines.hpp. I noticed that qldefines.hpp was generated in /home/foo/development/quant/QuantLib/ql/, but it was not installed to /home/foo/QuantLib/include/ql/. In the end, I managed to compile using: g++ BermudanSwaption.cpp -I/home/foo/development/quant/QuantLib -o BermudanSwaption -L/home/foo/QuantLib/lib -lQuantLib The contents of both directories (/home/foo/development/quant/QuantLib/ql/ and /home/foo/QuantLib/include/ql/) are listed in the attached file for reference. Could you please check whether the installation process or Makefile should be adjusted to ensure this header is copied? Best regards, Thomas Oliveira |
From: Stats S. <sta...@gm...> - 2025-05-28 04:58:25
|
Hi - I am trying to calculate the price of a discount bond on a path of short rates generated by a Hull White process. P(t, T) = 𝐴(𝑡,𝑇) exp( −𝐵(𝑡,𝑇)𝑟(𝑡) ) Example: 10y discount bond price 14 months from now, assuming one month increments. Is there a function in the QuantLib Python library that does this already? I have found the following implementation but am hesitant to use it because it seems to slightly differ from the formula in Hull's book. I am not a rates expert, so would appreciate any insight or feedback on how to do this. Many thanks. B = (1 - np.exp(-a * (T - t))) / a P_t = curve.discount(t) P_T = curve.discount(T) f_t = curve.forwardRate(t, t + 1e-5, ql.Continuous).rate() A = (P_T / P_t) * np.exp( B * f_t - (sigma**2 / (4 * a)) * (1 - np.exp(-2 * a * (T - t))) * B**2 ) return A * np.exp(-B * r_t) |
From: Luigi B. <lui...@gm...> - 2025-05-19 12:47:16
|
Hello João, if I understand your question correctly, I would create the swap schedule with the Unadjusted convention and specify ModifiedFollowing to adjust the payment dates. May you post your code so I can suggest where to put the changes? Best, Luigi On Tue, May 13, 2025 at 11:21 PM JOÃO FELIPE VILAS BOAS <B5...@fg...> wrote: > Good afternoon, > I'm currently encountering an issue while setting up an Overnight Indexed > Swap (OIS) in QuantLib using the CAD calendar. Specifically, the swap's > effective date falls on a weekend (e.g., a Saturday). When using the > ModifiedFollowing convention, QuantLib correctly adjusts the start of the > *schedule* to the next business day (i.e., Monday). However, the swap > does not appear to accrue interest properly from the Friday rate preceding > the weekend — unlike what is typically seen in Bloomberg. > In Bloomberg, there is a field called *Effective Date Adjustment*, which > allows configuration of how the effective date is adjusted (e.g., whether > it should be moved according to business day convention or left > unadjusted). I have not found a similar flag or mechanism in QuantLib to > apply this kind of granular control — particularly to adjust *only* the > effective date while preserving proper accrual logic (e.g., accruing the > Friday rate over the weekend). > My questions: > > 1. Is there a way in QuantLib to specify an adjusted effective date > (following a convention like ModifiedFollowing) while still ensuring > that the accrual of interest includes the weekend days from the last valid > fixing just in the effective date? > 2. Is there a recommended workaround or override to replicate > Bloomberg’s behavior in this scenario? > > Any guidance would be appreciated. > Best regards, > > _______________________________________________ > QuantLib-users mailing list > Qua...@li... > https://lists.sourceforge.net/lists/listinfo/quantlib-users > |
From: Marcin R. <mry...@gm...> - 2025-05-19 08:00:10
|
Hi Henry, The FX forward formula seems incorrect. Additionally, you need to calculate the forwards on the nodes of the MXN curve, and correct for the spot date. Something like this: # ====== Step 6: Calculate implied forward rates ====== print("\nImplied Forward USD/MXN Rates:") fx_spot_date = fx_calendar.advance(today, fixing_days, ql.Days, convention, end_of_month) for node, _ in mxn_curve.nodes()[1:]: # Calculate implied forward rate usd_discount = usd_curve.discount(node) usd_discount_spot = usd_curve.discount(fx_spot_date) mxn_discount = mxn_curve.discount(node) mxn_discount_spot = mxn_curve.discount(fx_spot_date) fwd_fx = spot_fx_usdmxn * (usd_discount / mxn_discount) * ( mxn_discount_spot / usd_discount_spot) points = (fwd_fx - spot_fx_usdmxn) * 10000 # Convert to pips print(f"{node}: {fwd_fx:.4f} (Points: {points:.1f})") Hope this helps. Cheers, Marcin On Sat, 17 May 2025 at 14:39, Henry Wu Hu <hen...@gm...> wrote: > Hello. I am trying to get implied fx forward using the FxRateSwapHelper. > Some how I am not able to get the same fx forward points when comparing > with the input. > > Am I missing something? All help is appreciated > > Thanks in advanced. > > > import QuantLib as ql > import datetime as dt > import numpy as np > import pandas as pd > > # Set evaluation date > today = ql.Date(16, 5, 2025) # May 16, 2025 > ql.Settings.instance().evaluationDate = today > > # ====== Step 1: Define market data ====== > # USD yield curve data (assuming we already have this) > usd_rate_dates = [ > today + ql.Period("1D"), > today + ql.Period("1W"), > today + ql.Period("1M"), > today + ql.Period("3M"), > today + ql.Period("6M"), > today + ql.Period("1Y"), > today + ql.Period("2Y"), > today + ql.Period("5Y") > ] > > usd_rates = [0.0520, 0.0525, 0.0530, 0.0535, 0.0540, 0.0550, 0.0560, > 0.0570] # Sample rates > > # FX Spot USDMXN rate > spot_fx_usdmxn = 17.8500 # USD/MXN spot rate > > # FX Swap points for different tenors (market quotes in pips) > fx_swap_tenors = [ql.Period("1M"), ql.Period("3M"), ql.Period("6M"), > ql.Period("1Y")] > fx_swap_points = [125, 375, 825, 1750] # Sample swap points in pips > > # ====== Step 2: Set up USD curve (base/collateral currency) ====== > usd_day_count = ql.Actual360() > usd_calendar = ql.UnitedStates(ql.UnitedStates.GovernmentBond) > usd_interpolation = ql.Linear() > usd_compounding = ql.Compounded > usd_compounding_freq = ql.Semiannual > > # Create USD deposit rate helpers > usd_rate_helpers = [] > for rate, maturity in zip(usd_rates, usd_rate_dates): > if maturity <= today + ql.Period("1Y"): # For maturities up to 1Y > days_to_maturity = (maturity - today) > usd_rate_helpers.append( > ql.DepositRateHelper( > ql.QuoteHandle(ql.SimpleQuote(rate)), > ql.Period(days_to_maturity, ql.Days), > 2, # fixing days > usd_calendar, > ql.ModifiedFollowing, > False, > usd_day_count > ) > ) > else: # For longer maturities, assume we're using swap rates > tenor_length = (maturity - today) / 365 # Approximate in years > usd_rate_helpers.append( > ql.SwapRateHelper( > ql.QuoteHandle(ql.SimpleQuote(rate)), > ql.Period(int(tenor_length), ql.Years), > usd_calendar, > ql.Semiannual, > ql.ModifiedFollowing, > usd_day_count, > ql.Euribor6M() # Example index, in reality would use > appropriate USD index > ) > ) > > # Build USD curve > usd_curve = ql.PiecewiseLinearZero( > today, usd_rate_helpers, usd_day_count > ) > usd_curve_handle = ql.YieldTermStructureHandle(usd_curve) > > # ====== Step 3: Set up FX swap rate helpers for MXN curve ====== > mxn_calendar = ql.Mexico() > # In FX markets, typically both calendars are considered > fx_calendar = ql.JointCalendar(usd_calendar, mxn_calendar) > fixing_days = 2 # Standard for FX markets > convention = ql.Following > end_of_month = False > # In USD/MXN, USD is the base currency, and if using USD as collateral: > is_fx_base_currency_collateral_currency = True > > # Create FX swap rate helpers > fx_swap_helpers = [] > for tenor, points in zip(fx_swap_tenors, fx_swap_points): > # Convert swap points from pips to decimal > swap_point_decimal = points / 10000.0 > > fx_swap_helpers.append( > ql.FxSwapRateHelper( > ql.QuoteHandle(ql.SimpleQuote(swap_point_decimal)), > ql.QuoteHandle(ql.SimpleQuote(spot_fx_usdmxn)), > tenor, > fixing_days, > fx_calendar, > convention, > end_of_month, > is_fx_base_currency_collateral_currency, > usd_curve_handle > ) > ) > > # ====== Step 4: Build MXN curve ====== > mxn_day_count = ql.Actual360() > mxn_curve = ql.PiecewiseLinearZero( > today, fx_swap_helpers, mxn_day_count > ) > > # ====== Step 5: Analyze the results ====== > print(f"Evaluation date: {today.ISO()}") > print(f"USD/MXN Spot Rate: {spot_fx_usdmxn}") > print("\nUSD Zero Rates:") > for date, rate in zip(usd_rate_dates, usd_rates): > days = (date - today) > print(f"{days} days: {rate*100:.4f}%") > > print("\nImplied MXN Zero Rates:") > for tenor in fx_swap_tenors: > date = today + tenor > mxn_zero_rate = mxn_curve.zeroRate( > date, mxn_day_count, ql.Continuous).rate() > print(f"{tenor}: {mxn_zero_rate*100:.4f}%") > > # ====== Step 6: Calculate implied forward rates ====== > print("\nImplied Forward USD/MXN Rates:") > for tenor in fx_swap_tenors: > date = today + tenor > # Calculate implied forward rate > usd_discount = usd_curve.discount(date) > mxn_discount = mxn_curve.discount(date) > fwd_fx = spot_fx_usdmxn * (mxn_discount / usd_discount) > > points = (fwd_fx - spot_fx_usdmxn) * 10000 # Convert to pips > print(f"{tenor}: {fwd_fx:.4f} (Points: {points:.1f})") > > Best Regards > Henry Wu Hu > _______________________________________________ > QuantLib-users mailing list > Qua...@li... > https://lists.sourceforge.net/lists/listinfo/quantlib-users > |
From: Henry Wu Hu <hen...@gm...> - 2025-05-17 12:37:58
|
Hello. I am trying to get implied fx forward using the FxRateSwapHelper. Some how I am not able to get the same fx forward points when comparing with the input. Am I missing something? All help is appreciated Thanks in advanced. import QuantLib as ql import datetime as dt import numpy as np import pandas as pd # Set evaluation date today = ql.Date(16, 5, 2025) # May 16, 2025 ql.Settings.instance().evaluationDate = today # ====== Step 1: Define market data ====== # USD yield curve data (assuming we already have this) usd_rate_dates = [ today + ql.Period("1D"), today + ql.Period("1W"), today + ql.Period("1M"), today + ql.Period("3M"), today + ql.Period("6M"), today + ql.Period("1Y"), today + ql.Period("2Y"), today + ql.Period("5Y") ] usd_rates = [0.0520, 0.0525, 0.0530, 0.0535, 0.0540, 0.0550, 0.0560, 0.0570] # Sample rates # FX Spot USDMXN rate spot_fx_usdmxn = 17.8500 # USD/MXN spot rate # FX Swap points for different tenors (market quotes in pips) fx_swap_tenors = [ql.Period("1M"), ql.Period("3M"), ql.Period("6M"), ql.Period("1Y")] fx_swap_points = [125, 375, 825, 1750] # Sample swap points in pips # ====== Step 2: Set up USD curve (base/collateral currency) ====== usd_day_count = ql.Actual360() usd_calendar = ql.UnitedStates(ql.UnitedStates.GovernmentBond) usd_interpolation = ql.Linear() usd_compounding = ql.Compounded usd_compounding_freq = ql.Semiannual # Create USD deposit rate helpers usd_rate_helpers = [] for rate, maturity in zip(usd_rates, usd_rate_dates): if maturity <= today + ql.Period("1Y"): # For maturities up to 1Y days_to_maturity = (maturity - today) usd_rate_helpers.append( ql.DepositRateHelper( ql.QuoteHandle(ql.SimpleQuote(rate)), ql.Period(days_to_maturity, ql.Days), 2, # fixing days usd_calendar, ql.ModifiedFollowing, False, usd_day_count ) ) else: # For longer maturities, assume we're using swap rates tenor_length = (maturity - today) / 365 # Approximate in years usd_rate_helpers.append( ql.SwapRateHelper( ql.QuoteHandle(ql.SimpleQuote(rate)), ql.Period(int(tenor_length), ql.Years), usd_calendar, ql.Semiannual, ql.ModifiedFollowing, usd_day_count, ql.Euribor6M() # Example index, in reality would use appropriate USD index ) ) # Build USD curve usd_curve = ql.PiecewiseLinearZero( today, usd_rate_helpers, usd_day_count ) usd_curve_handle = ql.YieldTermStructureHandle(usd_curve) # ====== Step 3: Set up FX swap rate helpers for MXN curve ====== mxn_calendar = ql.Mexico() # In FX markets, typically both calendars are considered fx_calendar = ql.JointCalendar(usd_calendar, mxn_calendar) fixing_days = 2 # Standard for FX markets convention = ql.Following end_of_month = False # In USD/MXN, USD is the base currency, and if using USD as collateral: is_fx_base_currency_collateral_currency = True # Create FX swap rate helpers fx_swap_helpers = [] for tenor, points in zip(fx_swap_tenors, fx_swap_points): # Convert swap points from pips to decimal swap_point_decimal = points / 10000.0 fx_swap_helpers.append( ql.FxSwapRateHelper( ql.QuoteHandle(ql.SimpleQuote(swap_point_decimal)), ql.QuoteHandle(ql.SimpleQuote(spot_fx_usdmxn)), tenor, fixing_days, fx_calendar, convention, end_of_month, is_fx_base_currency_collateral_currency, usd_curve_handle ) ) # ====== Step 4: Build MXN curve ====== mxn_day_count = ql.Actual360() mxn_curve = ql.PiecewiseLinearZero( today, fx_swap_helpers, mxn_day_count ) # ====== Step 5: Analyze the results ====== print(f"Evaluation date: {today.ISO()}") print(f"USD/MXN Spot Rate: {spot_fx_usdmxn}") print("\nUSD Zero Rates:") for date, rate in zip(usd_rate_dates, usd_rates): days = (date - today) print(f"{days} days: {rate*100:.4f}%") print("\nImplied MXN Zero Rates:") for tenor in fx_swap_tenors: date = today + tenor mxn_zero_rate = mxn_curve.zeroRate( date, mxn_day_count, ql.Continuous).rate() print(f"{tenor}: {mxn_zero_rate*100:.4f}%") # ====== Step 6: Calculate implied forward rates ====== print("\nImplied Forward USD/MXN Rates:") for tenor in fx_swap_tenors: date = today + tenor # Calculate implied forward rate usd_discount = usd_curve.discount(date) mxn_discount = mxn_curve.discount(date) fwd_fx = spot_fx_usdmxn * (mxn_discount / usd_discount) points = (fwd_fx - spot_fx_usdmxn) * 10000 # Convert to pips print(f"{tenor}: {fwd_fx:.4f} (Points: {points:.1f})") Best Regards Henry Wu Hu |
From: Peter C. <pca...@gm...> - 2025-05-17 07:49:52
|
Dear all, We will be hosting a meeting in London on June 3rd with presentations on the latest in Open-Source Risk Engine and QuantLib - the former is based on the latter, as you might know. There will also be talks on more general quant finance topics. I will attach the full invite below. Would be nice to see you there. Best Peter We’re delighted to invite you to the LSEG Post Trade Solutions (formerly Acadia) *Quant Summit*, taking place at the *LSEG Headquarters* in *London * on *Tuesday 3rd June*. Join us for an exciting day of insights and innovation in quantitative finance, bringing together leading professionals to share their expertise. You are invited to attend our morning Open-Source Risk Engine Technical Masterclass, and/or our afternoon Quant Summit packed with presentations and panels from industry leaders. This free-to-attend event is ideal for Heads of Traded Risk/XVA/Model Validation and Senior Quants supporting FO, risk or model validation and Quant Developers. It’s a fantastic opportunity to exchange ideas and connect with peers from across the industry. Feel free to share with colleagues who may be interested. The link below provides details on the agenda and registration form. https://solutions.lseg.com/Quant_Summit_London_2025 Register now to secure your place. We look forward to welcoming you! |
From: JOÃO F. V. B. <B5...@fg...> - 2025-05-13 21:18:14
|
Good afternoon, I'm currently encountering an issue while setting up an Overnight Indexed Swap (OIS) in QuantLib using the CAD calendar. Specifically, the swap's effective date falls on a weekend (e.g., a Saturday). When using the ModifiedFollowing convention, QuantLib correctly adjusts the start of the schedule to the next business day (i.e., Monday). However, the swap does not appear to accrue interest properly from the Friday rate preceding the weekend — unlike what is typically seen in Bloomberg. In Bloomberg, there is a field called Effective Date Adjustment, which allows configuration of how the effective date is adjusted (e.g., whether it should be moved according to business day convention or left unadjusted). I have not found a similar flag or mechanism in QuantLib to apply this kind of granular control — particularly to adjust only the effective date while preserving proper accrual logic (e.g., accruing the Friday rate over the weekend). My questions: 1. Is there a way in QuantLib to specify an adjusted effective date (following a convention like ModifiedFollowing) while still ensuring that the accrual of interest includes the weekend days from the last valid fixing just in the effective date? 2. Is there a recommended workaround or override to replicate Bloomberg’s behavior in this scenario? Any guidance would be appreciated. Best regards, |
From: Alexander <ale...@gm...> - 2025-05-09 08:14:26
|
Hi, I've been tinkering quite a bit with Quantlib for pricing commodity options - in particular the discrete arithmetic asian option pricing engines have been very neat. Is it also possible to price asian spread options in QuantLib, that settles as the spread between two averages such as: https://www.ice.com/products/57269835 (average of 3.5% rdam vs average of ICE Brent). An additional challenge is that the spread is negative. The Kirk engine only supports spreads without the asian element. Many thanks |
From: Gregory Z. <gre...@gm...> - 2025-05-01 00:43:10
|
I managed to get the SABR model to calibrate correctly by fixing the Beta parameter and removing short expiries (<1y). It seems that the short expiries were unable to be calibrated within the 1% tolerance, which I couldn't figure out how to change in python. Thanks, Greg On Mon, Apr 28, 2025 at 2:53 PM Gregory Zuroff <gre...@gm...> wrote: > Hello, > > I am hoping for some guidance in how to use the ql.SabrSwaptionVolatilityCube > class in python. I have been able to successfully use ql. > InterpolatedSwaptionVolatilityCube for pricing SOFR swaptions and would > like to be able to compare the pricing with a SABR model. > > Rather than sharing all of the data that goes into these classes, it may > be easier to show the working parameters for ql. > InterpolatedSwaptionVolatilityCube. > > vol_cube = ql.InterpolatedSwaptionVolatilityCube( > > ql.SwaptionVolatilityStructureHandle(swaptionVolMatrix), > > expiry_tenors, > > swap_tenors, > > [x / 10_000 for x in range(-100, 150, 50)], > > skew, > > base_index, > > base_index, > > False > > ) > > > When I try to take the same parameters and pass them to the SABR model, it > successfully creates the object. > > > vol_cube = ql.SabrSwaptionVolatilityCube( > > ql.SwaptionVolatilityStructureHandle(swaptionVolMatrix), > > expiry_tenors, > > swap_tenors, > > [x / 10_000 for x in range(-100, 150, 50)], > > skew, > > base_index, > > base_index, > > False, > > [[ql.QuoteHandle(ql.SimpleQuote(x)) for x in row] for row in > [(0.1, 0.1, 0.1, 0.1)] * (len(expiry_tenors) * len(swap_tenors))], > > [False, False, False, False], > > True > > ) > > > However, I am not sure how to calibrate the cube. When I try the exposed > methods like volCubeAtmCalibrated() I get an error saying that alpha must > be positive, not nan. > > Could anyone please provide guidance on how to use the SABR model, or if > it even works properly in python? > > Thank you, > Greg > > |
From: Aleksis A. R. <ale...@go...> - 2025-04-30 13:40:36
|
apologies for this, the StrippedOptionlet class does exactly what I needed. > On Apr 30, 2025, at 08:59, Aleksis Ali Raza <ale...@go...> wrote: > > In Quantlib python, the standard methodology I currently employ for building a capfloor volatility surface is: > > 1/ start with a matrix of cap/floor volatilities for a range of (fixed) strikes and a set of maturities > 2/ use the CapFloorVolTermSurface class to construct the interpolated cap floor vol surface term structure > 3/ strip this cap/floor surface using the OptionletStripper1 class to get an optionlet (caplet/floorlet) surface > 4/ feed this stripped structure into a StrippedOptionletAdapter class > 5/ apply a OptionVolatilityStructureHandle to the adapted structure to option the final surface > > The final surface can then be fed into a pricing engine for valuation…etc. > > What if my starting point is a matrix of optionlet volatilities for a range of strikes and a set of maturities? Is it possible to obtain the OptionletVolatilityStructureHandle from this data directly without having to go through the stripping process? > > Thanks, Aleksis |
From: Aleksis A. R. <ale...@go...> - 2025-04-30 03:59:47
|
In Quantlib python, the standard methodology I currently employ for building a capfloor volatility surface is: 1/ start with a matrix of cap/floor volatilities for a range of (fixed) strikes and a set of maturities 2/ use the CapFloorVolTermSurface class to construct the interpolated cap floor vol surface term structure 3/ strip this cap/floor surface using the OptionletStripper1 class to get an optionlet (caplet/floorlet) surface 4/ feed this stripped structure into a StrippedOptionletAdapter class 5/ apply a OptionVolatilityStructureHandle to the adapted structure to option the final surface The final surface can then be fed into a pricing engine for valuation…etc. What if my starting point is a matrix of optionlet volatilities for a range of strikes and a set of maturities? Is it possible to obtain the OptionletVolatilityStructureHandle from this data directly without having to go through the stripping process? Thanks, Aleksis |