Quantum Portfolio Optimizer: פונקציית Qiskit מאת Global Data Quantum
פונקציות 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.
קלט
ארגומנטי הקלט של הפונקציה מתוארים בטבלה הבאה. יש לספק את נתוני הנכסים ומפרטי הבעיה האחרים; בנוסף, ניתן לכלול הגדרות VQE להתאמה אישית של תהליך האופטימיזציה.
| שם | סוג | תיאור | נדרש | ברירת מחדל | דוגמה |
|---|---|---|---|---|---|
| assets | json | מילון עם מחירי הנכסים | כן | - | - |
| qubo_settings | json | הגדרות ה-QUBO | כן | - | ראה דוגמאות בטבלה למטה |
| ansatz_settings | json | הגדרות ה-ansatz | לא | None | ראה דוגמאות בטבלה למטה. |
| optimizer_settings | json | הגדרות האופטימייזר | לא | None | ראה דוגמאות בטבלה למטה. |
| backend | str | שם ה-Backend של QPU | לא | - | "ibm_torino" |
| previous_session_id | list of str | רשימת מזהי sessions לשליפת נתונים מריצות קודמות(*) | לא | רשימה ריקה | ["session_id_1", "session_id_2"] |
| apply_postprocess | bool | החלת עיבוד לאחור SQD מודע-רעש | לא | True | True |
| tags | list of strings | רשימת תגיות לזיהוי הניסוי | לא | רשימה ריקה | ["optimization", "quantum_computing"] |
*כדי לחדש הרצה או לשלוף משרות שעובדו בסשן אחד או יותר קודמים, יש להעביר את רשימת מזהי ה-sessions בפרמטר previous_session_id. שימושי במיוחד כאשר משימת אופטימיזציה לא הושלמה עקב שגיאה כלשהי, וצריך להמשיך את ההרצה. לשם כך, יש לספק את אותם ארגומנטים שהועברו בהרצה הראשונית, יחד עם רשימת previous_session_id כפי שמתואר.
טעינת נתונים מסשנים קודמים (לצורך חידוש אופטימיזציה) עלולה להימשך עד שעה.
assets
הנתונים חייבים להיות מובנים כאובייקט JSON המאחסן מידע על מחירי הסגירה של נכסים פיננסיים בתאריכים ספציפיים. הפורמט הוא כדלקמן:
- מפתח ראשי (מחרוזת): שם הנכס הפיננסי או סמל הטיקר שלו (לדוגמה, "8801.T").
- מפתח משני (מחרוזת): התאריך בפורמט YYYY-MM-DD.
- ערך (מספר): מחיר הסגירה של הנכס בתאריך הנתון. ניתן להזין מחירים מנורמלים או לא מנורמלים.
שים לב שכל המילונים חייבים להיות בעלי אותו מפתח משני (תאריכים). אם נכס מסוים חסר תאריך שיש לנכסים אחרים, יש למלא את הנתונים כדי להבטיח עקביות. לדוגמה, ניתן לעשות זאת על ידי שימוש במחיר הסגירה האחרון שנרשם עבור אותו נכס.
דוגמה
{
"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,
...
},
...
}
נתוני הנכסים חייבים להכיל לפחות את מחירי הסגירה ב-(nt+1) * dt (ראה את חלק הקלט של qubo_settings) חותמות זמן (לדוגמה, ימים).
qubo_settings
הטבלה הבאה מתארת את המפתחות של מילון qubo_settings. בנה את המילון תוך ציון מספר צעדי הזמן nt, מספר ה-Qubits של הרזולוציה nq, וה-max_investment — או שנה ערכי ברירת מחדל אחרים.
| שם | סוג | תיאור | נדרש | ברירת מחדל | דוגמה |
|---|---|---|---|---|---|
| nt | int | מספר צעדי הזמן | כן | - | 4 |
| nq | int | מספר ה-Qubits של הרזולוציה | כן | - | 4 |
| max_investment | float | מספר מקסימלי של יחידות מטבע מושקעות על פני כל הנכסים | כן | - | 10 |
| dt* | int | חלון הזמן הנלקח בחשבון בכל צעד זמן. היחידה תואמת את מרווחי הזמן שבין המפתחות בנתוני הנכסים | לא | 30 | - |
| risk_aversion | float | מקדם שנאת סיכון | לא | 1000 | - |
| transaction_fee | float | מקדם עמלת עסקה | לא | 0.01 | - |
| restriction_coeff | float | מכפיל Lagrange המשמש לאכיפת אילוץ הבעיה בתוך ניסוח ה-QUBO | לא | 1 | - |
ansatz_settings
כדי לשנות את אפשרויות ברירת המחדל, צור מילון עבור פרמטר ansatz_settings עם המפתחות הבאים. כברירת מחדל, ה-ansatz מוגדר ל-"real_amplitudes", ושתי האפשרויות הנוספות (ראה טבלה הבאה) מוגדרות ל-False.
| שם | סוג | תיאור | נדרש | ברירת מחדל |
|---|---|---|---|---|
| ansatz* | str | ה-Ansatz שישמש | לא | "real_amplitudes" |
| multiple_passmanager** | bool | מאפשר תת-שגרת passmanager מרובה (לא זמין ל-Tailored ansatz) | לא | False |
| dd_enable | bool | מוסיף decoupling דינמי | לא | False |
* Ansatzes זמינים
real_amplitudescyclicoptimized_real_amplitudestailored(רק ל-Backend שלibm_torino, 7 נכסים, 4 צעדי זמן ו-4 Qubits רזולוציה)
** אם multiple_passmanager מוגדר ל-False, הפונקציה משתמשת ב-pass manager ברירת המחדל של Qiskit עם optimization_level=3. אם מוגדר ל-True, תת-השגרה multiple_passmanager משווה בין שלושה pass managers: ה-pass manager ברירת המחדל הקודם של Qiskit, pass manager הממפה Qubits על שרשרת שכנים ראשונים של ה-QPU, ושירותי ה-AI transpiler. לאחר מכן נבחר ה-pass manager עם שגיאה צבורה מוערכת נמוכה יותר.
optimizer_settings
פרמטר זה הוא מילון עם כמה אפשרויות כוונון של תהליך האופטימיזציה.
| שם | סוג | תיאור | נדרש | ברירת מחדל |
|---|---|---|---|---|
| primitive_options | json | הגדרות ה-primitive | לא | - |
| optimizer | str | האופטימייזר הקלאסי שנבחר | לא | "differential_evolution" |
| optimizer_options | json | תצורת האופטימייזר | לא | - |
כרגע, אפשרות האופטימייזר היחידה הזמינה היא "differential_evolution".
תחת המפתחות primitive_options ו-optimizer_options מגדירים מילונים עם הפרמטרים הבאים:
primitive_options
| שם | סוג | תיאור | נדרש | ברירת מחדל | דוגמה |
|---|---|---|---|---|---|
| sampler_shots | int | מספר ה-shots של ה-Sampler. | לא | 100000 | - |
| estimator_shots | int | מספר ה-shots של ה-Estimator. | לא | 25000 | - |
| estimator_precision | float | הדיוק הרצוי של הערך הצפוי. אם מצוין, הדיוק ישמש במקום estimator_shots. | לא | None | 0.015625 · (1 / sqrt(4096)) |
| max_time | int or str | משך הזמן המקסימלי שסשן runtime יכול להישאר פתוח לפני סגירה כפויה. ניתן לתת בשניות (int) או כמחרוזת, כמו "2h 30m 40s". חייב להיות פחות מהמקסימום שמוטל על ידי המערכת. | לא | None | "1h 15m" |
optimizer_options
| שם | סוג | תיאור | נדרש | ברירת מחדל |
|---|---|---|---|---|
| num_generations | int | מספר הדורות | לא | 20 |
| population_size | int | גודל האוכלוסייה | לא | 20 |
| mutation_range | list | מקדם מוטציה מקסימלי ומינימלי | לא | [0, 0.25] |
| recombination | float | מקדם שילוב מחדש | לא | 0.4 |
| max_parallel_jobs | int | מספר מקסימלי של משרות QPU המורצות במקביל | לא | 3 |
| max_batchsize | int | גודל batch מקסימלי | לא | 200 |
-
מספר הדורות שמוערכים על ידי ה-differential evolution הוא
num_generations+ 1 מאחר שהאוכלוסייה הראשונית נכללת. -
המספר הכולל של המעגלים מחושב כ-
(num_generations + 1) * population_size. -
שימוש בגודל אוכלוסייה גדול יותר ויותר דורות משפר בדרך כלל את איכות תוצאות האופטימיזציה. עם זאת, לא מומלץ לחרוג מגודל אוכלוסייה של 120 ומספר דורות הגדול מ-20 (לדוגמה,
120 * 21 = 2520מעגלים כולל), שכן זה יגרום למספר מופרז של מעגלים, שעלול להיות יקר מבחינה חישובית ודורש זמן עיבוד רב. -
הפונקציה מאפשרת לך לחדש אופטימיזציה קודמת, ותמיד ניתן להגדיל את מספר הדורות (על ידי מתן אותו הקלט פרט ל-
previous_session_idו-num_generationsמוגדל).
ודא עמידה במגבלות משרות Qiskit Runtime.
- Sampler:
sampler_shots <= 10_000_000. - Estimator:
max_batchsize * estimator_shots * observable_size <= 10_000_000(עבור פונקציה זו, כל איברי ה-observable מתחלפים, כך ש-observable_size=1).
ראה את המדריך מגבלות משרה לפרטים נוספים.
פלט
הפונקציה מחזירה שני מילונים: מילון "result", המכיל את תוצאות האופטימיזציה הטובות ביותר, כולל הפתרון האופטימלי ועלות המטרה המינימלית הנלווית אליו; ו-"metadata", עם נתונים מכל התוצאות שהתקבלו במהלך תהליך האופטימיזציה, יחד עם המדדים שלהן.
המילון הראשון מתמקד בפתרון בעל הביצועים הטובים ביותר, בעוד השני מספק מידע מפורט על כל הפתרונות, כולל עלויות מטרה ומדדים רלוונטיים אחרים.
מילוני פלט:
| שם | סוג | תיאור | דוגמה |
|---|---|---|---|
| result | dict[str, dict[str, float]] | מכיל את אסטרטגיית ההשקעה לאורך זמן, כשכל חותמת זמן ממופה למשקלות השקעה ספציפיות לנכסים (כל משקל הוא סכום ההשקעה מנורמל לפי סך ההשקעה הכולל). | {'time_1': {'asset_1': 0.2, 'asset_2': 0.3, ...\}, ...\} |
| metadata | dict[str, Any] | נתונים שנוצרו במהלך הניתוח, כולל פתרונות, עלויות ומדדים. | ראה דוגמאות למטה |
תיאור מילון ה-metadata
| שם | סוג | תיאור | דוגמה |
|---|---|---|---|
| session_id | str | מזהה ייחודי לסשן IBM Quantum. | "d0h30qjvpqf00084fgw0" |
| all_samples_metrics | dict | מילון המכיל מדדים שונים לכל דגימה שעברה עיבוד לאחור, כגון עלויות או אילוצים. | ראה תיאור למטה |
| sampler_counts | dict[str, int] | מילון שבו המפתחות הם ייצוגי bitstring של פתרונות שנדגמו והערכים הם המספרים שלהם. | {"101010": 3, "111000": 1\} |
| asset_order | list[str] | רשימה עם סדר ההשקעה המתאים של הנכסים בכל צעד זמן בתוך אסטרטגיות ההשקעה. | ["Asset_0", "Asset_1", "Asset_3"] |
| QUBO | list[list[float]] | מטריצת ה-QUBO של הבעיה. | [[-6.96e-01, 5.81e-01, -1.26e-02, 0.00e+00], ...] |
| resource_summary | dict[str, dict[str, float]] | סיכום זמני שימוש ב-CPU וב-QPU (בשניות) על פני שלבים שונים של התהליך. | {'RUNNING: EXECUTING_QPU': {'CPU_TIME': 412.84, 'QPU_TIME': 87.22\}, ...\} |
תיאור מילון ה-all_samples_metrics
| שם | סוג | תיאור | דוגמה |
|---|---|---|---|
| investment_trajectories | list[list] | אסטרטגיות השקעה הנגזרות ממצבים קוונטיים מפוענחים. | [[1, 2, 2], [1, 2, 1]] |
| counts | list[int] | מספר הפעמים שכל מסלול השקעה נדגם. האינדקס תואם ל-investment_trajectories. | [5, 3] |
| objective_costs | list[float] | ערך פונקציית המטרה עבור כל מסלול השקעה, מסודר מהנמוך לגבוה. | [0.98, 1.25] |
| sharpe_ratios | list[float] | ביצועים מותאמי סיכון (יחס Sharpe) עבור כל מסלול השקעה. מיושר לפי אינדקס. | [1.1, 0.7] |
| returns | list[float] | תשואה צפויה עבור כל מסלול השקעה. מיושר לפי אינדקס. | [0.15, 0.10] |
| rest_breaches | list[float] | סטייה מקסימלית מהאילוץ בתוך כל מסלול השקעה. מיושר לפי אינדקס. | [0.0, 0.25] |
| transaction_costs | list[float] | עלות עסקה משוערת הקשורה לכל מסלול השקעה. מיושר לפי אינדקס. | [0.01, 0.02] |
התח לה
בצע אימות באמצעות מפתח ה-API שלך ובחר את פונקציית Qiskit כדלקמן. (קטע קוד זה מניח שכבר שמרת את חשבונך בסביבה המקומית שלך.)
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. שלוף תוצאות.
כאמור בחלק הפלט, הפונקציה מחזירה מילון עם מסלולי ההשקעה מסודרים מהנמוך לגבוה בהתאם לערך פונקציית המטרה שלהם. קבוצת תוצאות זו מאפשרת לזהות את המסלול בעל העלות הנמוכה ביותר והערכות ההשקעה המתאימות לו. בנוסף, היא מספקת ניתוח של מסלולים שונים, מה שמקל על בחירת אלה המתאימים ביותר לצרכים או למטרות ספציפיות. גמישות זו מבטיחה שניתן להתאים את הבחירות לסוגים שונים של העדפות או תרחישים. התחל בהצגת אסטרטגיית התוצאות שהשיגה את עלות המטרה הנמוכה ביותר שנמצאה במהלך התהליך.
# 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. במסרך, ספק את מזהה משרת הפונקציה.
צעדים הבאים
- קרא את המאמר המחקרי הנלווה.
- בקש גישה לפונקציה על ידי מילוי טופס זה.
- נסה את המדריך אופטימיזציה דינמית של תיק השקעות.