Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
131 commits
Select commit Hold shift + click to select a range
c84d01c
forge integration
da-roth Dec 12, 2025
a3605f9
Revert "forge integration"
da-roth Dec 15, 2025
98c276b
forge integration
da-roth Dec 15, 2025
6c331dc
up
da-roth Dec 15, 2025
15e8808
use setBackend
da-roth Dec 19, 2025
b08fd88
updates due to xad-jit
da-roth Dec 19, 2025
33e3d69
updated backend naming
da-roth Dec 19, 2025
8494c87
graph updates with jitnode
da-roth Dec 19, 2025
36eacb8
first refactor
da-roth Dec 22, 2025
311d387
revert changes on fork
da-roth Dec 22, 2025
2591bb5
update path
da-roth Dec 22, 2025
41dc182
update ci
da-roth Dec 22, 2025
a4021b2
remove compatibility layer
da-roth Dec 22, 2025
66b8ea2
updates
da-roth Dec 22, 2025
7771b93
update backend namespaces
da-roth Dec 25, 2025
b68d6f6
update c api workflow
da-roth Dec 25, 2025
7c75cd1
update benchmark yaml
da-roth Dec 25, 2025
8e1ce66
fix benchmark yaml
da-roth Dec 25, 2025
f7202e4
update ci.yaml
da-roth Dec 30, 2025
fbda9f6
updates
da-roth Dec 31, 2025
b8ca808
updated ci.yaml
da-roth Dec 31, 2025
95e634a
update ci.yaml
da-roth Dec 31, 2025
98d8b86
updated win build
da-roth Dec 31, 2025
c17f541
fix benchmark baseline
da-roth Jan 2, 2026
ed68306
updates
da-roth Jan 2, 2026
cf5030b
added benchmark_utils
da-roth Jan 2, 2026
8467808
temporarily use xad-jit
da-roth Jan 5, 2026
58267e1
up
da-roth Jan 5, 2026
3642cfa
up
da-roth Jan 7, 2026
7cda13d
use double forgebackend
da-roth Jan 9, 2026
3b5eb06
remove git ignore
da-roth Jan 10, 2026
ed5f877
update ci to use original xad
da-roth Jan 10, 2026
ad5dead
update reference in benchmark yaml
da-roth Jan 10, 2026
329aa79
new benchmarks.yaml
da-roth Jan 10, 2026
6bdd4d6
updated workflows
da-roth Jan 10, 2026
6275901
updates
da-roth Jan 10, 2026
6b74c54
up
da-roth Jan 10, 2026
608625e
udpated benchmark workflows
da-roth Jan 10, 2026
277b889
upda
da-roth Jan 10, 2026
9216536
udpates on benchmarks
da-roth Jan 10, 2026
814366a
added benchmark
da-roth Jan 10, 2026
c1e7296
added win and renamed a bit
da-roth Jan 10, 2026
ee695f8
up
da-roth Jan 10, 2026
86bfb8f
up
da-roth Jan 10, 2026
aa4a7da
update
da-roth Jan 10, 2026
43dfda7
remove unneeded workflows
da-roth Jan 10, 2026
957b93a
cleaning
da-roth Jan 10, 2026
1c6b0f9
udpates
da-roth Jan 10, 2026
c426d8e
re-route to original
da-roth Jan 10, 2026
9bc49c7
up
da-roth Jan 11, 2026
caae75e
Revert "up"
da-roth Jan 11, 2026
73cc721
remove copying around stuff
da-roth Jan 11, 2026
8e0d3ad
fixed config
da-roth Jan 14, 2026
2bbd67a
fix QL
da-roth Jan 14, 2026
f430020
up
da-roth Jan 14, 2026
cf239ff
up readme
da-roth Jan 16, 2026
1dd8047
Update .github/workflows/ci.yaml
da-roth Jan 20, 2026
469ccc6
Update .github/workflows/ci.yaml
da-roth Jan 20, 2026
4f07a96
Update .github/workflows/ci.yaml
da-roth Jan 20, 2026
ba2dd86
Update .github/workflows/ci.yaml
da-roth Jan 20, 2026
d484cd1
clean away the overhead test
da-roth Jan 20, 2026
619df09
updaed linux job initially
da-roth Jan 20, 2026
705c4d0
draft of new benchmark job structure
da-roth Jan 20, 2026
48e48c0
not trigger old ones
da-roth Jan 20, 2026
7bf0a1e
cleaned unneeded stuff
da-roth Jan 20, 2026
ce2c0d9
fix naming issues
da-roth Jan 20, 2026
2a208d4
up
da-roth Jan 20, 2026
21d241e
up
da-roth Jan 20, 2026
631f63a
new workflow
da-roth Jan 20, 2026
03434c4
up
da-roth Jan 20, 2026
c83be8f
up
da-roth Jan 20, 2026
b62d269
up
da-roth Jan 20, 2026
5732819
up
da-roth Jan 20, 2026
f69137f
up
da-roth Jan 20, 2026
3799ae8
up
da-roth Jan 20, 2026
5ad6ab0
up
da-roth Jan 20, 2026
4cd6880
up
da-roth Jan 20, 2026
046c66d
up
da-roth Jan 20, 2026
a636659
update output
da-roth Jan 21, 2026
cdc3d29
update output
da-roth Jan 21, 2026
c9a3106
remove v1
da-roth Jan 21, 2026
ebed861
clean cmake after rmv v1
da-roth Jan 21, 2026
037bf93
clean cmake for v2 rmv
da-roth Jan 21, 2026
77b6795
updated paths stuff
da-roth Jan 21, 2026
c1f0591
updates
da-roth Jan 21, 2026
7c7ffb6
up
da-roth Jan 21, 2026
e862c1a
udpdate
da-roth Jan 21, 2026
945dda2
updates
da-roth Jan 21, 2026
da7f123
name issue
da-roth Jan 21, 2026
f1311bf
update
da-roth Jan 21, 2026
c4a3e82
more iterations for prod example
da-roth Jan 22, 2026
e9206fe
refactor code
da-roth Jan 22, 2026
f272ecb
update pricing
da-roth Jan 23, 2026
d0e6706
order change
da-roth Jan 23, 2026
8f4f5a6
changed order
da-roth Jan 23, 2026
34a11ab
up
da-roth Jan 23, 2026
c02647b
sanity
da-roth Jan 23, 2026
18f4f15
up
da-roth Jan 23, 2026
897b74a
minor refactor
da-roth Jan 23, 2026
a28bc5e
Merge remote-tracking branch 'upstream/main' into forge
da-roth Jan 23, 2026
580ed86
added xadsplit
da-roth Jan 23, 2026
9d932e9
updated benchmark aad
da-roth Jan 23, 2026
4091fbb
reorder tests
da-roth Jan 23, 2026
5e8e53d
fix xad-split
da-roth Jan 23, 2026
ff880f0
up
da-roth Jan 23, 2026
b1b2789
up
da-roth Jan 23, 2026
e74420c
update
da-roth Jan 25, 2026
2ae3330
up
da-roth Jan 25, 2026
a834d63
script for local
da-roth Jan 25, 2026
be247fb
quicker build
da-roth Jan 25, 2026
971bac6
custom m1 and m2
da-roth Jan 25, 2026
4a25180
fix evolve
da-roth Jan 25, 2026
f14575d
up
da-roth Jan 25, 2026
1dc5410
remove sh
da-roth Jan 25, 2026
ba76944
update ci
da-roth Jan 25, 2026
5775a7e
update to have xad-split in xad
da-roth Jan 26, 2026
32964ff
update benchmarks yaml
da-roth Jan 26, 2026
d01e3c4
updated texts
da-roth Jan 26, 2026
9410273
update benchmark stuff
da-roth Jan 26, 2026
14cabf1
fix upstream
da-roth Jan 26, 2026
5a9cddf
use upstream ci names
da-roth Jan 29, 2026
e24e207
tried fixes
da-roth Feb 2, 2026
55de855
clean locally
da-roth Feb 2, 2026
8780440
up
da-roth Feb 2, 2026
834894e
up
da-roth Feb 2, 2026
9acf091
Revert "up"
da-roth Feb 3, 2026
a2c9376
Revert "up"
da-roth Feb 3, 2026
efd134c
Revert "clean locally"
da-roth Feb 3, 2026
8c3f726
Revert "tried fixes"
da-roth Feb 3, 2026
57ce5ab
improve matrix efficiency
da-roth Feb 3, 2026
b0ed41e
fix
da-roth Feb 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
904 changes: 604 additions & 300 deletions .github/workflows/ci.yaml

Large diffs are not rendered by default.

922 changes: 922 additions & 0 deletions .github/workflows/ql-benchmarks.yaml

Large diffs are not rendered by default.

65 changes: 60 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
##############################################################################
#
#
#
# This file is part of QuantLib-Risks, an adaptor module to enable using XAD with
# QuantLib. XAD is a fast and comprehensive C++ library for
Expand All @@ -19,17 +19,72 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#
##############################################################################

option(QLRISKS_DISABLE_AAD "Disable using XAD for QuantLib's Real, allowing to run samples with double" OFF)
option(QLRISKS_ENABLE_FORGE "Enable Forge JIT backend via xad-forge" OFF)
option(QLRISKS_USE_FORGE_CAPI "Use Forge C API instead of C++ API for binary compatibility" OFF)

add_subdirectory(ql)
if(MSVC)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()
add_subdirectory(Examples)
if(NOT QLRISKS_DISABLE_AAD)
# the test suite is not supporting double
add_subdirectory(test-suite)

##############################################################################
# QLRisks-Forge integration via xad-forge
# NOTE: This must be defined BEFORE test-suite so tests can link to it
##############################################################################

if(QLRISKS_ENABLE_FORGE)
message(STATUS "QLRisks-Forge: Looking for xad-forge...")

# Pass through the C API option to xad-forge
set(XAD_FORGE_USE_CAPI ${QLRISKS_USE_FORGE_CAPI} CACHE BOOL "" FORCE)

# Option 1: Check if xad-forge was added as subdirectory
if(TARGET xad-forge)
message(STATUS "QLRisks-Forge: Found xad-forge target (subdirectory mode)")
set(XAD_FORGE_FOUND TRUE)
endif()

# Option 2: Try find_package for pre-built xad-forge
if(NOT XAD_FORGE_FOUND)
find_package(xad-forge CONFIG QUIET)
if(xad-forge_FOUND)
message(STATUS "QLRisks-Forge: Found xad-forge package (pre-built mode)")
set(XAD_FORGE_FOUND TRUE)
endif()
endif()

if(XAD_FORGE_FOUND)
# Create qlrisks-forge as an INTERFACE library wrapping xad-forge
add_library(qlrisks-forge INTERFACE)
add_library(QLRisks::forge ALIAS qlrisks-forge)

target_link_libraries(qlrisks-forge INTERFACE
XADForge::xad-forge
)

target_compile_definitions(qlrisks-forge INTERFACE QLRISKS_HAS_FORGE=1)

message(STATUS "QLRisks-Forge: Configured with xad-forge")
else()
message(STATUS "QLRisks-Forge: xad-forge not found - ForgeBackend will not be available")
message(STATUS "QLRisks-Forge: To enable, either:")
message(STATUS " 1. Add xad-forge as subdirectory")
message(STATUS " 2. Set CMAKE_PREFIX_PATH to xad-forge installation")
endif()
endif()

##############################################################################
# Test suite (after QLRisks::forge is defined)
##############################################################################

# Add test-suite if:
# 1. AAD is enabled (for XAD-based tests and benchmarks), OR
# 2. FD benchmark is requested (works with plain double)
if(NOT QLRISKS_DISABLE_AAD OR QLRISKS_BUILD_BENCHMARK_FD)
add_subdirectory(test-suite)
endif()
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ This repository contains integration headers, examples, and tests required
for this integration.
It is not usable stand-alone.

## JIT Compilation Support

XAD is optimized for computing sensitivities efficiently in a single evaluation pass using adjoint mode. For workflows that require repeated evaluation across many scenarios—such as Monte Carlo simulations, XVA calculations, regulatory stress testing, or scenario-based risk analysis—XAD also supports recording computations into a [`JITGraph`](https://auto-differentiation.github.io/xad/ref/jit/) that can be compiled and re-evaluated efficiently using a JIT backend. The [xad-forge](https://github.com/da-roth/xad-forge) library provides Forge-based backends for this purpose, including vectorized AVX execution. See the [xad-forge README](https://github.com/da-roth/xad-forge#when-to-use-jit) for guidance on when JIT compilation is beneficial.

The repository includes a [swaption benchmark](.github/workflows/ql-benchmarks.yaml) that demonstrates a hybrid workflow: curve bootstrapping with XAD's tape, followed by Monte Carlo pricing with JIT-compiled evaluation, comparing tape-based, JIT, and JIT-AVX performance.

## Getting Started

For detailed build instructions with [XAD](https://auto-differentiation.github.io) and [QuantLib](https://www.quantlib.org), please refer to the [XAD documentation site](https://auto-differentiation.github.io/quantlib-risks/cxx/).
Expand Down
2 changes: 1 addition & 1 deletion ql/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ if(NOT QLRISKS_DISABLE_AAD)
else()
target_compile_definitions(QuantLib-Risks INTERFACE QLRISKS_DISABLE_AAD=1)
endif()
target_link_libraries(QuantLib-Risks INTERFACE XAD::xad)
if(MSVC)
target_compile_options(QuantLib-Risks INTERFACE /bigobj)
endif()
target_link_libraries(QuantLib-Risks INTERFACE XAD::xad)
set_target_properties(QuantLib-Risks PROPERTIES
EXPORT_NAME QuantLib-Risks
)
Expand Down
87 changes: 85 additions & 2 deletions test-suite/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
option(QLRISKS_BUILD_TEST_SUITE "Build the QuantLib-Risks test suite" OFF)
option(QLRISKS_ENABLE_FORGE_TESTS "Enable Forge JIT tests (requires Forge)" OFF)

set(QLRISKS_TEST_SOURCES
americanoption_xad.cpp
barrieroption_xad.cpp
Expand All @@ -9,14 +12,25 @@ set(QLRISKS_TEST_SOURCES
forwardrateagreement_xad.cpp
hestonmodel_xad.cpp
swap_xad.cpp

utilities_xad.cpp
quantlibtestsuite_xad.cpp
)

# Forge JIT tests - require Forge's native code backend
# Tests QuantLib-specific JIT functionality (swaption pricing pipeline)
set(QLRISKS_FORGE_TESTS_ENABLED FALSE)
if(QLRISKS_ENABLE_FORGE_TESTS AND TARGET QLRisks::forge)
message(STATUS "QLRisks test-suite: Adding Forge JIT tests (native code backend)")
list(APPEND QLRISKS_TEST_SOURCES swaption_jit_pipeline_xad.cpp)
set(QLRISKS_FORGE_TESTS_ENABLED TRUE)
elseif(QLRISKS_ENABLE_FORGE_TESTS)
message(WARNING "QLRisks test-suite: QLRISKS_ENABLE_FORGE_TESTS=ON but QLRisks::forge not available")
endif()

set(QLRISKS_TEST_HEADERS utilities_xad.hpp)

if(QL_BUILD_TEST_SUITE)
if(QL_BUILD_TEST_SUITE OR QLRISKS_BUILD_TEST_SUITE)
add_executable(QuantLib-Risks_test_suite ${QLRISKS_TEST_SOURCES} ${QLRISKS_TEST_HEADERS})
set_target_properties(QuantLib-Risks_test_suite PROPERTIES OUTPUT_NAME "quantlib-risks-test-suite")
if (NOT Boost_USE_STATIC_LIBS)
Expand All @@ -25,8 +39,77 @@ if(QL_BUILD_TEST_SUITE)
target_link_libraries(QuantLib-Risks_test_suite PRIVATE
ql_library
${QL_THREAD_LIBRARIES})

# ONLY link to Forge if Forge tests are actually enabled
# This is important because linking Forge brings in AVX2-compiled code
# which can cause ODR violations if not properly isolated
if(QLRISKS_FORGE_TESTS_ENABLED)
message(STATUS "QLRisks test-suite: Linking QLRisks::forge (Forge tests enabled)")
target_link_libraries(QuantLib-Risks_test_suite PRIVATE QLRisks::forge)
target_compile_definitions(QuantLib-Risks_test_suite PRIVATE QLRISKS_HAS_FORGE=1)
else()
message(STATUS "QLRisks test-suite: NOT linking Forge (Forge tests disabled)")
endif()

if (QL_INSTALL_TEST_SUITE)
install(TARGETS QuantLib-Risks_test_suite RUNTIME DESTINATION ${QL_INSTALL_BINDIR})
endif()
add_test(NAME QuantLib-Risks_test_suite COMMAND QuantLib-Risks_test_suite --log_level=message)
endif()

# =============================================================================
# Benchmark - Split FD/AAD executables for fair comparison
# =============================================================================

# FD benchmark - Finite Differences using plain double QuantLib
# This is built WITHOUT XAD to ensure fair FD vs AAD comparison
option(QLRISKS_BUILD_BENCHMARK_FD "Build FD benchmark (plain double, no XAD)" OFF)
if(QLRISKS_BUILD_BENCHMARK_FD)
message(STATUS "QLRisks: Building FD benchmark (plain double)")
add_executable(benchmark_fd
benchmark_fd.cpp
benchmark_common.hpp
benchmark_pricing.hpp
PlatformInfo.hpp
)
set_target_properties(benchmark_fd PROPERTIES
OUTPUT_NAME "benchmark-fd")
target_link_libraries(benchmark_fd PRIVATE
ql_library
${QL_THREAD_LIBRARIES})

if (QL_INSTALL_TEST_SUITE)
install(TARGETS benchmark_fd RUNTIME DESTINATION ${QL_INSTALL_BINDIR})
endif()
endif()

# AAD benchmark - XAD tape-based AAD and optionally Forge JIT
# Built with XAD-enabled QuantLib, optionally links Forge for JIT benchmarks
option(QLRISKS_BUILD_BENCHMARK_AAD "Build AAD benchmark (XAD tape, optionally Forge JIT)" OFF)
if(QLRISKS_BUILD_BENCHMARK_AAD)
message(STATUS "QLRisks: Building AAD benchmark")
add_executable(benchmark_aad
benchmark_aad.cpp
benchmark_common.hpp
benchmark_pricing.hpp
PlatformInfo.hpp
)
set_target_properties(benchmark_aad PROPERTIES
OUTPUT_NAME "benchmark-aad")
target_link_libraries(benchmark_aad PRIVATE
ql_library
${QL_THREAD_LIBRARIES})

# Link Forge if available for JIT benchmarks
if(TARGET QLRisks::forge)
message(STATUS "QLRisks AAD benchmark: Linking QLRisks::forge (JIT benchmarks enabled)")
target_link_libraries(benchmark_aad PRIVATE QLRisks::forge)
target_compile_definitions(benchmark_aad PRIVATE QLRISKS_HAS_FORGE=1)
else()
message(STATUS "QLRisks AAD benchmark: Building without Forge (XAD tape only)")
endif()

if (QL_INSTALL_TEST_SUITE)
install(TARGETS benchmark_aad RUNTIME DESTINATION ${QL_INSTALL_BINDIR})
endif()
endif()
Loading
Loading