def paint_prob_distribution(bins, prob_sim, S0, sig, r, T): """Funtion that returns a histogram with the probabilities of the outcome measures and compares it with the target probability distribution. Args: bins (int): number of bins of precision. prob_sim (list): probabilities from measuring the quantum circuit. S0 (real): initial asset price. sig (real): market volatility. r (real): market rate. T (real): maturity time. Returns: image of the probability histogram in a .png file. """ from scipy.integrate import trapz mu = (r - 0.5 * sig**2) * T + np.log(S0) mean = np.exp(mu + 0.5 * T * sig**2) variance = (np.exp(T * sig**2) - 1) * np.exp(2 * mu + T * sig**2) S = np.linspace(max(mean - 3 * np.sqrt(variance), 0), mean + 3 * np.sqrt(variance), bins) width = (S[1] - S[0]) / 1.2 fig, ax = plt.subplots() ax.bar(S, prob_sim, width, label='Quantum', alpha=0.8) x = np.linspace(max(mean - 3 * np.sqrt(variance), 0), mean + 3 * np.sqrt(variance), bins * 100) y = aux.log_normal(x, mu, sig * np.sqrt(T)) y = y * trapz(prob_sim, S) / trapz(y, x) ax.plot(x, y, label='PDF', color='black') plt.ylabel('Probability') plt.xlabel('Option price') plt.title('Option price distribution for {} qubits '.format(bins)) ax.legend() fig.tight_layout() fig.savefig('Probability_distribution.png')
def load_payoff_quantum_sim(qubits, S0, sig, r, T, K): """Measurement gates needed to measure the expected payoff and perform post-selection Args: qubits (int): number of qubits used for the unary basis. S0 (real): initial asset price. sig (real): market volatility. r (real): market rate. T (real): maturity time. K (real): strike price. Returns: circuit (Circuit): full quantum circuit with the amplitude distributor and payoff estimator. S (np.array): equivalent asset price for each element of the unary basis. """ mu = (r - 0.5 * sig**2) * T + np.log(S0) mean = np.exp(mu + 0.5 * T * sig**2) variance = (np.exp(T * sig**2) - 1) * np.exp(2 * mu + T * sig**2) S = np.linspace(max(mean - 3 * np.sqrt(variance), 0), mean + 3 * np.sqrt(variance), qubits) ln = aux.log_normal(S, mu, sig * np.sqrt(T)) q, ancilla, circuit = create_qc(qubits) lognormal_parameters = rw_parameters(qubits, ln) circuit.add(rw_circuit(qubits, lognormal_parameters)) circuit.add(payoff_circuit(qubits, ancilla, K, S)) circuit.add(measure_payoff(q, ancilla)) return circuit, S
def load_Q_operator(qubits, iterations, S0, sig, r, T, K): """Quantum circuit that performs the main operator for the amplitude estimation algorithm. Args: qubits (int): number of qubits used for the unary basis. iterations (int): number of consecutive implementations of operator Q. S0 (real): initial asset price. sig (real): market volatility. r (real): market rate. T (real): maturity time. K (real): strike price. Returns: circuit (Circuit): quantum circuit that performs the m=iterations step of the iterative amplitude estimation algorithm. """ iterations = int(iterations) mu = (r - 0.5 * sig**2) * T + np.log(S0) mean = np.exp(mu + 0.5 * T * sig**2) variance = (np.exp(T * sig**2) - 1) * np.exp(2 * mu + T * sig**2) S = np.linspace(max(mean - 3 * np.sqrt(variance), 0), mean + 3 * np.sqrt(variance), qubits) ln = aux.log_normal(S, mu, sig * np.sqrt(T)) lognormal_parameters = rw_parameters(qubits, ln) q, ancilla, circuit = create_qc(qubits) circuit.add(rw_circuit(qubits, lognormal_parameters)) circuit.add(payoff_circuit(qubits, ancilla, K, S)) for i in range(iterations): circuit.add(Q(qubits, ancilla, K, S, lognormal_parameters)) circuit.add(measure_payoff(q, ancilla)) return circuit
def get_pdf(qubits, S0, sig, r, T): """Get a pdf to input into the quantum register from a target probability distribution. Args: qubits (int): number of qubits used for the unary basis. S0 (real): initial asset price. sig (real): market volatility. r (real): market rate. T (real): maturity time. Returns: values (np.array): price values associated to the unary basis. pdf (np.array): probability distribution for the asset's price evolution. """ mu = (r - 0.5 * sig**2) * T + np.log(S0) mean = np.exp(mu + 0.5 * T * sig**2) variance = (np.exp(T * sig**2) - 1) * np.exp(2 * mu + T * sig**2) values = np.linspace(max(mean - 3 * np.sqrt(variance), 0), mean + 3 * np.sqrt(variance), qubits) pdf = aux.log_normal(values, mu, sig * np.sqrt(T)) return values, pdf
import matplotlib.pyplot as plt from aux_functions import log_normal S0 = 2 K = 1.9 sig = 0.4 r = 0.05 T = .1 qu = 20 fig, ax = plt.subplots() lognormal_parameters = [] (values, pdf), (mu, mean, variance) = get_pdf(qu, S0, sig, r, T) for t in np.linspace(0.01, T, 15): mu = (r - 0.5 * sig**2) * t + np.log(S0) pdf = log_normal(values, mu, sig * np.sqrt(t)) ax.plot(values, pdf) lognormal_parameters.append(rw_parameters(qu, pdf)) plt.show() lognormal_parameters = np.array(lognormal_parameters).transpose() fig, ax = plt.subplots() from scipy.optimize import curve_fit def func(x, a, b, c): return a * x**b + c for i in range(qu - 1):