01-Finance Tutorial-Portfolio Optimization

[ ]:
#Where to find this code?
#https://qiskit-community.github.io/qiskit-finance/tutorials/01_portfolio_optimization.html
[1]:
from qiskit.circuit.library import TwoLocal
from qiskit.result import QuasiDistribution
#from qiskit_aer.primitives import Sampler
from qiskit_algorithms import NumPyMinimumEigensolver, QAOA, SamplingVQE
from qiskit_algorithms.optimizers import COBYLA
from qiskit_finance.applications.optimization import PortfolioOptimization
from qiskit_finance.data_providers import RandomDataProvider
from qiskit_optimization.algorithms import MinimumEigenOptimizer
import numpy as np
import matplotlib.pyplot as plt
import datetime
[2]:
# set number of assets (= number of qubits)
num_assets = 4
seed = 123

# Generate expected return and covariance matrix from (random) time-series
stocks = [("TICKER%s" % i) for i in range(num_assets)]
data = RandomDataProvider(
    tickers=stocks,
    start=datetime.datetime(2016, 1, 1),
    end=datetime.datetime(2016, 1, 30),
    seed=seed,
)
data.run()
mu = data.get_period_return_mean_vector()
sigma = data.get_period_return_covariance_matrix()
[3]:
# plot sigma
plt.imshow(sigma, interpolation="nearest")
plt.show()
../_images/JupyterNotebooks_QR_for_qiskit_Finance_-_Portfolio_Optimization_4_0.png
[4]:
q = 0.5  # set risk factor
budget = num_assets // 2  # set budget
penalty = num_assets  # set parameter to scale the budget penalty term

portfolio = PortfolioOptimization(
    expected_returns=mu, covariances=sigma, risk_factor=q, budget=budget
)
qp = portfolio.to_quadratic_program()
qp
[4]:
<QuadraticProgram: minimize 0.001270694296030004*x_0^2 + 7.34022166934733e-05*..., 4 variables, 1 constraints, 'Portfolio optimization'>
[5]:
def print_result(result):
    selection = result.x
    value = result.fval
    print("Optimal: selection {}, value {:.4f}".format(selection, value))

    eigenstate = result.min_eigen_solver_result.eigenstate
    probabilities = (
        eigenstate.binary_probabilities()
        if isinstance(eigenstate, QuasiDistribution)
        else {k: np.abs(v) ** 2 for k, v in eigenstate.to_dict().items()}
    )
    print("\n----------------- Full result ---------------------")
    print("selection\tvalue\t\tprobability")
    print("---------------------------------------------------")
    probabilities = sorted(probabilities.items(), key=lambda x: x[1], reverse=True)

    for k, v in probabilities:
        x = np.array([int(i) for i in list(reversed(k))])
        value = portfolio.to_quadratic_program().objective.evaluate(x)
        print("%10s\t%.4f\t\t%.4f" % (x, value, v))
[6]:
exact_mes = NumPyMinimumEigensolver()
exact_eigensolver = MinimumEigenOptimizer(exact_mes)

result = exact_eigensolver.solve(qp)

print_result(result)
Optimal: selection [1. 0. 0. 1.], value -0.0149

----------------- Full result ---------------------
selection       value           probability
---------------------------------------------------
 [1 0 0 1]      -0.0149         1.0000
[7]:
from quantumrings.toolkit.qiskit import QrSamplerV1 as Sampler
sampler = Sampler()
[9]:
from qiskit_algorithms.utils import algorithm_globals

algorithm_globals.random_seed = 1234

cobyla = COBYLA()
cobyla.set_options(maxiter=500)
ry = TwoLocal(num_assets, "ry", "cz", reps=3, entanglement="full")
svqe_mes = SamplingVQE(sampler=Sampler(), ansatz=ry, optimizer=cobyla)
svqe = MinimumEigenOptimizer(svqe_mes)
result = svqe.solve(qp)

print_result(result)
Optimal: selection [1. 0. 0. 1.], value -0.0149

----------------- Full result ---------------------
selection       value           probability
---------------------------------------------------
 [1 0 0 1]      -0.0149         0.8193
 [0 0 1 1]      -0.0010         0.0830
 [0 1 0 1]      0.0002          0.0234
 [1 1 1 0]      -0.0130         0.0195
 [0 0 0 1]      -0.0008         0.0107
 [0 1 0 0]      0.0009          0.0098
 [1 0 1 1]      -0.0150         0.0088
 [1 1 1 1]      -0.0139         0.0059
 [0 0 0 0]      0.0000          0.0049
 [1 0 0 0]      -0.0140         0.0039
 [0 1 1 1]      -0.0000         0.0039
 [1 1 0 1]      -0.0139         0.0029
 [1 1 0 0]      -0.0130         0.0020
 [1 0 1 0]      -0.0140         0.0020
[10]:
algorithm_globals.random_seed = 1234

cobyla = COBYLA()
cobyla.set_options(maxiter=250)
qaoa_mes = QAOA(sampler=Sampler(), optimizer=cobyla, reps=3)
qaoa = MinimumEigenOptimizer(qaoa_mes)
result = qaoa.solve(qp)

print_result(result)
Optimal: selection [1. 0. 0. 1.], value -0.0149

----------------- Full result ---------------------
selection       value           probability
---------------------------------------------------
 [1 0 0 1]      -0.0149         0.1816
 [1 0 1 0]      -0.0140         0.1680
 [0 0 1 1]      -0.0010         0.1670
 [0 1 0 1]      0.0002          0.1650
 [1 1 0 0]      -0.0130         0.1602
 [0 1 1 0]      0.0008          0.1543
 [1 1 1 1]      -0.0139         0.0029
 [0 0 1 0]      -0.0001         0.0010
[ ]: