Quantum Portfolio Optimizer: una Qiskit Function de Global Data Quantum
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.
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.
| Nombre | Tipo | Descripción | Requerido | Valor por defecto | Ejemplo |
|---|---|---|---|---|---|
| assets | json | Diccionario con los precios de los activos | Sí | - | - |
| qubo_settings | json | Configuración del QUBO | Sí | - | Ver los ejemplos en la tabla siguiente |
| ansatz_settings | json | Configuración del ansatz | No | None | Ver los ejemplos en la tabla siguiente. |
| optimizer_settings | json | Configuración del optimizador | No | None | Ver los ejemplos en la tabla siguiente. |
| backend | str | Nombre del backend QPU | No | - | "ibm_torino" |
| previous_session_id | list of str | Lista de IDs de sesión para recuperar datos de ejecuciones anteriores(*) | No | Lista vacía | ["session_id_1", "session_id_2"] |
| apply_postprocess | bool | Aplica post-procesamiento SQD consciente del ruido | No | True | True |
| tags | list of strings | Lista de etiquetas para identificar el experimento | No | Lista 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.
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,
...
},
...
}
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.
| Nombre | Tipo | Descripción | Requerido | Por defecto | Ejemplo |
|---|---|---|---|---|---|
| nt | int | Número de pasos temporales | Sí | - | 4 |
| nq | int | Número de qubits de resolución | Sí | - | 4 |
| max_investment | float | Número máximo de unidades de moneda invertidas en todos los activos | Sí | - | 10 |
| dt* | int | Ventana temporal considerada en cada paso temporal. La unidad coincide con los intervalos de tiempo entre las claves de los datos de activos | No | 30 | - |
| risk_aversion | float | Coeficiente de aversión al riesgo | No | 1000 | - |
| transaction_fee | float | Coeficiente de comisión por transacción | No | 0.01 | - |
| restriction_coeff | float | Multiplicador de Lagrange utilizado para imponer la restricción del problema en la formulación QUBO | No | 1 | - |
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.
| Nombre | Tipo | Descripción | Requerido | Por defecto |
|---|---|---|---|---|
| ansatz* | str | Ansatz a utilizar | No | "real_amplitudes" |
| multiple_passmanager** | bool | Habilita la subrutina de múltiples gestores de pases (no disponible para el ansatz Tailored) | No | False |
| dd_enable | bool | Añade desacoplamiento dinámico | No | False |
* Ansatzes disponibles
real_amplitudescyclicoptimized_real_amplitudestailored(Solo para el backendibm_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.
| Nombre | Tipo | Descripción | Requerido | Por defecto |
|---|---|---|---|---|
| primitive_options | json | Configuración del primitivo | No | - |
| optimizer | str | Optimizador clásico seleccionado | No | "differential_evolution" |
| optimizer_options | json | Configuración del optimizador | No | - |
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
| Nombre | Tipo | Descripción | Requerido | Por defecto | Ejemplo |
|---|---|---|---|---|---|
| sampler_shots | int | Número de shots del Sampler. | No | 100000 | - |
| estimator_shots | int | Número de shots del Estimator. | No | 25000 | - |
| estimator_precision | float | Precisión deseada del valor esperado. Si se especifica, se usará la precisión en lugar de estimator_shots. | No | None | 0.015625 · (1 / sqrt(4096)) |
| max_time | int o str | Tiempo 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. | No | None | "1h 15m" |