Use this file to discover all available pages before exploring further.
View on GitHub
Open this notebook in GitHub to run it yourself
In finance models it is often interesting to calculate the average of a function of a given probability distribution (E[f(x)]).The most popular method to estimate the average is Monte Carlo [1] due to its flexibility and ability to generically handle stochastic parameters.Classical Monte Carlo methods, however, generally require extensive computational resources to provide an accurate estimation.
By leveraging the laws of quantum mechanics, a quantum computer may provide novel ways to solve computationally intensive financial problems, such as risk management, portfolio optimization, and option pricing.The core quantum advantage of several of these applications is the Amplitude Estimation algorithm [2], which can estimate a parameter with a
convergence rate of Ω(1/M1/2), compared to Ω(1/M) in the classical case, where M is the number of Grover iterations in the quantum case and the number of the Monte Carlo samples in the classical case.This represents a theoretical quadratic speed-up of the quantum method over classical Monte Carlo methods.
An option is the possibility to buy (call) or sell (put) an item (or share) at a known price (the strike price, K), where the option has a maturity price (S).For example, this is the payoff function to describe a European call option:$f(S)=
\Bigg{\begin{array}{lr}
0, & \text{when } K\geq S\
S
K, & \text{when } K < S\end{array}
$
The maturity price is unknown. Therefore, it is expressed by a price distribution function, which may be any type of a distribution function.For example, a log-normal distribution: ln(S)∼N(μ,σ),
where N(μ,σ) is the standard normal distribution with mean equal to μ and standard deviation equal to σ.To estimate the average option price using a quantum computer:
Load the distribution, i.e., discretize the distribution using 2n points (where n is the number of qubits) and truncate it.
Implement the payoff function that is equal to zero if S≤K and increases linearly otherwise.
The linear part is approximated to load it properly using Ry rotations [3].
Evaluate the expected payoff using amplitude estimation.
The algorithmic framework is called Quantum Monte Carlo Integration.For a basic example, see QMCI.This demonstration uses the same framework to estimate the European call option, where the underlying asset distribution at the maturity data is modeled as log-normal distribution.
The distribution describes the option underlying asset price at maturity date.Load a discrete version of the log normal probability with 2n points, when μ is equal to mu, σ is equal to sigma, and n is equal to num_qubits.In addition, choose K, the strike price:
num_qubits = 5mu = 0.7sigma = 0.13K = 1.9
import matplotlib.pyplot as pltimport numpy as npimport scipydef get_log_normal_probabilities(mu, sigma, num_points): mean = np.exp(mu + sigma**2 / 2) variance = (np.exp(sigma**2) - 1) * np.exp(2 * mu + sigma**2) stddev = np.sqrt(variance) # cut the distribution 3 sigmas from the mean low = np.maximum(0, mean - 3 * stddev) high = mean + 3 * stddev print(mean, variance, stddev, low, high) x = np.linspace(low, high, num_points) return x, scipy.stats.lognorm.pdf(x, s=sigma, scale=np.exp(mu))
grid_points, probs = get_log_normal_probabilities(mu, sigma, 2**num_qubits)# normalize the probabilitiesprobs = probs / np.sum(probs)fig, ax1 = plt.subplots()# Plot the probabilitiesax1.plot(grid_points, probs, "go-", label="Probability") # Green line with circlesax1.tick_params(axis="y", labelcolor="g")ax1.set_xlabel("Asset Value at Maturity Date")ax1.set_ylabel("Probability", color="g")# Create a second y-axis for the payoffax2 = ax1.twinx()ax2.plot(grid_points, np.maximum(grid_points - K, 0), "r-", label="Payoff") # Red lineax2.set_ylabel("Payoff", color="r")ax2.tick_params(axis="y", labelcolor="r")# Add grid and titleax1.grid(True)plt.title("Probability and Payoff vs.Asset Value")
The general inplace_prepare_state function is needed as it is repeatedly applied on the same quantum variable.For simplicity, use the general purpose state preparation.There are more efficient and scalable methods for preparing the required distribution; for example, see [4].
from classiq import *@qfuncdef load_distribution(asset: QNum): inplace_prepare_state(probabilities=probs.tolist(), bound=0, target=asset)
Create the payoff function by loading Upayoff∣S⟩∣0⟩=fpayoff(S)∣S⟩∣1⟩+1−fpayoff(S)∣S⟩∣0⟩.When building the European call option function, do nothing if the strike price is smaller than K; otherwise, apply a linear amplitude loading.NOTE: To save qubits and depth, the register ∣S⟩n holds a value in the range [0,2n−1], “labeling” the asset value.The mapping to the asset value space occurs in the comparator and amplitude loading, using this (classical) scale function:
from classiq.qmod.symbolic import ceilinggrid_step = (max(grid_points) - min(grid_points)) / (len(grid_points) - 1)# translate from qubit space to price spacedef scale(val): return val * grid_step + min(grid_points)# translate from price space to qubit spacedef descale(val: int): return (val - min(grid_points)) / grid_step@qfuncdef payoff(asset: Const[QNum], ind: QBit): # check if asset price is 'in the money' - crossed the strike price control(asset >= ceiling(descale(K)), lambda: payoff_linear(asset, ind))
For simplicity, use a general purpose amplitude loading method with the assign_amplitude_table function.The calculation is exact, however it is not scalable for large variable sizes.More scalable methods are mentioned in [4] and [6].Important: So that all loaded amplitudes are not greater than 1, normalize the payoff by a scaling_factor, later multiplied in the post-process stage:
After defining the probability distribution and the payoff function, pack them together as a state preparation in the Iterative Quantum Amplitude Estimation algorithm [5].The oracle is very simple and only needs to recognize whether the indicator qubit is in the ∣1⟩ state.The returned amplitude from the algorithm is according to the formula:∣Ψ⟩=x∑∣x⟩[p(x)f(x)∣1⟩ind+p(x)(1−f(x))∣0⟩ind]=a∣Ψ1⟩+1−a2∣Ψ0⟩which approximates the expectation value of the payoff:a2=x∑p(x)f(x)≈E[f]pThe built-in IQAE application expects a state preparation operand, and builds a model for the iterative amplitude estimation algorithm:
from classiq.applications.iqae.iqae import IQAEiqae = IQAE( state_prep_op=european_call_state_preparation, problem_vars_size=num_qubits, constraints=Constraints(max_width=20), preferences=Preferences(optimization_level=1),)