Ejemplo n.º 1
0
    def test_asian_barrier_spread(self):
        """Test the asian barrier spread model."""
        try:
            from qiskit.aqua.circuits import WeightedSumOperator, FixedValueComparator as Comparator
            from qiskit.aqua.components.uncertainty_problems import (
                UnivariatePiecewiseLinearObjective as PwlObjective,
                MultivariateProblem)
            from qiskit.aqua.components.uncertainty_models import MultivariateLogNormalDistribution
        except ImportError:
            import warnings
            warnings.warn(
                'Qiskit Aqua is not installed, skipping the application test.')
            return

        # number of qubits per dimension to represent the uncertainty
        num_uncertainty_qubits = 2

        # parameters for considered random distribution
        spot_price = 2.0  # initial spot price
        volatility = 0.4  # volatility of 40%
        interest_rate = 0.05  # annual interest rate of 5%
        time_to_maturity = 40 / 365  # 40 days to maturity

        # resulting parameters for log-normal distribution
        # pylint: disable=invalid-name
        mu = ((interest_rate - 0.5 * volatility**2) * time_to_maturity +
              np.log(spot_price))
        sigma = volatility * np.sqrt(time_to_maturity)
        mean = np.exp(mu + sigma**2 / 2)
        variance = (np.exp(sigma**2) - 1) * np.exp(2 * mu + sigma**2)
        stddev = np.sqrt(variance)

        # lowest and highest value considered for the spot price; in between,
        # an equidistant discretization is considered.
        low = np.maximum(0, mean - 3 * stddev)
        high = mean + 3 * stddev

        # map to higher dimensional distribution
        # for simplicity assuming dimensions are independent and identically distributed)
        dimension = 2
        num_qubits = [num_uncertainty_qubits] * dimension
        low = low * np.ones(dimension)
        high = high * np.ones(dimension)
        mu = mu * np.ones(dimension)
        cov = sigma**2 * np.eye(dimension)

        # construct circuit factory
        distribution = MultivariateLogNormalDistribution(num_qubits=num_qubits,
                                                         low=low,
                                                         high=high,
                                                         mu=mu,
                                                         cov=cov)

        # determine number of qubits required to represent total loss
        weights = []
        for n in num_qubits:
            for i in range(n):
                weights += [2**i]

        num_sum_qubits = WeightedSumOperator.get_required_sum_qubits(weights)

        # create circuit factoy
        agg = WeightedSumOperator(sum(num_qubits), weights)

        # set the strike price (should be within the low and the high value of the uncertainty)
        strike_price_1 = 3
        strike_price_2 = 4

        # set the barrier threshold
        barrier = 2.5

        # map strike prices and barrier threshold from [low, high] to {0, ..., 2^n-1}
        max_value = 2**num_sum_qubits - 1
        low_ = low[0]
        high_ = high[0]

        mapped_strike_price_1 = (strike_price_1 - dimension*low_) / \
            (high_ - low_) * (2**num_uncertainty_qubits - 1)
        mapped_strike_price_2 = (strike_price_2 - dimension*low_) / \
            (high_ - low_) * (2**num_uncertainty_qubits - 1)
        mapped_barrier = (barrier -
                          low) / (high - low) * (2**num_uncertainty_qubits - 1)

        conditions = []
        for i in range(dimension):
            # target dimension of random distribution and corresponding condition
            conditions += [(i,
                            Comparator(num_qubits[i],
                                       mapped_barrier[i] + 1,
                                       geq=False))]

        # set the approximation scaling for the payoff function
        c_approx = 0.25

        # setup piecewise linear objective fcuntion
        breakpoints = [0, mapped_strike_price_1, mapped_strike_price_2]
        slopes = [0, 1, 0]
        offsets = [0, 0, mapped_strike_price_2 - mapped_strike_price_1]
        f_min = 0
        f_max = mapped_strike_price_2 - mapped_strike_price_1
        bull_spread_objective = PwlObjective(num_sum_qubits, 0, max_value,
                                             breakpoints, slopes, offsets,
                                             f_min, f_max, c_approx)

        # define overall multivariate problem
        asian_barrier_spread = MultivariateProblem(distribution,
                                                   agg,
                                                   bull_spread_objective,
                                                   conditions=conditions)

        num_req_qubits = asian_barrier_spread.num_target_qubits
        num_req_ancillas = asian_barrier_spread.required_ancillas()

        qr = QuantumRegister(num_req_qubits, name='q')
        qr_ancilla = QuantumRegister(num_req_ancillas, name='q_a')
        qc = QuantumCircuit(qr, qr_ancilla)

        asian_barrier_spread.build(qc, qr, qr_ancilla)
        job = execute(qc,
                      backend=BasicAer.get_backend('statevector_simulator'))

        # evaluate resulting statevector
        value = 0
        for i, amplitude in enumerate(job.result().get_statevector()):
            b = ('{0:0%sb}' % asian_barrier_spread.num_target_qubits
                 ).format(i)[-asian_barrier_spread.num_target_qubits:]
            prob = np.abs(amplitude)**2
            if prob > 1e-4 and b[0] == '1':
                value += prob
                # all other states should have zero probability due to ancilla qubits
                if i > 2**num_req_qubits:
                    break

        # map value to original range
        mapped_value = asian_barrier_spread.value_to_estimation(value) / (
            2**num_uncertainty_qubits - 1) * (high_ - low_)
        expected = 0.83188
        self.assertAlmostEqual(mapped_value, expected, places=5)
    def test_conditional_value_at_risk(self, simulator):
        """ conditional value at risk test """
        # define backend to be used
        backend = BasicAer.get_backend(simulator)

        # set problem parameters
        n_z = 2
        z_max = 2
        # z_values = np.linspace(-z_max, z_max, 2 ** n_z)
        p_zeros = [0.15, 0.25]
        rhos = [0.1, 0.05]
        lgd = [1, 2]
        k_l = len(p_zeros)
        # alpha = 0.05

        # set var value
        var = 2
        var_prob = 0.961940

        # determine number of qubits required to represent total loss
        # n_s = WeightedSumOperator.get_required_sum_qubits(lgd)

        # create circuit factory (add Z qubits with weight/loss 0)
        agg = WeightedSumOperator(n_z + k_l, [0] * n_z + lgd)

        # define linear objective
        breakpoints = [0, var]
        slopes = [0, 1]
        offsets = [0, 0]  # subtract VaR and add it later to the estimate
        f_min = 0
        f_max = 3 - var
        c_approx = 0.25

        # construct circuit factory for uncertainty model (Gaussian Conditional Independence model)
        gci = GCI(n_z, z_max, p_zeros, rhos)

        cvar_objective = PwlObjective(
            agg.num_sum_qubits,
            0,
            2**agg.num_sum_qubits -
            1,  # max value that can be reached by the qubit register
            breakpoints,
            slopes,
            offsets,
            f_min,
            f_max,
            c_approx)

        multivariate_cvar = MultivariateProblem(gci, agg, cvar_objective)

        num_qubits = multivariate_cvar.num_target_qubits
        num_ancillas = multivariate_cvar.required_ancillas()

        q = QuantumRegister(num_qubits, name='q')
        q_a = QuantumRegister(num_ancillas, name='q_a')
        qc = QuantumCircuit(q, q_a)

        multivariate_cvar.build(qc, q, q_a)

        job = execute(qc, backend=backend)

        # evaluate resulting statevector
        value = 0
        for i, a_i in enumerate(job.result().get_statevector()):
            b = ('{0:0%sb}' %
                 multivariate_cvar.num_target_qubits).\
                format(i)[-multivariate_cvar.num_target_qubits:]
            a_m = np.round(np.real(a_i), decimals=4)
            if np.abs(a_m) > 1e-6 and b[0] == '1':
                value += a_m**2

        # normalize and add VaR to estimate
        value = multivariate_cvar.value_to_estimation(value)
        normalized_value = value / (1.0 - var_prob) + var

        # compare to precomputed solution
        self.assertEqual(0.0, np.round(normalized_value - 3.3796, decimals=4))
Ejemplo n.º 3
0
    def setUp(self):
        super().setUp()

        # number of qubits to represent the uncertainty
        num_uncertainty_qubits = 3

        # parameters for considered random distribution
        s_p = 2.0  # initial spot price
        vol = 0.4  # volatility of 40%
        r = 0.05  # annual interest rate of 4%
        t_m = 40 / 365  # 40 days to maturity

        # resulting parameters for log-normal distribution
        m_u = ((r - 0.5 * vol**2) * t_m + np.log(s_p))
        sigma = vol * np.sqrt(t_m)
        mean = np.exp(m_u + sigma**2 / 2)
        variance = (np.exp(sigma**2) - 1) * np.exp(2 * m_u + sigma**2)
        stddev = np.sqrt(variance)

        # lowest and highest value considered for the spot price;
        # in between, an equidistant discretization is considered.
        low = np.maximum(0, mean - 3 * stddev)
        high = mean + 3 * stddev

        # construct circuit factory for uncertainty model
        uncertainty_model = LogNormalDistribution(num_uncertainty_qubits,
                                                  mu=m_u,
                                                  sigma=sigma,
                                                  low=low,
                                                  high=high)

        # set the strike price (should be within the low and the high value of the uncertainty)
        strike_price = 1.896

        # set the approximation scaling for the payoff function
        c_approx = 0.1

        # setup piecewise linear objective function
        breakpoints = [uncertainty_model.low, strike_price]
        slopes = [0, 1]
        offsets = [0, 0]
        f_min = 0
        f_max = uncertainty_model.high - strike_price
        european_call_objective = PwlObjective(
            uncertainty_model.num_target_qubits, uncertainty_model.low,
            uncertainty_model.high, breakpoints, slopes, offsets, f_min, f_max,
            c_approx)

        # construct circuit factory for payoff function
        self.european_call = UnivariateProblem(uncertainty_model,
                                               european_call_objective)

        # construct circuit factory for payoff function
        self.european_call_delta = EuropeanCallDelta(
            uncertainty_model,
            strike_price=strike_price,
        )

        self._statevector = QuantumInstance(
            backend=BasicAer.get_backend('statevector_simulator'),
            seed_simulator=2,
            seed_transpiler=2)
        self._qasm = QuantumInstance(
            backend=BasicAer.get_backend('qasm_simulator'),
            shots=100,
            seed_simulator=2,
            seed_transpiler=2)
Ejemplo n.º 4
0
    def __init__(self, value, spot_price, volatility, int_rate, days,
                 strike_price):
        self.value = value
        # Number of qubits to represent the uncertainty
        num_uncertainty_qubits = 3

        # Parameters
        try:
            S = float(spot_price)
            vol = float(volatility)
            r = float(int_rate)
            T = int(days) / 365
            strike_price = float(strike_price)
        except ValueError:
            print("Some parameters wrong !!! ")

        mu = ((r - 0.5 * vol**2) * T + np.log(S))
        sigma = vol * np.sqrt(T)
        mean = np.exp(mu + sigma**2 / 2)
        variance = (np.exp(sigma**2) - 1) * np.exp(2 * mu + sigma**2)
        stddev = np.sqrt(variance)

        low = np.maximum(0, mean - 3 * stddev)
        high = mean + 3 * stddev

        # Circuit factory for uncertainty model
        self.uncertainty_model = LogNormalDistribution(num_uncertainty_qubits,
                                                       mu=mu,
                                                       sigma=sigma,
                                                       low=low,
                                                       high=high)

        try:
            self.strike_price = float(strike_price)
        except ValueError:
            print("Some parameters wrong !!! ")

        # The approximation scaling for the payoff function
        c_approx_payoff = 0.25  #abs(S-self.strike_price)
        print(c_approx_payoff)

        breakpoints = [self.uncertainty_model.low, self.strike_price]

        if self.value == str("call"):
            slopes_payoff = [0, 1]
        else:
            slopes_payoff = [-1, 0]

        if self.value == str("call"):
            offsets_payoff = [0, 0]
        else:
            offsets_payoff = [
                self.strike_price - self.uncertainty_model.low, 0
            ]

        f_min_payoff = 0

        if self.value == str("call"):
            f_max_payoff = self.uncertainty_model.high - self.strike_price
        else:
            f_max_payoff = self.strike_price - self.uncertainty_model.low

        european_objective = PwlObjective(
            self.uncertainty_model.num_target_qubits,
            self.uncertainty_model.low, self.uncertainty_model.high,
            breakpoints, slopes_payoff, offsets_payoff, f_min_payoff,
            f_max_payoff, c_approx_payoff)

        # Circuit factory for payoff function
        self.european_payoff = UnivariateProblem(self.uncertainty_model,
                                                 european_objective)

        slopes_delta = [0, 0]

        if self.value == str("call"):
            offsets_delta = [0, 1]
        else:
            offsets_delta = [1, 0]

        f_min_delta = 0

        f_max_delta = 1

        c_approx_delta = 1

        european_delta_objective = PwlObjective(
            self.uncertainty_model.num_target_qubits,
            self.uncertainty_model.low, self.uncertainty_model.high,
            breakpoints, slopes_delta, offsets_delta, f_min_delta, f_max_delta,
            c_approx_delta)

        self.european_delta = UnivariateProblem(self.uncertainty_model,
                                                european_delta_objective)
Ejemplo n.º 5
0
# In[10]:

# define linear objective function
breakpoints = [0]
slopes = [1]
offsets = [0]
f_min = 0
f_max = sum(lgd)
c_approx = 0.25

objective = PwlObjective(
    agg.num_sum_qubits,
    0,
    2**agg.num_sum_qubits -
    1,  # max value that can be reached by the qubit register (will not always be reached)
    breakpoints,
    slopes,
    offsets,
    f_min,
    f_max,
    c_approx)

# define overall multivariate problem
multivariate = MultivariateProblem(u, agg, objective)

# In[11]:

num_qubits = multivariate.num_target_qubits
num_ancillas = multivariate.required_ancillas()

q = QuantumRegister(num_qubits, name='q')
Ejemplo n.º 6
0
### Payoff Function
# set the strike price (should be within the low and the high value of the uncertainty)
strike_price_1 = 1.438
strike_price_2 = 2.584

# set the approximation scaling for the payoff function
c_approx = 0.25

# setup piecewise linear objective fcuntion
breakpoints = [uncertainty_model.low, strike_price_1, strike_price_2]
slopes = [0, 1, 0]
offsets = [0, 0, strike_price_2 - strike_price_1]
f_min = 0
f_max = strike_price_2 - strike_price_1
bull_spread_objective = PwlObjective(uncertainty_model.num_target_qubits,
                                     uncertainty_model.low,
                                     uncertainty_model.high, breakpoints,
                                     slopes, offsets, f_min, f_max, c_approx)

# construct circuit factory for payoff function
bull_spread = UnivariateProblem(uncertainty_model, bull_spread_objective)

# plot exact payoff function (evaluated on the grid of the uncertainty model)
x = uncertainty_model.values
y = np.minimum(np.maximum(0, x - strike_price_1),
               strike_price_2 - strike_price_1)
plt.plot(x, y, 'ro-')
plt.grid()
plt.title('Payoff Function', size=15)
plt.xlabel('Spot Price', size=15)
plt.ylabel('Payoff', size=15)
plt.xticks(x, size=15, rotation=90)