├── LICENSE ├── QPCA_4x4eigenstate.py ├── QPCA_QPhE.py ├── QPCA_eigenstate.py └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 amartin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /QPCA_4x4eigenstate.py: -------------------------------------------------------------------------------- 1 | from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit 2 | import numpy as np 3 | import math 4 | from qiskit import BasicAer, execute 5 | from qiskit.tools.visualization import plot_histogram 6 | from qiskit.tools.monitor import job_monitor 7 | from qiskit.providers.ibmq import least_busy 8 | 9 | q=QuantumRegister(3) 10 | c=ClassicalRegister(3) 11 | qc=QuantumCircuit(q,c) 12 | 13 | #initial state of the second and third qubit (eigenstate) 14 | state_vector=[math.sqrt(3087/(3087 + 906 + 1405 + 58)),math.sqrt(906/(3087 + 906 + 1405 + 58)),math.sqrt(1405/(3087 + 906 + 1405 + 58)),math.sqrt(58/(3087 + 906 + 1405 + 58))] 15 | qc.initialize(state_vector,[q[1],q[2]]) 16 | 17 | #preparation of the first qubits (1-bit eigenvalue estimation) 18 | qc.h(q[0]) 19 | 20 | #controlled Urho 21 | #cV1 22 | qc.u1(0.785398,q[1]) 23 | qc.cu3(1.1747,-2.83038,3.83087,q[1],q[2]) 24 | #cX 25 | qc.cx(q[0],q[1]) 26 | #cV1dag 27 | qc.u1(-0.785398,q[1]) 28 | qc.cu3(1.1747,-0.689273,-0.31121,q[1],q[2]) 29 | #cXV2X 30 | qc.u1(-1.5708,q[0]) 31 | qc.cu3(2.07033,3.76782,-0.626228,q[0],q[1]) 32 | #cV1 33 | qc.u1(0.785398,q[0]) 34 | qc.cu3(1.1747,-2.83038,3.83087,q[0],q[2]) 35 | #cX 36 | qc.cx(q[2],q[0]) 37 | #cV2Xdag 38 | qc.cu3(1.07126,0.626228,0.626228,q[0],q[1]) 39 | #cX 40 | qc.cx(q[2],q[0]) 41 | #cV2X 42 | qc.cu3(1.07126,-3.76782,2.51536,q[2],q[1]) 43 | #cV3 44 | qc.cu3(2.3749,-0.251338,-1.38469,q[1],q[2]) 45 | #cX 46 | qc.cx(q[0],q[1]) 47 | #cV3dag 48 | qc.cu3(2.3749,-1.7569,3.39293,q[1],q[2]) 49 | #cXvx 50 | qc.u1(1/4*np.pi,q[0]) 51 | qc.cu3(1/2*np.pi,-1/2*np.pi,1/2*np.pi,q[0],q[1]) 52 | #cV3 53 | qc.cu3(2.3749,-0.251338,-1.38469,q[1],q[2]) 54 | #cX 55 | qc.cx(q[2],q[0]) 56 | #cVxdag 57 | qc.u1(1/4*np.pi,q[0]) 58 | qc.cu3(1/2*np.pi,-1/2*np.pi,1/2*np.pi,q[0],q[1]) 59 | #cX 60 | qc.cx(q[2],q[0]) 61 | #cVx 62 | qc.u1(-1/4*np.pi,q[2]) 63 | qc.cu3(1/2*np.pi,1/2*np.pi,-1/2*np.pi,q[2],q[1]) 64 | 65 | #InverseQFT 66 | qc.h(q[0]) 67 | 68 | ##meassure on basis II 69 | #qc.h(q[1]) 70 | ##meassure on basis III 71 | #qc.h(q[2]) 72 | ##meassure on basis IV 73 | #qc.h(q[1]) 74 | #qc.h(q[2]) 75 | 76 | #projection and meassurement 77 | qc.barrier(q[0]) 78 | qc.barrier(q[1]) 79 | qc.barrier(q[2]) 80 | qc.measure(q[0],c[0]) 81 | qc.measure(q[1],c[1]) 82 | qc.measure(q[2],c[2]) 83 | qc.draw(output='mpl') 84 | 85 | #Run on qasm simulator 86 | backend_qasm=BasicAer.get_backend('qasm_simulator') 87 | job_qasm=execute(qc,backend_qasm,shots=8192) 88 | result_qasm=job_qasm.result() 89 | counts=result_qasm.get_counts(qc) 90 | print(counts) 91 | plot_histogram(counts) 92 | sim_jobID=job_qasm.job_id() 93 | print('SIMULATION JOB ID: {}'.format(sim_jobID)) 94 | 95 | #Run on real device 96 | backend_exp=IBMQ.get_backend('ibmqx2') 97 | backend_exp.name() 98 | job_exp=execute(qc,backend_exp,shots=8192)#,max_credits=3) 99 | job_monitor(job_exp) 100 | result_exp=job_exp.result() 101 | counts_exp = result_exp.get_counts() 102 | print(counts_exp) 103 | plot_histogram([counts_exp,counts]) 104 | jobID=job_exp.job_id() 105 | print('JOB ID: {}'.format(jobID)) 106 | -------------------------------------------------------------------------------- /QPCA_QPhE.py: -------------------------------------------------------------------------------- 1 | from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit 2 | import numpy as np 3 | from qiskit import BasicAer, execute 4 | from qiskit.tools.visualization import plot_histogram 5 | from qiskit.tools.monitor import job_monitor 6 | from qiskit.providers.ibmq import least_busy 7 | import cmath 8 | 9 | q=QuantumRegister(4) 10 | c=ClassicalRegister(4) 11 | qc=QuantumCircuit(q,c) 12 | 13 | #initial state of the fourth qubit (eigenstate) 14 | phase0=complex(math.cos(-0.1144),math.sin(-0.1144)) 15 | phase1=complex(math.cos(0.3252-0.1144),math.sin(0.3252-0.1144)) 16 | state_vector=[math.cos(0.4996)*phase0,math.sin(0.4996)*phase1] 17 | qc.initialize(state_vector,[q[3]]) 18 | #preparation of the three first qubits (3-bit eigenvalue estimation) 19 | qc.h(q[0]) 20 | qc.h(q[1]) 21 | qc.h(q[2]) 22 | 23 | #Controlled U_rho 24 | qc.cu3(1.59899,-1.11512,2.02647,q[2],q[3]) 25 | 26 | #Controlled U_rho^2 27 | qc.cu3(2.22862,0.513123,3.65472,q[1],q[3]) 28 | 29 | #Controlled U_rho^4 30 | qc.cu3(0.797922,-4.53103,-1.38944,q[0],q[3]) 31 | 32 | #Inverse QFT 33 | qc.h(q[0]) 34 | qc.cu1(-1/2*np.pi,q[0],q[1]) 35 | qc.h(q[1]) 36 | qc.cu1(-1/4*np.pi,q[0],q[2]) 37 | qc.cu1(-1/2*np.pi,q[1],q[2]) 38 | qc.h(q[2]) 39 | 40 | #Run on Statevector smulator 41 | backend_state=BasicAer.get_backend('statevector_simulator') 42 | job_state=execute(qc,backend_state) 43 | result_state=job_state.result() 44 | outputstate=result_state.get_statevector(qc,decimals=3) 45 | print(outputstate) 46 | 47 | #projection and meassurement 48 | qc.barrier(q[0]) 49 | qc.barrier(q[1]) 50 | qc.barrier(q[3]) 51 | qc.measure(q[0],c[0]) 52 | qc.measure(q[1],c[1]) 53 | qc.measure(q[2],c[2]) 54 | qc.measure(q[3],c[3]) 55 | qc.draw(output='mpl') 56 | 57 | #Run on qasm simulator 58 | backend_qasm=BasicAer.get_backend('qasm_simulator') 59 | job_qasm=execute(qc,backend_qasm,shots=8192) 60 | result_qasm=job_qasm.result() 61 | counts=result_qasm.get_counts(qc) 62 | print(counts) 63 | plot_histogram(counts) 64 | sim_jobID=job_qasm.job_id() 65 | print('SIMULATION JOB ID: {}'.format(sim_jobID)) 66 | 67 | #Run on real device 68 | backend_exp=IBMQ.get_backend('ibmqx2') 69 | backend_exp.name() 70 | job_exp=execute(qc,backend_exp,shots=8192)#,max_credits=3) 71 | job_monitor(job_exp) 72 | result_exp=job_exp.result() 73 | counts_exp = result_exp.get_counts() 74 | print(counts_exp) 75 | plot_histogram([counts_exp,counts]) 76 | jobID=job_exp.job_id() 77 | print('JOB ID: {}'.format(jobID)) -------------------------------------------------------------------------------- /QPCA_eigenstate.py: -------------------------------------------------------------------------------- 1 | 2 | from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit 3 | import numpy as np 4 | from qiskit import BasicAer, execute 5 | from qiskit.tools.visualization import plot_histogram 6 | from qiskit.tools.monitor import job_monitor 7 | from qiskit.providers.ibmq import least_busy 8 | import math 9 | 10 | q=QuantumRegister(3) 11 | c=ClassicalRegister(3) 12 | qc=QuantumCircuit(q,c) 13 | 14 | #initial state of the third qubit (eigenstate) 15 | state_vector=[1/math.sqrt(2),1/math.sqrt(2)] 16 | qc.initialize(state_vector,[q[2]]) 17 | #preparation of the two first qubits (2-bit eigenvalue estimation) 18 | qc.h(q[0]) 19 | qc.h(q[1]) 20 | 21 | #Controlled U_rho 22 | qc.cu3(1.59899,-1.11512,2.02647,q[1],q[2]) 23 | 24 | #Controlled U_rho^2 25 | qc.cu3(2.22862,0.513123,3.65472,q[0],q[2]) 26 | 27 | #Inverse QFT 28 | qc.h(q[0]) 29 | qc.cu1(-1/2*np.pi,q[0],q[1]) 30 | qc.h(q[1]) 31 | 32 | ##measure on X basis 33 | #qc.h(q[3]) 34 | 35 | ##measure on Y basis 36 | #qc.h(q[3]) 37 | #qc.u1(1/2*np.pi,q[3]) 38 | 39 | ##measure on Random basis 40 | #qc.u3(2*0.4987,0.9876,0.9876,q[2]) 41 | 42 | #Run on Statevector smulator 43 | backend_state=BasicAer.get_backend('statevector_simulator') 44 | job_state=execute(qc,backend_state) 45 | result_state=job_state.result() 46 | outputstate=result_state.get_statevector(qc,decimals=3) 47 | print(outputstate) 48 | 49 | #projection and meassurement 50 | qc.barrier(q[0]) 51 | qc.barrier(q[1]) 52 | qc.measure(q[0],c[0]) 53 | qc.measure(q[1],c[1]) 54 | qc.measure(q[2],c[2]) 55 | qc.draw(output='mpl') 56 | 57 | #Run on qasm simulator 58 | backend_qasm=BasicAer.get_backend('qasm_simulator') 59 | job_qasm=execute(qc,backend_qasm,shots=8192) 60 | result_qasm=job_qasm.result() 61 | counts=result_qasm.get_counts(qc) 62 | print(counts) 63 | plot_histogram(counts) 64 | sim_jobID=job_qasm.job_id() 65 | print('SIMULATION JOB ID: {}'.format(sim_jobID)) 66 | 67 | #Run on real device 68 | backend_exp=IBMQ.get_backend('ibmqx2') 69 | backend_exp.name() 70 | job_exp=execute(qc,backend_exp,shots=8192)#,max_credits=3) 71 | job_monitor(job_exp) 72 | result_exp=job_exp.result() 73 | counts_exp = result_exp.get_counts() 74 | print(counts_exp) 75 | plot_histogram([counts_exp,counts]) 76 | jobID=job_exp.job_id() 77 | print('REAL CHIP JOB ID: {}'.format(jobID)) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QPCA 2 | Codes used to perform the experiments described in this work: https://arxiv.org/abs/1904.05803 3 | 4 | # Towards Pricing Financial Derivatives with an IBM Quantum Computer 5 | 6 | Ana Martin, Bruno Candelas, Ángel Rodríguez-Rozas, José D. Martín-Guerrero, Xi Chen, Lucas Lamata, Román Orús, Enrique Solano, Mikel Sanz 7 | 8 | (Submitted on 11 Apr 2019) 9 | 10 | Pricing interest-rate financial derivatives is a major problem in finance, in which it is crucial to accurately reproduce the time-evolution of interest rates. Several stochastic dynamics have been proposed in the literature to model either the instantaneous interest rate or the instantaneous forward rate. A successful approach to model the latter is the celebrated Heath-Jarrow-Morton framework, in which its dynamics is entirely specified by volatility factors. On its multifactor version, this model considers several noisy components to capture at best the dynamics of several time-maturing forward rates. However, as no general analytical solution is available, there is a trade-off between the number of noisy factors considered and the computational time to perform a numerical simulation. Here, we employ the quantum principal component analysis to reduce the number of noisy factors required to accurately simulate the time evolution of several time-maturing forward rates. The principal components are experimentally estimated with the 5-qubit IBMQX2 quantum computer for 2×2 and 3×3 cross-correlation matrices, which are based on historical data for two and three time-maturing forward rates. This manuscript is a first step towards the design of a general quantum algorithm to fully simulate on quantum computers the Heath-Jarrow-Morton model for pricing interest-rate financial derivatives. It shows indeed that practical applications of quantum computers in finance will be achievable in the near future. 11 | --------------------------------------------------------------------------------