Skip to content

Finance

Classiq financial package provides a rich interface to automatically generate and execute quantum circuits for various financial problems, such as options pricing and risk analysis. The financial problems model is divided into two parts: the first is the financial model, and the second is the function that acts on this model.

Introduction and background

Complex models and simulations, borrowed from the world of physics, are very common in Finance. Many of these models are stochastic in nature, hence, numerical methods have to be employed for solving them. The most popular model 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 such computationally intensive financial problems. Relevant Financial applications include risk management, portfolio optimization, and option pricing. The core of several of these applications is the Amplitude Estimation algorithm [2] which can estimate a parameter with a convergence rate of 1/M, where M is the number of Grover iterations, representing a theoretical quadratic speed-up over classical Monte Carlo methods.

Example 1

Quantum Risk analysis

Risk analysis aims to evaluate the potential for loss in an investment. Specifically, an investor needs to quantify how large a loss on investment could be, given a certain level of confidence, over a period of time. This quantity is known as the Value at risk (VaR). The value at risk is based on the statistical characteristics of the investment, and the shape of its distribution curve. It is evaluated using intensive computations of the aggregated value for M different realizations of portfolio assets model. The width of the confidence interval scales like \(O(M^{-1/2})\). To calculate the value at risk of some assets portfolio on a quantum computer we define the VaR such that [3] :

\[ VaR = argmin_{x_0}{(P(x > x_0) <= \alpha)} \]

where \(x \in {0,...N-1}\) and \(\alpha\) is the confidence level, i.e. the percentage that a loss will be larger than the VaR. The VaR is the smallest value of x with a confidence level of \(\alpha\).

To create a quantum circuit that can solve this kind of problem, one needs to:

  • Create a distribution function that represents the assets portfolio
  • Construct the VaR operator
  • Extract the Value at Risk using amplitude estimation.

This can be done using classiq financial package in two phases:

  • Financial model which contains the distribution function and
  • Financial function \(f_x(i)\) that is implemented by the model.

Financial model:

{
    "logic_flow": [
        {
            "function": "Finance",
            "function_params": {
                "model": {
                    "name": "gaussian",
                    "params": {
                        "num_qubits":2,
                        "normal_max_value":2,
                        "default_probabilities":[0.15, 0.25],
                        "rhos":[0.1, 0.05],
                        "loss":[1, 2],
                        "min_loss":0
                    }
                },
                "finance_function": {
                    "f": "var",
                    "condition": {
                        "threshold":2,
                        "larger": true}
                }
            }
        }
    ]
}
from classiq import ModelDesigner
from classiq.builtin_functions import Finance
from classiq.interface.finance import (
    model_input,
    function_input,
    gaussian_model_input
)

model_designer = ModelDesigner()
gaussian_input = gaussian_model_input.GaussianModelInput(
    num_qubits=2,
    normal_max_value=2,
    default_probabilities=[0.15, 0.25],
    rhos=[0.1, 0.05],
    loss=[1, 2],
    min_loss=0
)
model = model_input.FinanceModelInput(name="gaussian", params=gaussian_input)

condition = function_input.FunctionCondition(threshold=2, larger=True)
finance_function = function_input.FinanceFunctionInput(
    f="var",
    condition=condition,
)
model_designer.Finance(Finance(model=model, finance_function=finance_function))

circuit = model_designer.synthesize()

In the example above the model is a gaussian model (called Conditioned Gaussian) of a two assets portfolio. The parameters that define this model are:

  • num qubits (int): Number of qubits that describes the accuracy of the Gaussian
  • normal max value (float): The discrete number where the Gaussian is truncated,
  • default probabilities (List[float]): The loss probability of each asset
  • rhos (List[float]): The width of the Gaussian
  • loss (List[int]): The loss of each asset
  • min loss (int): The minimum loss of the entire distribution

Financial Function

On the same financial model, one can generate several quantum circuits with different financial functions. In the current example we generate the VaR function:

{
  "logic_flow": [
    {
      "function": "Finance",
      "function_params": {
        "model": {
          "name": "gaussian",
          "params": {
            "num_qubits": 2,
            "normal_max_value": 2,
            "default_probabilities": [
              0.15,
              0.25
            ],
            "rhos": [
              0.1,
              0.05
            ],
            "loss": [
              1,
              2
            ],
            "min_loss": 0
          }
        },
        "finance_function": {
          "f": "var",
          "condition": {
            "threshold": 2,
            "larger": true
          }
        }
      }
    }
  ]
}
from classiq import ModelDesigner
from classiq.builtin_functions import Finance
from classiq.interface.finance import (
    model_input,
    function_input,
    gaussian_model_input
)

model_designer = ModelDesigner()
gaussian_input = gaussian_model_input.GaussianModelInput(
    num_qubits=2,
    normal_max_value=2,
    default_probabilities=[0.15, 0.25],
    rhos=[0.1, 0.05],
    loss=[1, 2],
    min_loss=0
)
model = model_input.FinanceModelInput(name="gaussian", params=gaussian_input)

condition = function_input.FunctionCondition(threshold=2, larger=True)
finance_function = function_input.FinanceFunctionInput(
    f="var",
    condition=condition,
)
model_designer.Finance(Finance(model=model, finance_function=finance_function))

circuit = model_designer.synthesize()

The output circuit will be: alt text

This circuit can be executed on a quantum computer.

Execute quantum circuit

Syntax:

Create the following file: execution_preferences.exct Run the command: "Execute Generated Circuit" when execution preferences are filled

{
    "preferences": {
        "num_shots": 100,
        "amplitude_estimation": {
            "alpha": 0.05,
            "epsilon": 0.01,
            "binary_search_threshold": 0.05
        }
    }
}
from classiq import ModelDesigner, Executor
from classiq.builtin_functions import Finance
from classiq.interface.executor import execution_request, execution_preferences
from classiq.interface.finance import model_input, function_input, gaussian_model_input

model_designer = ModelDesigner()
gaussian_input = gaussian_model_input.GaussianModelInput(
    num_qubits=2,
    normal_max_value=2,
    default_probabilities=[0.15, 0.25],
    rhos=[0.1, 0.05],
    loss=[1, 2],
    min_loss=0,
)
model = model_input.FinanceModelInput(name="gaussian", params=gaussian_input)

condition = function_input.FunctionCondition(threshold=2, larger=True)
finance_function = function_input.FinanceFunctionInput(
    f="var",
    condition=condition,
)
model_designer.Finance(Finance(model=model, finance_function=finance_function))

circuit = model_designer.synthesize()

res = Executor(
    amplitude_estimation=execution_preferences.AmplitudeEstimation(
        alpha=0.5, epsilon=0.5, binary_search_threshold=0.05
    )
).execute(circuit)

In this example, we are running amplitude estimation, which is the quantum analog to Monte Carlo simulation generally used for this kind of problems. To find the value at risk we use binary search. The value at risk is the loss value that corresponds to the percentile we have inserted at the binary search threshold.

Example 2

Option pricing

An option is the possibility to buy (call) or sell (put) an item (or share) at a known price - the strike price (K) The option has a maturity price (S). The payoff function to describe for example an european call option will be:

\[ \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 distribution function. For example a log-normal distribution: \(X=e^{\mu+\sigma Z}\), where \(\mu,\sigma\) are the mean and std respectively and Z is the standard normal distribution.

To estimate the option price using a quantum computer, one needs to:

  • Load the wanted distribution, that is, discretize the distribution using \(2^n\) points (n is the number of qubits) and truncate it,
  • Implement the payoff function that is equal to zero if \(S\leq{K}\) and increases linearly. The linear part is approximated in order to be loaded properly using \(R_y\) rotations [3] .
  • Evaluate the expected payoff using amplitude estimation

This can be implemented as follows:

{
    "logic_flow": [
        {
            "function": "Finance",
            "function_params": {
                "model": {
                    "name": "log normal",
                    "params": {
                        "num_qubits":3,
                        "mu":0.68986,
                        "sigma":0.132417
                    }
                },
                "finance_function": {
                    "f": "european call option",
                    "condition": {
                        "threshold":1.896,
                        "larger": true
                    }
                }
            }
        }
    ]
}
from classiq import ModelDesigner
from classiq.builtin_functions import Finance
from classiq.interface.finance import (
    model_input,
    function_input,
    log_normal_model_input,
)

model_designer = ModelDesigner()

log_normal_input = log_normal_model_input.LogNormalModelInput(
    num_qubits=3, mu=0.68986, sigma=0.132417
)
model = model_input.FinanceModelInput(name="log normal", params=log_normal_input)
condition = function_input.FunctionCondition(threshold=1.896, larger=True)
finance_function = function_input.FinanceFunctionInput(
    f="european call option",
    condition=condition,
)

model_designer.Finance(Finance(model=model, finance_function=finance_function))
circuit = model_designer.synthesize()

The output circuit is:

alt text

Execute this circuit:

{
    "preferences": {
        "num_shots": 100,
        "amplitude_estimation": {
            "alpha": 0.05,
            "epsilon": 0.01
        }
    }
}
from classiq import ModelDesigner, Executor
from classiq.builtin_functions import Finance
from classiq.interface.finance import (
    model_input,
    function_input,
    log_normal_model_input,
)
from classiq.interface.executor import execution_request, execution_preferences

model_designer = ModelDesigner()

log_normal_input = log_normal_model_input.LogNormalModelInput(
    num_qubits=3, mu=0.68986, sigma=0.132417
)
model = model_input.FinanceModelInput(name="log normal", params=log_normal_input)
condition = function_input.FunctionCondition(threshold=1.896, larger=True)
finance_function = function_input.FinanceFunctionInput(
    f="european call option",
    condition=condition,
)

model_designer.Finance(Finance(model=model, finance_function=finance_function))

circuit = model_designer.synthesize()
res = Executor(
    amplitude_estimation=execution_preferences.AmplitudeEstimation(
        alpha=0.5, epsilon=0.5, binary_search_threshold=None
    )
).execute(circuit)

Available models

The available models on the Classiq platform:

  • "gaussian", abbreviation for 'Gaussian conditional independence model'
  • "log normal"

Available functions

The available functions are:

  • "var"
  • "expected shortfall"
  • "european call option"
  • "x**2"

Example 3

Expected shortfall

In risk analysis, one may be interested in calculating the conditional value at risk, also known as the expected shortfall. To create a circuit that calculates this value we simply change the finance_function parameters. For example:

{
  "finance_function": {
    "f": "expected shortfall",
    "condition": {
      "threshold": 2,
      "larger": true
    },
    "tail_probability": 0.05
  }
}
from classiq.interface.finance import (
    function_input,
    log_normal_model_input,
)

condition = function_input.FunctionCondition(threshold=2, larger=True)
finance_function = function_input.FinanceFunctionInput(
    f="expected shortfall",
    condition=condition,
    tail_probability=0.05,
)

Note that the tail probability is the percentile value received from calculating the value at risk.

The Classiq finance package allows the generation of any function using Chebyshev polynomial approximations. In the following example, the polynomial degree is the approximation degree.

{
"finance_function": {
    "f": "european call option",
    "condition": {
        "threshold":1.896,
        "larger": true
    },
    "polynomial_degree": 1,
    "use_chebyshev_polynomial_approximation": true
  }
}
from classiq.interface.finance import (
    function_input,
    log_normal_model_input,
)

condition = function_input.FunctionCondition(threshold=1.896, larger=True)
finance_function = function_input.FinanceFunctionInput(
    f="european call option",
    condition=condition,
    polynomial_degree=1,
    use_chebyshev_polynomial_approximation=True,
)

References

[1] Paul Glasserman, Monte Carlo Methods in Financial Engineering. Springer-Verlag New York, 2003, p. 596.

[2] Gilles Brassard, Peter Hoyer, Michele Mosca, and Alain Tapp, Quantum Amplitude Amplification and Estimation. Contemporary Mathematics 305 (2002)

[3] Woerner, S., Egger, D.J. Quantum risk analysis. npj Quantum Inf 5, 15 (2019).