Przejdź do głównej treści

Quantum Portfolio Optimizer: funkcja Qiskit firmy Global Data Quantum

uwaga

Funkcje Qiskit to funkcjonalność eksperymentalna dostępna wyłącznie dla użytkowników planów IBM Quantum® Premium Plan, Flex Plan oraz On-Prem (przez IBM Quantum Platform API). Są w statusie podglądu i mogą ulec zmianie.

Przegląd

Quantum Portfolio Optimizer to funkcja Qiskit, która rozwiązuje problem dynamicznej optymalizacji portfela – standardowy problem w finansach polegający na okresowym równoważeniu inwestycji w zestawie aktywów w celu maksymalizacji zwrotów i minimalizacji ryzyka. Dzięki zastosowaniu najnowocześniejszych technik optymalizacji kwantowej funkcja upraszcza ten proces, umożliwiając użytkownikom nieposiadającym wiedzy z zakresu informatyki kwantowej skorzystanie z jej zalet przy wyznaczaniu optymalnych ścieżek inwestycyjnych. To narzędzie jest idealne dla zarządzających portfelami, badaczy z obszaru finansów ilościowych oraz indywidualnych inwestorów – umożliwia wsteczne testowanie strategii inwestycyjnych w optymalizacji portfela.

Opis funkcji

Funkcja Quantum Portfolio Optimizer wykorzystuje algorytm Variational Quantum Eigensolver (VQE) do rozwiązywania problemu kwadratowej niezwiązanej optymalizacji binarnej (QUBO), odpowiadającego problemowi dynamicznej optymalizacji portfela. Wystarczy, że podasz dane o cenach aktywów i zdefiniujesz ograniczenia inwestycyjne – funkcja uruchomi kwantowy proces optymalizacji i zwróci zestaw zoptymalizowanych ścieżek inwestycyjnych.

Proces składa się z czterech głównych etapów. Najpierw dane wejściowe są odwzorowywane na problem kompatybilny z kwantowym przetwarzaniem: budowany jest QUBO dla problemu dynamicznej optymalizacji portfela, a następnie przekształcany w operator kwantowy (hamiltonian Isinga). Następnie problem wejściowy oraz algorytm VQE są dostosowywane do uruchomienia na sprzęcie kwantowym. Algorytm VQE jest uruchamiany na sprzęcie kwantowym, po czym wyniki są poddawane przetwarzaniu końcowemu w celu wyznaczenia optymalnych ścieżek inwestycyjnych. System zawiera również przetwarzanie końcowe uwzględniające szumy (oparte na SQD), aby zmaksymalizować jakość wyników.

Ta funkcja Qiskit jest oparta na opublikowanym artykule naukowym firmy Global Data Quantum. Wizualizacja przepływu pracy funkcji

Dane wejściowe

Argumenty wejściowe funkcji są opisane w poniższej tabeli. Dane aktywów i inne specyfikacje problemu muszą być podane; opcjonalnie można uwzględnić ustawienia VQE, aby dostosować proces optymalizacji.

NazwaTypOpisWymaganeDomyślniePrzykład
assetsjsonSłownik z cenami aktywówTak--
qubo_settingsjsonUstawienia QUBOTak-Zobacz przykłady w poniższej tabeli
ansatz_settingsjsonUstawienia ansatzuNieNoneZobacz przykłady w poniższej tabeli.
optimizer_settingsjsonUstawienia optymalizatoraNieNoneZobacz przykłady w poniższej tabeli.
backendstrNazwa backendu QPUNie-"ibm_torino"
previous_session_idlist of strLista identyfikatorów Session do pobrania danych z poprzednich uruchomień(*)NiePusta lista["session_id_1", "session_id_2"]
apply_postprocessboolZastosuj przetwarzanie końcowe SQD uwzględniające szumyNieTrueTrue
tagslist of stringsLista tagów identyfikujących eksperymentNiePusta lista["optimization", "quantum_computing"]

*Aby wznowić wykonanie lub pobrać zadania przetworzone w jednej lub kilku poprzednich sesjach, lista identyfikatorów Session musi być przekazana w parametrze previous_session_id. Jest to szczególnie przydatne w sytuacjach, gdy zadanie optymalizacji nie zakończyło się z powodu błędu w procesie i wykonanie musi zostać dokończone. W tym celu należy podać te same argumenty, które były użyte przy pierwszym uruchomieniu, wraz z listą previous_session_id, jak opisano powyżej.

Ostrzeżenie

Wczytanie danych z poprzednich sesji (w celu wznowienia optymalizacji) może potrwać do jednej godziny.

assets

Dane muszą być ustrukturyzowane jako obiekt JSON przechowujący informacje o cenach zamknięcia aktywów finansowych w określonych datach. Format jest następujący:

  • Klucz główny (string): Nazwa lub symbol tickera aktywa finansowego (na przykład "8801.T").
  • Klucz pomocniczy (string): Data w formacie YYYY-MM-DD.
  • Wartość (number): Cena zamknięcia aktywa w podanej dacie. Ceny można podawać w formie znormalizowanej lub nieznormalizowanej.

Pamiętaj, że wszystkie słowniki muszą mieć te same klucze pomocnicze (daty). Jeśli dane aktywo nie posiada daty obecnej w innych słownikach, dane muszą być uzupełnione w celu zapewnienia spójności. Można to zrobić na przykład przez użycie ostatniej zarejestrowanej ceny zamknięcia tego aktywa.

Przykład

{
"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,
...
},
...
}
Uwaga

Dane aktywów muszą zawierać co najmniej ceny zamknięcia z (nt+1) * dt (zob. sekcję wejściową qubo_settings) znaczników czasu (na przykład dni).

qubo_settings

Poniższa tabela opisuje klucze słownika qubo_settings. Zbuduj słownik, podając liczbę kroków czasowych nt, liczbę Qubitów rozdzielczości nq oraz max_investment – lub zmień inne wartości domyślne.

NazwaTypOpisWymaganeDomyślniePrzykład
ntintLiczba kroków czasowychTak-4
nqintLiczba Qubitów rozdzielczościTak-4
max_investmentfloatMaksymalna liczba zainwestowanych jednostek walutowych we wszystkich aktywachTak-10
dt*intOkno czasowe uwzględniane w każdym kroku czasowym. Jednostka odpowiada przedziałom czasu między kluczami w danych aktywówNie30-
risk_aversionfloatWspółczynnik awersji do ryzykaNie1000-
transaction_feefloatWspółczynnik opłaty transakcyjnejNie0.01-
restriction_coefffloatMnożnik Lagrange'a stosowany do wymuszania ograniczenia problemu w sformułowaniu QUBONie1-

ansatz_settings

Aby zmienić domyślne opcje, utwórz słownik dla parametru ansatz_settings z następującymi kluczami. Domyślnie ansatz jest ustawiony na "real_amplitudes", a obie opcje dodatkowe (zob. poniższa tabela) mają wartość False.

NazwaTypOpisWymaganeDomyślnie
ansatz*strAnsatz do użyciaNie"real_amplitudes"
multiple_passmanager**boolWłącza podprocedurę multiple passmanager (niedostępną dla ansatzu Tailored)NieFalse
dd_enableboolDodaje dynamiczne odsprzęganie (dynamical decoupling)NieFalse

* Dostępne ansatze

  • real_amplitudes
  • cyclic
  • optimized_real_amplitudes
  • tailored (tylko dla backendu ibm_torino, 7 aktywów, 4 kroków czasowych i 4 Qubitów rozdzielczości)

** Jeśli multiple_passmanager jest ustawiony na False, funkcja używa domyślnego menedżera przejść Qiskit z optimization_level=3. Jeśli ustawiony na True, podprocedura multiple_passmanager porównuje trzy menedżery przejść: poprzedni domyślny menedżer przejść Qiskit, menedżer mapujący Qubity na łańcuch sąsiednich węzłów QPU oraz usługi Transpilatora AI. Następnie wybierany jest menedżer przejść z szacowanym niższym skumulowanym błędem.

optimizer_settings

Ten parametr to słownik z konfigurowalnymi opcjami procesu optymalizacji.

NazwaTypOpisWymaganeDomyślnie
primitive_optionsjsonUstawienia prymitywuNie-
optimizerstrWybrany klasyczny optymalizatorNie"differential_evolution"
optimizer_optionsjsonKonfiguracja optymalizatoraNie-
Uwaga

Aktualnie jedyną dostępną opcją optymalizatora jest "differential_evolution".

Pod kluczami primitive_options i optimizer_options ustawiamy słowniki z następującymi parametrami:

primitive_options

NazwaTypOpisWymaganeDomyślniePrzykład
sampler_shotsintLiczba pomiarów Samplera.Nie100000-
estimator_shotsintLiczba pomiarów Estimatora.Nie25000-
estimator_precisionfloatŻądana precyzja wartości oczekiwanej. Jeśli podana, precyzja zostanie użyta zamiast estimator_shots.NieNone0.015625 · (1 / sqrt(4096))
max_timeint lub strMaksymalny czas, przez który sesja runtime może pozostawać otwarta przed przymusowym zamknięciem. Można podać w sekundach (int) lub jako ciąg znaków, np. "2h 30m 40s". Musi być mniejszy niż maksimum narzucone przez system.NieNone"1h 15m"

optimizer_options

NazwaTypOpisWymaganeDomyślnie
num_generationsintLiczba generacjiNie20
population_sizeintRozmiar populacjiNie20
mutation_rangelistMaksymalny i minimalny współczynnik mutacjiNie[0, 0.25]
recombinationfloatWspółczynnik rekombinacjiNie0.4
max_parallel_jobsintMaksymalna liczba zadań QPU wykonywanych równolegleNie3
max_batchsizeintMaksymalny rozmiar partiiNie200
Uwaga
  • Liczba generacji obliczana przez ewolucję różnicową wynosi num_generations + 1, ponieważ uwzględniana jest populacja początkowa.

  • Całkowita liczba Circuit'ów obliczana jest jako (num_generations + 1) * population_size.

  • Używanie większej populacji i większej liczby generacji zazwyczaj poprawia jakość wyników optymalizacji. Nie zaleca się jednak przekraczania rozmiaru populacji 120 i liczby generacji większej niż 20 (na przykład 120 * 21 = 2520 Circuit'ów łącznie), ponieważ generowałoby to nadmierną liczbę Circuit'ów, co może być obliczeniowo kosztowne i czasochłonne.

  • Funkcja umożliwia wznowienie poprzedniej optymalizacji i zawsze można zwiększyć liczbę generacji (podając te same dane wejściowe z wyjątkiem previous_session_id i zwiększoną wartością num_generations).

Uwaga

Upewnij się, że przestrzegasz limitów zadań Qiskit Runtime.

  • Sampler: sampler_shots <= 10_000_000.
  • Estimator: max_batchsize * estimator_shots * observable_size <= 10_000_000 (w tej funkcji wszystkie składniki obserwowalnej dojeżdżają, więc observable_size=1).

Więcej informacji znajdziesz w przewodniku Limity zadań.

Dane wyjściowe

Funkcja zwraca dwa słowniki: słownik "result" zawierający najlepsze wyniki optymalizacji, w tym optymalne rozwiązanie i związany z nim minimalny koszt celu; oraz "metadata" z danymi ze wszystkich wyników uzyskanych podczas procesu optymalizacji wraz z odpowiednimi metrykami.

Pierwszy słownik skupia się na rozwiązaniu o najlepszej wydajności, podczas gdy drugi dostarcza szczegółowych informacji o wszystkich rozwiązaniach, w tym kosztach celu i innych istotnych metrykach.

Słowniki wyjściowe:

NazwaTypOpisPrzykład
resultdict[str, dict[str, float]]Zawiera strategię inwestycyjną w czasie – każdy znacznik czasu mapuje się na wagi inwestycyjne dla poszczególnych aktywów (każda waga to kwota inwestycji znormalizowana przez całkowitą kwotę inwestycji).{'time_1': {'asset_1': 0.2, 'asset_2': 0.3, ...\}, ...\}
metadatadict[str, Any]Dane wygenerowane podczas analizy, w tym rozwiązania, koszty i metryki.Zobacz przykłady poniżej

Opis słownika metadata

NazwaTypOpisPrzykład
session_idstrUnikalny identyfikator sesji IBM Quantum."d0h30qjvpqf00084fgw0"
all_samples_metricsdictSłownik zawierający różne metryki dla każdej próbki po przetwarzaniu końcowym, takie jak koszty lub ograniczenia.Zobacz opis poniżej
sampler_countsdict[str, int]Słownik, w którym kluczami są bitowe reprezentacje próbkowanych rozwiązań, a wartościami ich liczby wystąpień.{"101010": 3, "111000": 1\}
asset_orderlist[str]Lista z odpowiednią kolejnością inwestowania w aktywa w każdym kroku czasowym w ramach strategii inwestycyjnych.["Asset_0", "Asset_1", "Asset_3"]
QUBOlist[list[float]]Macierz QUBO problemu.[[-6.96e-01, 5.81e-01, -1.26e-02, 0.00e+00], ...]
resource_summarydict[str, dict[str, float]]Podsumowanie czasów użycia CPU i QPU (w sekundach) na różnych etapach procesu.{'RUNNING: EXECUTING_QPU': {'CPU_TIME': 412.84, 'QPU_TIME': 87.22\}, ...\}

Opis słownika all_samples_metrics

NazwaTypOpisPrzykład
investment_trajectorieslist[list]Strategie inwestycyjne wynikające z dekodowanych stanów kwantowych.[[1, 2, 2], [1, 2, 1]]

| counts | list[int] | Liczba razy, gdy każda ścieżka inwestycyjna została próbkowana. Indeks odpowiada investment_trajectories. | [5, 3] | | objective_costs | list[float] | Wartość funkcji celu dla każdej ścieżki inwestycyjnej, posortowana od najniższej do najwyższej. | [0.98, 1.25] | | sharpe_ratios | list[float] | Wyniki skorygowane o ryzyko (wskaźnik Sharpe'a) dla każdej ścieżki inwestycyjnej. Indeksy są zgodne. | [1.1, 0.7] | | returns | list[float] | Oczekiwany zwrot dla każdej ścieżki inwestycyjnej. Indeksy są zgodne. | [0.15, 0.10] | | rest_breaches | list[float] | Maksymalne odchylenie od ograniczenia w ramach każdej ścieżki inwestycyjnej. Indeksy są zgodne. | [0.0, 0.25] | | transaction_costs | list[float] | Szacowany koszt transakcyjny związany z każdą ścieżką inwestycyjną. Indeksy są zgodne. | [0.01, 0.02] |

Pierwsze kroki

Uwierzytelnij się przy użyciu swojego klucza API i wybierz funkcję Qiskit w następujący sposób. (Ten fragment kodu zakłada, że masz już zapisane konto w swoim lokalnym środowisku.)

from qiskit_ibm_catalog import QiskitFunctionsCatalog

catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")

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

Przykład: Dynamiczna optymalizacja portfela z siedmioma aktywami

Ten przykład pokazuje, jak uruchomić funkcję dynamicznej optymalizacji portfela (DPO) i dostosować jej ustawienia w celu uzyskania optymalnej wydajności. Zawiera szczegółowe kroki pozwalające na precyzyjne dostrojenie parametrów w celu osiągnięcia pożądanych wyników.

Ten przypadek obejmuje siedem aktywów, cztery kroki czasowe i cztery Qubity rozdzielczości, co w sumie wymaga 112 Qubitów.

1. Wczytaj aktywa wchodzące w skład portfela.

Jeśli wszystkie aktywa portfela są przechowywane w folderze pod określoną ścieżką, możesz załadować je do obiektu pandas.DataFrame i przekonwertować do formatu dict za pomocą poniższej funkcji.

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()

W tym przykładzie użyto aktywów 8801.T, CLF, GBPJPY, ITX.MC, META, TMBMKDE-10Y oraz XS2239553048. Poniższy rysunek ilustruje dane użyte w tym przykładzie, przedstawiając dzienną ewolucję cen zamknięcia aktywów od 1 stycznia do 1 września 2023 roku.

W tym przykładzie, aby zapewnić jednolitość dat, wypełniliśmy dni bez notowań ceną zamknięcia z poprzedniego dostępnego dnia. Zastosowaliśmy ten krok, ponieważ wybrane aktywa pochodzą z różnych rynków o zróżnicowanych dniach sesyjnych, co sprawia, że standaryzacja zbioru danych jest niezbędna dla zachowania spójności. Visualization of the historical data of the assets

2. Zdefiniuj problem.

Zdefiniuj specyfikację problemu, konfigurując parametry w słowniku 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. Zdefiniuj ustawienia optymalizatora i ansatzu. (Opcjonalne)

Opcjonalnie zdefiniuj szczegółowe wymagania dotyczące procesu optymalizacji, w tym wybór optymalizatora i jego parametrów, a także specyfikację prymitywu i jego konfiguracji.

W przypadku Tailored Ansatz wybrany rozmiar populacji był oparty na wcześniejszych eksperymentach, które wykazały, że ta wartość zapewnia stabilną i efektywną optymalizację.

W przypadku Real Amplitudes Ansatz możesz kierować się liniową zależnością pomiędzy population_size a liczbą Qubitów w Circuit. Jako przybliżona zasada praktyczna zaleca się stosowanie minimalnego population_size ~ 0.8 * n_qubits dla ansatzu real_amplitudes.

Oczekuje się, że Optimized Real Amplitudes będzie miał lepszą wydajność optymalizacji niż ansatz Real Amplitudes. Jednak liczba zmiennych do zoptymalizowania w tym ansatzu rośnie znacznie szybciej niż w przypadku Real Amplitudes (zob. manuskrypt). W związku z tym, dla dużych problemów, Optimized Real Amplitudes wymaga więcej uruchomień Circuit. Optimized Real Amplitudes będzie prawdopodobnie przydatny dla problemów wymagających do 100 Qubitów, jednak zaleca się ostrożność przy ustawianiu parametrów population_size. Jako przykład tego skalowania population_size, poprzednia tabela pokazuje, że dla problemu z 84 Qubitami Optimized Real Amplitudes wymaga population_size równego 120, natomiast dla problemu z 56 Qubitami wystarczy population_size równy 40.

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

Możliwe jest również wybranie konkretnego ansatzu. Poniżej użyto ansatzu 'Tailored'.

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

4. Uruchom 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. Pobierz wyniki.

Jak wspomniano w sekcji Dane wyjściowe, funkcja zwraca słownik z trajektoriami inwestycji uporządkowanymi od najniższej do najwyższej wartości funkcji celu. Ten zestaw wyników umożliwia identyfikację trajektorii o najniższym koszcie oraz odpowiadających jej ocen inwestycji. Dodatkowo pozwala na analizę różnych trajektorii, ułatwiając wybór tych, które najlepiej odpowiadają konkretnym potrzebom lub celom. Ta elastyczność sprawia, że wybory można dostosować do różnorodnych preferencji lub scenariuszy. Zacznij od przedstawienia strategii wynikowej, która osiągnęła najniższy koszt celu znaleziony podczas procesu.

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

Następnie, korzystając z metadanych, możesz uzyskać dostęp do wyników wszystkich próbkowanych strategii. Dzięki temu możesz przeprowadzić dalszą analizę alternatywnych trajektorii zwróconych przez optymalizator. W tym celu odczytaj słownik zapisany w dpo_result['metadata']['all_samples_metrics'], który zawiera nie tylko dodatkowe informacje o strategii optymalnej, ale także szczegóły dotyczące innych strategii kandydujących ocenianych podczas optymalizacji.

Poniższy przykład pokazuje, jak odczytać te informacje za pomocą pandas, aby wyodrębnić kluczowe metryki powiązane z optymalną strategią. Obejmują one Odchylenie od Ograniczeń (Restriction Deviation), Wskaźnik Sharpe'a (Sharpe Ratio) oraz odpowiadający zwrot z inwestycji.

# 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 wydajności

Na koniec przeanalizuj wydajność swojej aplikacji optymalizacyjnej. W szczególności porównaj uzyskane wyniki — z poprzedniego przykładu — z losowym punktem odniesienia, aby ocenić skuteczność zastosowanego podejścia. Jeśli algorytm kwantowy w sposób wyraźny i konsekwentny generuje wyniki o niższych wartościach kosztu, świadczy to o efektywnym procesie optymalizacji.

Rysunek przedstawia rozkłady prawdopodobieństwa kosztów celu. Aby wygenerować te rozkłady, pobierz listę kosztów celu z wyniku funkcji i policz wystąpienia każdej wartości kosztu (wartości zaokrąglone do drugiego miejsca po przecinku). Następnie zaktualizuj kolumnę zliczania, łącząc liczby identycznych zaokrąglonych wartości. Zwróć uwagę, że w celu lepszego porównania wizualnego liczby wystąpień zostały znormalizowane tak, aby każdy rozkład był wyświetlany w przedziale od 0 do 1. Visualization of the solution of the optimization Jak pokazano na rysunku (niebieska linia ciągła), rozkład kosztów dla podejścia opartego na Variational Quantum Eigensolver (po przetworzeniu końcowym z SQD) jest ostro skupiony przy niskich wartościach kosztu celu, co wskazuje na dobrą wydajność optymalizacji. W przeciwieństwie do tego, zaszumiony punkt odniesienia wykazuje szerszy rozkład skupiony wokół wyższych wartości kosztu. Szara przerywana linia pionowa reprezentuje wartość średnią rozkładu losowego, dodatkowo podkreślając spójność funkcji w zwracaniu zoptymalizowanych strategii inwestycyjnych. Dla dodatkowego porównania, czarna przerywana linia na rysunku odpowiada rozwiązaniu uzyskanemu za pomocą optymalizatora Gurobi (wersja bezpłatna). Wszystkie te wyniki są szerzej omówione w poniższych testach wydajnościowych dla przykładu „Mixed Assets" ocenianego z ansatzem „Tailored".

Testy wydajnościowe

Funkcja była testowana w różnych konfiguracjach Qubitów rozdzielczości, Circuit ansatzu oraz grupowań aktywów z różnych sektorów: mieszanina różnych aktywów (Zestaw 1), instrumenty pochodne ropy naftowej (Zestaw 2) oraz IBEX35 (Zestaw 3). Szczegóły zawiera poniższa tabela.

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

Do oceny jakości rozwiązań użyto dwóch kluczowych metryk.

  1. Koszt celu, który mierzy efektywność optymalizacji, porównując wartość funkcji kosztu z każdego eksperymentu z wynikami Gurobi (wersja bezpłatna).
  2. Wskaźnik Sharpe'a, który uwzględnia zwrot z portfela skorygowany o ryzyko, oferując wgląd w wyniki finansowe rozwiązań.

Łącznie te metryki stanowią punkt odniesienia zarówno dla obliczeniowych, jak i finansowych aspektów portfeli generowanych kwantowo.

PrzykładQubityAnsatzGłębokośćUżycie Runtime (s)Łączne użycie (s)Koszt celuSharpeKoszt celu GurobiSharpe Gurobi
Mixed Assets (Set 1, 4 kroki czasowe, 4-bitowy)112Tailored831273513095-3.7824.82-4.2524.71
Mixed Assets (Set 1, 4 kroki czasowe, 4 kroki czasowe, 4-bitowy)112Real Amplitudes3591173911903-3.3923.64-4.2524.71
Oil Derivatives (Set 2, 4 kroki czasowe, 3-bitowy)84Optimized Real Amplitudes7861806350-3.7319.13-4.1921.71
IBEX35 (Set 3, 4 kroki czasowe, 2-bitowy)56Optimized Real Amplitudes9633143523-3.6714.48-4.1116.44

Wyniki pokazują, że optymalizator kwantowy, z ansatzami dostosowanymi do problemu, skutecznie identyfikuje efektywne strategie inwestycyjne dla różnych typów portfeli. Poniżej szczegółowo opisujemy zarówno rozmiar populacji, jak i liczbę generacji określoną w słowniku optimizer_options. Wszystkie pozostałe parametry zostały ustawione na wartości domyślne.

Przykładpopulation_sizenum_generations
Mixed Assets Portfolio9020
Mixed Assets Portfolio9220
Oil Derivatives Portfolio12020
IBEX35 Portfolio4020

Liczba generacji została ustawiona na 20, ponieważ ta wartość okazała się wystarczająca do osiągnięcia zbieżności. Ponadto domyślne wartości parametrów wewnętrznych optymalizatora pozostały niezmienione, ponieważ konsekwentnie zapewniały dobrą wydajność i są ogólnie zalecane przez literaturę i wytyczne implementacyjne.

Uzyskaj wsparcie

Jeśli potrzebujesz pomocy, możesz wysłać wiadomość e-mail na adres qpo.support@globaldataquantum.com. W wiadomości podaj identyfikator zadania funkcji.

Następne kroki

Rekomendacje