דלג לתוכן הראשי

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 להתאמה אישית של תהליך האופטימיזציה.

שםסוגתיאורנדרשברירת מחדלדוגמה
assetsjsonמילון עם מחירי הנכסיםכן--
qubo_settingsjsonהגדרות ה-QUBOכן-ראה דוגמאות בטבלה למטה
ansatz_settingsjsonהגדרות ה-ansatzלאNoneראה דוגמאות בטבלה למטה.
optimizer_settingsjsonהגדרות האופטימייזרלאNoneראה דוגמאות בטבלה למטה.
backendstrשם ה-Backend של QPUלא-"ibm_torino"
previous_session_idlist of strרשימת מזהי sessions לשליפת נתונים מריצות קודמות(*)לארשימה ריקה["session_id_1", "session_id_2"]
apply_postprocessboolהחלת עיבוד לאחור SQD מודע-רעשלאTrueTrue
tagslist 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 — או שנה ערכי ברירת מחדל אחרים.

שםסוגתיאורנדרשברירת מחדלדוגמה
ntintמספר צעדי הזמןכן-4
nqintמספר ה-Qubits של הרזולוציהכן-4
max_investmentfloatמספר מקסימלי של יחידות מטבע מושקעות על פני כל הנכסיםכן-10
dt*intחלון הזמן הנלקח בחשבון בכל צעד זמן. היחידה תואמת את מרווחי הזמן שבין המפתחות בנתוני הנכסיםלא30-
risk_aversionfloatמקדם שנאת סיכוןלא1000-
transaction_feefloatמקדם עמלת עסקהלא0.01-
restriction_coefffloatמכפיל Lagrange המשמש לאכיפת אילוץ הבעיה בתוך ניסוח ה-QUBOלא1-

ansatz_settings

כדי לשנות את אפשרויות ברירת המחדל, צור מילון עבור פרמטר ansatz_settings עם המפתחות הבאים. כברירת מחדל, ה-ansatz מוגדר ל-"real_amplitudes", ושתי האפשרויות הנוספות (ראה טבלה הבאה) מוגדרות ל-False.

שםסוגתיאורנדרשברירת מחדל
ansatz*strה-Ansatz שישמשלא"real_amplitudes"
multiple_passmanager**boolמאפשר תת-שגרת passmanager מרובה (לא זמין ל-Tailored ansatz)לאFalse
dd_enableboolמוסיף decoupling דינמילאFalse

* Ansatzes זמינים

  • real_amplitudes
  • cyclic
  • optimized_real_amplitudes
  • tailored (רק ל-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_optionsjsonהגדרות ה-primitiveלא-
optimizerstrהאופטימייזר הקלאסי שנבחרלא"differential_evolution"
optimizer_optionsjsonתצורת האופטימייזרלא-
הערה

כרגע, אפשרות האופטימייזר היחידה הזמינה היא "differential_evolution".

תחת המפתחות primitive_options ו-optimizer_options מגדירים מילונים עם הפרמטרים הבאים:

primitive_options

שםסוגתיאורנדרשברירת מחדלדוגמה
sampler_shotsintמספר ה-shots של ה-Sampler.לא100000-
estimator_shotsintמספר ה-shots של ה-Estimator.לא25000-
estimator_precisionfloatהדיוק הרצוי של הערך הצפוי. אם מצוין, הדיוק ישמש במקום estimator_shots.לאNone0.015625 · (1 / sqrt(4096))
max_timeint or strמשך הזמן המקסימלי שסשן runtime יכול להישאר פתוח לפני סגירה כפויה. ניתן לתת בשניות (int) או כמחרוזת, כמו "2h 30m 40s". חייב להיות פחות מהמקסימום שמוטל על ידי המערכת.לאNone"1h 15m"

optimizer_options

שםסוגתיאורנדרשברירת מחדל
num_generationsintמספר הדורותלא20
population_sizeintגודל האוכלוסייהלא20
mutation_rangelistמקדם מוטציה מקסימלי ומינימלילא[0, 0.25]
recombinationfloatמקדם שילוב מחדשלא0.4
max_parallel_jobsintמספר מקסימלי של משרות QPU המורצות במקביללא3
max_batchsizeintגודל 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", עם נתונים מכל התוצאות שהתקבלו במהלך תהליך האופטימיזציה, יחד עם המדדים שלהן.

המילון הראשון מתמקד בפתרון בעל הביצועים הטובים ביותר, בעוד השני מספק מידע מפורט על כל הפתרונות, כולל עלויות מטרה ומדדים רלוונטיים אחרים.

מילוני פלט:

שםסוגתיאורדוגמה
resultdict[str, dict[str, float]]מכיל את אסטרטגיית ההשקעה לאורך זמן, כשכל חותמת זמן ממופה למשקלות השקעה ספציפיות לנכסים (כל משקל הוא סכום ההשקעה מנורמל לפי סך ההשקעה הכולל).{'time_1': {'asset_1': 0.2, 'asset_2': 0.3, ...\}, ...\}
metadatadict[str, Any]נתונים שנוצרו במהלך הניתוח, כולל פתרונות, עלויות ומדדים.ראה דוגמאות למטה

תיאור מילון ה-metadata

שםסוגתיאורדוגמה
session_idstrמזהה ייחודי לסשן IBM Quantum."d0h30qjvpqf00084fgw0"
all_samples_metricsdictמילון המכיל מדדים שונים לכל דגימה שעברה עיבוד לאחור, כגון עלויות או אילוצים.ראה תיאור למטה
sampler_countsdict[str, int]מילון שבו המפתחות הם ייצוגי bitstring של פתרונות שנדגמו והערכים הם המספרים שלהם.{"101010": 3, "111000": 1\}
asset_orderlist[str]רשימה עם סדר ההשקעה המתאים של הנכסים בכל צעד זמן בתוך אסטרטגיות ההשקעה.["Asset_0", "Asset_1", "Asset_3"]
QUBOlist[list[float]]מטריצת ה-QUBO של הבעיה.[[-6.96e-01, 5.81e-01, -1.26e-02, 0.00e+00], ...]
resource_summarydict[str, dict[str, float]]סיכום זמני שימוש ב-CPU וב-QPU (בשניות) על פני שלבים שונים של התהליך.{'RUNNING: EXECUTING_QPU': {'CPU_TIME': 412.84, 'QPU_TIME': 87.22\}, ...\}

תיאור מילון ה-all_samples_metrics

שםסוגתיאורדוגמה
investment_trajectorieslist[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). ראה פרטים נוספים בטבלה הבאה.

סטתאריךנכסים
סט 101/01/20238801.T, CL=F, GBPJPY=X, ITX.MC, META, TMBMKDE-10Y, XS2239553048
סט 201/06/2023CL=F, BZ=F, HO=F, NG=F, XOM, RB=F, 2222.SR
סט 301/11/2022ACS.MC, ITX.MC, FER.MC, ELE.MC, SCYR.MC, AENA.MC, AMS.MC

שני מדדי מפתח שימשו להערכת איכות הפתרון.

  1. עלות המטרה, המודדת יעילות אופטימיזציה על ידי השוואת ערך פונקציית העלות מכל ניסוי עם תוצאות Gurobi (גרסה חינמית).
  2. יחס Sharpe, הלוכד את התשואה המותאמת לסיכון של כל תיק השקעות, ומספק תובנה על הביצועים הפיננסיים של הפתרונות.

יחד, מדדים אלה מבצעים benchmark על ההיבטים החישוביים והפיננסיים כאחד של התיקים שנוצרו קוונטית.

דוגמהQubitsAnsatzעומקשימוש Runtime (שנ')שימוש כולל (שנ')עלות מטרהSharpeעלות מטרה GurobiGurobi Sharpe
Mixed Assets (סט 1, 4 צעדי זמן, 4-bit)112Tailored831273513095-3.7824.82-4.2524.71
Mixed Assets (סט 1, 4 צעדי זמן, 4 צעדי זמן, 4-bit)112Real Amplitudes3591173911903-3.3923.64-4.2524.71
Oil Derivatives (סט 2, 4 צעדי זמן, 3-bit)84Optimized Real Amplitudes7861806350-3.7319.13-4.1921.71
IBEX35 (סט 3, 4 צעדי זמן, 2-bit)56Optimized Real Amplitudes9633143523-3.6714.48-4.1116.44

התוצאות מראות שהאופטימייזר הקוונטי, עם ansatzes ספציפיים לבעיה, מזהה ביעילות אסטרטגיות השקעה יעילות על פני סוגים שונים של תיקים. להלן פירוט גודל האוכלוסייה ומספר הדורות שצוינו במילון optimizer_options. כל שאר הפרמטרים הוגדרו לערכי ברירת המחדל שלהם.

דוגמהpopulation_sizenum_generations
Mixed Assets Portfolio9020
Mixed Assets Portfolio9220
Oil Derivatives Portfolio12020
IBEX35 Portfolio4020

מספר הדורות הוגדר ל-20, מאחר שנמצא שערך זה מספיק להגעה לכיול. בנוסף, ערכי ברירת המחדל עבור הפרמטרים הפנימיים של האופטימייזר נותרו ללא שינוי, מאחר שהם מספקים עקביות ביצועים טובים ומומלצים בדרך כלל על ידי הספרות והנחיות המימוש.

קבלת תמיכה

אם אתה זקוק לעזרה, תוכל לשלוח דוא"ל לכתובת qpo.support@globaldataquantum.com. במסרך, ספק את מזהה משרת הפונקציה.

צעדים הבאים

המלצות