Quantum Portfolio Optimizer: O Funcție Qiskit de la Global Data Quantum
Funcțiile Qiskit sunt o funcționalitate experimentală disponibilă doar utilizatorilor planurilor IBM Quantum® Premium, Flex și On-Prem (prin API-ul IBM Quantum Platform). Acestea se află în stadiu de previzualizare și pot suferi modificări.
Prezentare generală
Quantum Portfolio Optimizer este o Funcție Qiskit care abordează problema optimizării dinamice a portofoliului, o problemă standard în finanțe ce urmărește reechilibrarea periodică a investițiilor într-un set de active, pentru a maximiza randamentele și a minimiza riscurile. Prin aplicarea tehnicilor de vârf din optimizarea cuantică, această funcție simplifică procesul astfel încât utilizatorii, fără expertiză în calculul cuantic, să poată beneficia de avantajele sale în identificarea traiectoriilor optime de investiție. Ideală pentru managerii de portofoliu, cercetătorii în finanțe cantitative și investitorii individuali, acest instrument permite back-testarea strategiilor de tranzacționare în optimizarea portofoliului.
Descrierea funcției
Funcția Quantum Portfolio Optimizer folosește algoritmul Variational Quantum Eigensolver (VQE) pentru a rezolva o problemă de Optimizare Binară Neconstrasă Pătratică (QUBO), abordând probleme de optimizare dinamică a portofoliului. Utilizatorii trebuie doar să furnizeze datele privind prețurile activelor și să definească constrângerea de investiție, după care funcția rulează procesul de optimizare cuantică ce returnează un set de traiectorii de investiție optimizate.
Procesul constă în patru etape principale. Mai întâi, datele de intrare sunt mapate într-o problemă compatibilă cu calculul cuantic, construindu-se qubo-ul problemei de optimizare dinamică a portofoliului și transformându-l într-un operator cuantic (Hamiltonianul Ising). Apoi, problema de intrare și algoritmul VQE sunt adaptate pentru a fi rulate pe hardware cuantic. Algoritmul VQE este apoi rulat pe hardware cuantic, iar în final, rezultatele sunt post-procesate pentru a furniza traiectoriile optime de investiție. Sistemul include, de asemenea, o post-procesare conștientă de zgomot (bazată pe SQD) pentru a maximiza calitatea rezultatelor.
Această Funcție Qiskit se bazează pe manuscrisul publicat de Global Data Quantum.
Date de intrare
Argumentele de intrare ale funcției sunt descrise în tabelul următor. Datele despre active și alte specificații ale problemei trebuie furnizate; în plus, setările VQE pot fi incluse pentru a personaliza procesul de optimizare.
| Nume | Tip | Descriere | Obligatoriu | Implicit | Exemplu |
|---|---|---|---|---|---|
| assets | json | Dicționar cu prețurile activelor | Da | - | - |
| qubo_settings | json | Setările QUBO | Da | - | Vezi exemplele din tabelul de mai jos |
| ansatz_settings | json | Setările ansatz-ului | Nu | None | Vezi exemplele din tabelul de mai jos. |
| optimizer_settings | json | Setările Optimizer-ului | Nu | None | Vezi exemplele din tabelul de mai jos. |
| backend | str | Numele backend-ului QPU | Nu | - | "ibm_torino" |
| previous_session_id | list of str | Lista ID-urilor de Session pentru a prelua date din rulări anterioare(*) | Nu | Listă goală | ["session_id_1", "session_id_2"] |
| apply_postprocess | bool | Aplică post-procesarea SQD conștientă de zgomot | Nu | True | True |
| tags | list of strings | Listă de etichete pentru identificarea experimentului | Nu | Listă goală | ["optimization", "quantum_computing"] |
*Pentru a relua o execuție sau pentru a recupera job-uri procesate în una sau mai multe sesiuni anterioare, lista ID-urilor de Session trebuie pasată în parametrul previous_session_id. Acest lucru este deosebit de util în cazurile în care o sarcină de optimizare nu a putut fi finalizată din cauza unei erori în proces, iar execuția trebuie continuată. Pentru a realiza acest lucru, trebuie să furnizezi aceleași argumente utilizate în execuția inițială, împreună cu lista previous_session_id descrisă mai sus.
Încărcarea datelor pentru sesiunile anterioare (pentru reluarea unei optimizări) poate dura până la o oră.
assets
Datele trebuie structurate ca un obiect JSON ce stochează informații despre prețurile de închidere ale activelor financiare la date specifice. Formatul este următorul:
- Cheie primară (string): Numele sau simbolul ticker al activului financiar (de exemplu, "8801.T").
- Cheie secundară (string): Data în formatul YYYY-MM-DD.
- Valoare (number): Prețul de închidere al activului la data specificată. Prețurile pot fi introduse fie normalizate, fie nenormalizate.
Rețineți că toate dicționarele trebuie să aibă aceeași cheie secundară (date). Dacă un anumit activ nu are o dată pe care celelalte o au, datele trebuie completate pentru a asigura consistența. De exemplu, acest lucru se poate face folosind ultimul preț de închidere înregistrat al acelui activ.
Exemplu
{
"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,
...
},
...
}
Datele despre active trebuie să conțină cel puțin prețurile de închidere la (nt+1) * dt (vezi secțiunea de intrare qubo_settings) marcaje temporale (de exemplu, zile).
qubo_settings
Tabelul următor descrie cheile dicționarului qubo_settings. Construiește dicționarul specificând numărul de pași de timp nt, numărul de Qubit-uri de rezoluție nq și max_investment - sau modifică alte valori implicite.
| Nume | Tip | Descriere | Obligatoriu | Implicit | Exemplu |
|---|---|---|---|---|---|
| nt | int | Numărul de pași de timp | Da | - | 4 |
| nq | int | Numărul de Qubit-uri de rezoluție | Da | - | 4 |
| max_investment | float | Numărul maxim de unități de monedă investite pe toate activele | Da | - | 10 |
| dt* | int | Fereastra de timp luată în considerare la fiecare pas de timp. Unitatea corespunde intervalelor de timp dintre cheile din datele activului | Nu | 30 | - |
| risk_aversion | float | Coeficientul de aversiune față de risc | Nu | 1000 | - |
| transaction_fee | float | Coeficientul taxei de tranzacție | Nu | 0.01 | - |
| restriction_coeff | float | Multiplicatorul Lagrange utilizat pentru a impune constrângerea problemei în formularea QUBO | Nu | 1 | - |
ansatz_settings
Pentru a modifica opțiunile implicite, creează un dicționar pentru parametrul ansatz_settings cu cheile următoare. În mod implicit, ansatz-ul este setat la "real_amplitudes", iar ambele opțiuni suplimentare (vezi tabelul următor) sunt setate la False.
| Nume | Tip | Descriere | Obligatoriu | Implicit |
|---|---|---|---|---|
| ansatz* | str | ansatz-ul de utilizat | Nu | "real_amplitudes" |
| multiple_passmanager** | bool | Activează subrutina multiple passmanager (indisponibilă pentru ansatz-ul Tailored) | Nu | False |
| dd_enable | bool | Adaugă decuplare dinamică | Nu | False |
* ansatz-uri disponibile
real_amplitudescyclicoptimized_real_amplitudestailored(Doar pentru backend-ulibm_torino, 7 active, 4 pași de timp și 4 Qubit-uri de rezoluție)
** Dacă multiple_passmanager este setat la False, funcția folosește managerul de pasare implicit Qiskit cu optimization_level=3. Dacă este setat la True, subrutina multiple_passmanager compară trei manageri de pasare: managerul de pasare implicit Qiskit anterior, un manager de pasare care mapează Qubit-urile pe lanțul de vecini apropiați ai QPU și serviciile Transpiler AI. Apoi, este selectat managerul de pasare cu eroarea cumulată estimată mai mică.
optimizer_settings
Acest parametru este un dicționar cu câteva opțiuni reglabile ale procesului de optimizare.
| Nume | Tip | Descriere | Obligatoriu | Implicit |
|---|---|---|---|---|
| primitive_options | json | Setările primitivei | Nu | - |
| optimizer | str | Optimizer-ul clasic selectat | Nu | "differential_evolution" |
| optimizer_options | json | Configurarea Optimizer-ului | Nu | - |
În prezent, singura opțiune de Optimizer disponibilă este "differential_evolution".
Sub cheile primitive_options și optimizer_options se setează dicționare cu următorii parametri:
primitive_options
| Nume | Tip | Descriere | Obligatoriu | Implicit | Exemplu |
|---|---|---|---|---|---|
| sampler_shots | int | Numărul de shot-uri ale Sampler-ului. | Nu | 100000 | - |
| estimator_shots | int | Numărul de shot-uri ale Estimator-ului. | Nu | 25000 | - |
| estimator_precision | float | Precizia dorită a valorii așteptate. Dacă este specificată, precizia va fi utilizată în locul estimator_shots. | Nu | None | 0.015625 · (1 / sqrt(4096)) |
| max_time | int or str | Durata maximă de timp în care o Session de runtime poate rămâne deschisă înainte de a fi închisă forțat. Poate fi specificată în secunde (int) sau ca șir de caractere, precum "2h 30m 40s". Trebuie să fie mai mică decât maximul impus de sistem. | Nu | None | "1h 15m" |
optimizer_options
| Nume | Tip | Descriere | Obligatoriu | Implicit |
|---|---|---|---|---|
| num_generations | int | Numărul de generații | Nu | 20 |
| population_size | int | Mărimea populației | Nu | 20 |
| mutation_range | list | Factorul maxim și minim de mutație | Nu | [0, 0.25] |
| recombination | float | Factorul de recombinare | Nu | 0.4 |
| max_parallel_jobs | int | Numărul maxim de job-uri QPU executate în paralel | Nu | 3 |
| max_batchsize | int | Dimensiunea maximă a lotului | Nu | 200 |
-
Numărul de generații evaluate de evoluția diferențială este
num_generations+ 1, deoarece populația inițială este inclusă. -
Numărul total de Circuit-uri este calculat ca
(num_generations + 1) * population_size. -
Utilizarea unei populații mai mari și a mai multor generații îmbunătățește în general calitatea rezultatelor optimizării. Cu toate acestea, nu se recomandă depășirea unui
population_sizede 120 și a unui număr de generații mai mare de 20 (de exemplu,120 * 21 = 2520Circuit-uri totale), deoarece aceasta ar genera un număr excesiv de Circuit-uri, care poate fi costisitor din punct de vedere computațional și consumator de timp. -
Funcția îți permite să reiei optimizări anterioare și este întotdeauna posibil să crești numărul de generații (furnizând aceleași date de intrare, cu excepția
previous_session_idși a unuinum_generationsmărit).
Asigură-te că respecți limitele job-urilor Qiskit Runtime.
- Sampler:
sampler_shots <= 10_000_000. - Estimator:
max_batchsize * estimator_shots * observable_size <= 10_000_000(pentru această funcție, toți termenii observabilului comutează, deciobservable_size=1).
Vezi ghidul Limitele job-urilor pentru mai multe informații.
Rezultate
Funcția returnează două dicționare: dicționarul "result", care conține cele mai bune rezultate ale optimizării, inclusiv soluția optimă și costul obiectiv minim asociat; și "metadata", cu date din toate rezultatele obținute în timpul procesului de optimizare, împreună cu metricile respective.
Primul dicționar se concentrează pe soluția cu cele mai bune performanțe, în timp ce al doilea oferă informații detaliate despre toate soluțiile, inclusiv costurile obiective și alte metrici relevante.
Output dictionaries:
| Nume | Tip | Descriere | Exemplu |
|---|---|---|---|
| result | dict[str, dict[str, float]] | Conține strategia de investiții în timp, fiecare marcaj temporal mapând ponderi de investiție specifice activelor (fiecare pondere reprezintă suma investită normalizată prin suma totală a investiției). | {'time_1': {'asset_1': 0.2, 'asset_2': 0.3, ...\}, ...\} |
| metadata | dict[str, Any] | Date generate în timpul analizei, inclusiv soluții, costuri și metrici. | Vezi exemplele de mai jos |
Descrierea dicționarului metadata
| Nume | Tip | Descriere | Exemplu |
|---|---|---|---|
| session_id | str | Identificator unic pentru sesiunea IBM Quantum. | "d0h30qjvpqf00084fgw0" |
| all_samples_metrics | dict | Dicționar care conține diverse metrici pentru fiecare eșantion postprocesat, cum ar fi costuri sau constrângeri. | Vezi descrierea de mai jos |
| sampler_counts | dict[str, int] | Dicționar în care cheile sunt reprezentări sub formă de șir de biți ale soluțiilor eșantionate, iar valorile sunt numărul lor de apariții. | {"101010": 3, "111000": 1\} |
| asset_order | list[str] | Listă cu ordinea de investiție corespunzătoare a activelor la fiecare pas de timp în cadrul strategiilor de investiții. | ["Asset_0", "Asset_1", "Asset_3"] |
| QUBO | list[list[float]] | Matricea qubo a problemei. | [[-6.96e-01, 5.81e-01, -1.26e-02, 0.00e+00], ...] |
| resource_summary | dict[str, dict[str, float]] | Rezumat al timpilor de utilizare CPU și QPU (în secunde) în diferite etape ale procesului. | {'RUNNING: EXECUTING_QPU': {'CPU_TIME': 412.84, 'QPU_TIME': 87.22\}, ...\} |
Descrierea dicționarului all_samples_metrics
| Nume | Tip | Descriere | Exemplu |
|---|---|---|---|
| investment_trajectories | list[list] | Strategii de investiții derivate din stările cuantice decodate. | [[1, 2, 2], [1, 2, 1]] |
| counts | list[int] | Numărul de ori în care fiecare traiectorie de investiție a fost eșantionată. Indexul corespunde cu investment_trajectories. | [5, 3] |
| objective_costs | list[float] | Valoarea funcției obiectiv pentru fiecare traiectorie de investiție, ordonată de la cea mai mică la cea mai mare. | [0.98, 1.25] |
| sharpe_ratios | list[float] | Performanța ajustată la risc (raportul Sharpe) pentru fiecare traiectorie de investiție. Aliniate după index. | [1.1, 0.7] |
| returns | list[float] | Randamentul așteptat pentru fiecare traiectorie de investiție. Aliniat după index. | [0.15, 0.10] |
| rest_breaches | list[float] | Abaterea maximă a constrângerii în cadrul fiecărei traiectorii de investiție. Aliniată după index. | [0.0, 0.25] |
| transaction_costs | list[float] | Costul estimat al tranzacției asociat fiecărei traiectorii de investiție. Aliniat după index. | [0.01, 0.02] |
Începe
Autentifică-te folosind cheia ta API și selectează Qiskit Function-ul după cum urmează. (Acest fragment presupune că ți-ai salvat deja contul în mediul tău 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")
Exemplu: Optimizarea dinamică a portofoliului cu șapte active
Acest exemplu demonstrează cum să execuți funcția de optimizare dinamică a portofoliului (DPO) și cum să îi ajustezi setările pentru performanță optimă. Include pași detaliați pentru reglarea fină a parametrilor în vederea obținerii rezultatelor dorite.
Acest caz implică șapte active, patru pași de timp și patru Qubit de rezoluție, rezultând un total de 112 qubiți necesari.
1. Citește activele incluse în portofoliu.
Dacă toate activele din portofoliu sunt stocate într-un folder la o cale specifică, le poți încărca într-un pandas.DataFrame și le poți converti în obiect de tip dict folosind funcția de mai jos.
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()
Pentru acest exemplu, am utilizat activele 8801.T, CLF, GBPJPY, ITX.MC, META, TMBMKDE-10Y și XS2239553048. Figura de mai jos ilustrează datele utilizate în acest exemplu, prezentând evoluția zilnică a prețului de închidere al activelor în perioada 1 ianuarie – 1 septembrie 2023.
În acest exemplu, pentru a asigura uniformitatea datelor, am completat zilele fără tranzacționare cu prețul de închidere din ziua disponibilă anterioară. Aplicăm acest pas deoarece activele selectate provin din piețe diferite cu zile de tranzacționare variate, fiind esențial să standardizăm setul de date pentru consistență.
2. Definește problema.
Definește specificațiile problemei configurând parametrii din dicționarul 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ște setările Optimizer-ului și ale ansatz-ului. (Opțional)
Opțional, poți defini cerințe specifice pentru procesul de optimizare, inclusiv alegerea Optimizer-ului și a parametrilor acestuia, precum și specificarea primitivei și a configurațiilor sale.
Pentru Tailored Ansatz, dimensiunea populației aleasă s-a bazat pe experimente anterioare care au arătat că această valoare produce o optimizare stabilă și eficientă.
În cazul Real Amplitudes Ansatz, poți urma o relație liniară între population_size și numărul de qubiți din Circuit. Ca regulă aproximativă orientativă, se recomandă utilizarea unui population_size minim ~ 0.8 * n_qubits pentru ansatz-ul real_amplitudes.
Se preconizează că Optimized Real Amplitudes va avea o performanță de optimizare mai bună decât ansatz-ul Real Amplitudes. Totuși, numărul de variabile de optimizat în acest ansatz crește mult mai rapid decât în cazul Real Amplitudes (a se vedea manuscrisul). Prin urmare, pentru probleme de mari dimensiuni, Optimized Real Amplitudes necesită mai multe execuții de Circuit. Optimized Real Amplitudes este probabil util pentru probleme care necesită până la 100 de qubiți, însă se recomandă precauție la setarea parametrilor population_size. Ca exemplu al acestei scalări a population_size, tabelul anterior arată că pentru o problemă cu 84 de qubiți, Optimized Real Amplitudes necesită un population_size de 120, în timp ce pentru o problemă cu 56 de qubiți, un population_size de 40 este suficient.
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,
},
}
De asemenea, este posibil să alegi un ansatz specific. Exemplul de mai jos folosește ansatz-ul 'Tailored'.
ansatz_settings = {
"ansatz": "tailored",
"multiple_passmanager": False,
}
4. Run the problem.
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. Retrieve results.
Așa cum s-a menționat în secțiunea Output, funcția returnează un dicționar cu traiectoriile de investiții ordonate de la cea mai mică la cea mai mare valoare a funcției obiectiv. Acest set de rezultate permite identificarea traiectoriei cu cel mai mic cost și a evaluărilor corespunzătoare ale investițiilor. În plus, oferă posibilitatea de a analiza diferite traiectorii, facilitând selectarea celor care se aliniază cel mai bine cu nevoile sau obiectivele specifice. Această flexibilitate asigură că alegerile pot fi adaptate pentru a corespunde unei varietăți de preferințe sau scenarii. Începe prin a prezenta strategia rezultată care a obținut cel mai mic cost obiectiv găsit în timpul procesului.
# 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}}
Ulterior, folosind metadatele, poți accesa rezultatele tuturor strategiilor eșantionate. Astfel, poți analiza în continuare traiectoriile alternative returnate de Optimizer. Pentru a face acest lucru, citește dicționarul stocat în dpo_result['metadata']['all_samples_metrics'], care conține nu doar informații suplimentare despre strategia optimă, ci și detalii despre celelalte strategii candidate evaluate în timpul optimizării.
Următorul exemplu arată cum să citești aceste informații folosind pandas pentru a extrage valorile cheie asociate strategiei optime. Acestea includ Deviația de Restricție, Raportul Sharpe și rentabilitatea corespunzătoare a investiției.
# 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. Analiza performanței
În final, analizează performanța aplicației tale de optimizare. Mai concret, compară rezultatele tale, obținute în exemplul anterior, cu o linie de bază aleatorie pentru a evalua eficacitatea abordării noastre. Dacă algoritmul cuantic produce în mod demonstrabil și consistent rezultate cu valori de cost mai mici, acest lucru indică un proces de optimizare eficient.
Figura prezintă distribuțiile de probabilitate ale costurilor obiectiv. Pentru a genera aceste distribuții, ia lista costurilor obiectiv din rezultatul funcției și numără aparițiile fiecărei valori de cost (valori rotunjite la a doua zecimală). Apoi, actualizează coloana de numărare în mod corespunzător, combinând numărătorile valorilor rotunjite identice. Rețineți că, pentru o mai bună comparație vizuală, numărătorile de apariții au fost normalizate astfel încât fiecare distribuție să fie afișată între 0 și 1.
Așa cum se arată în figură (linia albastră continuă), distribuția costurilor pentru abordarea noastră bazată pe Variational Quantum Eigensolver (post-procesată cu SQD) este puternic concentrată la valori de cost obiectiv mai mici, indicând o bună performanță de optimizare. În contrast, linia de bază cu zgomot prezintă o distribuție mai largă, centrată în jurul unor valori de cost mai mari. Linia verticală gri punctată reprezintă valoarea medie a distribuției aleatoare, evidențiind și mai mult consistența funcției în returnarea strategiilor de investiții optimizate. Ca o comparație suplimentară, linia neagră punctată din figură corespunde soluției obținute cu optimizatorul Gurobi (versiunea gratuită). Toate aceste rezultate sunt explorate mai detaliat în benchmark-urile de mai jos pentru exemplul „Active Mixte" evaluat cu ansatz-ul „Tailored".
Benchmark-uri
Această funcție a fost testată în diferite configurații de qubiți de rezoluție, circuite ansatz și grupări de active din diverse sectoare: un mix de active diferite (Setul 1), derivative petroliere (Setul 2) și IBEX35 (Setul 3). Vezi mai multe detalii în tabelul următor.
| Set | Dată | Active |
|---|---|---|
| Setul 1 | 01/01/2023 | 8801.T, CL=F, GBPJPY=X, ITX.MC, META, TMBMKDE-10Y, XS2239553048 |
| Setul 2 | 01/06/2023 | CL=F, BZ=F, HO=F, NG=F, XOM, RB=F, 2222.SR |
| Setul 3 | 01/11/2022 | ACS.MC, ITX.MC, FER.MC, ELE.MC, SCYR.MC, AENA.MC, AMS.MC |
Au fost utilizate două metrici cheie pentru a evalua calitatea soluției.
- Costul obiectiv, care măsoară eficiența optimizării comparând valoarea funcției de cost din fiecare experiment cu rezultatele din Gurobi (versiunea gratuită).
- Indicele Sharpe, care surprinde randamentul ajustat la risc al fiecărui portofoliu, oferind o perspectivă asupra performanței financiare a soluțiilor.
Împreună, aceste metrici servesc drept benchmark atât pentru aspectele computaționale, cât și pentru cele financiare ale portofoliilor generate cuantic.
| Exemplu | Qubiți | Ansatz | Adâncime | Utilizare Runtime (s) | Utilizare totală (s) | Cost obiectiv | Sharpe | Cost obiectiv Gurobi | Sharpe Gurobi |
|---|---|---|---|---|---|---|---|---|---|
| Active Mixte (Setul 1, 4 pași de timp, 4 biți) | 112 | Tailored | 83 | 12735 | 13095 | -3.78 | 24.82 | -4.25 | 24.71 |
| Active Mixte (Setul 1, 4 pași de timp, 4 pași de timp, 4 biți) | 112 | Real Amplitudes | 359 | 11739 | 11903 | -3.39 | 23.64 | -4.25 | 24.71 |
| Derivative Petroliere (Setul 2, 4 pași de timp, 3 biți) | 84 | Optimized Real Amplitudes | 78 | 6180 | 6350 | -3.73 | 19.13 | -4.19 | 21.71 |
| IBEX35 (Setul 3, 4 pași de timp, 2 biți) | 56 | Optimized Real Amplitudes | 96 | 3314 | 3523 | -3.67 | 14.48 | -4.11 | 16.44 |
Rezultatele arată că Optimizer-ul cuantic, cu ansatz-uri specifice problemei, identifică eficient strategii de investiții eficiente pentru diverse tipuri de portofolii.
Mai jos detaliem atât dimensiunea populației, cât și numărul de generații specificate în dicționarul optimizer_options. Toți ceilalți parametri au fost setați la valorile lor implicite.
| Exemplu | population_size | num_generations |
|---|---|---|
| Portofoliu Active Mixte | 90 | 20 |
| Portofoliu Active Mixte | 92 | 20 |
| Portofoliu Derivative Petroliere | 120 | 20 |
| Portofoliu IBEX35 | 40 | 20 |
Numărul de generații a fost setat la 20, deoarece s-a constatat că această valoare este suficientă pentru a atinge convergența. În plus, valorile implicite pentru parametrii interni ai optimizatorului au rămas neschimbate, deoarece acestea au furnizat în mod constant performanțe bune și sunt în general recomandate de literatura de specialitate și ghidurile de implementare.
Obține suport
Dacă ai nevoie de ajutor, poți trimite un e-mail la qpo.support@globaldataquantum.com. În mesajul tău, furnizează ID-ul jobului funcției.
Pașii următori
- Citește lucrarea de cercetare asociată.
- Solicită acces la funcție completând acest formular.
- Încearcă tutorialul Dynamic Portfolio Optimization.