Saltar al contenido principal

Quantum Portfolio Optimizer: una Qiskit Function de Global Data Quantum

nota

Las Qiskit Functions son una funcionalidad experimental disponible únicamente para usuarios del Plan Premium, Plan Flex y Plan On-Prem (a través de la API de IBM Quantum Platform) de IBM Quantum®. Se encuentran en estado de versión preliminar y pueden cambiar.

Descripción general

El Quantum Portfolio Optimizer es una Qiskit Function que aborda el problema de optimización dinámica de carteras, un problema estándar en finanzas que busca rebalancear inversiones periódicas en un conjunto de activos para maximizar rendimientos y minimizar riesgos. Al desplegar técnicas de optimización cuántica de vanguardia, esta función simplifica el proceso para que los usuarios, sin experiencia en computación cuántica, puedan beneficiarse de sus ventajas a la hora de encontrar trayectorias de inversión óptimas. Ideal para gestores de carteras, investigadores en finanzas cuantitativas e inversores individuales, esta herramienta permite realizar backtesting de estrategias de negociación en optimización de carteras.

Descripción de la función

La función Quantum Portfolio Optimizer utiliza el algoritmo Variational Quantum Eigensolver (VQE) para resolver un problema de Optimización Binaria Cuadrática sin Restricciones (QUBO), abordando problemas de optimización dinámica de carteras. Los usuarios solo necesitan proporcionar los datos de precios de los activos y definir la restricción de inversión; luego, la función ejecuta el proceso de optimización cuántica que devuelve un conjunto de trayectorias de inversión optimizadas.

El proceso consta de cuatro etapas principales. Primero, los datos de entrada se mapean a un problema compatible con la computación cuántica, construyendo el QUBO del problema de optimización dinámica de carteras y transformándolo en un operador cuántico (hamiltoniano de Ising). A continuación, el problema de entrada y el algoritmo VQE se adaptan para ejecutarse en hardware cuántico. El algoritmo VQE se ejecuta entonces en el hardware cuántico y, finalmente, los resultados se post-procesan para proporcionar las trayectorias de inversión óptimas. El sistema también incluye un post-procesamiento consciente del ruido (basado en SQD) para maximizar la calidad de la salida.

Esta Qiskit Function está basada en el artículo publicado por Global Data Quantum. Visualización del flujo de trabajo de la función

Entrada

Los argumentos de entrada de la función se describen en la siguiente tabla. Se deben proporcionar los datos de los activos y otras especificaciones del problema; además, se pueden incluir los ajustes del VQE para personalizar el proceso de optimización.

NombreTipoDescripciónRequeridoValor por defectoEjemplo
assetsjsonDiccionario con los precios de los activos--
qubo_settingsjsonConfiguración del QUBO-Ver los ejemplos en la tabla siguiente
ansatz_settingsjsonConfiguración del ansatzNoNoneVer los ejemplos en la tabla siguiente.
optimizer_settingsjsonConfiguración del optimizadorNoNoneVer los ejemplos en la tabla siguiente.
backendstrNombre del backend QPUNo-"ibm_torino"
previous_session_idlist of strLista de IDs de sesión para recuperar datos de ejecuciones anteriores(*)NoLista vacía["session_id_1", "session_id_2"]
apply_postprocessboolAplica post-procesamiento SQD consciente del ruidoNoTrueTrue
tagslist of stringsLista de etiquetas para identificar el experimentoNoLista vacía["optimization", "quantum_computing"]

*Para reanudar una ejecución o recuperar trabajos procesados en una o más sesiones anteriores, la lista de IDs de sesión debe pasarse en el parámetro previous_session_id. Esto resulta especialmente útil cuando una tarea de optimización no pudo completarse debido a algún error en el proceso y la ejecución necesita terminar. Para lograrlo, debes proporcionar los mismos argumentos utilizados en la ejecución inicial, junto con la lista previous_session_id tal como se describe.

Advertencia

La carga de datos de sesiones anteriores (para reanudar una optimización) puede tardar hasta una hora.

assets

Los datos deben estructurarse como un objeto JSON que almacene información sobre los precios de cierre de activos financieros en fechas específicas. El formato es el siguiente:

  • Clave primaria (string): El nombre o símbolo ticker del activo financiero (por ejemplo, "8801.T").
  • Clave secundaria (string): La fecha en formato YYYY-MM-DD.
  • Valor (número): El precio de cierre del activo en la fecha especificada. Los precios pueden introducirse normalizados o sin normalizar.

Ten en cuenta que todos los diccionarios deben tener la misma clave secundaria (fechas). Si a un activo concreto le falta una fecha que otros tienen, los datos deben completarse para garantizar la consistencia. Por ejemplo, esto puede hacerse usando el último precio de cierre registrado de ese activo.

Ejemplo

{
"8801.T": {
"2023-01-01": 2374.0,
"2023-01-02": 2374.0,
"2023-01-03": 2374.0,
"2023-01-04": 2356.5,
...
},
"AAPL": {
"2023-01-01": 145.2,
"2023-01-02": 146.5,
"2023-01-03": 147.3,
"2023-01-04": 148.1,
...
},
...
}
# Added by doQumentation — required packages for this notebook
!pip install -q pandas qiskit-ibm-catalog
{
"asset_name": {
"date": closing_value,
...
},
...
}
Nota

Los datos de activos deben contener, como mínimo, los precios de cierre en (nt+1) * dt (consulta la sección de entrada qubo_settings) marcas de tiempo (por ejemplo, días).

qubo_settings

La siguiente tabla describe las claves del diccionario qubo_settings. Construye el diccionario especificando el número de pasos temporales nt, el número de qubits de resolución nq y el max_investment, o cambia otros valores por defecto.

NombreTipoDescripciónRequeridoPor defectoEjemplo
ntintNúmero de pasos temporales-4
nqintNúmero de qubits de resolución-4
max_investmentfloatNúmero máximo de unidades de moneda invertidas en todos los activos-10
dt*intVentana temporal considerada en cada paso temporal. La unidad coincide con los intervalos de tiempo entre las claves de los datos de activosNo30-
risk_aversionfloatCoeficiente de aversión al riesgoNo1000-
transaction_feefloatCoeficiente de comisión por transacciónNo0.01-
restriction_coefffloatMultiplicador de Lagrange utilizado para imponer la restricción del problema en la formulación QUBONo1-

ansatz_settings

Para modificar las opciones por defecto, crea un diccionario para el parámetro ansatz_settings con las siguientes claves. Por defecto, el ansatz está configurado como "real_amplitudes" y ambas opciones adicionales (ver la tabla siguiente) están establecidas en False.

NombreTipoDescripciónRequeridoPor defecto
ansatz*strAnsatz a utilizarNo"real_amplitudes"
multiple_passmanager**boolHabilita la subrutina de múltiples gestores de pases (no disponible para el ansatz Tailored)NoFalse
dd_enableboolAñade desacoplamiento dinámicoNoFalse

* Ansatzes disponibles

  • real_amplitudes
  • cyclic
  • optimized_real_amplitudes
  • tailored (Solo para el backend ibm_torino, 7 activos, 4 pasos temporales y 4 qubits de resolución)

** Si multiple_passmanager está establecido en False, la función usa el gestor de pases de Qiskit por defecto con optimization_level=3. Si se establece en True, la subrutina multiple_passmanager compara tres gestores de pases: el gestor de pases de Qiskit por defecto anterior, un gestor de pases que mapea qubits sobre la cadena de primeros vecinos del QPU y los servicios del transpilador de IA. Luego, se selecciona el gestor de pases con el menor error acumulado estimado.

optimizer_settings

Este parámetro es un diccionario con algunas opciones configurables del proceso de optimización.

NombreTipoDescripciónRequeridoPor defecto
primitive_optionsjsonConfiguración del primitivoNo-
optimizerstrOptimizador clásico seleccionadoNo"differential_evolution"
optimizer_optionsjsonConfiguración del optimizadorNo-
Nota

Actualmente, la única opción de optimizador disponible es "differential_evolution".

Bajo las claves primitive_options y optimizer_options se definen diccionarios con los siguientes parámetros:

primitive_options

NombreTipoDescripciónRequeridoPor defectoEjemplo
sampler_shotsintNúmero de shots del Sampler.No100000-
estimator_shotsintNúmero de shots del Estimator.No25000-
estimator_precisionfloatPrecisión deseada del valor esperado. Si se especifica, se usará la precisión en lugar de estimator_shots.NoNone0.015625 · (1 / sqrt(4096))
max_timeint o strTiempo máximo que una sesión de runtime puede permanecer abierta antes de cerrarse forzosamente. Puede darse en segundos (int) o como string, como "2h 30m 40s". Debe ser menor que el máximo impuesto por el sistema.NoNone"1h 15m"

optimizer_options

NombreTipoDescripciónRequeridoPor defecto
num_generationsintNúmero de generacionesNo20
population_sizeintTamaño de la poblaciónNo20
mutation_rangelistFactor de mutación máximo y mínimoNo[0, 0.25]
recombinationfloatFactor de recombinaciónNo0.4
max_parallel_jobsintNúmero máximo de trabajos QPU ejecutados en paraleloNo3
max_batchsizeintTamaño máximo del loteNo200
Nota
  • El número de generaciones evaluadas por la evolución diferencial es num_generations + 1, ya que la población inicial está incluida.

  • El número total de circuitos se calcula como (num_generations + 1) * population_size.

  • Usar un tamaño de población mayor y más generaciones generalmente mejora la calidad de los resultados de optimización. Sin embargo, no se recomienda superar un tamaño de población de 120 ni un número de generaciones mayor de 20 (por ejemplo, 120 * 21 = 2520 circuitos en total), ya que esto generaría un número excesivo de circuitos, lo que puede ser costoso computacionalmente y llevar mucho tiempo.

  • La función te permite reanudar optimizaciones anteriores, y siempre es posible aumentar el número de generaciones (proporcionando la misma entrada excepto previous_session_id y un num_generations incrementado).

Nota

Asegúrate de cumplir con los límites de trabajos de Qiskit Runtime.

  • Sampler: sampler_shots <= 10_000_000.
  • Estimator: max_batchsize * estimator_shots * observable_size <= 10_000_000 (para esta función, todos los términos del observable conmutan, por lo que observable_size=1).

Consulta la guía de límites de trabajos para más información.

Salida

La función devuelve dos diccionarios: el diccionario "result", que contiene los mejores resultados de optimización, incluida la solución óptima y su coste objetivo mínimo asociado; y "metadata", con datos de todos los resultados obtenidos durante el proceso de optimización, junto con sus métricas respectivas.

El primer diccionario se centra en la solución con mejor rendimiento, mientras que el segundo proporciona información detallada sobre todas las soluciones, incluidos los costes objetivo y otras métricas relevantes.

Diccionarios de salida:

NombreTipoDescripciónEjemplo
resultdict[str, dict[str, float]]Contiene la estrategia de inversión a lo largo del tiempo, donde cada marca temporal mapea los pesos de inversión específicos por activo (cada peso es el monto de inversión normalizado por el monto total de inversión).{'time_1': {'asset_1': 0.2, 'asset_2': 0.3, ...\}, ...\}
metadatadict[str, Any]Datos generados durante el análisis, incluidas soluciones, costes y métricas.Ver ejemplos a continuación

Descripción del diccionario metadata

NombreTipoDescripciónEjemplo
session_idstrIdentificador único para la sesión de IBM Quantum."d0h30qjvpqf00084fgw0"
all_samples_metricsdictDiccionario que contiene diversas métricas para cada muestra post-procesada, como costes o restricciones.Ver descripción a continuación
sampler_countsdict[str, int]Diccionario donde las claves son representaciones en cadena de bits de las soluciones muestreadas y los valores son sus conteos.{"101010": 3, "111000": 1\}
asset_orderlist[str]Lista con el orden de inversión correspondiente de los activos en cada paso temporal dentro de las estrategias de inversión.["Asset_0", "Asset_1", "Asset_3"]
QUBOlist[list[float]]Matriz QUBO del problema.[[-6.96e-01, 5.81e-01, -1.26e-02, 0.00e+00], ...]
resource_summarydict[str, dict[str, float]]Resumen de los tiempos de uso de CPU y QPU (en segundos) en diferentes etapas del proceso.{'RUNNING: EXECUTING_QPU': {'CPU_TIME': 412.84, 'QPU_TIME': 87.22\}, ...\}

Descripción del diccionario all_samples_metrics

NombreTipoDescripciónEjemplo
investment_trajectorieslist[list]Estrategias de inversión derivadas de estados cuánticos decodificados.[[1, 2, 2], [1, 2, 1]]

| counts | list[int] | Número de veces que se muestreó cada trayectoria de inversión. El índice coincide con investment_trajectories. | [5, 3] | | objective_costs | list[float] | Valor de la función objetivo para cada trayectoria de inversión, ordenado de menor a mayor. | [0.98, 1.25] | | sharpe_ratios | list[float] | Rendimiento ajustado al riesgo (ratio de Sharpe) para cada trayectoria de inversión. Alineado por índice. | [1.1, 0.7] | | returns | list[float] | Rendimiento esperado para cada trayectoria de inversión. Alineado por índice. | [0.15, 0.10] | | rest_breaches | list[float] | Desviación máxima de la restricción dentro de cada trayectoria de inversión. Alineado por índice. | [0.0, 0.25] | | transaction_costs | list[float] | Coste de transacción estimado asociado a cada trayectoria de inversión. Alineado por índice. | [0.01, 0.02] |

Comenzar

Autentícate con tu clave de API y selecciona la Qiskit Function de la siguiente manera. (Este fragmento asume que ya has guardado tu cuenta en tu entorno local.)

from qiskit_ibm_catalog import QiskitFunctionsCatalog

catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")

# Access function
dpo_solver = catalog.load("global-data-quantum/quantum-portfolio-optimizer")

Ejemplo: Optimización dinámica de carteras con siete activos

Este ejemplo demuestra cómo ejecutar la función de optimización dinámica de carteras (DPO) y ajustar su configuración para un rendimiento óptimo. Incluye pasos detallados para ajustar los parámetros y lograr los resultados deseados.

Este caso implica siete activos, cuatro pasos temporales y cuatro qubits de resolución, lo que resulta en un requisito total de 112 qubits.

1. Lee los activos incluidos en la cartera.

Si todos los activos de la cartera están almacenados en una carpeta en una ruta específica, puedes cargarlos en un pandas.DataFrame y convertirlos a un objeto en formato dict usando la siguiente función.

import os
import glob
import pandas as pd

def read_and_join_csv(file_pattern):
"""
Reads multiple CSV files matching the file pattern and combines them into a single DataFrame.

Parameters:
file_pattern (str): The pattern to match CSV files.

Returns:
pd.DataFrame: Combined DataFrame with data from all CSV files.
"""
# Find all files matching the pattern
csv_files = glob.glob(file_pattern)
# Get the base file names without the .csv extension
file_names = [os.path.basename(f).replace(".csv", "") for f in csv_files]
# Read each CSV file into a DataFrame and set the first column as the index
df_list = [pd.read_csv(f).set_index("Unnamed: 0") for f in csv_files]

# Rename columns in each DataFrame to the base file names
for df, name in zip(df_list, file_names):
df.columns = [name]

# Combine all DataFrames into one by merging them side by side
combined_df = pd.concat(df_list, axis=1)
return combined_df

file_pattern = "route/to/folder/with/assets/data/*.csv"
assets = read_and_join_csv(file_pattern).to_dict()

Para este ejemplo, hemos utilizado los activos 8801.T, CLF, GBPJPY, ITX.MC, META, TMBMKDE-10Y y XS2239553048. La siguiente figura ilustra los datos utilizados en este ejemplo, mostrando la evolución diaria del precio de cierre de los activos del 1 de enero al 1 de septiembre de 2023.

En este ejemplo, para garantizar la uniformidad entre fechas, hemos rellenado los días no bursátiles con el precio de cierre de la fecha disponible anterior. Aplicamos este paso porque los activos seleccionados provienen de diferentes mercados con distintos días de negociación, lo que hace esencial estandarizar el conjunto de datos para mantener la consistencia. Visualización de los datos históricos de los activos

2. Define el problema.

Define las especificaciones del problema configurando los parámetros en el diccionario qubo_settings.

qubo_settings = {
"nt": 4,
"nq": 4,
"dt": 30,
"max_investment": 25,
"risk_aversion": 1000.0,
"transaction_fee": 0.01,
"restriction_coeff": 1.0,
}

3. Define la configuración del optimizador y del ansatz. (Opcional)

Opcionalmente, define requisitos específicos para el proceso de optimización, incluida la selección del optimizador y sus parámetros, así como la especificación del primitivo y sus configuraciones.

Para el Tailored Ansatz, el tamaño de población elegido se basó en experimentos previos que muestran que este valor produce una optimización estable y eficiente.

En el caso del Real Amplitudes Ansatz, puedes seguir una relación lineal entre el population_size y el número de qubits en el circuito. Como regla general aproximada, se recomienda usar un mínimo de population_size ~ 0.8 * n_qubits para el ansatz real_amplitudes.

Se espera que el Optimized Real Amplitudes tenga un mejor rendimiento de optimización que el ansatz Real Amplitudes. Sin embargo, el número de variables a optimizar en este ansatz crece mucho más rápido que en el caso de Real Amplitudes (consulta el artículo). Por lo tanto, para problemas grandes, el Optimized Real Amplitudes requiere más ejecuciones de circuitos. Es probable que el Optimized Real Amplitudes sea útil para problemas de hasta 100 qubits, pero se recomienda ser cuidadoso al establecer los parámetros population_size. Como ejemplo de este escalado en population_size, la tabla anterior muestra que para un problema de 84 qubits, el Optimized Real Amplitudes requiere 120 de population_size, mientras que para un problema de 56 qubits, un population_size de 40 es suficiente.

optimizer_settings = {
"de_optimizer_settings": {
"num_generations": 20,
"population_size": 90,
"recombination": 0.4,
"max_parallel_jobs": 5,
"max_batchsize": 4,
"mutation_range": [0.0, 0.25],
},
"optimizer": "differential_evolution",
"primitive_settings": {
"estimator_shots": 25_000,
"estimator_precision": None,
"sampler_shots": 100_000,
},
}

También es posible elegir un ansatz específico. El siguiente código usa el ansatz 'Tailored'.

ansatz_settings = {
"ansatz": "tailored",
"multiple_passmanager": False,
}

4. Ejecuta el problema.

dpo_job = dpo_solver.run(
assets=assets,
qubo_settings=qubo_settings,
optimizer_settings=optimizer_settings,
ansatz_settings=ansatz_settings,
backend_name="<backend name>",
previous_session_id=[],
apply_postprocess=True,
)

5. Recupera los resultados.

Como se menciona en la sección Salida, la función devuelve un diccionario con las trayectorias de inversión ordenadas de menor a mayor según su valor de función objetivo. Este conjunto de resultados permite identificar la trayectoria con el menor coste y sus evaluaciones de inversión correspondientes. Además, permite analizar diferentes trayectorias, facilitando la selección de las que mejor se adaptan a necesidades u objetivos específicos. Esta flexibilidad garantiza que las decisiones puedan adaptarse a una variedad de preferencias o escenarios. Comienza presentando la estrategia resultante que logró el menor coste objetivo encontrado durante el proceso.

# Get the results of the job
dpo_result = dpo_job.result()

# Show the solution strategy
dpo_result["result"]
{'time_step_0': {'8801.T': 0.11764705882352941,
'ITX.MC': 0.20588235294117646,
'META': 0.38235294117647056,
'GBPJPY=X': 0.058823529411764705,
'TMBMKDE-10Y': 0.0,
'CLF': 0.058823529411764705,
'XS2239553048': 0.17647058823529413},
'time_step_1': {'8801.T': 0.11428571428571428,
'ITX.MC': 0.14285714285714285,
'META': 0.2,
'GBPJPY=X': 0.02857142857142857,
'TMBMKDE-10Y': 0.42857142857142855,
'CLF': 0.0,
'XS2239553048': 0.08571428571428572},
'time_step_2': {'8801.T': 0.0,
'ITX.MC': 0.09375,
'META': 0.3125,
'GBPJPY=X': 0.34375,
'TMBMKDE-10Y': 0.0,
'CLF': 0.0,
'XS2239553048': 0.25},
'time_step_3': {'8801.T': 0.3939393939393939,
'ITX.MC': 0.09090909090909091,
'META': 0.12121212121212122,
'GBPJPY=X': 0.18181818181818182,
'TMBMKDE-10Y': 0.0,
'CLF': 0.0,
'XS2239553048': 0.21212121212121213}}

A continuación, usando los metadatos, puedes acceder a los resultados de todas las estrategias muestreadas. Así puedes analizar con mayor detalle las trayectorias alternativas devueltas por el optimizador. Para ello, lee el diccionario almacenado en dpo_result['metadata']['all_samples_metrics'], que contiene no solo información adicional sobre la estrategia óptima, sino también detalles de las otras estrategias candidatas evaluadas durante la optimización.

El siguiente ejemplo muestra cómo leer esta información usando pandas para extraer métricas clave asociadas a la estrategia óptima. Estas incluyen la Desviación de Restricción, el Ratio de Sharpe y el rendimiento de inversión correspondiente.

# Convert metadata to a DataFrame
df = pd.DataFrame(dpo_result["metadata"]["all_samples_metrics"])

# Find the minimum objective cost
min_cost = df["objective_costs"].min()
print(f"Minimum Objective Cost Found: {min_cost:.2f}")

# Extract the row with the lowest cost
best_row = df[df["objective_costs"] == min_cost].iloc[0]

# Display the results associated with the best solution
print("Best Solution:")
print(f" - Restriction Deviation: {best_row['rest_breaches']}%")
print(f" - Sharpe Ratio: {best_row['sharpe_ratios']:.2f}")
print(f" - Return: {best_row['returns']}")
Minimum Objective Cost Found: -3.78
Best Solution:
- Restriction Deviation: 40.0
- Sharpe Ratio: 24.82
- Return: 0.46

6. Análisis de rendimiento

Por último, analiza el rendimiento de tu aplicación de optimización. Específicamente, compara tus resultados, obtenidos en el ejemplo anterior, contra una línea base aleatoria para evaluar la efectividad de nuestro enfoque. Si el algoritmo cuántico produce de manera demostrable y consistente resultados con valores de coste más bajos, esto indica un proceso de optimización efectivo.

La figura presenta las distribuciones de probabilidad de los costes objetivo. Para generar estas distribuciones, toma la lista de costes objetivo del resultado de la función y cuenta las ocurrencias de cada valor de coste (valores redondeados al segundo decimal). Luego, actualiza la columna de conteos uniendo los conteos de valores redondeados idénticos. Ten en cuenta que, para una mejor comparación visual, los conteos de ocurrencias se han normalizado para que cada distribución se muestre entre 0 y 1. Visualización de la solución de la optimización Como se muestra en la figura (línea sólida azul), la distribución de costes para nuestro enfoque con Variational Quantum Eigensolver (post-procesado con SQD) está concentrada de forma marcada en valores de coste objetivo más bajos, lo que indica un buen rendimiento de optimización. En contraste, la línea base ruidosa exhibe una distribución más amplia, centrada en torno a valores de coste más altos. La línea vertical discontinua gris representa el valor medio de la distribución aleatoria, lo que resalta aún más la consistencia de la función al devolver estrategias de inversión optimizadas. Para una comparación adicional, la línea discontinua negra en la figura corresponde a la solución obtenida con el optimizador Gurobi (versión gratuita). Todos estos resultados se exploran con más detalle en los benchmarks a continuación para el ejemplo de "Activos Mixtos" evaluado con el ansatz "Tailored".

Benchmarks

Esta función se probó bajo diferentes configuraciones de qubits de resolución, circuitos ansatz y agrupaciones de activos de varios sectores: una mezcla de diferentes activos (Conjunto 1), derivados del petróleo (Conjunto 2) e IBEX35 (Conjunto 3). Consulta más detalles en la siguiente tabla.

ConjuntoFechaActivos
Conjunto 101/01/20238801.T, CL=F, GBPJPY=X, ITX.MC, META, TMBMKDE-10Y, XS2239553048
Conjunto 201/06/2023CL=F, BZ=F, HO=F, NG=F, XOM, RB=F, 2222.SR
Conjunto 301/11/2022ACS.MC, ITX.MC, FER.MC, ELE.MC, SCYR.MC, AENA.MC, AMS.MC

Se utilizaron dos métricas clave para evaluar la calidad de la solución.

  1. El coste objetivo, que mide la eficiencia de optimización comparando el valor de la función de coste de cada experimento con los resultados de Gurobi (versión gratuita).
  2. El ratio de Sharpe, que captura el rendimiento ajustado al riesgo de cada cartera, ofreciendo información sobre el rendimiento financiero de las soluciones.

Juntas, estas métricas sirven de referencia tanto para los aspectos computacionales como financieros de las carteras generadas cuánticamente.

EjemploQubitsAnsatzProfundidadUso en Runtime (s)Uso total (s)Coste objetivoSharpeCoste objetivo GurobiSharpe Gurobi
Activos Mixtos (Conjunto 1, 4 pasos temporales, 4-bit)112Tailored831273513095-3.7824.82-4.2524.71
Activos Mixtos (Conjunto 1, 4 pasos temporales, 4-bit)112Real Amplitudes3591173911903-3.3923.64-4.2524.71
Derivados del Petróleo (Conjunto 2, 4 pasos temporales, 3-bit)84Optimized Real Amplitudes7861806350-3.7319.13-4.1921.71
IBEX35 (Conjunto 3, 4 pasos temporales, 2-bit)56Optimized Real Amplitudes9633143523-3.6714.48-4.1116.44

Los resultados muestran que el optimizador cuántico, con ansatzes específicos para el problema, identifica eficazmente estrategias de inversión eficientes en varios tipos de carteras. A continuación detallamos tanto el tamaño de la población como el número de generaciones especificados en el diccionario optimizer_options. Todos los demás parámetros se establecieron con sus valores por defecto.

Ejemplopopulation_sizenum_generations
Cartera de Activos Mixtos9020
Cartera de Activos Mixtos9220
Cartera de Derivados del Petróleo12020
Cartera IBEX354020

El número de generaciones se fijó en 20, ya que se comprobó que este valor es suficiente para alcanzar la convergencia. Además, los valores por defecto de los parámetros internos del optimizador se dejaron sin cambios, ya que proporcionan consistentemente un buen rendimiento y están generalmente recomendados por la literatura y las directrices de implementación.

Obtener soporte

Si necesitas ayuda, puedes enviar un correo electrónico a qpo.support@globaldataquantum.com. En tu mensaje, proporciona el ID del trabajo de la función.

Próximos pasos

Recomendaciones