├── .gitattributes
├── .github
├── dependabot.yml
└── workflows
│ └── quantlib-risks.yml
├── .gitignore
├── .gitmodules
├── CHANGELOG.md
├── CMakeLists.txt
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── ChangeLog.txt
├── LICENSE.md
├── Python
├── CMakeLists.txt
├── QuantLib_Risks
│ ├── CMakeLists.txt
│ ├── __init__.py
│ ├── converters.cpp
│ └── converters.hpp
├── README.md
├── build_extensions.py.in
├── examples
│ ├── README.md
│ ├── american-option.py
│ ├── basket-option.py
│ ├── bermudan-swaption.py
│ ├── bonds.py
│ ├── callablebonds.py
│ ├── capsfloors.py
│ ├── cashflows.py
│ ├── cds.py
│ ├── european-option.py
│ ├── gaussian1d-models.py
│ ├── global-bootstrap.py
│ ├── isda-engine.py
│ ├── multicurve-bootstrapping.py
│ ├── slv.py
│ ├── swap-adjoint.py
│ ├── swap.py
│ └── swing.py
├── pyproject.toml.in
├── run_tests.bat
├── run_tests.sh
└── test
│ ├── QuantLibTestSuite.py
│ ├── __init__.py
│ ├── test_americanquantooption.py
│ ├── test_assetswap.py
│ ├── test_blackformula.py
│ ├── test_bondfunctions.py
│ ├── test_bonds.py
│ ├── test_calendars.py
│ ├── test_capfloor.py
│ ├── test_cms.py
│ ├── test_coupons.py
│ ├── test_currencies.py
│ ├── test_date.py
│ ├── test_daycounters.py
│ ├── test_equityindex.py
│ ├── test_extrapolation.py
│ ├── test_fdm.py
│ ├── test_iborindex.py
│ ├── test_inflation.py
│ ├── test_instruments.py
│ ├── test_integrals.py
│ ├── test_marketelements.py
│ ├── test_ode.py
│ ├── test_options.py
│ ├── test_ratehelpers.py
│ ├── test_risks.py
│ ├── test_sabr.py
│ ├── test_slv.py
│ ├── test_solvers1d.py
│ ├── test_swap.py
│ ├── test_swaption.py
│ ├── test_termstructures.py
│ └── test_volatilities.py
├── README.md
├── SWIG
├── asianoptions.i
├── barrieroptions.i
├── basketoptions.i
├── blackformula.i
├── bondfunctions.i
├── bonds.i
├── calendars.i
├── calibratedmodel.i
├── calibrationhelpers.i
├── capfloor.i
├── cashflows.i
├── cliquetoptions.i
├── common.i
├── convertiblebonds.i
├── credit.i
├── creditdefaultswap.i
├── currencies.i
├── date.i
├── date_extra.i
├── daycounters.i
├── defaultprobability.i
├── discountcurve.i
├── distributions.i
├── dividends.i
├── exchangerates.i
├── exercise.i
├── fdm.i
├── fdm_extra.i
├── fittedbondcurve.i
├── forward.i
├── forwardcurve.i
├── fra.i
├── functions.i
├── futures.i
├── gaussian1dmodel.i
├── grid.i
├── indexes.i
├── inflation.i
├── instruments.i
├── integrals.i
├── interestrate.i
├── interpolation.i
├── lazyobject.i
├── linearalgebra.i
├── lmm.i
├── localvolatilities.i
├── lookbackoptions.i
├── marketelements.i
├── money.i
├── montecarlo.i
├── null.i
├── observer.i
├── ode.i
├── old_volatility.i
├── operators.i
├── optimizers.i
├── options.i
├── parameter.i
├── payoffs.i
├── piecewiseyieldcurve.i
├── ql.i
├── quantlib.i
├── randomnumbers.i
├── ratehelpers.i
├── rounding.i
├── sampledcurve.i
├── scheduler.i
├── settings.i
├── shortratemodels.i
├── slv.i
├── spreadoption.i
├── statistics.i
├── stochasticprocess.i
├── swap.i
├── swaption.i
├── swingoption.i
├── tape.i
├── termstructures.i
├── timebasket.i
├── timeseries.i
├── tracing.i
├── tuple.i
├── types.i
├── vectors.i
├── vectors_extra.i
├── volatilities.i
├── volatilitymodels.i
└── zerocurve.i
├── binder
├── labconfig
│ └── default_setting_overrides.json
├── postBuild
└── requirements.txt
└── tools
├── prebuild_ql-risks.bat
└── prebuild_ql-risks.sh
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.i linguist-detectable=false
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 |
4 | - package-ecosystem: "github-actions"
5 | directory: "/"
6 | schedule:
7 | # Check for updates to GitHub Actions every weekday
8 | interval: "weekly"
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compilation artifacts
2 | Python/QuantLib/quantlib_wrap.cpp
3 | Python/.cache/
4 | Python/QuantLib.egg-info
5 | Python/QuantLib_Python.egg-info
6 | Python/dist
7 | Python/examples/*.ipynb
8 | Python/examples/.ipynb_checkpoints
9 |
10 | # Build outputs
11 | **/x64/Debug
12 | **/x64/Release
13 | **/Debug
14 | **/Release
15 | **/bin/*.xml
16 | **/bin/*.manifest
17 |
18 | # CLion
19 | .idea
20 | cmake-build-debug
21 |
22 | # Artifacts created in multiple directories
23 | Makefile
24 | Makefile.in
25 | testCaseCollection.xml
26 | .deps
27 | .libs
28 | *.la
29 | *.lo
30 | *.o
31 | *.so
32 | *.dylib
33 | .build-stamp
34 | *.pyc
35 | *.exe
36 | *.dll
37 | *.exp
38 | *.lib
39 | *.pdb
40 | *.ilk
41 | *.class
42 | *~
43 | *.ncb
44 | *.suo
45 | *.vcproj.*.user
46 | *.vcxproj.user
47 | *.VC.db
48 | *.VC.opendb
49 | *.log
50 | *.sdf
51 | *.opensdf
52 | *.pch
53 | *.idb
54 | *.ipch
55 |
56 | # Outputs
57 | Python/QuantLib_Risks/QuantLib_Risks.py
58 | Python/build
59 |
60 | .vscode
61 | **/venv
62 | /build
63 | **/.venv
64 | __pycache__
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "lib/QuantLib"]
2 | path = lib/QuantLib
3 | url = https://github.com/lballabio/QuantLib.git
4 | [submodule "lib/xad"]
5 | path = lib/xad
6 | url = https://github.com/auto-differentiation/xad.git
7 | [submodule "lib/QuantLib-Risks-Cpp"]
8 | path = lib/QuantLib-Risks-Cpp
9 | url = https://github.com/auto-differentiation/QuantLib-Risks-Cpp.git
10 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # ChangeLog
2 |
3 | This log is to be read in conjunction with [ChangeLog.txt](./ChangeLog.txt).
4 | It lists the QuantLib-Risks specific changes on top of what is already listed in
5 | the underlying QuantLib-SWIG changelog.
6 |
7 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
8 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
9 |
10 | ## [1.33.3] - 2024-04-04
11 |
12 | - Builds against renamed xad-autodiff -> xad Python package
13 | - Cleanup of repository
14 |
15 | ## [1.33.2] - 2024-03-29
16 |
17 | - Renaming quantlib-risks -> QuantLib-Risks for consistency
18 | - Fixing markdown annotations in examples
19 | - otherwise technically identical
20 |
21 | ## [1.33] - 2024-03-25
22 |
23 | Initial release, matching QuantLib Python bindings version 1.33
24 |
25 |
26 | [1.33.3]: https://github.com/auto-differentiation/QuantLib-Risks-Py/compare/v1.33.2...v1.33.3
27 |
28 | [1.33.2]: https://github.com/auto-differentiation/QuantLib-Risks-Py/compare/v1.33...v1.33.2
29 |
30 | [1.33]: https://github.com/auto-differentiation/QuantLib-Risks-Py/releases/tag/v1.33
31 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ##############################################################################
2 | # CMake file for QuantLib-Risks. The version set here is used for the Python
3 | # package.
4 | #
5 | # This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
6 | # for risk computation using automatic differentiation. It uses XAD,
7 | # a fast and comprehensive C++ library for automatic differentiation.
8 | #
9 | # Copyright (C) 2010-2024 Xcelerit Computing Ltd.
10 | #
11 | # This program is free software: you can redistribute it and/or modify
12 | # it under the terms of the GNU Affero General Public License as published
13 | # by the Free Software Foundation, either version 3 of the License, or
14 | # (at your option) any later version.
15 | #
16 | # This program is distributed in the hope that it will be useful,
17 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | # GNU Affero General Public License for more details.
20 | #
21 | # You should have received a copy of the GNU Affero General Public License
22 | # along with this program. If not, see .
23 | #
24 | ##############################################################################
25 |
26 | cmake_minimum_required(VERSION 3.15.0)
27 | project(QuantLib_Risks LANGUAGES CXX VERSION 1.33.3)
28 |
29 | # For MSVC RUNTIME LIBRARY, need CMP0091=NEW and cmake 3.15+
30 | cmake_policy(SET CMP0091 NEW)
31 | set(PACKAGE_VERSION "${PROJECT_VERSION}")
32 | set(PACKAGE_VERSION_HEX "0x013303f0")
33 | set(QLR_VERSION ${PACKAGE_VERSION})
34 | set(QLR_HEX_VERSION ${PACKAGE_VERSION_HEX})
35 |
36 |
37 | find_package(QuantLib-Risks REQUIRED)
38 | find_package(SWIG REQUIRED)
39 |
40 | include(UseSWIG)
41 |
42 | enable_testing()
43 |
44 |
45 | add_subdirectory(Python)
46 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to contribute
2 |
3 | We love pull requests from everyone. By participating in this project, you agree to abide
4 | by our [code of conduct](CODE_OF_CONDUCT.md).
5 |
6 | Note that this fork is importing all changes from the QuantLib-SWIG repository on each
7 | release. Changes related to QuantLib's own Python bindings will be included in each new
8 | release.
9 | Contributions to this repository should only be made if they are related to building
10 | the Python bindings for QuantLib-Risks (enabled with XAD).
11 |
12 | 1. Fork, then clone the repository:
13 |
14 | ```bash
15 | git clone https://github.com/yourusername/QuantLib-Risks.git
16 | ```
17 |
18 | 2. Follow the [Build Instructions](README.md) to setup the dependencies and
19 | build the software. Make sure all tests pass.
20 |
21 | 3. Create a feature branch, typically based on master, for your change
22 |
23 | ```bash
24 | git checkout -b feature/my-change main
25 | ```
26 |
27 | 4. Make your changes, adding tests as you go, and commit. Again, make sure all
28 | tests pass.
29 |
30 | 5. Push your fork
31 |
32 | 6. [Submit a pull request][pr]. Not that you will have to sign the [Contributor License Agreement][cla]
33 | before the PR can be merged.
34 |
35 | At this point, you are depending on the core team to review your request.
36 | We may suggest changes, improvements, or alternatives.
37 | We strive to at least comment on a pull request within 3 business days.
38 | After feedback has been given, we expect a response within 2 weeks,
39 | after which we may close the pull request if it isn't showing activity.
40 |
41 | Some things that will highly increase the chance that your pull request gets
42 | accepted:
43 |
44 | - Discuss the change you wish to make via issue or email
45 |
46 | - Write good tests for all added features
47 |
48 | - Write good commit messages (short one-liner, followed by a blank line,
49 | followed by a more detailed explanation)
50 |
51 |
52 | [pr]: https://github.com/auto-differentiation/QuantLib-Risks/compare/
53 |
54 | [cla]: https://gist.github.com/auto-differentiation-dev/5c6121c3f341e2de710fa034e9ff3263
55 |
--------------------------------------------------------------------------------
/Python/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ##############################################################################
2 | # Main CMake file for the Python extension.
3 | #
4 | # This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
5 | # for risk computation using automatic differentiation. It uses XAD,
6 | # a fast and comprehensive C++ library for automatic differentiation.
7 | #
8 | # Copyright (C) 2010-2024 Xcelerit Computing Ltd.
9 | #
10 | # This program is free software: you can redistribute it and/or modify
11 | # it under the terms of the GNU Affero General Public License as published
12 | # by the Free Software Foundation, either version 3 of the License, or
13 | # (at your option) any later version.
14 | #
15 | # This program is distributed in the hope that it will be useful,
16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | # GNU Affero General Public License for more details.
19 | #
20 | # You should have received a copy of the GNU Affero General Public License
21 | # along with this program. If not, see .
22 | #
23 | ##############################################################################
24 | if(NOT "${QLR_PYTHON_VERSION}" STREQUAL "")
25 | find_package (Python3 ${QLR_PYTHON_VERSION} EXACT COMPONENTS Interpreter Development.Module REQUIRED)
26 | else()
27 | find_package (Python3 COMPONENTS Interpreter Development.Module REQUIRED)
28 | endif()
29 |
30 | # fetch pybind11 dependency on the fly
31 | include(FetchContent)
32 |
33 | FetchContent_Declare(pybind11
34 | GIT_REPOSITORY https://github.com/pybind/pybind11.git
35 | GIT_TAG v2.11.1)
36 | FetchContent_GetProperties(pybind11)
37 | if(NOT pybind11_POPULATED)
38 | FetchContent_Populate(pybind11)
39 | add_subdirectory(${pybind11_SOURCE_DIR} ${pybind11_BINARY_DIR})
40 | endif()
41 |
42 | if(WIN32)
43 | set(QL_MODULE_SUFFIX ".${Python3_SOABI}.pyd")
44 | else()
45 | set(QL_MODULE_SUFFIX ".${Python3_SOABI}${CMAKE_SHARED_MODULE_SUFFIX}")
46 | endif()
47 |
48 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/build_extensions.py.in
49 | ${CMAKE_CURRENT_BINARY_DIR}/build_extensions.py @ONLY)
50 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pyproject.toml.in
51 | ${CMAKE_CURRENT_BINARY_DIR}/pyproject.toml @ONLY)
52 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/README.md
53 | ${CMAKE_CURRENT_BINARY_DIR}/README.md COPYONLY)
54 |
55 |
56 | add_subdirectory(QuantLib_Risks)
57 |
58 |
--------------------------------------------------------------------------------
/Python/QuantLib_Risks/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ##############################################################################
2 | # Build SWIG binary module and optionally wheel package.
3 | #
4 | # This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
5 | # for risk computation using automatic differentiation. It uses XAD,
6 | # a fast and comprehensive C++ library for automatic differentiation.
7 | #
8 | # Copyright (C) 2010-2024 Xcelerit Computing Ltd.
9 | #
10 | # This program is free software: you can redistribute it and/or modify
11 | # it under the terms of the GNU Affero General Public License as published
12 | # by the Free Software Foundation, either version 3 of the License, or
13 | # (at your option) any later version.
14 | #
15 | # This program is distributed in the hope that it will be useful,
16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | # GNU Affero General Public License for more details.
19 | #
20 | # You should have received a copy of the GNU Affero General Public License
21 | # along with this program. If not, see .
22 | #
23 | ##############################################################################
24 |
25 | set_property(SOURCE ${PROJECT_SOURCE_DIR}/SWIG/quantlib.i PROPERTY CPLUSPLUS ON)
26 | set_property(SOURCE ${PROJECT_SOURCE_DIR}/SWIG/quantlib.i PROPERTY USE_SWIG_DEPENDENCIES TRUE)
27 | set_property(SOURCE ${PROJECT_SOURCE_DIR}/SWIG/quantlib.i PROPERTY COMPILE_OPTIONS
28 | -DQL_XAD=1
29 | -DQLR_VERSION=\"${QLR_VERSION}\"
30 | -DQLR_HEX_VERSION=${QLR_HEX_VERSION})
31 | swig_add_library(QuantLib_Risks
32 | LANGUAGE python
33 | OUTPUT_DIR .
34 | SOURCES ${PROJECT_SOURCE_DIR}/SWIG/quantlib.i converters.cpp
35 | )
36 | target_link_libraries(QuantLib_Risks PRIVATE Python3::Module QuantLib::QuantLib pybind11::headers)
37 | target_compile_features(QuantLib_Risks PRIVATE cxx_std_17)
38 | target_compile_definitions(QuantLib_Risks PRIVATE QL_XAD=1 QLR_VERSION=\"${QLR_VERSION}\" QLR_HEX_VERSION=${QLR_HEX_VERSION})
39 | target_include_directories(QuantLib_Risks PRIVATE .)
40 | set_property(TARGET QuantLib_Risks PROPERTY SUFFIX "${QL_MODULE_SUFFIX}")
41 | if(MSVC)
42 | # we build with the static runtime in Windows
43 | set_target_properties(QuantLib_Risks PROPERTIES
44 | MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>")
45 | endif()
46 |
47 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/__init__.py
48 | ${CMAKE_CURRENT_BINARY_DIR}/__init__.py COPYONLY)
49 |
50 | if(WIN32)
51 | set(VENV_PYTHON ${CMAKE_CURRENT_BINARY_DIR}/../.venv/Scripts/python.exe)
52 | else()
53 | set(VENV_PYTHON ${CMAKE_CURRENT_BINARY_DIR}/../.venv/bin/python)
54 | endif()
55 |
56 | add_custom_command(
57 | OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/../wheel.stamp
58 | DEPENDS QuantLib_Risks
59 | ${CMAKE_CURRENT_BINARY_DIR}/../pyproject.toml
60 | ${CMAKE_CURRENT_BINARY_DIR}/../build_extensions.py
61 | ${CMAKE_CURRENT_BINARY_DIR}/../README.md
62 | __init__.py
63 | # create environment
64 | COMMAND ${Python3_EXECUTABLE} -m venv .venv
65 | # install build dependencies
66 | COMMAND ${VENV_PYTHON} -m pip install -U pip setuptools wheel build
67 | # build the wheel
68 | COMMAND ${VENV_PYTHON} -m pip wheel .
69 | # install the wheel in the venv
70 | COMMAND ${VENV_PYTHON} -m pip install QuantLib_Risks*.whl --force-reinstall
71 | # install other dependencies for running the examples / tests
72 | COMMAND ${VENV_PYTHON} -m pip install -r ${PROJECT_SOURCE_DIR}/binder/requirements.txt
73 | # update the stamp file, to keep track of when we last build it
74 | COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/../wheel.stamp
75 | COMMENT "Building Python wheel..."
76 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/..
77 | )
78 |
79 | # main target for building the python wheel - custom command above will be hooked to this target
80 | add_custom_target(python_wheel
81 | DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/../wheel.stamp)
82 |
83 |
--------------------------------------------------------------------------------
/Python/QuantLib_Risks/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: iso-8859-1 -*-
2 | """
3 | Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
4 | Copyright (C) 2024 Xcelerit Computing Limited.
5 |
6 | This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
7 | for risk computation using automatic differentiation. It uses XAD,
8 | a fast and comprehensive C++ library for automatic differentiation.
9 |
10 | QuantLib-Risks and XAD are free software: you can redistribute it and/or modify
11 | it under the terms of the GNU Affero General Public License as published
12 | by the Free Software Foundation, either version 3 of the License, or
13 | (at your option) any later version.
14 |
15 | QuantLib-Risks is distributed in the hope that it will be useful,
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | GNU Affero General Public License for more details.
19 |
20 | You should have received a copy of the GNU Affero General Public License
21 | along with this program. If not, see .
22 |
23 | QuantLib is free software: you can redistribute it and/or modify it
24 | under the terms of the QuantLib license. You should have received a
25 | copy of the license along with this program; if not, please email
26 | . The license is also available online at
27 | .
28 |
29 | This program is distributed in the hope that it will be useful, but WITHOUT
30 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
31 | FOR A PARTICULAR PURPOSE. See the license for more details.
32 | """
33 |
34 | from .QuantLib_Risks import *
35 |
36 | if XAD_ENABLED:
37 | from xad.adj_1st import Real, Tape
38 | from typing import Union, Tuple, List
39 |
40 | # as part of the input at the top, we'll have _QuantLib_Risks in scope
41 | DoubleVector = _QuantLib_Risks.DoubleVector
42 | DoublePairVector = _QuantLib_Risks.DoublePairVector
43 | DoubleVectorVector = _QuantLib_Risks.DoubleVectorVector
44 |
45 | def Concentrating1dMesherPoint(
46 | x1: Union[Real, float, int], x2: Union[Real, float, int], v: bool
47 | ) -> Tuple[Real, Real, bool]:
48 | return (Real(x1), Real(x2), bool(v))
49 |
50 | def PairDoubleVector(
51 | x1: List[Union[Real, float, int]] = [], x2: List[Union[Real, float, int]] = []
52 | ) -> Tuple[List[Real], List[Real]]:
53 | return ([Real(x) for x in x1], [Real(x) for x in x2])
54 |
55 | # monkey-patch the tape activation function to register this tape with QuantLib's internal
56 | # global tape pointer (we have 2 due to double static linking)
57 | def _wrap_tape_activation():
58 | original_enter = Tape.__enter__
59 |
60 | def _tape_enter(t: Tape):
61 | t = original_enter(t)
62 | _QuantLib_Risks._activate_tape(t)
63 | return t
64 |
65 | original_exit = Tape.__exit__
66 |
67 | def _tape_exit(t: Tape, *args, **kwargs):
68 | original_exit(t, *args, **kwargs)
69 | _QuantLib_Risks._deactivate_tape()
70 |
71 | original_activate = Tape.activate
72 |
73 | def _tape_activate(t: Tape):
74 | original_activate(t)
75 | _QuantLib_Risks._activate_tape(t)
76 |
77 | original_deactivate = Tape.deactivate
78 |
79 | def _tape_deactivate(t: Tape):
80 | original_deactivate(t)
81 | _QuantLib_Risks._deactivate_tape()
82 |
83 | Tape.__enter__ = _tape_enter
84 | Tape.__exit__ = _tape_exit
85 | Tape.activate = _tape_activate
86 | Tape.deactivate = _tape_deactivate
87 |
88 | _wrap_tape_activation()
89 |
90 | if hasattr(_QuantLib_Risks, "__version__"):
91 | __version__ = _QuantLib_Risks.__version__
92 | elif hasattr(_QuantLib_Risks.cvar, "__version__"):
93 | __version__ = _QuantLib_Risks.cvar.__version__
94 | else:
95 | print("Could not find __version__ attribute")
96 |
97 | if hasattr(_QuantLib_Risks, "__hexversion__"):
98 | __hexversion__ = _QuantLib_Risks.__hexversion__
99 | elif hasattr(_QuantLib_Risks.cvar, "__hexversion__"):
100 | __hexversion__ = _QuantLib_Risks.cvar.__hexversion__
101 | else:
102 | print("Could not find __hexversion__ attribute")
103 |
--------------------------------------------------------------------------------
/Python/README.md:
--------------------------------------------------------------------------------
1 | This package enables fast risks calculations on the QuantLib Python package.
2 | It provides the same interface as the [standard QuantLib package](https://pypi.org/project/QuantLib/), and in addition allows to calculate risks (sensitivities) using automatic differentiation via the [XAD automatic differentiation tool](https://auto-differentation.github.io).
3 |
4 | Useful links:
5 |
6 | - [QuantLib Documentation](https://www.quantlib.org)
7 | - [XAD Documentation, incl Python bindings and QuantLib integration](https://auto-differentiation.github.io/quantlib-risks/python/)
8 |
9 | ## Installation
10 |
11 | ```
12 | pip install QuantLib-Risks
13 | ```
14 |
15 | ## Usage Illustration
16 |
17 | ```python
18 | import QuantLib_Risks as ql
19 | from xad.adj_1st import Tape
20 |
21 | with Tape() as t:
22 | rate = ql.Real(0.2)
23 | tape.registerInput(rate)
24 |
25 | # quantlib pricing code
26 | ...
27 | npv = option.NPV()
28 |
29 |
30 | tape.registerOutput(npv)
31 | npv.derivative = 1.0
32 | tape.computeAdjoints()
33 |
34 | print(f"price = {npv}")
35 | print(f"delta = {rate.derivative}")
36 | ```
37 |
38 | ## Related Projects
39 |
40 | - XAD Comprehensive automatic differentiation in [Python](https://github.com/auto-differentiation/xad-py) and [C++](https://github.com/auto-differentiation/xad)
41 | - QuantLib-Risks: Fast risk evaluations in [Python](https://github.com/auto-differentiation/QuantLib-Risks-Py) and [C++](https://github.com/auto-differentiation/QuantLib-Risks-Cpp)
42 |
--------------------------------------------------------------------------------
/Python/build_extensions.py.in:
--------------------------------------------------------------------------------
1 | ##############################################################################
2 | #
3 | # Build file for extension module - using pre-built binary with SWIG/CMake.
4 | #
5 | # This was inspired by:
6 | # https://github.com/tim-mitchell/prebuilt_binaries/tree/main
7 | #
8 | #
9 | # This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
10 | # for risk computation using automatic differentiation. It uses XAD,
11 | # a fast and comprehensive C++ library for automatic differentiation.
12 | #
13 | # Copyright (C) 2010-2024 Xcelerit Computing Ltd.
14 | #
15 | # This program is free software: you can redistribute it and/or modify
16 | # it under the terms of the GNU Affero General Public License as published
17 | # by the Free Software Foundation, either version 3 of the License, or
18 | # (at your option) any later version.
19 | #
20 | # This program is distributed in the hope that it will be useful,
21 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
22 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 | # GNU Affero General Public License for more details.
24 | #
25 | # You should have received a copy of the GNU Affero General Public License
26 | # along with this program. If not, see .
27 | #
28 | ##############################################################################
29 |
30 | import os
31 | from pathlib import Path
32 | from distutils.file_util import copy_file
33 | try:
34 | from setuptools import Extension
35 | from setuptools.command.build_ext import build_ext
36 | except ImportError:
37 | from distutils.command.build_ext import build_ext
38 | from distutils.extension import Extension
39 |
40 |
41 | class QuantLibExtension(Extension):
42 | """Extension module for QuantLib, using the pre-built file from CMAKE instead of
43 | actually building it."""
44 |
45 | def __init__(self, name: str, input_file: str):
46 | filepath = Path(input_file)
47 | if not filepath.exists():
48 | raise ValueError(f"extension file {input_file} does not exist")
49 | self.input_file = input_file
50 |
51 | super().__init__(f"QuantLib_Risks.{name}", ["dont-need-this-source-file.c"])
52 |
53 | class ql_build_ext(build_ext):
54 | """Overrides build_ext to simply copy the file built with CMake into the
55 | right location, rather than actually building it"""
56 |
57 | def run(self):
58 | for ext in self.extensions:
59 | if not isinstance(ext, QuantLibExtension):
60 | raise ValueError("Only pre-built extensions supported")
61 |
62 | fullname = self.get_ext_fullname(ext.name)
63 | filename = self.get_ext_filename(fullname)
64 | dest_path = Path(self.build_lib) / "QuantLib_Risks"
65 | dest_path.mkdir(parents=True, exist_ok=True)
66 | dest_filename = dest_path / os.path.basename(filename)
67 |
68 | copy_file(
69 | ext.input_file,
70 | dest_filename,
71 | verbose=self.verbose,
72 | dry_run=self.dry_run,
73 | )
74 |
75 | if self.inplace:
76 | self.copy_extensions_to_source()
77 |
78 | def build(setup_kwargs: dict):
79 | """Main extension build file"""
80 | ext_modules = [QuantLibExtension("_QuantLib_Risks",
81 | 'QuantLib_Risks/_QuantLib_Risks@QL_MODULE_SUFFIX@')]
82 | setup_kwargs.update(
83 | {
84 | "ext_modules": ext_modules,
85 | "cmdclass": {"build_ext": ql_build_ext},
86 | "zip_safe": False
87 | }
88 | )
89 |
--------------------------------------------------------------------------------
/Python/examples/README.md:
--------------------------------------------------------------------------------
1 | # QuantLib-Risks Python examples
2 |
3 | [](https://mybinder.org/v2/gh/auto-differentiation/QuantLib-Risks/main?labpath=Python%2Fexamples)
4 |
5 | This directory contains a number of examples of using risk-enabled QuantLib from
6 | Python. They can also run as Jupyter notebooks by means of
7 | [Jupytext](https://jupytext.readthedocs.io/).
8 |
9 | You can try them online thanks to [Binder](https://mybinder.org/).
10 | If you're seeing this file as a notebook, you're probably there already.
11 | If not, you can click the "Launch Binder" badge at the top of this file.
12 |
13 | If you want to run these examples locally, you'll need the modules listed in the
14 | `requirements.txt` file in the `binder` folder at the root of the [QuantLib-Risks
15 | repository](https://github.com/auto-differentiation/QuantLib-Risks); to install
16 | them, you can execute
17 |
18 | pip install -r requirements.txt
19 |
20 | from that directory.
21 |
--------------------------------------------------------------------------------
/Python/examples/callablebonds.py:
--------------------------------------------------------------------------------
1 | # ---
2 | # jupyter:
3 | # jupytext:
4 | # formats: py:light
5 | # text_representation:
6 | # extension: .py
7 | # format_name: light
8 | # format_version: '1.5'
9 | # jupytext_version: 1.14.5
10 | # kernelspec:
11 | # display_name: Python 3 (ipykernel)
12 | # language: python
13 | # name: python3
14 | # ---
15 |
16 | # # Callable bonds
17 | #
18 | # This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
19 | # for risk computation using automatic differentiation. It uses XAD,
20 | # a fast and comprehensive C++ library for automatic differentiation.
21 | #
22 | # QuantLib-Risks and XAD are free software: you can redistribute it and/or modify
23 | # it under the terms of the GNU Affero General Public License as published
24 | # by the Free Software Foundation, either version 3 of the License, or
25 | # (at your option) any later version.
26 | #
27 | # QuantLib-Risks is distributed in the hope that it will be useful,
28 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
29 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 | # GNU Affero General Public License for more details.
31 | #
32 | # You should have received a copy of the GNU Affero General Public License
33 | # along with this program. If not, see .
34 | #
35 | # QuantLib is free software: you can redistribute it and/or modify it under the
36 | # terms of the QuantLib license. You should have received a copy of the
37 | # license along with this program; if not, please email
38 | # . The license is also available online at
39 | # .
40 | #
41 | # This program is distributed in the hope that it will be useful, but WITHOUT
42 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
43 | # FOR A PARTICULAR PURPOSE. See the license for more details.
44 |
45 | import QuantLib_Risks as ql
46 | import numpy as np
47 |
48 | calcDate = ql.Date(16, 8, 2006)
49 | ql.Settings.instance().evaluationDate = calcDate
50 |
51 | dayCount = ql.ActualActual(ql.ActualActual.Bond)
52 | rate = 0.0465
53 | termStructure = ql.FlatForward(calcDate, rate, dayCount, ql.Compounded, ql.Semiannual)
54 | term_structure_handle = ql.RelinkableYieldTermStructureHandle(termStructure)
55 |
56 | callabilitySchedule = ql.CallabilitySchedule()
57 | callPrice = 100.0
58 | callDate = ql.Date(15, ql.September, 2006);
59 | nc = ql.NullCalendar()
60 |
61 | # Number of calldates is 24
62 | for i in range(0, 24):
63 | callabilityPrice = ql.BondPrice(callPrice, ql.BondPrice.Clean)
64 | callabilitySchedule.append(ql.Callability(callabilityPrice, ql.Callability.Call, callDate))
65 | callDate = nc.advance(callDate, 3, ql.Months)
66 |
67 | issueDate = ql.Date(16, ql.September, 2004)
68 | maturityDate = ql.Date(15, ql.September, 2012)
69 | calendar = ql.UnitedStates(ql.UnitedStates.GovernmentBond)
70 | tenor = ql.Period(ql.Quarterly)
71 | accrualConvention = ql.Unadjusted
72 | schedule = ql.Schedule(issueDate, maturityDate, tenor, calendar,
73 | accrualConvention, accrualConvention, ql.DateGeneration.Backward, False)
74 |
75 | settlement_days = 3
76 | faceAmount = 100
77 | accrual_daycount = ql.ActualActual(ql.ActualActual.Bond)
78 | coupon = 0.025
79 | bond = ql.CallableFixedRateBond(settlement_days, faceAmount, schedule,
80 | [coupon], accrual_daycount, ql.Following,
81 | faceAmount, issueDate, callabilitySchedule)
82 |
83 | def engine(a, s, grid_points):
84 | model = ql.HullWhite(term_structure_handle, a, s)
85 | return ql.TreeCallableFixedRateBondEngine(model, grid_points)
86 |
87 | # 6% mean reversion and 20% volatility
88 | bond.setPricingEngine(engine(0.06, 0.20, 40))
89 | print("Bond price: ", bond.cleanPrice())
90 |
91 | # 3% mean reversion and 15% volatility
92 | bond.setPricingEngine(engine(0.03, 0.15, 40))
93 | print("Bond price: ", bond.cleanPrice())
94 |
--------------------------------------------------------------------------------
/Python/examples/capsfloors.py:
--------------------------------------------------------------------------------
1 | # ---
2 | # jupyter:
3 | # jupytext:
4 | # formats: py:light
5 | # text_representation:
6 | # extension: .py
7 | # format_name: light
8 | # format_version: '1.5'
9 | # jupytext_version: 1.14.5
10 | # kernelspec:
11 | # display_name: Python 3 (ipykernel)
12 | # language: python
13 | # name: python3
14 | # ---
15 |
16 | # # Caps and Floors
17 | #
18 | # This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
19 | # for risk computation using automatic differentiation. It uses XAD,
20 | # a fast and comprehensive C++ library for automatic differentiation.
21 | #
22 | # QuantLib-Risks and XAD are free software: you can redistribute it and/or modify
23 | # it under the terms of the GNU Affero General Public License as published
24 | # by the Free Software Foundation, either version 3 of the License, or
25 | # (at your option) any later version.
26 | #
27 | # QuantLib-Risks is distributed in the hope that it will be useful,
28 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
29 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 | # GNU Affero General Public License for more details.
31 | #
32 | # You should have received a copy of the GNU Affero General Public License
33 | # along with this program. If not, see .
34 | #
35 | # QuantLib is free software: you can redistribute it and/or modify it under the
36 | # terms of the QuantLib license. You should have received a copy of the
37 | # license along with this program; if not, please email
38 | # . The license is also available online at
39 | # .
40 | #
41 | # This program is distributed in the hope that it will be useful, but WITHOUT
42 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
43 | # FOR A PARTICULAR PURPOSE. See the license for more details.
44 |
45 | import QuantLib_Risks as ql
46 |
47 | calcDate = ql.Date(14, 6, 2016)
48 | ql.Settings.instance().evaluationDate = calcDate
49 |
50 | dates = [ql.Date(14,6,2016), ql.Date(14,9,2016),
51 | ql.Date(14,12,2016), ql.Date(14,6,2017),
52 | ql.Date(14,6,2019), ql.Date(14,6,2021),
53 | ql.Date(15,6,2026), ql.Date(16,6,2031),
54 | ql.Date(16,6,2036), ql.Date(14,6,2046)]
55 |
56 | yields = [0.000000, 0.006616, 0.007049, 0.007795,
57 | 0.009599, 0.011203, 0.015068, 0.017583,
58 | 0.018998, 0.020080]
59 |
60 | dayCount = ql.ActualActual(ql.ActualActual.Bond)
61 | calendar = ql.UnitedStates(ql.UnitedStates.GovernmentBond)
62 | interpolation = ql.Linear()
63 | compounding = ql.Compounded
64 | compoundingFrequency = ql.Annual
65 | term_structure = ql.ZeroCurve(dates, yields, dayCount, calendar, interpolation, compounding, compoundingFrequency)
66 | ts_handle = ql.YieldTermStructureHandle(term_structure)
67 |
68 | start_date = ql.Date(14, 6, 2016)
69 | end_date = ql.Date(14, 6 , 2026)
70 | period = ql.Period(3, ql.Months)
71 | buss_convention = ql.ModifiedFollowing
72 | rule = ql.DateGeneration.Forward
73 | end_of_month = False
74 | schedule = ql.Schedule(start_date, end_date, period, calendar, buss_convention, buss_convention, rule, end_of_month)
75 |
76 | iborIndex = ql.USDLibor(ql.Period(3, ql.Months), ts_handle)
77 | iborIndex.addFixing(ql.Date(10,6,2016), 0.0065560)
78 | ibor_leg = ql.IborLeg([1000000], schedule, iborIndex)
79 |
80 | strike = 0.02
81 | cap = ql.Cap(ibor_leg, [strike])
82 | vols = ql.QuoteHandle(ql.SimpleQuote(0.547295))
83 | engine = ql.BlackCapFloorEngine(ts_handle, vols)
84 | cap.setPricingEngine(engine)
85 | print("Value of Caps given constant volatility:", cap.NPV())
86 |
--------------------------------------------------------------------------------
/Python/examples/cds.py:
--------------------------------------------------------------------------------
1 | # ---
2 | # jupyter:
3 | # jupytext:
4 | # formats: py:light
5 | # text_representation:
6 | # extension: .py
7 | # format_name: light
8 | # format_version: '1.5'
9 | # jupytext_version: 1.4.2
10 | # kernelspec:
11 | # display_name: Python 3
12 | # language: python
13 | # name: python3
14 | # ---
15 |
16 | # # Credit default swaps
17 | #
18 | # Copyright (©) 2014 Thema Consulting SA
19 | # Copyright (©) 2024 Xcelerit Computing Limited.
20 | #
21 | # This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
22 | # for risk computation using automatic differentiation. It uses XAD,
23 | # a fast and comprehensive C++ library for automatic differentiation.
24 | #
25 | # QuantLib-Risks and XAD are free software: you can redistribute it and/or modify
26 | # it under the terms of the GNU Affero General Public License as published
27 | # by the Free Software Foundation, either version 3 of the License, or
28 | # (at your option) any later version.
29 | #
30 | # QuantLib-Risks is distributed in the hope that it will be useful,
31 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
32 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 | # GNU Affero General Public License for more details.
34 | #
35 | # You should have received a copy of the GNU Affero General Public License
36 | # along with this program. If not, see .
37 | #
38 | # QuantLib is free software: you can redistribute it and/or modify it under the
39 | # terms of the QuantLib license. You should have received a copy of the
40 | # license along with this program; if not, please email
41 | # . The license is also available online at
42 | # .
43 | #
44 | # This program is distributed in the hope that it will be useful, but WITHOUT
45 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
46 | # FOR A PARTICULAR PURPOSE. See the license for more details.
47 |
48 | # ### Setup
49 |
50 | import QuantLib_Risks as ql
51 |
52 | calendar = ql.TARGET()
53 |
54 | todaysDate = ql.Date(15, ql.May, 2007)
55 | ql.Settings.instance().evaluationDate = todaysDate
56 |
57 | risk_free_rate = ql.YieldTermStructureHandle(ql.FlatForward(todaysDate, 0.01, ql.Actual365Fixed()))
58 |
59 | # ### CDS parameters
60 |
61 | recovery_rate = 0.5
62 | quoted_spreads = [0.0150, 0.0150, 0.0150, 0.0150]
63 | tenors = [ql.Period(3, ql.Months), ql.Period(6, ql.Months), ql.Period(1, ql.Years), ql.Period(2, ql.Years)]
64 | maturities = [calendar.adjust(todaysDate + x, ql.Following) for x in tenors]
65 |
66 | instruments = [
67 | ql.SpreadCdsHelper(
68 | ql.QuoteHandle(ql.SimpleQuote(s)),
69 | tenor,
70 | 0,
71 | calendar,
72 | ql.Quarterly,
73 | ql.Following,
74 | ql.DateGeneration.TwentiethIMM,
75 | ql.Actual365Fixed(),
76 | recovery_rate,
77 | risk_free_rate,
78 | )
79 | for s, tenor in zip(quoted_spreads, tenors)
80 | ]
81 |
82 | hazard_curve = ql.PiecewiseFlatHazardRate(todaysDate, instruments, ql.Actual365Fixed())
83 | print("Calibrated hazard rate values: ")
84 | for x in hazard_curve.nodes():
85 | print("hazard rate on {} is {:.7f}".format(*x))
86 |
87 | print("Some survival probability values: ")
88 | print(
89 | "1Y survival probability: {:.4g}, \n\t\texpected {:.4g}".format(
90 | hazard_curve.survivalProbability(todaysDate + ql.Period("1Y")), 0.9704)
91 | )
92 | print(
93 | "2Y survival probability: {:.4g}, \n\t\texpected {:.4g}".format(
94 | hazard_curve.survivalProbability(todaysDate + ql.Period("2Y")), 0.9418)
95 | )
96 |
97 | # ### Reprice instruments
98 |
99 | nominal = 1000000.0
100 | probability = ql.DefaultProbabilityTermStructureHandle(hazard_curve)
101 |
102 | # We'll create a cds for every maturity:
103 |
104 | all_cds = []
105 | for maturity, s in zip(maturities, quoted_spreads):
106 | schedule = ql.Schedule(
107 | todaysDate,
108 | maturity,
109 | ql.Period(ql.Quarterly),
110 | calendar,
111 | ql.Following,
112 | ql.Unadjusted,
113 | ql.DateGeneration.TwentiethIMM,
114 | False,
115 | )
116 | cds = ql.CreditDefaultSwap(ql.Protection.Seller, nominal, s, schedule, ql.Following, ql.Actual365Fixed())
117 | engine = ql.MidPointCdsEngine(probability, recovery_rate, risk_free_rate)
118 | cds.setPricingEngine(engine)
119 | all_cds.append(cds)
120 |
121 | print("Repricing of quoted CDSs employed for calibration: ")
122 | for cds, tenor in zip(all_cds, tenors):
123 | print("{} fair spread: {:.7g}".format(tenor, cds.fairSpread()))
124 | print(" NPV: {:g}".format(cds.NPV()))
125 | print(" default leg: {:.7g}".format(cds.defaultLegNPV()))
126 | print(" coupon leg: {:.7g}".format(cds.couponLegNPV()))
127 | print("")
128 |
--------------------------------------------------------------------------------
/Python/examples/swing.py:
--------------------------------------------------------------------------------
1 | # ---
2 | # jupyter:
3 | # jupytext:
4 | # formats: py:light
5 | # text_representation:
6 | # extension: .py
7 | # format_name: light
8 | # format_version: '1.5'
9 | # jupytext_version: 1.4.2
10 | # kernelspec:
11 | # display_name: Python 3
12 | # language: python
13 | # name: python3
14 | # ---
15 |
16 | # # Swing options
17 | #
18 | # Copyright (©) 2018 Klaus Spanderen
19 | # Copyright (©) 2024 Xcelerit Computing Limited.
20 | #
21 | # This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
22 | # for risk computation using automatic differentiation. It uses XAD,
23 | # a fast and comprehensive C++ library for automatic differentiation.
24 | #
25 | # QuantLib-Risks and XAD are free software: you can redistribute it and/or modify
26 | # it under the terms of the GNU Affero General Public License as published
27 | # by the Free Software Foundation, either version 3 of the License, or
28 | # (at your option) any later version.
29 | #
30 | # QuantLib-Risks is distributed in the hope that it will be useful,
31 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
32 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 | # GNU Affero General Public License for more details.
34 | #
35 | # You should have received a copy of the GNU Affero General Public License
36 | # along with this program. If not, see .
37 | #
38 | # QuantLib is free software: you can redistribute it and/or modify it under the
39 | # terms of the QuantLib license. You should have received a copy of the
40 | # license along with this program; if not, please email
41 | # . The license is also available online at
42 | # .
43 | #
44 | # This program is distributed in the hope that it will be useful, but WITHOUT
45 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
46 | # FOR A PARTICULAR PURPOSE. See the license for more details.
47 |
48 | import QuantLib_Risks as ql
49 | from xad import math
50 |
51 | todaysDate = ql.Date(30, ql.September, 2018)
52 | ql.Settings.instance().evaluationDate = todaysDate
53 | settlementDate = todaysDate
54 | riskFreeRate = ql.FlatForward(settlementDate, 0.0, ql.Actual365Fixed())
55 | dividendYield = ql.FlatForward(settlementDate, 0.0, ql.Actual365Fixed())
56 | underlying = ql.SimpleQuote(30.0)
57 | volatility = ql.BlackConstantVol(todaysDate, ql.TARGET(), 0.20, ql.Actual365Fixed())
58 |
59 |
60 | exerciseDates = [ql.Date(1, ql.January, 2019) + i for i in range(31)]
61 |
62 | swingOption = ql.VanillaSwingOption(
63 | ql.VanillaForwardPayoff(ql.Option.Call, underlying.value()), ql.SwingExercise(exerciseDates), 0, len(exerciseDates)
64 | )
65 |
66 | bsProcess = ql.BlackScholesMertonProcess(
67 | ql.QuoteHandle(underlying),
68 | ql.YieldTermStructureHandle(dividendYield),
69 | ql.YieldTermStructureHandle(riskFreeRate),
70 | ql.BlackVolTermStructureHandle(volatility),
71 | )
72 |
73 | swingOption.setPricingEngine(ql.FdSimpleBSSwingEngine(bsProcess))
74 |
75 | print("Black Scholes Price: {:f}".format(swingOption.NPV()))
76 |
77 | x0 = 0.0
78 | x1 = 0.0
79 |
80 | beta = 4.0
81 | eta = 4.0
82 | jumpIntensity = 1.0
83 | speed = 1.0
84 | volatility = 0.1
85 |
86 | curveShape = []
87 | for d in exerciseDates:
88 | t = ql.Actual365Fixed().yearFraction(todaysDate, d)
89 | gs = (
90 | math.log(underlying.value())
91 | - volatility * volatility / (4 * speed) * (1 - math.exp(-2 * speed * t))
92 | - jumpIntensity / beta * math.log((eta - math.exp(-beta * t)) / (eta - 1.0))
93 | )
94 | curveShape.append((t, gs))
95 |
96 | ouProcess = ql.ExtendedOrnsteinUhlenbeckProcess(speed, volatility, x0, lambda x: x0)
97 | jProcess = ql.ExtOUWithJumpsProcess(ouProcess, x1, beta, jumpIntensity, eta)
98 |
99 | swingOption.setPricingEngine(ql.FdSimpleExtOUJumpSwingEngine(jProcess, riskFreeRate, 25, 25, 200, curveShape))
100 |
101 | print("Kluge Model Price : {:f}".format(swingOption.NPV()))
102 |
--------------------------------------------------------------------------------
/Python/pyproject.toml.in:
--------------------------------------------------------------------------------
1 | ##############################################################################
2 | # Pypproject main file for QuantLib-Risks
3 | #
4 | # This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
5 | # for risk computation using automatic differentiation. It uses XAD,
6 | # a fast and comprehensive C++ library for automatic differentiation.
7 | #
8 | # Copyright (C) 2010-2024 Xcelerit Computing Ltd.
9 | #
10 | # This program is free software: you can redistribute it and/or modify
11 | # it under the terms of the GNU Affero General Public License as published
12 | # by the Free Software Foundation, either version 3 of the License, or
13 | # (at your option) any later version.
14 | #
15 | # This program is distributed in the hope that it will be useful,
16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | # GNU Affero General Public License for more details.
19 | #
20 | # You should have received a copy of the GNU Affero General Public License
21 | # along with this program. If not, see .
22 | #
23 | ##############################################################################
24 |
25 | [tool.poetry]
26 | name = "QuantLib-Risks"
27 | version = "@PACKAGE_VERSION@"
28 | description = "Fast risks calculations in QuantLib"
29 | authors = [
30 | "Auto Differentiation Dev Team ",
31 | "QuantLib Team "
32 | ]
33 | readme = "README.md"
34 | homepage = "https://auto-differentiation.github.io"
35 | repository = "https://github.com/auto-differentiation/QuantLib-Risks-Py"
36 | documentation = "https://auto-differentiation.github.io/quantlib-risks"
37 | keywords = [
38 | "automatic-differentiation",
39 | "derivatives",
40 | "risk-management",
41 | "quant-finance",
42 | "greeks",
43 | "risks"
44 | ]
45 | classifiers = [
46 | "Development Status :: 5 - Production/Stable",
47 | "Intended Audience :: Developers",
48 | "Intended Audience :: Education",
49 | "Intended Audience :: Financial and Insurance Industry",
50 | "Intended Audience :: Science/Research",
51 | "Intended Audience :: End Users/Desktop",
52 | "License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)",
53 | "License :: Other/Proprietary License",
54 | "Operating System :: MacOS :: MacOS X",
55 | "Operating System :: Microsoft :: Windows",
56 | "Operating System :: POSIX :: Linux",
57 | "Natural Language :: English",
58 | "Programming Language :: Python :: 3.8",
59 | "Programming Language :: Python :: 3.9",
60 | "Programming Language :: Python :: 3.10",
61 | "Programming Language :: Python :: 3.11",
62 | "Programming Language :: Python :: 3.12",
63 | "Programming Language :: Python :: Implementation :: CPython",
64 | "Topic :: Scientific/Engineering",
65 | "Topic :: Software Development"
66 | ]
67 | license = "AGPL-3.0-or-later"
68 | packages = [
69 | { include = "QuantLib_Risks" }
70 | ]
71 | exclude = [
72 | "QuantLib_Risks/CMakeFiles",
73 | "QuantLib_Risks/*.cmake",
74 | "QuantLib_Risks/*.cxx",
75 | ]
76 |
77 | [tool.poetry.urls]
78 | download = "https://pypi.org/project/QuantLib-Risks/#files"
79 | tracker = "https://github.com/auto-differentiation/QuantLib-Risks-Py/issues"
80 |
81 | [tool.poetry.build]
82 | script = "build_extensions.py"
83 | generate-setup-file = false
84 |
85 | [tool.poetry.dependencies]
86 | python = ">=3.8.1,<4.0"
87 | xad = ">=1.5.2"
88 |
89 |
90 | [build-system]
91 | requires = [
92 | "poetry-core>=1.0.0",
93 | "setuptools>=42"
94 | ]
95 | build-backend = "poetry.core.masonry.api"
96 |
97 |
--------------------------------------------------------------------------------
/Python/run_tests.bat:
--------------------------------------------------------------------------------
1 | :: #############################################################################
2 | ::
3 | ::
4 | :: This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
5 | :: for risk computation using automatic differentiation. It uses XAD,
6 | :: a fast and comprehensive C++ library for automatic differentiation.
7 | ::
8 | :: Copyright (C) 2010-2024 Xcelerit Computing Ltd.
9 | ::
10 | :: This program is free software: you can redistribute it and/or modify
11 | :: it under the terms of the GNU Affero General Public License as published
12 | :: by the Free Software Foundation, either version 3 of the License, or
13 | :: (at your option) any later version.
14 | ::
15 | :: This program is distributed in the hope that it will be useful,
16 | :: but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | :: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | :: GNU Affero General Public License for more details.
19 | ::
20 | :: You should have received a copy of the GNU Affero General Public License
21 | :: along with this program. If not, see .
22 | ::
23 | :: #############################################################################
24 |
25 | @echo on
26 |
27 |
28 | "C:\Program Files\Git\bin\bash.exe" "%~dp0\run_tests.sh" || exit 1
--------------------------------------------------------------------------------
/Python/run_tests.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | ##############################################################################
4 | #
5 | #
6 | # This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
7 | # for risk computation using automatic differentiation. It uses XAD,
8 | # a fast and comprehensive C++ library for automatic differentiation.
9 | #
10 | # Copyright (C) 2010-2024 Xcelerit Computing Ltd.
11 | #
12 | # This program is free software: you can redistribute it and/or modify
13 | # it under the terms of the GNU Affero General Public License as published
14 | # by the Free Software Foundation, either version 3 of the License, or
15 | # (at your option) any later version.
16 | #
17 | # This program is distributed in the hope that it will be useful,
18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | # GNU Affero General Public License for more details.
21 | #
22 | # You should have received a copy of the GNU Affero General Public License
23 | # along with this program. If not, see .
24 | #
25 | ##############################################################################
26 |
27 | set -e
28 |
29 | SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
30 |
31 | python "${SCRIPT_DIR}/test/QuantLibTestSuite.py"
32 |
33 | cd "${SCRIPT_DIR}/examples"
34 |
35 | had_errors=0
36 | for f in "swap-adjoint.py" "swap.py" "multicurve-bootstrapping.py" ; do
37 | echo ""
38 | echo "----------- RUNNING $f ----------------"
39 | python "$f" || had_errors=1
40 | done
41 |
42 | if [ "$had_errors" == "1" ] ; then
43 | echo "there were errors"
44 | exit 1
45 | fi
46 |
--------------------------------------------------------------------------------
/Python/test/QuantLibTestSuite.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
3 | Copyright (C) 2009 Joseph Malicki
4 | Copyright (C) 2024 Xcelerit Computing Limited.
5 |
6 | This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
7 | for risk computation using automatic differentiation. It uses XAD,
8 | a fast and comprehensive C++ library for automatic differentiation.
9 |
10 | QuantLib-Risks and XAD are free software: you can redistribute it and/or modify
11 | it under the terms of the GNU Affero General Public License as published
12 | by the Free Software Foundation, either version 3 of the License, or
13 | (at your option) any later version.
14 |
15 | QuantLib-Risks is distributed in the hope that it will be useful,
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | GNU Affero General Public License for more details.
19 |
20 | You should have received a copy of the GNU Affero General Public License
21 | along with this program. If not, see .
22 |
23 | QuantLib is free software: you can redistribute it and/or modify it
24 | under the terms of the QuantLib license. You should have received a
25 | copy of the license along with this program; if not, please email
26 | . The license is also available online at
27 | .
28 |
29 | This program is distributed in the hope that it will be useful, but WITHOUT
30 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
31 | FOR A PARTICULAR PURPOSE. See the license for more details.
32 | """
33 |
34 | import os
35 | import sys
36 | import unittest
37 |
38 | import QuantLib_Risks as ql
39 |
40 |
41 | def test():
42 | print('testing QuantLib_Risks', ql.__version__)
43 | sys.argv[1:1] = ['discover', '-s', os.path.dirname(__file__)]
44 | unittest.main(module=None, verbosity=2)
45 |
46 |
47 | if __name__ == '__main__':
48 | test()
49 |
--------------------------------------------------------------------------------
/Python/test/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/auto-differentiation/QuantLib-Risks-Py/30235106779882720d2adf154f78e1f322922b1e/Python/test/__init__.py
--------------------------------------------------------------------------------
/Python/test/test_americanquantooption.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2019 Klaus Spanderen
3 | Copyright (C) 2024 Xcelerit Computing Limited.
4 |
5 | This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
6 | for risk computation using automatic differentiation. It uses XAD,
7 | a fast and comprehensive C++ library for automatic differentiation.
8 |
9 | QuantLib-Risks and XAD are free software: you can redistribute it and/or modify
10 | it under the terms of the GNU Affero General Public License as published
11 | by the Free Software Foundation, either version 3 of the License, or
12 | (at your option) any later version.
13 |
14 | QuantLib-Risks is distributed in the hope that it will be useful,
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | GNU Affero General Public License for more details.
18 |
19 | You should have received a copy of the GNU Affero General Public License
20 | along with this program. If not, see .
21 |
22 | QuantLib is free software: you can redistribute it and/or modify it
23 | under the terms of the QuantLib license. You should have received a
24 | copy of the license along with this program; if not, please email
25 | . The license is also available online at
26 | .
27 |
28 | This program is distributed in the hope that it will be useful, but WITHOUT
29 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
30 | FOR A PARTICULAR PURPOSE. See the license for more details.
31 | """
32 |
33 | import unittest
34 | import QuantLib_Risks as ql
35 |
36 | class AmericanQuantoOptionTest(unittest.TestCase):
37 | def setUp(self):
38 | self.today = ql.Date(21, ql.April, 2019)
39 | self.dc = ql.Actual365Fixed()
40 | ql.Settings.instance().evaluationDate = self.today
41 |
42 | self.domesticTS = ql.FlatForward(self.today, 0.025, self.dc)
43 | self.foreignTS = ql.FlatForward(self.today, 0.075, self.dc)
44 | self.fxVolTS = ql.BlackConstantVol(self.today, ql.TARGET(), 0.15, self.dc)
45 |
46 | self.quantoHelper = ql.FdmQuantoHelper(
47 | self.domesticTS, self.foreignTS, self.fxVolTS, -0.75, 1.0)
48 |
49 | self.divYieldTS = ql.FlatForward(self.today, 0.03, self.dc)
50 |
51 | divDate = ql.DateVector()
52 | divDate.push_back(self.today + ql.Period(6, ql.Months))
53 |
54 | divAmount = ql.DoubleVector()
55 | divAmount.push_back(8.0)
56 |
57 | maturityDate = self.today + ql.Period(9, ql.Months)
58 |
59 | self.option = ql.DividendVanillaOption(
60 | ql.PlainVanillaPayoff(ql.Option.Call, 105),
61 | ql.AmericanExercise(self.today, maturityDate),
62 | divDate,
63 | divAmount)
64 |
65 |
66 | def tearDown(self):
67 | ql.Settings.instance().evaluationDate = ql.Date()
68 |
69 | def testAmericanBSQuantoOption(self):
70 | """ Testing American Black-Scholes quanto option """
71 |
72 | volTS = ql.BlackConstantVol(self.today, ql.TARGET(), 0.3, self.dc)
73 |
74 | bsmProcess = ql.BlackScholesMertonProcess(
75 | ql.QuoteHandle(ql.SimpleQuote(100)),
76 | ql.YieldTermStructureHandle(self.divYieldTS),
77 | ql.YieldTermStructureHandle(self.domesticTS),
78 | ql.BlackVolTermStructureHandle(volTS))
79 |
80 | fdmBlackScholesEngine = ql.FdBlackScholesVanillaEngine(
81 | bsmProcess, self.quantoHelper, 100, 400, 1)
82 |
83 | self.option.setPricingEngine(fdmBlackScholesEngine)
84 |
85 | fdmPrice = self.option.NPV()
86 | expected = 8.90611734
87 |
88 | self.assertAlmostEqual(fdmPrice, expected, 3,
89 | msg="Unable to reproduce American BS quanto option price.")
90 |
91 |
92 | def testAmericanHestonQuantoOption(self):
93 | """ Testing American Heston quanto option """
94 |
95 | hestonModel = ql.HestonModel(
96 | ql.HestonProcess(
97 | ql.YieldTermStructureHandle(self.domesticTS),
98 | ql.YieldTermStructureHandle(self.divYieldTS),
99 | ql.QuoteHandle(ql.SimpleQuote(100)),
100 | 0.09, 1.0, 0.09, 1e-4, 0.0))
101 |
102 | fdmHestonVanillaEngine = ql.FdHestonVanillaEngine(
103 | hestonModel, self.quantoHelper, 100, 400, 3, 1)
104 |
105 | self.option.setPricingEngine(fdmHestonVanillaEngine)
106 |
107 | fdmPrice = self.option.NPV()
108 | expected = 8.90611734
109 |
110 | self.assertAlmostEqual(fdmPrice, expected, 3,
111 | msg="Unable to reproduce American Heston quanto option price.")
112 |
113 |
114 | if __name__ == '__main__':
115 | print("testing QuantLib", ql.__version__)
116 | unittest.main(verbosity=2)
117 |
--------------------------------------------------------------------------------
/Python/test/test_calendars.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2023 Skandinaviska Enskilda Banken AB (publ)
3 | Copyright (C) 2024 Xcelerit Computing Limited.
4 |
5 | This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
6 | for risk computation using automatic differentiation. It uses XAD,
7 | a fast and comprehensive C++ library for automatic differentiation.
8 |
9 | QuantLib-Risks and XAD are free software: you can redistribute it and/or modify
10 | it under the terms of the GNU Affero General Public License as published
11 | by the Free Software Foundation, either version 3 of the License, or
12 | (at your option) any later version.
13 |
14 | QuantLib-Risks is distributed in the hope that it will be useful,
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | GNU Affero General Public License for more details.
18 |
19 | You should have received a copy of the GNU Affero General Public License
20 | along with this program. If not, see .
21 |
22 | QuantLib is free software: you can redistribute it and/or modify it
23 | under the terms of the QuantLib license. You should have received a
24 | copy of the license along with this program; if not, please email
25 | . The license is also available online at
26 | .
27 |
28 | This program is distributed in the hope that it will be useful, but WITHOUT
29 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
30 | FOR A PARTICULAR PURPOSE. See the license for more details.
31 | """
32 | import itertools
33 | import unittest
34 |
35 | import QuantLib_Risks as ql
36 |
37 |
38 | class JointCalendarTest(unittest.TestCase):
39 |
40 | def test_joint_calendar_holidays(self):
41 | base_calendars = [ql.Sweden(), ql.Denmark(), ql.Finland(), ql.Norway(), ql.Iceland()]
42 | joint_nordics = ql.JointCalendar(base_calendars)
43 | start_date = ql.Date(1, ql.January, 2023)
44 | end_date = ql.Date(31, ql.December, 2023)
45 |
46 | joint_holidays = set(joint_nordics.holidayList(start_date, end_date))
47 | base_holidays = [calendar.holidayList(start_date, end_date) for calendar in base_calendars]
48 | base_holidays = set(itertools.chain.from_iterable(base_holidays))
49 | for holiday in base_holidays:
50 | self.assertIn(holiday, joint_holidays)
51 |
52 |
53 | class ResetBespokeCalendarTest(unittest.TestCase):
54 |
55 | def test_reset_added_holidays(self):
56 | calendar = ql.BespokeCalendar("bespoke thing")
57 |
58 | test_date: ql.Date = ql.Date(1, ql.January, 2024)
59 | self.assertFalse(calendar.isHoliday(test_date))
60 | calendar.addHoliday(test_date)
61 | self.assertTrue(calendar.isHoliday(test_date))
62 | # TODO: Can extend test with this, if exposed:
63 | # self.assertEqual(len(calendar.addedHolidays()), 1)
64 | calendar.resetAddedAndRemovedHolidays()
65 | self.assertFalse(calendar.isHoliday(test_date))
66 |
67 |
68 | if __name__ == "__main__":
69 | print("testing QuantLib", ql.__version__)
70 | unittest.main(verbosity=2)
71 |
--------------------------------------------------------------------------------
/Python/test/test_currencies.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2021 Marcin Rybacki
3 | Copyright (C) 2024 Xcelerit Computing Limited.
4 |
5 | This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
6 | for risk computation using automatic differentiation. It uses XAD,
7 | a fast and comprehensive C++ library for automatic differentiation.
8 |
9 | QuantLib-Risks and XAD are free software: you can redistribute it and/or modify
10 | it under the terms of the GNU Affero General Public License as published
11 | by the Free Software Foundation, either version 3 of the License, or
12 | (at your option) any later version.
13 |
14 | QuantLib-Risks is distributed in the hope that it will be useful,
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | GNU Affero General Public License for more details.
18 |
19 | You should have received a copy of the GNU Affero General Public License
20 | along with this program. If not, see .
21 |
22 | QuantLib is free software: you can redistribute it and/or modify it
23 | under the terms of the QuantLib license. You should have received a
24 | copy of the license along with this program; if not, please email
25 | . The license is also available online at
26 | .
27 |
28 | This program is distributed in the hope that it will be useful, but WITHOUT
29 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
30 | FOR A PARTICULAR PURPOSE. See the license for more details.
31 | """
32 |
33 | import unittest
34 | import QuantLib_Risks as ql
35 |
36 |
37 | class CurrencyTest(unittest.TestCase):
38 |
39 | def test_default_currency_constructor(self):
40 | """Testing default currency constructor"""
41 | fail_msg = "Failed to create default currency."
42 | default_ccy = ql.Currency()
43 | self.assertTrue(default_ccy.empty(), fail_msg)
44 |
45 | def test_eur_constructor(self):
46 | """Testing EUR constructor"""
47 | fail_msg = "Failed to create EUR currency."
48 | eur = ql.EURCurrency()
49 | self.assertFalse(eur.empty(), fail_msg)
50 |
51 | def test_bespoke_currency_constructor(self):
52 | """Testing bespoke currency constructor"""
53 | fail_msg = "Failed to create bespoke currency."
54 | custom_ccy = ql.Currency(
55 | "CCY", "CCY", 100, "#", "", 100, ql.Rounding(), "")
56 | self.assertFalse(custom_ccy.empty(), fail_msg)
57 |
58 |
59 | if __name__ == '__main__':
60 | print("testing QuantLib", ql.__version__)
61 | unittest.main(verbosity=2)
62 |
--------------------------------------------------------------------------------
/Python/test/test_date.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
3 | Copyright (C) 2024 Xcelerit Computing Limited.
4 |
5 | This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
6 | for risk computation using automatic differentiation. It uses XAD,
7 | a fast and comprehensive C++ library for automatic differentiation.
8 |
9 | QuantLib-Risks and XAD are free software: you can redistribute it and/or modify
10 | it under the terms of the GNU Affero General Public License as published
11 | by the Free Software Foundation, either version 3 of the License, or
12 | (at your option) any later version.
13 |
14 | QuantLib-Risks is distributed in the hope that it will be useful,
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | GNU Affero General Public License for more details.
18 |
19 | You should have received a copy of the GNU Affero General Public License
20 | along with this program. If not, see .
21 |
22 | QuantLib is free software: you can redistribute it and/or modify it
23 | under the terms of the QuantLib license. You should have received a
24 | copy of the license along with this program; if not, please email
25 | . The license is also available online at
26 | .
27 |
28 | This program is distributed in the hope that it will be useful, but WITHOUT
29 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
30 | FOR A PARTICULAR PURPOSE. See the license for more details.
31 | """
32 |
33 | import QuantLib_Risks as ql
34 | import unittest
35 |
36 |
37 | class DateTest(unittest.TestCase):
38 | def setUp(self):
39 | pass
40 |
41 | def testArithmetics(self):
42 | "Testing date arithmetics"
43 | today = ql.Date.todaysDate()
44 | date = today - ql.Period(30, ql.Years)
45 | end_date = today + ql.Period(30, ql.Years)
46 |
47 | dold = date.dayOfMonth()
48 | mold = date.month()
49 | yold = date.year()
50 |
51 | while date < end_date:
52 | date += 1
53 |
54 | d = date.dayOfMonth()
55 | m = date.month()
56 | y = date.year()
57 |
58 | # check if skipping any date
59 | if not (
60 | (d == dold + 1 and m == mold and y == yold)
61 | or (d == 1 and m == mold + 1 and y == yold)
62 | or (d == 1 and m == 1 and y == yold + 1)
63 | ):
64 | self.fail(
65 | """
66 | wrong day, month, year increment
67 | date: %(t)s
68 | day, month, year: %(d)d, %(m)d, %(y)d
69 | previous: %(dold)d, %(mold)d, %(yold)d
70 | """
71 | % locals()
72 | )
73 | dold = d
74 | mold = m
75 | yold = y
76 |
77 | def testHolidayList(self):
78 | """ Testing Calendar testHolidayList() method. """
79 | holidayLstFunction = ql.Calendar.holidayList(ql.Poland(), ql.Date(31, 12, 2014), ql.Date(3, 4, 2015), False)
80 | holidayLstManual = (ql.Date(1, 1, 2015), ql.Date(6, 1, 2015))
81 | # check if dates both from function and from manual imput are the same
82 | self.assertTrue(all([(a == b) for a, b in zip(holidayLstFunction, holidayLstManual)]))
83 |
84 | def tearDown(self):
85 | pass
86 |
87 |
88 | if __name__ == "__main__":
89 | print("testing QuantLib", ql.__version__)
90 | unittest.main(verbosity=2)
91 |
--------------------------------------------------------------------------------
/Python/test/test_daycounters.py:
--------------------------------------------------------------------------------
1 | """
2 | This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
3 | for risk computation using automatic differentiation. It uses XAD,
4 | a fast and comprehensive C++ library for automatic differentiation.
5 |
6 | QuantLib-Risks and XAD are free software: you can redistribute it and/or modify
7 | it under the terms of the GNU Affero General Public License as published
8 | by the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | QuantLib-Risks is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU Affero General Public License for more details.
15 |
16 | You should have received a copy of the GNU Affero General Public License
17 | along with this program. If not, see .
18 |
19 | QuantLib is free software: you can redistribute it and/or modify it
20 | under the terms of the QuantLib license. You should have received a
21 | copy of the license along with this program; if not, please email
22 | . The license is also available online at
23 | .
24 |
25 | This program is distributed in the hope that it will be useful, but WITHOUT
26 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
27 | FOR A PARTICULAR PURPOSE. See the license for more details.
28 | """
29 |
30 | import QuantLib_Risks as ql
31 | import unittest
32 |
33 |
34 | class DayCountersTest(unittest.TestCase):
35 | def test_bus252(self):
36 | """Test Business252 daycounter"""
37 |
38 | calendar = ql.UnitedStates(ql.UnitedStates.GovernmentBond)
39 |
40 | #
41 | # Check that SWIG signature for Business252 calendar allows to
42 | # pass custom calendar into the class constructor. Old
43 | # QuantLib-SWIG versions allow only to create Business252
44 | # calendar with default constructor parameter (Brazil
45 | # calendar), and generate an exception when trying to pass a
46 | # custom calendar as a parameter. So we just check here that
47 | # no exception occurs.
48 | #
49 | ql.Business252(calendar)
50 |
51 |
52 | if __name__ == "__main__":
53 | print("testing QuantLib", ql.__version__)
54 | unittest.main(verbosity=2)
55 |
--------------------------------------------------------------------------------
/Python/test/test_equityindex.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2023 Marcin Rybacki
3 | Copyright (C) 2024 Xcelerit Computing Limited.
4 |
5 | This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
6 | for risk computation using automatic differentiation. It uses XAD,
7 | a fast and comprehensive C++ library for automatic differentiation.
8 |
9 | QuantLib-Risks and XAD are free software: you can redistribute it and/or modify
10 | it under the terms of the GNU Affero General Public License as published
11 | by the Free Software Foundation, either version 3 of the License, or
12 | (at your option) any later version.
13 |
14 | QuantLib-Risks is distributed in the hope that it will be useful,
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | GNU Affero General Public License for more details.
18 |
19 | You should have received a copy of the GNU Affero General Public License
20 | along with this program. If not, see .
21 |
22 | QuantLib is free software: you can redistribute it and/or modify it
23 | under the terms of the QuantLib license. You should have received a
24 | copy of the license along with this program; if not, please email
25 | . The license is also available online at
26 | .
27 |
28 | This program is distributed in the hope that it will be useful, but WITHOUT
29 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
30 | FOR A PARTICULAR PURPOSE. See the license for more details.
31 | """
32 |
33 | import QuantLib_Risks as ql
34 | import unittest
35 |
36 |
37 | EPSILON = 1.e-2
38 |
39 | CAL = ql.TARGET()
40 | DCT = ql.Actual365Fixed()
41 | VALUATION_DATE = CAL.adjust(ql.Date(31, ql.January, 2023))
42 |
43 |
44 | def flat_rate(rate):
45 | return ql.FlatForward(
46 | 2, CAL, ql.QuoteHandle(ql.SimpleQuote(rate)), DCT)
47 |
48 |
49 | class EquityIndexTest(unittest.TestCase):
50 | def setUp(self):
51 | ql.Settings.instance().evaluationDate = VALUATION_DATE
52 |
53 | self.interest_handle = ql.YieldTermStructureHandle(flat_rate(0.03))
54 | self.dividend_handle = ql.YieldTermStructureHandle(flat_rate(0.01))
55 | spot_handle = ql.QuoteHandle(ql.SimpleQuote(8690.0))
56 |
57 | ql.IndexManager.instance().clearHistory("eq_idx")
58 | self.equity_idx = ql.EquityIndex(
59 | "eq_idx", CAL, self.interest_handle, self.dividend_handle, spot_handle)
60 |
61 | def test_equity_index_inspectors(self):
62 | """Testing equity index inspectors"""
63 | fail_msg = "Unable to replicate the properties of an equity index."
64 |
65 | self.assertEqual(self.equity_idx.name(), "eq_idx", msg=fail_msg)
66 | self.assertEqual(self.equity_idx.fixingCalendar(), CAL, msg=fail_msg)
67 |
68 | def test_equity_index_projections(self):
69 | """Testing equity index projections"""
70 | fail_msg = "Failed to calculate the expected index projection."
71 |
72 | self.assertAlmostEqual(
73 | self.equity_idx.fixing(VALUATION_DATE), 8690.0, delta=EPSILON, msg=fail_msg)
74 |
75 | future_dt = ql.Date(20, ql.May, 2030)
76 | self.assertAlmostEqual(
77 | self.equity_idx.fixing(future_dt), 10055.76, delta=EPSILON, msg=fail_msg)
78 |
79 |
80 | if __name__ == '__main__':
81 | print("testing QuantLib", ql.__version__)
82 | unittest.main(verbosity=2)
83 |
--------------------------------------------------------------------------------
/Python/test/test_extrapolation.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2019 Klaus Spanderen
3 | Copyright (C) 2024 Xcelerit Computing Limited.
4 |
5 | This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
6 | for risk computation using automatic differentiation. It uses XAD,
7 | a fast and comprehensive C++ library for automatic differentiation.
8 |
9 | QuantLib-Risks and XAD are free software: you can redistribute it and/or modify
10 | it under the terms of the GNU Affero General Public License as published
11 | by the Free Software Foundation, either version 3 of the License, or
12 | (at your option) any later version.
13 |
14 | QuantLib-Risks is distributed in the hope that it will be useful,
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | GNU Affero General Public License for more details.
18 |
19 | You should have received a copy of the GNU Affero General Public License
20 | along with this program. If not, see .
21 |
22 | QuantLib is free software: you can redistribute it and/or modify it
23 | under the terms of the QuantLib license. You should have received a
24 | copy of the license along with this program; if not, please email
25 | . The license is also available online at
26 | .
27 |
28 | This program is distributed in the hope that it will be useful, but WITHOUT
29 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
30 | FOR A PARTICULAR PURPOSE. See the license for more details.
31 | """
32 |
33 | import unittest
34 |
35 | import QuantLib_Risks as ql
36 | if ql.XAD_ENABLED:
37 | from xad import math
38 | else:
39 | import math
40 |
41 |
42 | class ExtrapolationTest(unittest.TestCase):
43 | def testKnownExpExtrapolation(self):
44 | """Testing Richardson extrapolation of e^x at x->1 with known order of convergence"""
45 | f = lambda x: math.exp(1+x)
46 | x = ql.RichardsonExtrapolation(f, 0.01, 1.0)(4.0)
47 |
48 | self.assertAlmostEqual(x, math.exp(1), 4,
49 | msg="Unable to extrapolate exp(x) at x->1")
50 |
51 | def testUnknownExpExtrapolation(self):
52 | """Testing Richardson extrapolation of e^x at x->1 with unknown order of convergence"""
53 | f = lambda x: math.exp(1+x)
54 | x = ql.RichardsonExtrapolation(f, 0.01)(4.0, 2.0)
55 |
56 | self.assertAlmostEqual(x, math.exp(1), 4,
57 | msg="Unable to extrapolate exp(x) at x->1")
58 |
59 |
60 | if __name__ == "__main__":
61 | print("testing QuantLib", ql.__version__)
62 | unittest.main(verbosity=2)
63 |
--------------------------------------------------------------------------------
/Python/test/test_iborindex.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8-unix
2 | """
3 | Copyright (C) 2018 Wojciech Ślusarski
4 | Copyright (C) 2024 Xcelerit Computing Limited.
5 |
6 | This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
7 | for risk computation using automatic differentiation. It uses XAD,
8 | a fast and comprehensive C++ library for automatic differentiation.
9 |
10 | QuantLib-Risks and XAD are free software: you can redistribute it and/or modify
11 | it under the terms of the GNU Affero General Public License as published
12 | by the Free Software Foundation, either version 3 of the License, or
13 | (at your option) any later version.
14 |
15 | QuantLib-Risks is distributed in the hope that it will be useful,
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | GNU Affero General Public License for more details.
19 |
20 | You should have received a copy of the GNU Affero General Public License
21 | along with this program. If not, see .
22 |
23 | QuantLib is free software: you can redistribute it and/or modify it
24 | under the terms of the QuantLib license. You should have received a
25 | copy of the license along with this program; if not, please email
26 | . The license is also available online at
27 | .
28 |
29 | This program is distributed in the hope that it will be useful, but WITHOUT
30 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
31 | FOR A PARTICULAR PURPOSE. See the license for more details.
32 | """
33 |
34 | import QuantLib_Risks as ql
35 | import unittest
36 |
37 |
38 | class IborIndexTest(unittest.TestCase):
39 | @classmethod
40 | def setUpClass(cls):
41 | cls.euribor3m = ql.Euribor3M()
42 |
43 | def setUp(self):
44 | self.euribor3m.clearFixings()
45 | # values are not real due to copyrights of the fixing
46 | self.euribor3m.addFixing(ql.Date(17, 7, 2018), -0.3)
47 | self.euribor3m.addFixings([ql.Date(12, 7, 2018), ql.Date(13, 7, 2018)], [-0.3, -0.3])
48 |
49 | def testAddFixingFail(self):
50 | """Testing for RuntimeError while trying to overwrite fixing value"""
51 |
52 | with self.assertRaises(RuntimeError):
53 | # attempt to overwrite value that is already set at different level
54 | self.euribor3m.addFixing(ql.Date(17, 7, 2018), -0.4)
55 |
56 | with self.assertRaises(RuntimeError):
57 | # attempt to overwrite value that is already set at different level
58 | self.euribor3m.addFixings([ql.Date(12, 7, 2018), ql.Date(13, 7, 2018)], [-0.4, -0.4])
59 |
60 | def testAddFixing(self):
61 | """Testing for overwriting fixing value"""
62 |
63 | force_overwrite = True
64 | try:
65 | # attempt to overwrite value that is already set at different level
66 | self.euribor3m.addFixing(ql.Date(17, 7, 2018), -0.4, force_overwrite)
67 | self.euribor3m.addFixings([ql.Date(12, 7, 2018), ql.Date(13, 7, 2018)], [-0.4, -0.4], force_overwrite)
68 | # try clearFixings and repeat with original levels
69 | self.euribor3m.clearFixings()
70 | self.euribor3m.addFixing(ql.Date(17, 7, 2018), -0.3)
71 | self.euribor3m.addFixings([ql.Date(12, 7, 2018), ql.Date(13, 7, 2018)], [-0.3, -0.3])
72 |
73 | except RuntimeError as err:
74 | raise AssertionError("Failed to overwrite index fixixng " + "{}".format(err))
75 |
76 | def testTimeSeries(self):
77 | """Testing for getting time series of the fixing"""
78 |
79 | dates = (ql.Date(12, 7, 2018), ql.Date(13, 7, 2018), ql.Date(17, 7, 2018))
80 | values = (-0.3, -0.3, -0.3)
81 | for expected, actual in zip(dates, self.euribor3m.timeSeries().dates()):
82 | self.assertTrue(expected == actual)
83 | for expected, actual in zip(values, self.euribor3m.timeSeries().values()):
84 | self.assertTrue(expected == actual)
85 |
86 |
87 | if __name__ == "__main__":
88 | print("testing QuantLib", ql.__version__)
89 | unittest.main(verbosity=2)
90 |
--------------------------------------------------------------------------------
/Python/test/test_instruments.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
3 | Copyright (C) 2024 Xcelerit Computing Limited.
4 |
5 | This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
6 | for risk computation using automatic differentiation. It uses XAD,
7 | a fast and comprehensive C++ library for automatic differentiation.
8 |
9 | QuantLib-Risks and XAD are free software: you can redistribute it and/or modify
10 | it under the terms of the GNU Affero General Public License as published
11 | by the Free Software Foundation, either version 3 of the License, or
12 | (at your option) any later version.
13 |
14 | QuantLib-Risks is distributed in the hope that it will be useful,
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | GNU Affero General Public License for more details.
18 |
19 | You should have received a copy of the GNU Affero General Public License
20 | along with this program. If not, see .
21 |
22 | QuantLib is free software: you can redistribute it and/or modify it
23 | under the terms of the QuantLib license. You should have received a
24 | copy of the license along with this program; if not, please email
25 | . The license is also available online at
26 | .
27 |
28 | This program is distributed in the hope that it will be useful, but WITHOUT
29 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
30 | FOR A PARTICULAR PURPOSE. See the license for more details.
31 | """
32 |
33 | import QuantLib_Risks as ql
34 | import unittest
35 |
36 | flag = None
37 |
38 |
39 | def raiseFlag():
40 | global flag
41 | flag = 1
42 |
43 |
44 | class InstrumentTest(unittest.TestCase):
45 | def testObservable(self):
46 | "Testing observability of stocks"
47 | global flag
48 | flag = None
49 | me1 = ql.SimpleQuote(0.0)
50 | h = ql.RelinkableQuoteHandle(me1)
51 | s = ql.Stock(h)
52 | s.NPV()
53 |
54 | obs = ql.Observer(raiseFlag)
55 | obs.registerWith(s)
56 |
57 | me1.setValue(3.14)
58 | if not flag:
59 | self.fail("Observer was not notified of instrument change")
60 |
61 | s.NPV()
62 | flag = None
63 | me2 = ql.SimpleQuote(0.0)
64 | h.linkTo(me2)
65 | if not flag:
66 | self.fail("Observer was not notified of instrument change")
67 |
68 | s.NPV()
69 | flag = None
70 | s.freeze()
71 | me2.setValue(2.71)
72 | if flag:
73 | self.fail("Observer was notified of frozen instrument change")
74 | s.unfreeze()
75 | if not flag:
76 | self.fail("Observer was not notified of instrument change")
77 |
78 |
79 | if __name__ == "__main__":
80 | print("testing QuantLib", ql.__version__)
81 | unittest.main(verbosity=2)
82 |
--------------------------------------------------------------------------------
/Python/test/test_integrals.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
3 | Copyright (C) 2024 Xcelerit Computing Limited.
4 |
5 | This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
6 | for risk computation using automatic differentiation. It uses XAD,
7 | a fast and comprehensive C++ library for automatic differentiation.
8 |
9 | QuantLib-Risks and XAD are free software: you can redistribute it and/or modify
10 | it under the terms of the GNU Affero General Public License as published
11 | by the Free Software Foundation, either version 3 of the License, or
12 | (at your option) any later version.
13 |
14 | QuantLib-Risks is distributed in the hope that it will be useful,
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | GNU Affero General Public License for more details.
18 |
19 | You should have received a copy of the GNU Affero General Public License
20 | along with this program. If not, see .
21 |
22 | QuantLib is free software: you can redistribute it and/or modify it
23 | under the terms of the QuantLib license. You should have received a
24 | copy of the license along with this program; if not, please email
25 | . The license is also available online at
26 | .
27 |
28 | This program is distributed in the hope that it will be useful, but WITHOUT
29 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
30 | FOR A PARTICULAR PURPOSE. See the license for more details.
31 | """
32 |
33 | import QuantLib_Risks as ql
34 | import unittest
35 | if ql.XAD_ENABLED:
36 | from xad import math
37 | else:
38 | import math
39 |
40 |
41 | class IntegralTest(unittest.TestCase):
42 | def Gauss(self, x):
43 | return math.exp(-x * x / 2.0) / math.sqrt(2 * math.pi)
44 |
45 | def singleTest(self, I):
46 | tolerance = 1e-4
47 | cases = [
48 | ["f(x) = 1", lambda x: 1, 0.0, 1.0, 1.0],
49 | ["f(x) = x", lambda x: x, 0.0, 1.0, 0.5],
50 | ["f(x) = x^2", lambda x: x * x, 0.0, 1.0, 1.0 / 3.0],
51 | ["f(x) = sin(x)", math.sin, 0.0, math.pi, 2.0],
52 | ["f(x) = cos(x)", math.cos, 0.0, math.pi, 0.0],
53 | ["f(x) = Gauss(x)", self.Gauss, -10.0, 10.0, 1.0],
54 | ]
55 |
56 | for tag, f, a, b, expected in cases:
57 | calculated = I(f, a, b)
58 | if not (abs(calculated - expected) <= tolerance):
59 | self.fail(
60 | """
61 | integrating %(tag)s
62 | calculated: %(calculated)f
63 | expected : %(expected)f
64 | """
65 | % locals()
66 | )
67 |
68 | def testSegment(self):
69 | "Testing segment integration"
70 | self.singleTest(ql.SegmentIntegral(10000))
71 |
72 | def testTrapezoid(self):
73 | "Testing trapezoid integration"
74 | self.singleTest(ql.TrapezoidIntegralDefault(1.0e-4, 1000))
75 |
76 | def testSimpson(self):
77 | "Testing Simpson integration"
78 | self.singleTest(ql.SimpsonIntegral(1.0e-4, 1000))
79 |
80 | def testKronrod(self):
81 | "Testing Gauss-Kronrod integration"
82 | self.singleTest(ql.GaussKronrodAdaptive(1.0e-4))
83 |
84 |
85 | if __name__ == "__main__":
86 | print("testing QuantLib", ql.__version__)
87 | unittest.main(verbosity=2)
88 |
--------------------------------------------------------------------------------
/Python/test/test_marketelements.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
3 | Copyright (C) 2024 Xcelerit Computing Limited.
4 |
5 | This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
6 | for risk computation using automatic differentiation. It uses XAD,
7 | a fast and comprehensive C++ library for automatic differentiation.
8 |
9 | QuantLib-Risks and XAD are free software: you can redistribute it and/or modify
10 | it under the terms of the GNU Affero General Public License as published
11 | by the Free Software Foundation, either version 3 of the License, or
12 | (at your option) any later version.
13 |
14 | QuantLib-Risks is distributed in the hope that it will be useful,
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | GNU Affero General Public License for more details.
18 |
19 | You should have received a copy of the GNU Affero General Public License
20 | along with this program. If not, see .
21 |
22 | QuantLib is free software: you can redistribute it and/or modify it
23 | under the terms of the QuantLib license. You should have received a
24 | copy of the license along with this program; if not, please email
25 | . The license is also available online at
26 | .
27 |
28 | This program is distributed in the hope that it will be useful, but WITHOUT
29 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
30 | FOR A PARTICULAR PURPOSE. See the license for more details.
31 | """
32 |
33 | import QuantLib_Risks as ql
34 | import unittest
35 |
36 | flag = None
37 |
38 |
39 | def raiseFlag():
40 | global flag
41 | flag = 1
42 |
43 |
44 | class MarketElementTest(unittest.TestCase):
45 | def testObservable(self):
46 | "Testing observability of market elements"
47 | global flag
48 | flag = None
49 | me = ql.SimpleQuote(0.0)
50 | obs = ql.Observer(raiseFlag)
51 | obs.registerWith(me)
52 | me.setValue(3.14)
53 | if not flag:
54 | self.fail("Observer was not notified of market element change")
55 |
56 | def testObservableHandle(self):
57 | "Testing observability of market element handles"
58 | global flag
59 | flag = None
60 | me1 = ql.SimpleQuote(0.0)
61 | h = ql.RelinkableQuoteHandle(me1)
62 | obs = ql.Observer(raiseFlag)
63 | obs.registerWith(h)
64 | me1.setValue(3.14)
65 | if not flag:
66 | self.fail("Observer was not notified of market element change")
67 | flag = None
68 | me2 = ql.SimpleQuote(0.0)
69 | h.linkTo(me2)
70 | if not flag:
71 | self.fail("Observer was not notified of market element change")
72 |
73 |
74 | if __name__ == "__main__":
75 | print("testing QuantLib", ql.__version__)
76 | unittest.main(verbosity=2)
77 |
--------------------------------------------------------------------------------
/Python/test/test_ode.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2019 Klaus Spanderen
3 | Copyright (C) 2024 Xcelerit Computing Limited.
4 |
5 | This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
6 | for risk computation using automatic differentiation. It uses XAD,
7 | a fast and comprehensive C++ library for automatic differentiation.
8 |
9 | QuantLib-Risks and XAD are free software: you can redistribute it and/or modify
10 | it under the terms of the GNU Affero General Public License as published
11 | by the Free Software Foundation, either version 3 of the License, or
12 | (at your option) any later version.
13 |
14 | QuantLib-Risks is distributed in the hope that it will be useful,
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | GNU Affero General Public License for more details.
18 |
19 | You should have received a copy of the GNU Affero General Public License
20 | along with this program. If not, see .
21 |
22 | QuantLib is free software: you can redistribute it and/or modify it
23 | under the terms of the QuantLib license. You should have received a
24 | copy of the license along with this program; if not, please email
25 | . The license is also available online at
26 | .
27 |
28 | This program is distributed in the hope that it will be useful, but WITHOUT
29 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
30 | FOR A PARTICULAR PURPOSE. See the license for more details.
31 | """
32 |
33 | import unittest
34 |
35 | import QuantLib_Risks as ql
36 | if ql.XAD_ENABLED:
37 | from xad import math
38 | else:
39 | import math
40 |
41 | class OdeTest(unittest.TestCase):
42 |
43 | def test1dODE(self):
44 | """ Testing one dimesnional ODE """
45 |
46 | yEnd = ql.RungeKutta(1e-8)(lambda x, y : y, 1, 0, 1)
47 |
48 | self.assertAlmostEqual(yEnd, math.exp(1), 5,
49 | msg="Unable to reproduce one dimensional ODE solution.")
50 |
51 |
52 | def test2dODE(self):
53 | """ Testing multi-dimesnional ODE """
54 |
55 | yEnd = ql.RungeKutta(1e-8)(lambda x, y : [y[1], -y[0]],
56 | [0, 1], 0, 0.5*math.pi)[0]
57 |
58 | self.assertAlmostEqual(yEnd, 1.0, 5,
59 | msg="Unable to reproduce multi-dimensional ODE solution.")
60 |
61 |
62 | if __name__ == '__main__':
63 | print("testing QuantLib", ql.__version__)
64 | unittest.main(verbosity=2)
65 |
--------------------------------------------------------------------------------
/Python/test/test_solvers1d.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
3 | Copyright (C) 2024 Xcelerit Computing Limited.
4 |
5 | This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
6 | for risk computation using automatic differentiation. It uses XAD,
7 | a fast and comprehensive C++ library for automatic differentiation.
8 |
9 | QuantLib-Risks and XAD are free software: you can redistribute it and/or modify
10 | it under the terms of the GNU Affero General Public License as published
11 | by the Free Software Foundation, either version 3 of the License, or
12 | (at your option) any later version.
13 |
14 | QuantLib-Risks is distributed in the hope that it will be useful,
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | GNU Affero General Public License for more details.
18 |
19 | You should have received a copy of the GNU Affero General Public License
20 | along with this program. If not, see .
21 |
22 | QuantLib is free software: you can redistribute it and/or modify it
23 | under the terms of the QuantLib license. You should have received a
24 | copy of the license along with this program; if not, please email
25 | . The license is also available online at
26 | .
27 |
28 | This program is distributed in the hope that it will be useful, but WITHOUT
29 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
30 | FOR A PARTICULAR PURPOSE. See the license for more details.
31 | """
32 |
33 | import unittest
34 | import QuantLib_Risks as ql
35 |
36 |
37 | class Foo:
38 | def __call__(self, x):
39 | return x * x - 1.0
40 |
41 | def derivative(self, x):
42 | return 2.0 * x
43 |
44 |
45 | class Solver1DTest(unittest.TestCase):
46 | def test_solve(self):
47 | "Testing 1-D solvers"
48 | for factory in [ql.Brent, ql.Bisection, ql.FalsePosition, ql.Ridder, ql.Secant]:
49 | solver = factory()
50 | for accuracy in [1.0e-4, 1.0e-6, 1.0e-8]:
51 | root = solver.solve(lambda x: x * x - 1.0, accuracy, 1.5, 0.1)
52 | if not (abs(root - 1.0) < accuracy):
53 | self.fail(
54 | """
55 | %(factory)s
56 | solve():
57 | expected: 1.0
58 | calculated root: %(root)g
59 | accuracy: %(accuracy)s
60 | """
61 | % locals()
62 | )
63 | root = solver.solve(lambda x: x * x - 1.0, accuracy, 1.5, 0.0, 1.0)
64 | if not (abs(root - 1.0) < accuracy):
65 | self.fail(
66 | """
67 | %(factory)s
68 | bracketed solve():
69 | expected: 1.0
70 | calculated root: %(root)g
71 | accuracy: %(accuracy)s
72 | """
73 | % locals()
74 | )
75 | for factory in [ql.Newton, ql.NewtonSafe]:
76 | solver = factory()
77 | for accuracy in [1.0e-4, 1.0e-6, 1.0e-8]:
78 | root = solver.solve(Foo(), accuracy, 1.5, 0.1)
79 | if not (abs(root - 1.0) < accuracy):
80 | self.fail(
81 | """
82 | %(factory)s
83 | solve():
84 | expected: 1.0
85 | calculated root: %(root)g
86 | accuracy: %(accuracy)s
87 | """
88 | % locals()
89 | )
90 | root = solver.solve(Foo(), accuracy, 1.5, 0.0, 1.0)
91 | if not (abs(root - 1.0) < accuracy):
92 | self.fail(
93 | """
94 | %(factory)s
95 | bracketed solve():
96 | expected: 1.0
97 | calculated root: %(root)g
98 | accuracy: %(accuracy)s
99 | """
100 | % locals()
101 | )
102 |
103 |
104 | if __name__ == "__main__":
105 | print("testing QuantLib", ql.__version__)
106 | unittest.main(verbosity=2)
107 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | QuantLib-Risks: Risk-enabled QuantLib for Python
3 | ================================================
4 |
5 | [](https://github.com/auto-differentiation/QuantLib-Risks-Py/releases/latest)
6 | [](https://pypi.org/project/QuantLib-Risks)
7 |
8 | ---
9 |
10 | This repository builds QuantLib Python bindings with automatic differentiation, enabling
11 | fast risks calculation with QuantLib in Python.
12 | It wraps [C++ QuantLib-Risks](https://github.com/auto-differentiation/QuantLib-Risks-Cpp)
13 | in Python.
14 | It uses elements from [QuantLib-SWIG](https://github.com/lballabio/QuantLib-SWIG) and
15 | is kept in sync with it.
16 |
17 | ## Getting Started
18 |
19 | You can install it as:
20 |
21 | ```
22 | pip install QuantLib-Risks
23 | ```
24 |
25 | ## Getting Help
26 |
27 | For documentation and other resources, see https://auto-differentiation.github.io/quantlib-risks/python/ .
28 |
29 | If you have found an issue, want to report a bug, or have a feature request, please raise a [GitHub issue](https://github.com/auto-differentiation/QuantLib-Risks-Py/issues).
30 |
31 | ## Related Projects
32 |
33 | - XAD Comprehensive automatic differentiation in [Python](https://github.com/auto-differentiation/xad-py) and [C++](https://github.com/auto-differentiation/xad)
34 | - QuantLib-Risks: Fast risk evaluations in [Python](https://github.com/auto-differentiation/QuantLib-Risks-Py) and [C++](https://github.com/auto-differentiation/QuantLib-Risks-Cpp)
35 |
36 | ## Contributing
37 |
38 | Please read [CONTRIBUTING](CONTRIBUTING.md) for the process of contributing to this project.
39 | Please also obey our [Code of Conduct](CODE_OF_CONDUCT.md) in all communication.
40 |
41 | ## Versioning
42 |
43 | This repository follows the QuantLib versions closely. With each new QuantLib release,
44 | a new release of QuantLib-Risks is prepared with the same version number.
45 |
46 | ## License
47 |
48 | This project is licensed under the GNU Affero General Public License - see the [LICENSE.md](LICENSE.md) file for details.
49 |
50 | It contains code from [QuantLib](https://www.quantlib.org)
51 | and [QuantLib-SWIG](https://github.com/lballabio/QuantLib-SWIG),
52 | which are shipped with a different (compatible) license.
53 | Both licenses are included in [LICENSE.md](LICENSE.md)
54 |
--------------------------------------------------------------------------------
/SWIG/calibratedmodel.i:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
3 | Copyright (C) 2003, 2007, 2009 StatPro Italia srl
4 | Copyright (C) 2005 Dominic Thuillier
5 | Copyright (C) 2007 Luis Cota
6 | Copyright (C) 2016 Gouthaman Balaraman
7 | Copyright (C) 2016 Peter Caspers
8 | Copyright (C) 2018 Matthias Lungwitz
9 |
10 | This file is part of QuantLib, a free-software/open-source library
11 | for financial quantitative analysts and developers - http://quantlib.org/
12 |
13 | QuantLib is free software: you can redistribute it and/or modify it
14 | under the terms of the QuantLib license. You should have received a
15 | copy of the license along with this program; if not, please email
16 | . The license is also available online at
17 | .
18 |
19 | This program is distributed in the hope that it will be useful, but WITHOUT
20 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
21 | FOR A PARTICULAR PURPOSE. See the license for more details.
22 | */
23 |
24 | #ifndef quantlib_calibrated_model_i
25 | #define quantlib_calibrated_model_i
26 |
27 | %include termstructures.i
28 | %include optimizers.i
29 | %include linearalgebra.i
30 | %include types.i
31 | %include vectors.i
32 |
33 | %{
34 | using QuantLib::CalibrationHelper;
35 | %}
36 |
37 | // calibration helpers
38 | %shared_ptr(CalibrationHelper)
39 | class CalibrationHelper {
40 | public:
41 | Real calibrationError();
42 | private:
43 | CalibrationHelper();
44 | };
45 |
46 |
47 | // allow use of vectors of helpers
48 | #if defined(SWIGCSHARP)
49 | SWIG_STD_VECTOR_ENHANCED( ext::shared_ptr )
50 | #endif
51 | namespace std {
52 | %template(CalibrationHelperVector) vector >;
53 | }
54 |
55 | // the base class for calibrated models
56 | %{
57 | using QuantLib::CalibratedModel;
58 | using QuantLib::TermStructureConsistentModel;
59 | %}
60 |
61 | %shared_ptr(CalibratedModel)
62 | class CalibratedModel : public virtual Observable {
63 | #if defined(SWIGCSHARP)
64 | %rename("parameters") params;
65 | #endif
66 | public:
67 | Array params() const;
68 | virtual void calibrate(
69 | const std::vector >&,
70 | OptimizationMethod&, const EndCriteria &,
71 | const Constraint& constraint = Constraint(),
72 | const std::vector& weights = std::vector(),
73 | const std::vector& fixParameters = std::vector());
74 |
75 | void setParams(const Array& params);
76 | Real value(const Array& params,
77 | const std::vector >&);
78 | const ext::shared_ptr& constraint() const;
79 | EndCriteria::Type endCriteria() const;
80 | const Array& problemValues() const;
81 | Integer functionEvaluation() const;
82 | private:
83 | CalibratedModel();
84 | };
85 |
86 | %shared_ptr(TermStructureConsistentModel)
87 | class TermStructureConsistentModel : public virtual Observable{
88 | public:
89 | const Handle& termStructure() const;
90 | private:
91 | TermStructureConsistentModel();
92 | };
93 |
94 | %template(CalibratedModelHandle) Handle;
95 | %template(RelinkableCalibratedModelHandle) RelinkableHandle;
96 |
97 |
98 |
99 | #endif
100 |
--------------------------------------------------------------------------------
/SWIG/cliquetoptions.i:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2021 Jack Gillett
3 |
4 | This file is part of QuantLib, a free-software/open-source library
5 | for financial quantitative analysts and developers - http://quantlib.org/
6 |
7 | QuantLib is free software: you can redistribute it and/or modify it
8 | under the terms of the QuantLib license. You should have received a
9 | copy of the license along with this program; if not, please email
10 | . The license is also available online at
11 | .
12 |
13 | This program is distributed in the hope that it will be useful, but WITHOUT
14 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 | FOR A PARTICULAR PURPOSE. See the license for more details.
16 | */
17 |
18 | #ifndef quantlib_cliquet_options_i
19 | #define quantlib_cliquet_options_i
20 |
21 | %include options.i
22 |
23 | %{
24 | using QuantLib::CliquetOption;
25 | %}
26 |
27 | %shared_ptr(CliquetOption)
28 | class CliquetOption : public OneAssetOption {
29 | public:
30 | CliquetOption(const ext::shared_ptr& payoff,
31 | const ext::shared_ptr& maturity,
32 | std::vector resetDates);
33 | };
34 |
35 |
36 | %{
37 | using QuantLib::AnalyticCliquetEngine;
38 | using QuantLib::AnalyticPerformanceEngine;
39 | using QuantLib::MCPerformanceEngine;
40 | %}
41 |
42 |
43 | %shared_ptr(AnalyticCliquetEngine)
44 | class AnalyticCliquetEngine : public PricingEngine {
45 | public:
46 | AnalyticCliquetEngine(
47 | const ext::shared_ptr& process);
48 | };
49 |
50 |
51 | %shared_ptr(AnalyticPerformanceEngine)
52 | class AnalyticPerformanceEngine : public PricingEngine {
53 | public:
54 | AnalyticPerformanceEngine(
55 | const ext::shared_ptr process);
56 | };
57 |
58 |
59 | %shared_ptr(MCPerformanceEngine);
60 | %shared_ptr(MCPerformanceEngine);
61 |
62 | template
63 | class MCPerformanceEngine : public PricingEngine {
64 | #if !defined(SWIGJAVA) && !defined(SWIGCSHARP)
65 | %feature("kwargs") MCPerformanceEngine;
66 | #endif
67 | public:
68 | %extend {
69 | MCPerformanceEngine(ext::shared_ptr process,
70 | bool brownianBridge = false,
71 | bool antitheticVariate = false,
72 | intOrNull requiredSamples = Null(),
73 | doubleOrNull requiredTolerance = Null(),
74 | intOrNull maxSamples = Null(),
75 | BigInteger seed = 0) {
76 | return new MCPerformanceEngine(process,
77 | brownianBridge,
78 | antitheticVariate,
79 | requiredSamples,
80 | requiredTolerance,
81 | maxSamples,
82 | seed);
83 | }
84 | }
85 | };
86 |
87 | %template(MCPRPerformanceEngine) MCPerformanceEngine;
88 | %template(MCLDPerformanceEngine) MCPerformanceEngine;
89 |
90 | #if defined(SWIGPYTHON)
91 | %pythoncode %{
92 | def MCPerformanceEngine(process,
93 | traits,
94 | brownianBridge=False,
95 | antitheticVariate=False,
96 | requiredSamples=None,
97 | requiredTolerance=None,
98 | maxSamples=None,
99 | seed=0):
100 | traits = traits.lower()
101 | if traits == "pr" or traits == "pseudorandom":
102 | cls = MCPRPerformanceEngine
103 | elif traits == "ld" or traits == "lowdiscrepancy":
104 | cls = MCLDPerformanceEngine
105 | else:
106 | raise RuntimeError("unknown MC traits: %s" % traits);
107 | return cls(process,
108 | brownianBridge,
109 | antitheticVariate,
110 | requiredSamples,
111 | requiredTolerance,
112 | maxSamples,
113 | seed)
114 | %}
115 | #endif
116 |
117 |
118 | #endif
119 |
--------------------------------------------------------------------------------
/SWIG/common.i:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
4 |
5 | This file is part of QuantLib, a free-software/open-source library
6 | for financial quantitative analysts and developers - http://quantlib.org/
7 |
8 | QuantLib is free software: you can redistribute it and/or modify it
9 | under the terms of the QuantLib license. You should have received a
10 | copy of the license along with this program; if not, please email
11 | . The license is also available online at
12 | .
13 |
14 | This program is distributed in the hope that it will be useful, but WITHOUT
15 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 | FOR A PARTICULAR PURPOSE. See the license for more details.
17 | */
18 |
19 | #ifndef quantlib_common_i
20 | #define quantlib_common_i
21 |
22 | %{
23 | namespace QuantLib { namespace ext {} }
24 | namespace ext = QuantLib::ext;
25 | %}
26 | #define SWIG_SHARED_PTR_NAMESPACE ext
27 |
28 | %include stl.i
29 | %include exception.i
30 | %include boost_shared_ptr.i
31 |
32 | %define QL_TYPECHECK_BOOL 7210 %enddef
33 |
34 | %{
35 | // This is necessary to avoid compile failures on
36 | // GCC 4
37 | // see http://svn.boost.org/trac/boost/ticket/1793
38 |
39 | #if defined(NDEBUG)
40 | #define BOOST_DISABLE_ASSERTS 1
41 | #endif
42 |
43 | #include
44 | %}
45 |
46 | #if defined(SWIGPYTHON)
47 | %typemap(in) ext::optional %{
48 | if($input == Py_None)
49 | $1 = ext::nullopt;
50 | else if ($input == Py_True)
51 | $1 = true;
52 | else
53 | $1 = false;
54 | %}
55 | %typecheck (QL_TYPECHECK_BOOL) ext::optional {
56 | if (PyBool_Check($input) || Py_None == $input)
57 | $1 = 1;
58 | else
59 | $1 = 0;
60 | }
61 | #else
62 | #if defined(SWIGCSHARP)
63 | %typemap(cscode) ext::optional %{
64 | public static implicit operator OptionalBool(bool b) => new OptionalBool(b);
65 | %}
66 | #endif
67 | namespace ext {
68 | template
69 | class optional {
70 | public:
71 | optional(T t);
72 | };
73 | }
74 | %template(OptionalBool) ext::optional;
75 | #endif
76 |
77 | %{
78 | // generally useful classes
79 | using QuantLib::Error;
80 | using QuantLib::Handle;
81 | using QuantLib::RelinkableHandle;
82 | %}
83 |
84 | namespace ext {
85 |
86 | %extend shared_ptr {
87 | T* operator->() {
88 | return (*self).operator->();
89 | }
90 | #if defined(SWIGPYTHON)
91 | bool __nonzero__() {
92 | return !!(*self);
93 | }
94 | bool __bool__() {
95 | return !!(*self);
96 | }
97 | #else
98 | bool isNull() {
99 | return !(*self);
100 | }
101 | #endif
102 | }
103 | }
104 |
105 |
106 | template
107 | class Handle {
108 | public:
109 | Handle(const ext::shared_ptr& = ext::shared_ptr());
110 | ext::shared_ptr operator->();
111 | ext::shared_ptr currentLink();
112 | #if defined(SWIGPYTHON)
113 | %extend {
114 | bool __nonzero__() {
115 | return !self->empty();
116 | }
117 | bool __bool__() {
118 | return !self->empty();
119 | }
120 | }
121 | #else
122 | bool empty();
123 | #endif
124 | };
125 |
126 | template
127 | class RelinkableHandle : public Handle {
128 | public:
129 | RelinkableHandle(const ext::shared_ptr& = ext::shared_ptr());
130 | void linkTo(const ext::shared_ptr&);
131 | %extend {
132 | // could be defined in C++ class, added here in the meantime
133 | void reset() {
134 | self->linkTo(ext::shared_ptr());
135 | }
136 | }
137 | };
138 |
139 | %define swigr_list_converter(ContainerRType,
140 | ContainerCType, ElemCType)
141 | #if defined(SWIGR)
142 | %Rruntime %{
143 | setMethod('print', 'ContainerCType',
144 | function(x) print(as(x, "ElemCType")))
145 |
146 | setAs("ContainerCType", "ElemCType",
147 | function(from) {if (from$size()) from[1:from$size()] else NULL} )
148 |
149 | setAs("ElemCType", "ContainerCType",
150 | function(from) { a <- ContainerRType(length(from));
151 | sapply(1:length(from), function(n) {
152 | a[n] <- from[n] } )
153 | a
154 | })
155 | %}
156 | #endif
157 | %enddef
158 |
159 |
160 | %define deprecate_feature(OldName, NewName)
161 | #if defined(SWIGPYTHON)
162 | %pythoncode %{
163 | def OldName(*args, **kwargs):
164 | from warnings import warn
165 | warn('%s is deprecated; use %s' % (OldName.__name__, NewName.__name__))
166 | return NewName(*args, **kwargs)
167 | %}
168 | #endif
169 | %enddef
170 |
171 |
172 | #endif
173 |
--------------------------------------------------------------------------------
/SWIG/credit.i:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2008 StatPro Italia srl
3 |
4 | This file is part of QuantLib, a free-software/open-source library
5 | for financial quantitative analysts and developers - http://quantlib.org/
6 |
7 | QuantLib is free software: you can redistribute it and/or modify it
8 | under the terms of the QuantLib license. You should have received a
9 | copy of the license along with this program; if not, please email
10 | . The license is also available online at
11 | .
12 |
13 | This program is distributed in the hope that it will be useful, but WITHOUT
14 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 | FOR A PARTICULAR PURPOSE. See the license for more details.
16 | */
17 |
18 | #ifndef quantlib_credit_i
19 | #define quantlib_credit_i
20 |
21 | %include defaultprobability.i
22 |
23 | %{
24 | using QuantLib::Protection;
25 | %}
26 |
27 | struct Protection {
28 | enum Side { Buyer, Seller };
29 | };
30 |
31 |
32 | #endif
33 |
--------------------------------------------------------------------------------
/SWIG/date_extra.i:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Extra type converters for Dates that are needed with QuantLib-Risks in order
3 | * to cover pair and vectors thereof. The functions are declared in
4 | * converters.hpp
5 | *
6 | * This file is part of QuantLib-Risks, a Python wrapper for QuantLib enabled
7 | * for risk computation using automatic differentiation. It uses XAD,
8 | * a fast and comprehensive C++ library for automatic differentiation.
9 | *
10 | * Copyright (C) 2010-2024 Xcelerit Computing Ltd.
11 | *
12 | * This program is free software: you can redistribute it and/or modify
13 | * it under the terms of the GNU Affero General Public License as published
14 | * by the Free Software Foundation, either version 3 of the License, or
15 | * (at your option) any later version.
16 | *
17 | * This program is distributed in the hope that it will be useful,
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | * GNU Affero General Public License for more details.
21 | *
22 | * You should have received a copy of the GNU Affero General Public License
23 | * along with this program. If not, see .
24 | *
25 | ******************************************************************************/
26 |
27 | #ifndef quantlib_date_extra_i
28 | #define quantlib_date_extra_i
29 |
30 | %{
31 |
32 | PyObject* convert_to_SwigDate(const Date& date) {
33 | return SWIG_NewPointerObj(
34 | (new Date(static_cast< const Date& >(date))),
35 | SWIGTYPE_p_Date,
36 | SWIG_POINTER_OWN | 0 );
37 | }
38 |
39 | Date convert_to_QlDate(PyObject* obj) {
40 | void* argp1 = nullptr;
41 | int res1 = SWIG_ConvertPtr(obj, &argp1,SWIGTYPE_p_Date, 0 | 0 );
42 | if (!SWIG_IsOK(res1)) {
43 | throw std::runtime_error("error in date conversion");
44 | }
45 | Date *arg1 = reinterpret_cast(argp1);
46 | return *arg1;
47 | }
48 |
49 | PyObject* make_date_real_pair_tuple(const std::pair& p) {
50 | auto t = PyTuple_New(2);
51 | PyTuple_SET_ITEM(t, 0, convert_to_SwigDate(p.first));
52 | PyTuple_SET_ITEM(t, 1, make_PyObject(p.second));
53 | return t;
54 | }
55 |
56 | std::pair make_date_real_pair_from_tuple(PyObject* obj) {
57 | Date d = convert_to_QlDate(PyTuple_GetItem(obj, 0));
58 | Real r = make_Real(PyTuple_GetItem(obj, 1));
59 | return {d, r};
60 | }
61 |
62 | bool check_date_real_pair_input(PyObject* obj)
63 | {
64 | if (!PyTuple_Check(obj))
65 | return false;
66 | if (PyTuple_Size(obj) != 2)
67 | return false;
68 | if (!check_Real(PyTuple_GetItem(obj, 1)))
69 | return false;
70 | void* argp1 = nullptr;
71 | int res1 = SWIG_ConvertPtr(obj, &argp1,SWIGTYPE_p_Date, 0 | 0 );
72 | if (!SWIG_IsOK(res1))
73 | return false;
74 | return true;
75 | }
76 |
77 | %}
78 |
79 | %typemap(in) std::pair {
80 | if (PyTuple_Check($input) && PyTuple_Size($input) == 2) {
81 | $1 = make_date_real_pair_from_tuple($input);
82 | } else {
83 | SWIG_exception(SWIG_TypeError, "Could not convert to date/Real pair")
84 | }
85 | }
86 |
87 | %typemap(in) const std::pair& (std::pair temp) {
88 | if (PyTuple_Check($input) && PyTuple_Size($input) == 2) {
89 | temp = make_date_real_pair_from_tuple($input);
90 | $1 = &temp;
91 |
92 | } else {
93 | SWIG_exception(SWIG_TypeError, "Could not convert to date/Real pair")
94 | }
95 | }
96 |
97 | %typemap(out) std::pair {
98 | $result = make_date_real_pair_tuple($1);
99 | }
100 |
101 | %define QL_TYPECHECK_REALDATEOBJ_PAIR 4993 %enddef
102 |
103 | %typecheck(QL_TYPECHECK_REALDATEOBJ_PAIR) std::pair, const std::pair& {
104 | $1 = check_date_real_pair_input($input) ? 1 : 0;
105 | }
106 |
107 | #endif
--------------------------------------------------------------------------------
/SWIG/daycounters.i:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
4 | Copyright (C) 2003, 2004, 2005 StatPro Italia srl
5 | Copyright (C) 2005 Johan Witters
6 | Copyright (C) 2022 Ignacio Anguita
7 |
8 | This file is part of QuantLib, a free-software/open-source library
9 | for financial quantitative analysts and developers - http://quantlib.org/
10 |
11 | QuantLib is free software: you can redistribute it and/or modify it
12 | under the terms of the QuantLib license. You should have received a
13 | copy of the license along with this program; if not, please email
14 | . The license is also available online at
15 | .
16 |
17 | This program is distributed in the hope that it will be useful, but WITHOUT
18 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 | FOR A PARTICULAR PURPOSE. See the license for more details.
20 | */
21 |
22 | #ifndef quantlib_day_counters_i
23 | #define quantlib_day_counters_i
24 |
25 | %include common.i
26 | %include calendars.i
27 | %include date.i
28 | %include types.i
29 | %include stl.i
30 | %include null.i
31 |
32 | %{
33 | using QuantLib::DayCounter;
34 | %}
35 |
36 | class DayCounter {
37 | protected:
38 | DayCounter();
39 | public:
40 | BigInteger dayCount(const Date& d1, const Date& d2) const;
41 | Time yearFraction(const Date& d1, const Date& d2,
42 | const Date& startRef = Date(),
43 | const Date& endRef = Date()) const;
44 | std::string name() const;
45 | %extend {
46 | std::string __str__() {
47 | return self->name()+" day counter";
48 | }
49 | #if defined(SWIGPYTHON) || defined(SWIGJAVA)
50 | bool __eq__(const DayCounter& other) {
51 | return (*self) == other;
52 | }
53 | bool __ne__(const DayCounter& other) {
54 | return (*self) != other;
55 | }
56 | #endif
57 | }
58 | #if defined(SWIGPYTHON)
59 | %pythoncode %{
60 | def __hash__(self):
61 | return hash(self.name())
62 | %}
63 | #endif
64 | };
65 |
66 | namespace QuantLib {
67 |
68 | class Actual360 : public DayCounter {
69 | public:
70 | Actual360(const bool includeLastDay = false);
71 | };
72 | class Actual366 : public DayCounter {
73 | public:
74 | Actual366(const bool includeLastDay = false);
75 | };
76 | class Actual36525 : public DayCounter {
77 | public:
78 | Actual36525(const bool includeLastDay = false);
79 | };
80 | class Actual364 : public DayCounter {};
81 | class Actual365Fixed : public DayCounter {
82 | public:
83 | enum Convention { Standard, Canadian, NoLeap };
84 | Actual365Fixed(Convention c = Standard);
85 | };
86 | class Thirty360 : public DayCounter {
87 | public:
88 | enum Convention { USA, BondBasis, European, EurobondBasis, Italian, German, ISMA, ISDA, NASD };
89 | Thirty360(Convention c, const Date& terminationDate = Date());
90 | };
91 | class Thirty365 : public DayCounter {};
92 | class ActualActual : public DayCounter {
93 | public:
94 | enum Convention { ISMA, Bond, ISDA, Historical, Actual365, AFB, Euro };
95 | ActualActual(Convention c, const Schedule& schedule = Schedule());
96 | };
97 | class OneDayCounter : public DayCounter {};
98 | class SimpleDayCounter : public DayCounter {};
99 | class Business252 : public DayCounter {
100 | public:
101 | Business252(Calendar c = Brazil());
102 | };
103 |
104 | }
105 |
106 | %{
107 | using QuantLib::yearFractionToDate;
108 | %}
109 |
110 | Date yearFractionToDate(
111 | const DayCounter& dayCounter, const Date& referenceDate, Time t);
112 |
113 | #endif
114 |
--------------------------------------------------------------------------------
/SWIG/discountcurve.i:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
4 | Copyright (C) 2003, 2004, 2005, 2006 StatPro Italia srl
5 | Copyright (C) 2015 Matthias Groncki
6 |
7 | This file is part of QuantLib, a free-software/open-source library
8 | for financial quantitative analysts and developers - http://quantlib.org/
9 |
10 | QuantLib is free software: you can redistribute it and/or modify it
11 | under the terms of the QuantLib license. You should have received a
12 | copy of the license along with this program; if not, please email
13 | . The license is also available online at
14 | .
15 |
16 | This program is distributed in the hope that it will be useful, but WITHOUT
17 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 | FOR A PARTICULAR PURPOSE. See the license for more details.
19 | */
20 |
21 | #ifndef quantlib_discount_curve_i
22 | #define quantlib_discount_curve_i
23 |
24 | %include termstructures.i
25 | %include interpolation.i
26 |
27 | %{
28 | using QuantLib::InterpolatedDiscountCurve;
29 | %}
30 |
31 | %shared_ptr(InterpolatedDiscountCurve);
32 | %shared_ptr(InterpolatedDiscountCurve);
33 | %shared_ptr(InterpolatedDiscountCurve);
34 | %shared_ptr(InterpolatedDiscountCurve);
35 | %shared_ptr(InterpolatedDiscountCurve);
36 | %shared_ptr(InterpolatedDiscountCurve);
37 |
38 | template
39 | class InterpolatedDiscountCurve : public YieldTermStructure {
40 | public:
41 | InterpolatedDiscountCurve(const std::vector& dates,
42 | const std::vector& discounts,
43 | const DayCounter& dayCounter,
44 | const Calendar& calendar = Calendar(),
45 | const Interpolator& i = Interpolator());
46 | const std::vector