Skip to main content
IBM Quantum Platform

Quantum Portfolio Optimizer: Eine Qiskit-Funktion von Global Data Quantum

Siehe API-Referenz

Note

Qiskit-Funktionen sind eine experimentelle Funktion, die nur für Benutzer des IBM Quantum® Premium Plan, Flex Plan und On-Prem (über IBM Quantum Platform API) Plan verfügbar ist. Sie befinden sich im Status einer Vorabversion und können sich noch ändern.


Übersicht

Der Quantum Portfolio Optimizer ist eine Qiskit-Funktion, die sich mit dem Problem der dynamischen Portfolio-Optimierung befasst, einem Standardproblem im Finanzwesen, das darauf abzielt, periodische Investitionen in einer Reihe von Vermögenswerten neu zu verteilen, um die Erträge zu maximieren und die Risiken zu minimieren. Durch den Einsatz modernster Quantenoptimierungstechniken vereinfacht diese Funktion den Prozess, so dass auch Nutzer ohne Fachkenntnisse im Quantencomputing von den Vorteilen dieser Funktion bei der Suche nach optimalen Investitionspfaden profitieren können. Dieses Tool ist ideal für Portfoliomanager, Forscher im Bereich der quantitativen Finanzen und Privatanleger und ermöglicht das Backtesting von Handelsstrategien zur Portfoliooptimierung.


Funktionsbeschreibung

Die Funktion Quantum Portfolio Optimizer verwendet den Algorithmus Variational Quantum Eigensolver (VQE) zur Lösung eines quadratischen, uneingeschränkten binären Optimierungsproblems (QUBO), das sich mit dynamischen Portfolio-Optimierungsproblemen befasst. Die Benutzer müssen lediglich die Preisdaten für die Vermögenswerte angeben und die Investitionsbeschränkung definieren, woraufhin die Funktion den Quantenoptimierungsprozess durchführt, der eine Reihe optimierter Investitionstrajektorien liefert.

Der Prozess besteht aus vier Hauptphasen. Zunächst werden die Eingabedaten auf ein quantenkompatibles Problem abgebildet, wobei das QUBO des dynamischen Portfoliooptimierungsproblems konstruiert und in einen Quantenoperator (Ising-Hamiltonian) umgewandelt wird. Anschließend werden das Eingabeproblem und der VQE-Algorithmus so angepasst, dass sie auf der Quantenhardware ausgeführt werden können. Anschließend wird der VQE-Algorithmus auf der Quantenhardware ausgeführt, und schließlich werden die Ergebnisse nachbearbeitet, um die optimalen Investitionsverläufe zu ermitteln. Das System umfasst zudem eine rauschbewusste ( SQD -basierte) Nachbearbeitung, um die Qualität des Ergebnisses zu optimieren.

Diese Qiskit-Funktion basiert auf dem veröffentlichten Manuskript von Global Data Quantum.

Visualisierung des Arbeitsablaufs der Funktion

Erste Schritte

Authentifizieren Sie sich mit Ihrem API-Schlüssel und wählen Sie die Qiskit-Funktion wie folgt aus. (In diesem Codeausschnitt wird davon ausgegangen, dass Sie Ihr Konto bereits in Ihrer lokalen Umgebung gespeichert haben.)

from qiskit_ibm_catalog import QiskitFunctionsCatalog

catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")

# Verify that you have access to the function
catalog.list()

Output:

[QiskitFunction(qunova/hivqe-chemistry),
 QiskitFunction(global-data-quantum/quantum-portfolio-optimizer),
 QiskitFunction(algorithmiq/tem),
 QiskitFunction(qedma/qesem),
 QiskitFunction(multiverse/singularity),
 QiskitFunction(ibm/circuit-function),
 QiskitFunction(q-ctrl/optimization-solver),
 QiskitFunction(colibritd/quick-pde),
 QiskitFunction(q-ctrl/performance-management),
 QiskitFunction(kipu-quantum/iskay-quantum-optimizer)]
# Access function
dpo_solver = catalog.load("global-data-quantum/quantum-portfolio-optimizer")

Beispiel: Dynamische Portfoliooptimierung mit sieben Vermögenswerten

In diesem Beispiel wird gezeigt, wie Sie die dynamische Portfoliooptimierung (DPO) ausführen und ihre Einstellungen für eine optimale Leistung anpassen. Er enthält detaillierte Schritte zur Feinabstimmung der Parameter, um die gewünschten Ergebnisse zu erzielen.

In diesem Fall sind sieben Aktiva, vier Zeitschritte und vier Auflösungs-Qubits erforderlich, was einen Gesamtbedarf von 112 Qubits ergibt.

1. Sehen Sie sich die im Portfolio enthaltenen Vermögenswerte an

Wenn alle Assets des Portfolios in einem Ordner unter einem bestimmten Pfad gespeichert sind, können Sie sie mit der folgenden Funktion in ein pandas.DataFrame laden und in ein Objekt im Format dict konvertieren.

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

Für dieses Beispiel haben wir die Assets 8801.T, CLF, GBPJPY, ITX.MC, META, TMBMKDE-10Y, und XS2239553048. Die folgende Abbildung veranschaulicht die in diesem Beispiel verwendeten Daten und zeigt die tägliche Schlusskursentwicklung der Vermögenswerte vom 1. Januar bis zum 1. September 2023.

In diesem Beispiel haben wir, um die Einheitlichkeit der Daten zu gewährleisten, nicht gehandelte Tage mit dem Schlusskurs des letzten verfügbaren Datums gefüllt. Wir wenden diesen Schritt an, weil die ausgewählten Vermögenswerte von verschiedenen Märkten mit unterschiedlichen Handelstagen stammen, so dass eine Standardisierung des Datensatzes aus Konsistenzgründen unerlässlich ist.

Visualisierung der historischen Daten der Assets

2. Das Problem definieren

Definieren Sie die Spezifikationen des Problems, indem Sie die Parameter im Wörterbuch qubo_settings konfigurieren.

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

3. Legen Sie die Einstellungen für den Optimierer und den Ansatz fest (optional)

Definieren Sie optional spezifische Anforderungen für den Optimierungsprozess, einschließlich der Auswahl des Optimierers und seiner Parameter sowie der Spezifikation des Primitivs und seiner Konfigurationen.

Für den Tailored Ansatz wurde die Populationsgröße auf der Grundlage früherer Experimente gewählt, die gezeigt haben, dass dieser Wert eine stabile und effiziente Optimierung ermöglicht.

Im Falle des Ansatzes der reellen Amplituden kann man eine lineare Beziehung zwischen population_size und der Anzahl der Qubits in der Schaltung verfolgen. Als ungefähre Faustregel wird empfohlen, ein Minimum von population_size ~ 0.8 * n_qubits für den Ansatz real_amplitudes zu verwenden.

Es wird erwartet, dass die Optimierten Realen Amplituden eine bessere Optimierungsleistung aufweisen als der Ansatz der Realen Amplituden. Allerdings steigt die Anzahl der zu optimierenden Variablen in diesem Ansatz viel schneller als im Fall der reellen Amplituden (siehe Manuskript ). Bei großen Problemen erfordert die Optimierte Reale Amplitude daher mehr Schaltkreisausführungen. Die optimierten realen Amplituden sind wahrscheinlich nützlich für Probleme, die bis zu 100 Qubits erfordern, aber es wird empfohlen, bei der Einstellung der population_size Parameter vorsichtig zu sein. Als Beispiel für diese Skalierung in population_size zeigt die vorherige Tabelle, dass für ein 84-Qubit-Problem die Optimize Real Amplitudes 120 population_size benötigt, während für ein 56-Qubit-Problem eine population_size von 40 ausreicht.

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

Es ist auch möglich, einen bestimmten Ansatz zu wählen. Im Folgenden wird der Ansatz 'Tailored' verwendet.

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

4. Führen Sie das Programm aus

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. Ergebnisse abrufen

Die Funktion gibt ein Wörterbuch zurück, in dem die Investitionsverläufe nach ihrem Zielfunktionswert von niedrig nach hoch sortiert sind (siehe Abschnitt „Ausgabe“ in der API-Referenz). Anhand dieser Ergebnisse lassen sich die kostengünstigste Vorgehensweise und die entsprechenden Investitionsbewertungen ermitteln. Darüber hinaus ermöglicht es die Analyse verschiedener Entwicklungswege und erleichtert so die Auswahl derjenigen, die den spezifischen Bedürfnissen oder Zielen am besten entsprechen. Diese Flexibilität gewährleistet, dass die Auswahlmöglichkeiten auf eine Vielzahl von Vorlieben oder Szenarien zugeschnitten werden können.

Beginnen Sie mit der Darstellung der Strategie, die zu den niedrigsten objektiven Kosten geführt hat, die während des Prozesses gefunden wurden.

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

# Show the solution strategy
dpo_result["result"]

Output:

{'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}}

Anschließend können Sie über die Metadaten auf die Ergebnisse aller Strategien der Stichprobe zugreifen. Auf diese Weise können Sie die vom Optimierer zurückgegebenen alternativen Trajektorien weiter analysieren. Lesen Sie dazu das in dpo_result['metadata']['all_samples_metrics'] gespeicherte Wörterbuch, das nicht nur zusätzliche Informationen über die optimale Strategie, sondern auch Einzelheiten über die anderen während der Optimierung bewerteten Kandidatenstrategien enthält.

Das folgende Beispiel zeigt, wie diese Informationen mit Hilfe von pandas gelesen werden können, um die mit der optimalen Strategie verbundenen Schlüsselkennzahlen zu extrahieren. Dazu gehören Restriktionsabweichung, Sharpe Ratio und die entsprechende Anlagerendite.

# 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']}")

Output:

Minimum Objective Cost Found: -3.78
Best Solution:
  - Restriction Deviation: 40.0
  - Sharpe Ratio: 24.82
  - Return: 0.46

6. Leistungsanalyse

Analysieren Sie schließlich die Leistung Ihrer Optimierungsanwendung. Vergleichen Sie insbesondere Ihre Ergebnisse aus dem vorherigen Beispiel mit einer zufälligen Basislinie, um die Wirksamkeit unseres Ansatzes zu bewerten. Wenn der Quantenalgorithmus nachweislich und durchgängig Ergebnisse mit niedrigeren Kostenwerten liefert, deutet dies auf einen effektiven Optimierungsprozess hin.

Die Abbildung zeigt die Wahrscheinlichkeitsverteilungen der objektiven Kosten. Um diese Verteilungen zu erstellen, nehmen Sie die Liste der objektiven Kosten aus dem Funktionsergebnis und zählen Sie die Häufigkeit der einzelnen Kostenwerte (Werte auf die zweite Dezimalstelle gerundet). Aktualisieren Sie dann die Zählspalte entsprechend, indem Sie die Zählungen identischer gerundeter Werte verbinden. Um einen besseren visuellen Vergleich zu ermöglichen, wurde die Anzahl der Vorkommen normalisiert, so dass jede Verteilung zwischen 0 und 1 angezeigt wird.

Visualisierung der Lösung der Optimierungsaufgabe

Wie in der Abbildung (blaue durchgezogene Linie) zu sehen ist, konzentriert sich die Kostenverteilung für unseren Ansatz des Variational Quantum Eigensolver (nachbearbeitet mit SQD) stark auf die niedrigeren Zielkostenwerte, was auf eine gute Optimierungsleistung hinweist. Im Gegensatz dazu weist die verrauschte Basislinie eine breitere Verteilung auf, die sich auf höhere Kostenwerte konzentriert. Die graue, gestrichelte vertikale Linie stellt den Mittelwert der Zufallsverteilung dar, was die Konsistenz der Funktion bei der Ermittlung optimierter Anlagestrategien weiter verdeutlicht. Die schwarze gestrichelte Linie in der Abbildung entspricht der Lösung, die mit dem Gurobi-Optimierer (kostenlose Version) erzielt wurde, um einen zusätzlichen Vergleich zu ermöglichen. Alle diese Ergebnisse werden in den nachstehenden Benchmarks für das Beispiel "Gemischte Vermögenswerte", das mit dem "maßgeschneiderten" Ansatz bewertet wurde, näher untersucht.

Benchmarks

Diese Funktion wurde unter verschiedenen Konfigurationen von Auflösungsqubits, Ansatzschaltungen und Gruppierungen von Vermögenswerten aus verschiedenen Sektoren getestet: eine Mischung verschiedener Vermögenswerte (Set 1), Ölderivate (Set 2) und IBEX35 (Set 3). Weitere Einzelheiten finden Sie in der folgenden Tabelle.

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

Zur Bewertung der Lösungsqualität wurden zwei Schlüsselkennzahlen herangezogen.

  1. Die objektiven Kosten, die die Effizienz der Optimierung messen, indem der Wert der Kostenfunktion jedes Experiments mit den Ergebnissen von Gurobi (kostenlose Version) verglichen wird.
  2. Die Sharpe-Ratio, die die risikobereinigte Rendite jedes Portfolios erfasst und einen Einblick in die finanzielle Leistung der Lösungen bietet.

Mit diesen Kennzahlen werden sowohl die rechnerischen als auch die finanziellen Aspekte der durch Quanten generierten Portfolios bewertet.

Beispiel
Qubits
Ansatz
Tiefe
Laufzeitverbrauch (s)
Gesamtverbrauch (s)
Objektive Kosten
Sharpe
Gurobi objektive Kosten
Gurobi Sharpe
Gemischte Anlagen (Satz 1, 4 Zeitschritte, 4-Bit)112Gerader Rock831273513095-3.7824.82-4.2524.71
Gemischte Anlagen (Satz 1, 4 Zeitschritte, 4 Zeitschritte, 4 Bit)112Reale Amplituden3591173911903-3.3923.64-4.2524.71
Ölderivate (Satz 2, 4 Zeitschritte, 3-Bit)84Optimierte reale Amplituden7861806350-3.7319.13-4.1921.71
IBEX35 (Satz 3, 4 Zeitschritte, 2-Bit)56Optimierte reale Amplituden9633143523-3.6714.48-4.1116.44

Die Ergebnisse zeigen, dass der Quantenoptimierer mit problemspezifischen Ansätzen effektiv effiziente Anlagestrategien für verschiedene Portfoliotypen identifiziert.

Im Folgenden werden sowohl die Größe der Population als auch die Anzahl der Generationen, die im Wörterbuch optimizer_options angegeben sind, näher erläutert. Alle anderen Parameter wurden auf ihre Standardwerte gesetzt.

Beispiel
population_size
num_generations
Portfolio gemischter Vermögenswerte9020 Jahre
Portfolio gemischter Vermögenswerte9220 Jahre
Portfolio von Ölderivaten12020 Jahre
IBEX35 Portfolio4020 Jahre

Die Anzahl der Generationen wurde auf 20 festgelegt, da sich dieser Wert als ausreichend erwiesen hat, um Konvergenz zu erreichen. Darüber hinaus wurden die Standardwerte für die internen Parameter des Optimierers unverändert belassen, da sie durchweg gute Leistungen erbrachten und in der Literatur und in den Implementierungsrichtlinien allgemein empfohlen werden.

Unterstützung anfordern

Wenn Sie Hilfe benötigen, können Sie eine E-Mail globaldataquantum.com qpo.support senden. Geben Sie in Ihrer Nachricht die Job-ID der Funktion an.


Nächste Schritte

Empfehlungen
War diese Seite hilfreich?
Melden Sie auf GitHub einen Fehler, einen Tippfehler oder fordern Sie Inhalte an.