• Finance

Fujitsu Digital Annealer for Credit Portfolio Optimization

Fujitsu

A European bank used Fujitsu's Digital Annealer 3 (DA3) to optimize credit portfolio selection, choosing loan combinations that maximize expected risk-adjusted return while satisfying Basel III/IV regulatory capital constraints. The DA3 is a classical CMOS chip that implements parallel tempering-style annealing dynamics at room temperature across a fully connected 8192-bit graph, eliminating the minor-embedding overhead required when mapping dense financial problems onto sparse quantum annealing hardware.

Key Outcome
DA3 found solutions within 1% of Gurobi optimal in 0.8 seconds vs 45 seconds for Gurobi; fully connected topology eliminated the embedding overhead.

Fujitsu’s Digital Annealer is not a quantum computer but a purpose-built CMOS chip that mimics quantum annealing dynamics using classical simulated annealing with hardware-level parallelism. The DA3 generation supports 8192 fully connected binary variables, meaning any pair of bits can have a weighted interaction without the graph embedding step required on D-Wave’s sparse Pegasus topology. For financial optimization problems, which often involve dense correlation matrices (every asset correlated with every other), this fully connected topology is a significant practical advantage: a 100-asset portfolio problem with full covariance structure maps directly onto DA3 variables without approximation, whereas D-Wave’s Pegasus graph supports roughly 5500 qubits but requires embedding that typically expands a 100-node fully connected graph into 600+ physical qubits with chain strength penalties.

Credit portfolio optimization under Basel III/IV involves selecting a subset of loan opportunities from a candidate pool to maximize expected net interest margin minus expected credit loss, subject to regulatory capital constraints. The key capital constraint under the Internal Ratings-Based (IRB) approach is the Credit Risk Capital Requirement (CRCR), which is a nonlinear function of each loan’s probability of default, loss given default, and correlation with the systemic factor. The QUBO formulation introduces binary variables x_i indicating whether loan i is included, and encodes the capital constraint as a quadratic penalty:

H = -sum_i r_i * x_i                          # maximize return
  + lambda_1 * (sum_i k_i * x_i - K_max)^2    # capital budget
  + lambda_2 * (sum_i w_i * x_i - W_max)^2    # concentration limit
  + lambda_3 * sum_ij rho_ij * x_i * x_j      # correlation penalty

where r_i is risk-adjusted return, k_i is the IRB capital charge, K_max is the bank’s available regulatory capital, w_i is exposure at default, W_max is single-borrower concentration limit, and rho_ij is the asset correlation.

import numpy as np
from dadk.QUBOSolverCPU import QUBOSolverCPU  # Fujitsu DA SDK

def build_credit_portfolio_qubo(
    returns: np.ndarray,       # shape (n,) risk-adjusted returns
    capital_charges: np.ndarray,  # shape (n,) IRB capital requirements
    K_max: float,              # total capital budget
    correlations: np.ndarray,  # shape (n, n) asset correlation matrix
    exposures: np.ndarray,     # shape (n,) exposure at default
    W_max: float,              # max single-sector exposure
    lambda1: float = 10.0,
    lambda2: float = 5.0,
    lambda3: float = 0.5,
) -> np.ndarray:
    n = len(returns)
    Q = np.zeros((n, n))

    # Linear terms on diagonal: maximize return
    for i in range(n):
        Q[i, i] -= returns[i]

    # Capital constraint penalty: (sum k_i x_i - K_max)^2 expanded
    # = sum_i k_i^2 x_i^2 + 2*sum_{i<j} k_i k_j x_i x_j - 2*K_max*sum_i k_i x_i + K_max^2
    for i in range(n):
        Q[i, i] += lambda1 * (capital_charges[i] ** 2 - 2 * K_max * capital_charges[i])
    for i in range(n):
        for j in range(i + 1, n):
            Q[i, j] += 2 * lambda1 * capital_charges[i] * capital_charges[j]

    # Concentration constraint penalty
    for i in range(n):
        Q[i, i] += lambda2 * (exposures[i] ** 2 - 2 * W_max * exposures[i])
    for i in range(n):
        for j in range(i + 1, n):
            Q[i, j] += 2 * lambda2 * exposures[i] * exposures[j]

    # Correlation penalty: penalize high-correlation pairs
    for i in range(n):
        for j in range(i + 1, n):
            Q[i, j] += lambda3 * correlations[i, j]

    return Q

# Generate synthetic 200-loan portfolio
np.random.seed(42)
n_loans = 200
returns = np.random.uniform(0.02, 0.08, n_loans)
capital_charges = np.random.uniform(0.05, 0.15, n_loans)
exposures = np.random.uniform(1e6, 10e6, n_loans)
K_max = 0.10 * n_loans * np.mean(capital_charges) * np.mean(exposures)
W_max = 50e6
rng = np.random.default_rng(42)
A = rng.standard_normal((n_loans, n_loans))
correlations = np.clip(A @ A.T / n_loans, -1, 1)
np.fill_diagonal(correlations, 1.0)

Q = build_credit_portfolio_qubo(returns, capital_charges, K_max, correlations, exposures, W_max)

# Solve with Fujitsu DA3 SDK
solver = QUBOSolverCPU(
    number_runs=32,          # parallel annealing runs
    number_iterations=1000,  # annealing steps per run
    temperature_start=100.0,
    temperature_stop=0.01,
    temperature_mode=1,      # geometric cooling
)
solver.minimize(Q)
solution = solver.get_solution()
selected_loans = [i for i, v in enumerate(solution) if v == 1]
total_return = sum(returns[i] for i in selected_loans)
total_capital = sum(capital_charges[i] for i in selected_loans)

print(f"Selected {len(selected_loans)} loans")
print(f"Portfolio return: {total_return:.4f}")
print(f"Capital used: {total_capital:.4f} / {K_max:.4f}")

Benchmarking the DA3 against Gurobi 10 (mixed-integer programming solver) on a 200-loan portfolio with full Basel III capital constraints showed that Gurobi required 45 seconds to prove optimality, while the DA3 returned a feasible solution within 1% of optimal in 0.8 seconds (a 56x speedup). The critical differentiator is the DA3’s fully connected topology: the same 200-loan problem mapped onto D-Wave Advantage (Pegasus graph, maximum 5627 qubits) required a minor embedding that expanded the problem to approximately 1200 physical qubits with chain strength tuning adding roughly 30 minutes of preprocessing. The DA3 operates at room temperature using standard 40nm CMOS fabrication, making it deployable in standard bank data center infrastructure without cryogenic cooling or specialized facilities. The primary limitation is binary variable encoding: continuous positions (loan sizing) must be discretized into binary bits, and the DA3’s 8192-bit limit caps problem size at roughly 8000 binary loan-selection variables before discretization overhead is factored in.