Quantum Portfolio Optimizer: פונקציית Qiskit מאת Global Data Quantum
ראה את הפניית ה-API
פונקציות Qiskit הן תכונה ניסיונית הזמינה רק למשתמשי IBM Quantum® Premium Plan, Flex Plan ו-On-Prem (דרך IBM Quantum Platform API) Plan. הן נמצאות בגרסת תצוגה מקדימה וצפויות לשינויים.
סקירה כללית
ה-Quantum Portfolio Optimizer הוא פונקציית Qiskit המתמודדת עם בעיית אופטימיזציה דינמית של תיק השקעות — בעיה סטנדרטית בתחום הפיננסים, שמטרתה לאזן מחדש השקעות תקופתיות בקבוצת נכסים כדי למקסם תשואות ולמזער סיכונים. הפונקציה מנצלת טכניקות אופטימיזציה קוונטיות מתקדמות ומפשטת את התהליך כך שמשתמשים, ללא ניסיון בחישוב קוונטי, יוכלו ליהנות מיתרונותיה במציאת מסלולי השקעה אופטימליים. הכלי מתאים במיוחד למנהלי תיקים, חוקרים בתחום הפינ נסים הכמותיים ומשקיעים פרטיים, ומאפשר בחינה לאחור (back-testing) של אסטרטגיות מסחר באופטימיזציה של תיקי השקעות.
תיאור הפונקציה
פונקציית ה-Quantum Portfolio Optimizer משתמשת באלגוריתם VQE (Variational Quantum Eigensolver) לפתרון בעיית QUBO (Quadratic Unconstrained Binary Optimization), ובכך מטפלת בבעיות אופטימיזציה דינמית של תיקי השקעות. המשתמשים צריכים רק לספק את נתוני מחיר הנכסים ולהגדיר את אילוץ ההשקעה, ואז הפונקציה מריצה את תהליך האופטימיזציה הקוונטית ומחזירה קבוצה של מסלולי השקעה אופטימליים.
התהליך מורכב מארבעה שלבים עיקריים. ראשית, נתוני הקלט ממופים לבעיה תואמת-קוונטית, תוך בניית ה-QUBO של בעיית אופטימיזציה דינמית של תיק ההשקעות והמרתה לאופרטור קוונטי (Ising Hamiltonian). לאחר מכן, בעיית הקלט ואלגוריתם ה-VQE מותאמים להרצה על חומרה קוונטית. לאחר מכן מופעל אלגוריתם VQE על החומרה הקוונטית, ולבסוף, התוצאות עוברות עיבוד לאחור (post-processing) על מנת לספק את מסלולי ההשקעה האופטימליים. המערכת כוללת גם עיבוד לאחור מודע-רעש (מבוסס SQD) לשיפור איכות הפלט.
פונקציית Qiskit זו מבוססת על המאמר המדעי שפורסם מאת Global Data Quantum.
התחלה
בצע אימות באמצעות מפתח ה-API שלך ובחר את פונקציית Qiskit כדלקמן. (קטע קוד זה מניח שכבר שמרת את חשבונך בסביבה המקומית שלך.)
# Added by doQumentation — required packages for this notebook
!pip install -q pandas qiskit-ibm-catalog
from qiskit_ibm_catalog import QiskitFunctionsCatalog
catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")
# Access function
dpo_solver = catalog.load("global-data-quantum/quantum-portfolio-optimizer")
דוגמה: אופטימיזציה דינמית של תיק השקעות עם שבעה נכסים
דוגמה זו מדגימה כיצד להריץ את פונקציית אופטימיזציה דינמית של תיק ההשקעות (DPO) ולכוונן את הגדרותיה לביצועים אופטימליים. היא כוללת שלבים מפורטים לכוונון עדין של הפרמטרים להשגת תוצאות רצויות.
מקרה זה כולל שבעה נכסים, ארבעה צעדי זמן וארבעה Qubits רזולוציה, מה שמביא לדרישה כוללת של 112 Qubits.
1. קרא את הנכסים הכלולים בתיק ההשקעות.
אם כל הנכסים בתיק מאוחסנים בתיקייה בנתיב ספציפי, תוכל לטעון אותם ל-pandas.DataFrame ולהמיר אותם לאובייקט בפורמט dict באמצעות הפונקציה הבאה.
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()
בדוגמה זו השתמשנו בנכסים 8801.T, CLF, GBPJPY, ITX.MC, META, TMBMKDE-10Y, ו-XS2239553048. האיור הבא ממחיש את הנתונים שנעשה בהם שימוש בדוגמה זו, ומציג את התפתחות מחיר הסגירה היומי של הנכסים מ-1 בינואר עד 1 בספטמבר 2023.
בדוגמה זו, כדי להבטיח אחידות בין תאריכים, מילאנו ימי לא-מסחר במחיר הסגירה מהתארי ך הזמין הקודם. אנחנו מיישמים שלב זה מכיוון שהנכסים שנבחרו מגיעים משווקים שונים עם ימי מסחר משתנים, מה שהופך את תקנון מערך הנתונים לעקביות לחיוני.
2. הגדר את הבעיה.
הגדר את מפרטי הבעיה על ידי קביעת הפרמטרים במילון 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. הגדר את הגדרות האופטימייזר וה-ansatz (אופציונלי)
הגדר אופציונלית דרישות ספציפיות לתהליך האופטימיזציה, כולל בחירת האופטימייזר ופרמטריו, וכן ציון ה-primitive ותצורותיו.
עבור ה-Tailored Ansatz, גודל האוכלוסייה שנבחר התבסס על ניסויים קודמים שהראו שערך זה מניב אופטימיזציה יציבה ויעילה.
במקרה של Real Amplitudes Ansatz, ניתן לפעול לפי קשר ליניארי בין population_size לבין מספר ה-Qubits במעגל. כחוק אצבע משוערת, מומלץ להשתמש ב-מינימום population_size ~ 0.8 * n_qubits עבור ה-ansatz של real_amplitudes.
צפוי שה-Optimized Real Amplitudes יניב ביצועי אופטימיזציה טובים יותר מה-ansatz של Real Amplitudes. עם זאת, מספר המשתנים לאופטימיזציה ב-ansatz זה גדל הרבה יותר מהר מאשר במקרה של Real Amplitudes (ראה המאמר המדעי). לפיכך, עבור בעיות גדולות, ה-Optimized Real Amplitudes דורש יותר הרצות מעגלים. ה-Optimized Real Amplitudes ככל הנראה שימושי עבור בעיות הדורשות עד 100 Qubits, אך מומלץ לשים לב בעת קביעת פרמטרי population_size. כדוגמה להגדלה זו ב-population_size, הטבלה הקודמת מציגה שעבור בעיית 84 Qubits, ה-Optimize Real Amplitudes דורש population_size של 120, בעוד שעבור בעיית 56 Qubits, מספיק population_size של 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,
},
}
ניתן גם לבחור ansatz ספציפי. הדוגמה הבאה משתמשת ב-ansatz של 'Tailored'.
ansatz_settings = {
"ansatz": "tailored",
"multiple_passmanager": False,
}
4. הרץ את הבעיה.
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. שלוף תוצאות
הפונקציה מחזירה מילון עם מסלולי ההשקעה מסודרים מהנמוך לגבוה בהתאם לערך פונקציית המטרה שלהם (ראה את החלק Output בהפניית ה-API). קבוצת תוצאות זו מאפשרת לזהות את המסלול בעל העלות הנמוכה ביותר והערכות ההשקעה המתאימות לו. בנוסף, היא מספקת ניתוח של מסלולים שונים, מה שמקל על בחירת אלה המתאימים ביותר לצרכים או למטרות ספציפיות. גמישות זו מבטיחה שניתן להתאים את הבחירות לסוגים שונים של העדפות או תרחישים. התחל בהצגת אסטרטגיית התוצאות שהשיגה את עלות המטרה הנמוכה ביותר שנמצאה במהלך התהליך.
# 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}}
לאחר מכן, באמצעות המטא- נתונים, תוכל לגשת לתוצאות של כל האסטרטגיות שנדגמו. כך תוכל לנתח עוד יותר את המסלולים החלופיים שהאופטימייזר החזיר. לשם כך, קרא את המילון המאוחסן ב-dpo_result['metadata']['all_samples_metrics'], המכיל לא רק מידע נוסף על האסטרטגיה האופטימלית, אלא גם פרטים על אסטרטגיות המועמדות האחרות שהוערכו במהלך האופטימיזציה.
הדוגמה הבאה מציגה כיצד לקרוא מידע זה באמצעות pandas כדי לחלץ מדדי מפתח הקשורים לאסטרטגיה האופטימלית. אלה כוללים סטיית אילוץ, יחס Sharpe והתשואה המקבילה על ההשקעה.
# 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. ניתוח ביצועים
לבסוף, נתח את ביצועי יישום האופטימיזציה שלך. ספציפית, השווה את תוצאותיך, שהתקבלו בדוגמה הקודמת, מול קו בסיס אקראי כדי להעריך את יעילות הגישה שלנו. אם האלגוריתם הקוונטי מדגים באופן עקבי ומוכח תוצאות עם ערכי עלות נמוכים יותר, הדבר מצביע על תהליך אופטימיזציה יעיל.
האיור מציג את התפלגויות ההסתברות של עלויות המטרה. כדי לייצר התפלגויות אלה, קח את רשימת עלויות המטרה מתוצאת הפונקציה וספור את המופעים של כל ערך עלות (ערכים מעוגלים למקום העשרוני השני). לאחר מכן, עדכן את עמודת הספירה בהתאם על ידי חיבור ספירות של ערכים מעוגלים זהים. שים לב שלצורך השוואה חזותית טובה יותר, ספירות המופעים נורמלו כך שכל התפלגות מוצגת בין 0 ל-1.
כפי שמוצג באיור (הקו הכחול הרציף), התפלגות העלויות עבור גישת ה-VQE (Variational Quantum Eigensolver) שלנו (לאחר עיבוד עם SQD) מרוכזת בחדות בערכי עלות מטרה נמוכים, מה שמצביע על ביצועי אופטימיזציה טובים. לעומת זאת, קו הב סיס הרועש מציג התפלגות רחבה יותר, ממורכזת סביב ערכי עלות גבוהים יותר. הקו האנכי המקווקו האפור מייצג את ערך הממוצע של ההתפלגות האקראית, ומדגיש עוד יותר את עקביות הפונקציה בהחזרת אסטרטגיות השקעה אופטימליות. להשוואה נוספת, הקו המקווקו השחור באיור תואם לפתרון שהתקבל עם אופטימייזר Gurobi (גרסה חינמית). כל תוצאות אלה נחקרות עוד יותר ב-benchmarks הבאים עבור דוגמת ה-"Mixed Assets" שהוערכה עם ה-ansatz מסוג "Tailored".
Benchmarks
פונקציה זו נבדקה תחת תצורות שונות של Qubits רזולוציה, מעגלי ansatz וקיבוצים של נכסים ממגזרים שונים: תמהיל של נכסים שונים (סט 1), נגזרי נפט (סט 2) ו-IBEX35 (סט 3). ראה פרטים נוספים בטבלה הבאה.
| סט | תאריך | נכסים |
|---|---|---|
| סט 1 | 01/01/2023 | 8801.T, CL=F, GBPJPY=X, ITX.MC, META, TMBMKDE-10Y, XS2239553048 |
| סט 2 | 01/06/2023 | CL=F, BZ=F, HO=F, NG=F, XOM, RB=F, 2222.SR |
| סט 3 | 01/11/2022 | ACS.MC, ITX.MC, FER.MC, ELE.MC, SCYR.MC, AENA.MC, AMS.MC |
שני מדדי מפתח שימשו להערכת איכות הפתרון.
- עלות המטרה, המודדת יעילות אופטימיזציה על ידי השוואת ערך פונקציית העלות מכל ניסוי עם תוצאות Gurobi (גרסה חינמית).
- יחס Sharpe, הלוכד את התשואה המותאמת לסיכון של כל תיק השקעות, ומספק תובנה על הביצועים הפיננסיים של הפתרונו ת.
יחד, מדדים אלה מבצעים benchmark על ההיבטים החישוביים והפיננסיים כאחד של התיקים שנוצרו קוונטית.
| דוגמה | Qubits | Ansatz | עומק | שימוש Runtime (שנ') | שימוש כולל (שנ') | עלות מטרה | Sharpe | עלות מטרה Gurobi | Gurobi Sharpe |
|---|---|---|---|---|---|---|---|---|---|
| Mixed Assets (סט 1, 4 צעדי זמן, 4-bit) | 112 | Tailored | 83 | 12735 | 13095 | -3.78 | 24.82 | -4.25 | 24.71 |
| Mixed Assets (סט 1, 4 צעדי זמן, 4 צעדי זמן, 4-bit) | 112 | Real Amplitudes | 359 | 11739 | 11903 | -3.39 | 23.64 | -4.25 | 24.71 |
| Oil Derivatives (סט 2, 4 צעדי זמן, 3-bit) | 84 | Optimized Real Amplitudes | 78 | 6180 | 6350 | -3.73 | 19.13 | -4.19 | 21.71 |
| IBEX35 (סט 3, 4 צעדי זמן, 2-bit) | 56 | Optimized Real Amplitudes | 96 | 3314 | 3523 | -3.67 | 14.48 | -4.11 | 16.44 |
התוצאות מראות שהאופטימייזר הקוונטי, עם ansatzes ספציפיים לבעיה, מזהה ביעילות אסטרטגיות השקעה יעילות על פני סוגים שונים של תיקים.
להלן פירוט גודל האוכלוסייה ומספר הדורות שצוינו במילון optimizer_options. כל שאר הפרמטרים הוגדרו לערכי ברירת המחדל שלהם.
| דוגמה | population_size | num_generations |
|---|---|---|
| Mixed Assets Portfolio | 90 | 20 |
| Mixed Assets Portfolio | 92 | 20 |
| Oil Derivatives Portfolio | 120 | 20 |
| IBEX35 Portfolio | 40 | 20 |
מספר הדורות הוגדר ל-20, מאחר שנמצא שערך זה מספיק להגעה לכיול. בנוסף, ערכי ברירת המחדל עבור הפרמטרים הפנימיים של האופטימייזר נותרו ללא שינוי, מאחר שהם מספקים עקביות ביצועים טובים ומומלצים בדרך כלל על ידי הספרות והנחיות המימוש.
קבלת תמיכה
אם אתה זקוק לעזרה, תוכל לשלוח דוא"ל לכתובת qpo.support@globaldataquantum.com. במסרך, ספק את מזהה משרת הפונקציה.
צעדים הבאים
- קרא את המאמר המחקרי הנלווה.
-
- בקר ב-הפניית ה-API של פונקציית Qiskit זו.
- בקש גישה לפונקציה על ידי מילוי טופס זה.
- נסה את המדריך אופטימיזציה דינמית של תיק השקעות.