Pular para o conteúdo principal

Quantum Portfolio Optimizer: Uma Função Qiskit da Global Data Quantum

nota

As Funções Qiskit são um recurso experimental disponível apenas para usuários dos planos IBM Quantum® Premium, Flex e On-Prem (via IBM Quantum Platform API). Elas estão em status de pré-lançamento e sujeitas a alterações.

Visão geral

O Quantum Portfolio Optimizer é uma Função Qiskit que aborda o problema de otimização dinâmica de portfólio, um problema padrão em finanças que visa rebalancear investimentos periódicos em um conjunto de ativos, maximizando retornos e minimizando riscos. Ao empregar técnicas de otimização quântica de ponta, esta função simplifica o processo para que usuários, sem expertise em computação quântica, possam se beneficiar de suas vantagens na busca de trajetórias de investimento ideais. Ideal para gestores de portfólio, pesquisadores em finanças quantitativas e investidores individuais, esta ferramenta permite o back-testing de estratégias de negociação em otimização de portfólio.

Descrição da função

A função Quantum Portfolio Optimizer usa o algoritmo Variational Quantum Eigensolver (VQE) para resolver um problema de Otimização Binária Irrestrita Quadrática (QUBO), abordando problemas de otimização dinâmica de portfólio. Os usuários precisam apenas fornecer os dados de preço dos ativos e definir a restrição de investimento; em seguida, a função executa o processo de otimização quântica que retorna um conjunto de trajetórias de investimento otimizadas.

O processo consiste em quatro etapas principais. Primeiro, os dados de entrada são mapeados para um problema compatível com quantum, construindo o QUBO do problema de otimização dinâmica de portfólio e transformando-o em um operador quântico (Hamiltoniano de Ising). Em seguida, o problema de entrada e o algoritmo VQE são adaptados para execução no hardware quântico. O algoritmo VQE é então executado no hardware quântico e, por fim, os resultados são pós-processados para fornecer as trajetórias de investimento ideais. O sistema também inclui um pós-processamento ciente de ruído (baseado em SQD) para maximizar a qualidade da saída.

Esta Função Qiskit é baseada no artigo publicado pela Global Data Quantum. Visualização do fluxo de trabalho da função

Entrada

Os argumentos de entrada da função estão descritos na tabela a seguir. Os dados dos ativos e outras especificações do problema devem ser fornecidos; além disso, as configurações do VQE podem ser incluídas para personalizar o processo de otimização.

NomeTipoDescriçãoObrigatórioPadrãoExemplo
assetsjsonDicionário com os preços dos ativosSim--
qubo_settingsjsonConfigurações do QUBOSim-Veja os exemplos na tabela abaixo
ansatz_settingsjsonConfigurações do ansatzNãoNoneVeja os exemplos na tabela abaixo.
optimizer_settingsjsonConfigurações do otimizadorNãoNoneVeja os exemplos na tabela abaixo.
backendstrNome do backend QPUNão-"ibm_torino"
previous_session_idlist of strLista de IDs de sessão para recuperar dados de execuções anteriores(*)NãoLista vazia["session_id_1", "session_id_2"]
apply_postprocessboolAplica pós-processamento SQD ciente de ruídoNãoTrueTrue
tagslist of stringsLista de tags para identificar o experimentoNãoLista vazia["optimization", "quantum_computing"]

*Para retomar uma execução ou recuperar jobs processados em uma ou mais sessões anteriores, a lista de IDs de sessão deve ser passada no parâmetro previous_session_id. Isso é particularmente útil em casos onde uma tarefa de otimização não foi concluída devido a algum erro no processo e a execução precisa ser finalizada. Para isso, você deve fornecer os mesmos argumentos usados na execução inicial, juntamente com a lista previous_session_id conforme descrito.

Aviso

O carregamento de dados de sessões anteriores (para retomar uma otimização) pode levar até uma hora.

assets

Os dados devem ser estruturados como um objeto JSON que armazena informações sobre os preços de fechamento de ativos financeiros em datas específicas. O formato é o seguinte:

  • Chave primária (string): o nome ou símbolo ticker do ativo financeiro (por exemplo, "8801.T").
  • Chave secundária (string): a data no formato AAAA-MM-DD.
  • Valor (número): o preço de fechamento do ativo na data especificada. Os preços podem ser inseridos normalizados ou não normalizados.

Observe que todos os dicionários devem ter a mesma chave secundária (datas). Se um ativo específico não tiver uma data que outros possuem, os dados devem ser preenchidos para garantir consistência. Por exemplo, isso pode ser feito usando o último preço de fechamento registrado desse ativo.

Exemplo

{
"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

Os dados do ativo devem conter, no mínimo, os preços de fechamento em (nt+1) * dt (veja a seção de entrada qubo_settings) registros de tempo (por exemplo, dias).

qubo_settings

A tabela a seguir descreve as chaves do dicionário qubo_settings. Construa o dicionário especificando o número de passos de tempo nt, o número de qubits de resolução nq e o max_investment - ou altere outros valores padrão.

NomeTipoDescriçãoObrigatórioPadrãoExemplo
ntintNúmero de passos de tempoSim-4
nqintNúmero de qubits de resoluçãoSim-4
max_investmentfloatNúmero máximo de unidades de moeda investidas em todos os ativosSim-10
dt*intJanela de tempo considerada em cada passo de tempo. A unidade corresponde aos intervalos de tempo entre as chaves nos dados do ativoNão30-
risk_aversionfloatCoeficiente de aversão ao riscoNão1000-
transaction_feefloatCoeficiente de taxa de transaçãoNão0.01-
restriction_coefffloatMultiplicador de Lagrange usado para impor a restrição do problema na formulação QUBONão1-

ansatz_settings

Para modificar as opções padrão, crie um dicionário para o parâmetro ansatz_settings com as chaves a seguir. Por padrão, o ansatz é definido como "real_amplitudes" e ambas as opções extras (veja a tabela a seguir) são definidas como False.

NomeTipoDescriçãoObrigatórioPadrão
ansatz*strAnsatz a ser usadoNão"real_amplitudes"
multiple_passmanager**boolHabilita a sub-rotina de múltiplos passmanagers (não disponível para o ansatz Tailored)NãoFalse
dd_enableboolAdiciona desacoplamento dinâmicoNãoFalse

* Ansatzes disponíveis

  • real_amplitudes
  • cyclic
  • optimized_real_amplitudes
  • tailored (apenas para o backend ibm_torino, 7 ativos, 4 passos de tempo e 4 qubits de resolução)

** Se multiple_passmanager for definido como False, a função usa o pass manager padrão do Qiskit com optimization_level=3. Se definido como True, a sub-rotina multiple_passmanager compara três pass managers: o pass manager padrão anterior do Qiskit, um pass manager que mapeia qubits sobre a cadeia de primeiros vizinhos do QPU e os serviços do transpilador de IA. Em seguida, o pass manager com o menor erro cumulativo estimado é selecionado.

optimizer_settings

Este parâmetro é um dicionário com algumas opções ajustáveis do processo de otimização.

NomeTipoDescriçãoObrigatórioPadrão
primitive_optionsjsonConfigurações da primitivaNão-
optimizerstrOtimizador clássico selecionadoNão"differential_evolution"
optimizer_optionsjsonConfiguração do otimizadorNão-
Nota

Atualmente, a única opção de otimizador disponível é "differential_evolution".

Sob as chaves primitive_options e optimizer_options definimos dicionários com os seguintes parâmetros:

primitive_options

NomeTipoDescriçãoObrigatórioPadrãoExemplo
sampler_shotsintNúmero de shots do Sampler.Não100000-
estimator_shotsintNúmero de shots do Estimator.Não25000-
estimator_precisionfloatPrecisão desejada do valor esperado. Se especificada, a precisão será usada em vez de estimator_shots.NãoNone0.015625 · (1 / sqrt(4096))
max_timeint ou strTempo máximo que uma sessão de runtime pode permanecer aberta antes de ser encerrada à força. Pode ser fornecido em segundos (int) ou como uma string, como "2h 30m 40s". Deve ser menor que o máximo imposto pelo sistema.NãoNone"1h 15m"

optimizer_options

NomeTipoDescriçãoObrigatórioPadrão
num_generationsintNúmero de geraçõesNão20
population_sizeintTamanho da populaçãoNão20
mutation_rangelistFator de mutação máximo e mínimoNão[0, 0.25]
recombinationfloatFator de recombinaçãoNão0.4
max_parallel_jobsintNúmero máximo de jobs QPU executados em paraleloNão3
max_batchsizeintTamanho máximo do loteNão200
Nota
  • O número de gerações avaliadas pela evolução diferencial é num_generations + 1, pois a população inicial é incluída.

  • O número total de circuits é calculado como (num_generations + 1) * population_size.

  • Usar um tamanho de população maior e mais gerações geralmente melhora a qualidade dos resultados de otimização. No entanto, não é recomendado exceder um tamanho de população de 120 e um número de gerações maior que 20 (por exemplo, 120 * 21 = 2520 circuits no total), pois isso geraria um número excessivo de circuits, o que pode ser computacionalmente custoso e demorado para processar.

  • A função permite retomar otimizações anteriores, e sempre é possível aumentar o número de gerações (fornecendo a mesma entrada, exceto por previous_session_id e um num_generations aumentado).

Nota

Garanta o cumprimento dos limites de jobs do Qiskit Runtime.

  • Sampler: sampler_shots <= 10_000_000.
  • Estimator: max_batchsize * estimator_shots * observable_size <= 10_000_000 (para esta função, todos os termos do observável comutam, portanto observable_size=1).

Veja o guia Limites de jobs para mais informações.

Saída

A função retorna dois dicionários: o dicionário "result", contendo os melhores resultados de otimização, incluindo a solução ideal e seu custo objetivo mínimo associado; e "metadata", com dados de todos os resultados obtidos durante o processo de otimização, junto com suas respectivas métricas.

O primeiro dicionário foca na solução de melhor desempenho, enquanto o segundo fornece informações detalhadas sobre todas as soluções, incluindo custos objetivo e outras métricas relevantes.

Dicionários de saída:

NomeTipoDescriçãoExemplo
resultdict[str, dict[str, float]]Contém a estratégia de investimento ao longo do tempo, com cada registro de tempo mapeado para pesos de investimento específicos por ativo (cada peso é o valor investido normalizado pelo valor total de investimento).{'time_1': {'asset_1': 0.2, 'asset_2': 0.3, ...\}, ...\}
metadatadict[str, Any]Dados gerados durante a análise, incluindo soluções, custos e métricas.Veja os exemplos abaixo

Descrição do dicionário metadata

NomeTipoDescriçãoExemplo
session_idstrIdentificador único para a sessão do IBM Quantum."d0h30qjvpqf00084fgw0"
all_samples_metricsdictDicionário contendo várias métricas para cada amostra pós-processada, como custos ou restrições.Veja a descrição abaixo
sampler_countsdict[str, int]Dicionário em que as chaves são representações de bitstring das soluções amostradas e os valores são suas contagens.{"101010": 3, "111000": 1\}
asset_orderlist[str]Lista com a ordem de investimento correspondente dos ativos em cada passo de tempo dentro das estratégias de investimento.["Asset_0", "Asset_1", "Asset_3"]
QUBOlist[list[float]]Matriz QUBO do problema.[[-6.96e-01, 5.81e-01, -1.26e-02, 0.00e+00], ...]
resource_summarydict[str, dict[str, float]]Resumo dos tempos de uso de CPU e QPU (em segundos) em diferentes etapas do processo.{'RUNNING: EXECUTING_QPU': {'CPU_TIME': 412.84, 'QPU_TIME': 87.22\}, ...\}

Descrição do dicionário all_samples_metrics

NomeTipoDescriçãoExemplo
investment_trajectorieslist[list]Estratégias de investimento derivadas de estados quânticos decodificados.[[1, 2, 2], [1, 2, 1]]

| counts | list[int] | Número de vezes que cada trajetória de investimento foi amostrada. O índice corresponde a investment_trajectories. | [5, 3] | | objective_costs | list[float] | Valor da função objetivo para cada trajetória de investimento, ordenado do menor para o maior. | [0.98, 1.25] | | sharpe_ratios | list[float] | Desempenho ajustado ao risco (índice de Sharpe) para cada trajetória de investimento. Alinhado por índice. | [1.1, 0.7] | | returns | list[float] | Retorno esperado para cada trajetória de investimento. Alinhado por índice. | [0.15, 0.10] | | rest_breaches | list[float] | Desvio máximo de restrição dentro de cada trajetória de investimento. Alinhado por índice. | [0.0, 0.25] | | transaction_costs | list[float] | Custo de transação estimado associado a cada trajetória de investimento. Alinhado por índice. | [0.01, 0.02] |

Como começar

Autentique-se usando sua chave de API e selecione a Função Qiskit conforme descrito a seguir. (Este trecho assume que você já salvou sua conta no seu ambiente 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")

Exemplo: Otimização dinâmica de portfólio com sete ativos

Este exemplo demonstra como executar a função de otimização dinâmica de portfólio (DPO) e ajustar suas configurações para desempenho ideal. Ele inclui etapas detalhadas para ajustar os parâmetros e alcançar os resultados desejados.

Este caso envolve sete ativos, quatro passos de tempo e quatro qubits de resolução, resultando em um requisito total de 112 qubits.

1. Leia os ativos incluídos no portfólio.

Se todos os ativos do portfólio estiverem armazenados em uma pasta em um caminho específico, você pode carregá-los em um pandas.DataFrame e convertê-los para um objeto no formato dict usando a seguinte função.

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 exemplo, usamos os ativos 8801.T, CLF, GBPJPY, ITX.MC, META, TMBMKDE-10Y e XS2239553048. A figura a seguir ilustra os dados usados neste exemplo, mostrando a evolução diária do preço de fechamento dos ativos de 1º de janeiro a 1º de setembro de 2023.

Neste exemplo, para garantir uniformidade entre as datas, preenchemos os dias sem negociação com o preço de fechamento da data disponível anterior. Aplicamos esta etapa porque os ativos selecionados provêm de diferentes mercados com dias de negociação variados, tornando essencial padronizar o conjunto de dados para consistência. Visualização dos dados históricos dos ativos

2. Defina o problema.

Defina as especificações do problema configurando os parâmetros no dicionário 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. Defina as configurações do otimizador e do ansatz. (Opcional)

Opcionalmente, defina requisitos específicos para o processo de otimização, incluindo a seleção do otimizador e seus parâmetros, bem como a especificação da primitiva e suas configurações.

Para o Ansatz Tailored, o tamanho de população escolhido foi baseado em experimentos anteriores que mostraram que este valor produz uma otimização estável e eficiente.

No caso do Ansatz Real Amplitudes, você pode seguir uma relação linear entre o population_size e o número de qubits no Circuit. Como regra geral aproximada, é recomendado usar um population_size mínimo de ~ 0.8 * n_qubits para o ansatz real_amplitudes.

Espera-se que o Optimized Real Amplitudes tenha um desempenho de otimização melhor do que o ansatz Real Amplitudes. No entanto, o número de variáveis a otimizar neste ansatz aumenta muito mais rapidamente do que no caso do Real Amplitudes (veja o artigo). Portanto, para problemas grandes, o Optimized Real Amplitudes requer mais execuções de Circuit. O Optimized Real Amplitudes provavelmente será útil para problemas que requerem até 100 qubits, mas é recomendado ter cuidado ao definir os parâmetros population_size. Como exemplo desse aumento de escala em population_size, a tabela anterior mostra que para um problema de 84 qubits, o Optimized Real Amplitudes requer population_size de 120, enquanto para um problema de 56 qubits, um population_size de 40 é 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,
},
}

Também é possível escolher um ansatz específico. O exemplo a seguir usa o ansatz 'Tailored'.

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

4. Execute o 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. Recupere os resultados.

Conforme mencionado na seção Saída, a função retorna um dicionário com as trajetórias de investimento ordenadas do menor para o maior de acordo com o valor de sua função objetivo. Este conjunto de resultados permite a identificação da trajetória com o menor custo e suas correspondentes avaliações de investimento. Além disso, fornece a análise de diferentes trajetórias, facilitando a seleção das que melhor se alinham com necessidades ou objetivos específicos. Essa flexibilidade garante que as escolhas possam ser adaptadas para atender a uma variedade de preferências ou cenários. Comece apresentando a estratégia resultante que alcançou o menor custo objetivo encontrado durante o processo.

# 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}}

Posteriormente, usando os metadados, você pode acessar os resultados de todas as estratégias amostradas. Você pode, assim, analisar mais a fundo as trajetórias alternativas retornadas pelo otimizador. Para isso, leia o dicionário armazenado em dpo_result['metadata']['all_samples_metrics'], que contém não apenas informações adicionais sobre a estratégia ideal, mas também detalhes das outras estratégias candidatas avaliadas durante a otimização.

O exemplo a seguir mostra como ler essas informações usando pandas para extrair métricas-chave associadas à estratégia ideal. Estas incluem Desvio de Restrição, Índice de Sharpe e o retorno de investimento correspondente.

# 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álise de desempenho

Por fim, analise o desempenho da sua aplicação de otimização. Especificamente, compare seus resultados, obtidos no exemplo anterior, com uma linha de base aleatória para avaliar a eficácia da nossa abordagem. Se o algoritmo quântico produzir demonstravelmente e consistentemente resultados com valores de custo mais baixos, isso indica um processo de otimização eficaz.

A figura apresenta as distribuições de probabilidade dos custos objetivo. Para gerar essas distribuições, pegue a lista de custos objetivo do resultado da função e conte as ocorrências de cada valor de custo (valores arredondados para a segunda casa decimal). Em seguida, atualize a coluna de contagem adequadamente, juntando as contagens de valores arredondados idênticos. Observe que, para melhor comparação visual, as contagens de ocorrências foram normalizadas para que cada distribuição seja exibida entre 0 e 1. Visualização da solução da otimização Como mostrado na figura (linha sólida azul), a distribuição de custos para a nossa abordagem com o Variational Quantum Eigensolver (pós-processado com SQD) está concentrada de forma acentuada em valores de custo objetivo mais baixos, indicando bom desempenho de otimização. Em contraste, a linha de base com ruído exibe uma distribuição mais ampla, centrada em torno de valores de custo mais altos. A linha vertical tracejada cinza representa o valor médio da distribuição aleatória, destacando ainda mais a consistência da função em retornar estratégias de investimento otimizadas. Para uma comparação adicional, a linha tracejada preta na figura corresponde à solução obtida com o otimizador Gurobi (versão gratuita). Todos esses resultados são explorados mais detalhadamente nos benchmarks abaixo para o exemplo de "Ativos Mistos" avaliado com o ansatz "Tailored".

Benchmarks

Esta função foi testada em diferentes configurações de qubits de resolução, circuits ansatz e agrupamentos de ativos de vários setores: uma mistura de ativos diferentes (Conjunto 1), derivativos de petróleo (Conjunto 2) e IBEX35 (Conjunto 3). Veja mais detalhes na tabela a seguir.

ConjuntoDataAtivos
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

Duas métricas-chave foram usadas para avaliar a qualidade da solução.

  1. O custo objetivo, que mede a eficiência da otimização comparando o valor da função de custo de cada experimento com os resultados do Gurobi (versão gratuita).
  2. O índice de Sharpe, que captura o retorno ajustado ao risco de cada portfólio, oferecendo perspectiva sobre o desempenho financeiro das soluções.

Juntas, essas métricas estabelecem benchmarks dos aspectos computacionais e financeiros dos portfólios gerados pelo quantum.

ExemploQubitsAnsatzProfundidadeUso de Runtime (s)Uso total (s)Custo objetivoSharpeCusto objetivo GurobiSharpe Gurobi
Ativos Mistos (Conjunto 1, 4 passos de tempo, 4-bit)112Tailored831273513095-3.7824.82-4.2524.71
Ativos Mistos (Conjunto 1, 4 passos de tempo, 4 passos de tempo, 4-bit)112Real Amplitudes3591173911903-3.3923.64-4.2524.71
Derivativos de Petróleo (Conjunto 2, 4 passos de tempo, 3-bit)84Optimized Real Amplitudes7861806350-3.7319.13-4.1921.71
IBEX35 (Conjunto 3, 4 passos de tempo, 2-bit)56Optimized Real Amplitudes9633143523-3.6714.48-4.1116.44

Os resultados mostram que o otimizador quântico, com ansatzes específicos do problema, identifica efetivamente estratégias de investimento eficientes em vários tipos de portfólio. Abaixo detalhamos tanto o tamanho da população quanto o número de gerações especificados no dicionário optimizer_options. Todos os outros parâmetros foram definidos com seus valores padrão.

Exemplopopulation_sizenum_generations
Portfólio de Ativos Mistos9020
Portfólio de Ativos Mistos9220
Portfólio de Derivativos de Petróleo12020
Portfólio IBEX354020

O número de gerações foi definido como 20, pois esse valor foi considerado suficiente para atingir a convergência. Além disso, os valores padrão para os parâmetros internos do otimizador foram mantidos inalterados, pois consistentemente forneceram bom desempenho e são geralmente recomendados pela literatura e pelas diretrizes de implementação.

Obter suporte

Se você precisar de ajuda, pode enviar um e-mail para qpo.support@globaldataquantum.com. Na sua mensagem, forneça o ID do job da função.

Próximos passos

Recomendações