محسِّن المحفظة الكمية: دالة Qiskit من Global Data Quantum
دوال Qiskit ميزة تجريبية متاحة فقط لمستخدمي خطط IBM Quantum® Premium Plan وFlex Plan وOn-Prem (عبر IBM Quantum Platform API). وهي في مرحلة إصدار أولي وقابلة للتغيير.
نظرة عامة
محسِّن المحفظة الكمية هو دالة Qiskit تتعامل مع مشكلة تحسين المحفظة الديناميكية، وهي مشكلة معيارية في مجال التمويل تهدف إلى إعادة توازن الاستثمارات الدورية عبر مجموعة من الأصول بما يعظّم العائدات ويقلّل المخاطر. وبالاستعانة بأحدث تقنيات التحسين الكمي، تبسّط هذه الدالة العملية بحيث يتمكن المستخدمون، حتى من ليس لديهم خبرة في الحوسبة الكمية، من الاستفادة من مزاياها في إيجاد مسارات استثمارية مثلى. إنها أداة مثالية لمديري المحافظ والباحثين في مجال التمويل الكمي والمستثمرين الأفراد، إذ تتيح اختبار استراتيجيات التداول في مجال تحسين المحافظ بصورة رجعية.
وصف الدالة
تستخدم دالة محسِّن المحفظة الكمية خوارزمية Variational Quantum Eigensolver (VQE) لحل مشكلة Quadratic Unconstrained Binary Optimization (QUBO)، بما يعالج مشكلات تحسين المحفظة الديناميكية. يكتفي المستخدمون بتوفير بيانات أسعار الأصول وتحديد قيد الاستثمار، ثم تُشغّل الدالة عملية التحسين الكمي التي تُعيد مجموعة من مسارات الاستثمار المثلى.
تتألف العملية من أربع مراحل رئيسية. أولاً، يُحوَّل البيان المُدخَل إلى مشكلة متوافقة مع الحوسبة الكمية بإنشاء QUBO لمشكلة تحسين المحفظة الديناميكية وتحويله إلى عامل كمي (Ising Hamiltonian). بعد ذلك، يُكيَّف البيان المُدخَل وخوارزمية VQE للتشغيل على الأجهزة ا لكمية. ثم تُشغَّل خوارزمية VQE على الأجهزة الكمية، وأخيراً تُعالَج النتائج لاستخراج مسارات الاستثمار المثلى. يتضمّن النظام أيضاً معالجةً لاحقةً مدركةً للضجيج (مستندةً إلى 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 | قائمة بمعرّفات الجلسات لاسترجاع البيانات من تشغيلات سابقة (*) | لا | قائمة فارغة | ["session_id_1", "session_id_2"] |
| apply_postprocess | bool | تطبيق المعالجة اللاحقة المدركة للضجيج باستخدام SQD | لا | True | True |
| tags | list of strings | قائمة بالوسوم للتعريف بالتجربة | لا | قائمة فارغة | ["optimization", "quantum_computing"] |
لاستئناف تنفيذ أو استرداد وظائف جرت معالجتها في جلسة أو أكثر من الجلسات السابقة، يجب تمرير قائمة معرّفات الجلسات في معامل 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 وعدد Qubit الدقة nq وقيمة max_investment — أو بتغيير القيم الافتراضية الأخرى.
| الاسم | النوع | الوصف | مطلوب | الافتراضي | مثال |
|---|---|---|---|---|---|
| nt | int | عدد الخطوات الزمنية | نعم | - | 4 |
| nq | int | عدد Qubit الدقة | نعم | - | 4 |
| max_investment | float | الحد الأقصى لعدد وحدات العملة المستثمرة عبر جميع الأصول | نعم | - | 10 |
| dt* | int | النافذة الزمنية المُعتبَرة في كل خطوة زمنية. الوحدة تتطابق مع الفترات الزمنية بين المفاتيح في بيانات الأصول | لا | 30 | - |
| risk_aversion | float | معامل النفور من المخاطرة | لا | 1000 | - |
| transaction_fee | float | معامل رسوم المعاملة | لا | 0.01 | - |
| restriction_coeff | float | مضاعف لاغرانج المستخدم لفرض قيد المشكلة ضمن صياغة 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 | يضيف Dynamical Decoupling | لا | False |
* الـ ansatz المتاحة
real_amplitudescyclicoptimized_real_amplitudestailored(متاح فقط لـibm_torinobackend، و7 أصول، و4 خطوات زمنية، و4 Qubit دقة)
** إذا كان multiple_passmanager مضبوطاً على False، تستخدم الدالة مدير التمرير الافتراضي لـ Qiskit مع optimization_level=3. أما إذا كان مضبوطاً على True، فإن روتين multiple_passmanager يقارن بين ثلاثة مديري تمرير: مدير التمرير الافتراضي السابق لـ Qiskit، ومدير تمرير يُعيِّن الـ Qubit على سلسلة الجيران الأولى لوحدة QPU، وخدمات AI transpiler. ثم يُختار مدير التمرير ذو الخطأ التراكمي المُقدَّر الأدنى.
optimizer_settings
هذا المعامل هو قاموس يحتوي على بعض الخيارات القابلة للضبط في عملية التحسين.
| الاسم | النوع | الوصف | مطلوب | الافتراضي |
|---|---|---|---|---|
| primitive_options | json | إعدادات العنصر الأساسي (primitive) | لا | - |
| optimizer | str | المُحسِّن الكلاسيكي المختار | لا | "differential_evolution" |
| optimizer_options | json | تكوين المُحسِّن | لا | - |
حالياً، خيار المُحسِّن الوحيد المتاح هو "differential_evolution".
نضبط تحت مفاتيح primitive_options وoptimizer_options قواميساً بالمعاملات التالية:
primitive_options
| الاسم | النوع | الوصف | مطلوب | الافتراضي | مثال |
|---|---|---|---|---|---|
| sampler_shots | int | عدد لقطات الـ Sampler. | لا | 100000 | - |
| estimator_shots | int | عدد لقطات الـ Estimator. | لا | 25000 | - |
| estimator_precision | float | الدقة المطلوبة للقيمة المتوقعة. إذا حُدِّدت، ستُستخدَم الدقة بدلاً من estimator_shots. | لا | None | 0.015625 · (1 / sqrt(4096)) |
| max_time | int أو str | الحد الأقصى لوقت بقاء جلسة التشغيل مفتوحة قبل إغلاقها قسراً. يمكن تحديده بالثواني (int) أو كسلسلة نصية مثل "2h 30m 40s". يجب أن يكون أقل من الحد الأقصى المفروض من النظام. | لا | None | "1h 15m" |
optimizer_options
| الاسم | النوع | الوصف | مطلوب | الافتراضي |
|---|---|---|---|---|
| num_generations | int | عدد الأجيال | لا | 20 |
| population_size | int | حجم المجتمع (population) | لا | 20 |
| mutation_range | list | الحد الأقصى والأدنى لمعامل الطفرة | لا | [0, 0.25] |
| recombination | float | معامل إعادة التركيب | لا | 0.4 |
| max_parallel_jobs | int | الحد الأقصى لعدد وظائف QPU المنفَّذة بالتوازي | لا | 3 |
| max_batchsize | int | الحد الأقصى لحجم الدُّفعة (batch) | لا | 200 |
-
عدد الأجيال التي يُقيِّمها التطور التفاضلي هو
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] | قاموس مفاتيحه تمثيلات بتية لحلول مُعيَّنة وقيمه عدد تكراراتها. | {"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] | الأداء المُعدَّل وفق المخاطرة (نسبة شارب) لكل مسار استثماري. مُوافِق للفهرس. | [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) وضبط إعداداتها للحصول على أفضل أداء ممكن. ويتضمّن خطوات تفصيلية لضبط المعاملات بدقة لتحقيق النتائج المطلوبة.
يتناول هذا المثال سبعة أصول، وأربع خطوات زمنية، وأربعة كيوبتات للدقة، مما يستلزم إجمالاً 112 كيوبت.
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. (اختياري)
يمكنك اختياريًا تحديد متطلبات خاصة لعملية التحسين، تشمل اختيار المُحسِّن ومعاملاته، فضلاً عن تحديد البدائي وإعداداته.
بالنسبة إلى Tailored Ansatz، استُند في اختيار حجم المجتمع إلى تجارب سابقة أثبتت أن هذه القيمة تُنتج تحسينًا مستقرًا وفعّالًا.
أما في حالة Real Amplitudes Ansatz، يمكنك اتّباع علاقة خطية بين population_size وعدد الكيوبتات في الدائرة. كقاعدة تقريبية، يُنصح باستخدام حد أدنى population_size ~ 0.8 * n_qubits للـ real_amplitudes ansatz.
من المتوقع أن يُحقق Optimized Real Amplitudes أداءً أفضل في التحسين مقارنةً بـ Real Amplitudes ansatz. غير أن عدد المتغيرات المطلوب تحسينها في هذا الـ ansatz يتزايد بوتيرة أسرع بكثير مقارنةً بحالة Real Amplitudes (راجع المخطوطة). لذا، في المسائل الكبيرة، يستلزم Optimized Real Amplitudes تنفيذ دوائر أكثر. ومن المرجّح أن يكون Optimized Real Amplitudes مفيدًا للمسائل التي تتطلب حتى 100 كيوبت، إلا أنه يُوصى بالحذر عند ضبط معاملات population_size. وكمثال على هذا التوسّع في population_size، يتّضح من الجدول السابق أن مسألة من 84 كيوبت تستلزم population_size مقداره 120 في Optimized Real Amplitudes، بينما تكفي قيمة population_size مقدارها 40 لمسألة من 56 كيوبت.
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 محدد. يستخدم المثال التالي الـ 'Tailored' ansatz.
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 لاستخراج المقاييس الرئيسية المرتبطة بالاستراتيجية المثلى. وتشمل هذه المقاييس: انحراف القيد، ونسبة شارب، وعائد الاستثمار المقابل.
# 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.
كما يتضح من الشكل (الخط الأزرق المتصل)، يتركّز توزيع التكلفة لنهجنا القائم على Variational Quantum Eigensolver (المعالَج بعد التنفيذ باستخدام SQD) بشكل حاد عند قيم تكلفة هدف أدنى، مما يدل على أداء تحسيني جيد. في المقابل، يُظهر خط الأساس الضوضائي توزيعًا أوسع يتمحور حول قيم تكلفة أعلى. يمثّل الخط الرمادي المتقطع العمودي متوسط قيمة التوزيع العشوائي، مما يبرز أكثر اتساق الدالة في إعادة استراتيجيات استثمار محسَّنة. وللمزيد من المقارنة، يتوافق الخط الأسود المتقطع في الشكل مع الحل المحصّل بواسطة مُحسِّن Gurobi (النسخة المجانية). تُستكشف جميع هذه النتائج بمزيد من التفصيل في المعايير المرجعية أدناه لمثال "الأصول المختلطة" المُقيَّم باستخدام الـ "Tailored" ansatz.
المعايير المرجعية
جرى اختبار هذه الدالة تحت تكوينات مختلفة من كيوبتات الدقة ودوائر الـ 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 (النسخة المجانية).
- نسبة شارب، التي تلتقط العائد المعدَّل بالمخاطر لكل محفظة، مما يوفّر رؤية حول الأداء المالي للحلول.
يقيس كلا المقياسين معًا الجوانب الحسابية والمالية للمحافظ المولَّدة كميًا كمعيار مرجعي.
| المثال | الكيوبتات | الـ Ansatz | العمق | استخدام وقت التشغيل (ث) | إجمالي الاستخدام (ث) | تكلفة الهدف | شارب | تكلفة هدف Gurobi | شارب Gurobi |
|---|---|---|---|---|---|---|---|---|---|
| أصول مختلطة (المجموعة 1، 4 خ طوات زمنية، 4 بت) | 112 | Tailored | 83 | 12735 | 13095 | -3.78 | 24.82 | -4.25 | 24.71 |
| أصول مختلطة (المجموعة 1، 4 خطوات زمنية، 4 خطوات زمنية، 4 بت) | 112 | Real Amplitudes | 359 | 11739 | 11903 | -3.39 | 23.64 | -4.25 | 24.71 |
| مشتقات النفط (المجموعة 2، 4 خطوات زمنية، 3 بت) | 84 | Optimized Real Amplitudes | 78 | 6180 | 6350 | -3.73 | 19.13 | -4.19 | 21.71 |
| IBEX35 (المجموعة 3، 4 خطوات زمنية، 2 بت) | 56 | Optimized Real Amplitudes | 96 | 3314 | 3523 | -3.67 | 14.48 | -4.11 | 16.44 |
تُظهر النتائج أن المُحسِّن الكمومي، باستخدام الـ ansatz المتخصص في المسألة، يُحدّد بفعالية استراتيجيات استثمارية كفؤة عبر أنواع محافظ مختلفة.
نُفصّل أدناه كلًا من حجم المجتمع وعدد الأجيال المحددَين في قاموس optimizer_options. وقد جرى ضبط جميع المعاملات الأخرى على قيمها الافتراضية.
| المثال | population_size | num_generations |
|---|---|---|
| محفظة الأصول المختلطة | 90 | 20 |
| محفظة الأصول المختلطة | 92 | 20 |
| محفظة مشتقات النفط | 120 | 20 |
| محفظة IBEX35 | 40 | 20 |
تم ضبط عدد الأجيال على 20، إذ تبيّن أن هذه القيمة كافية للوصول إلى التقارب. علاوة على ذلك، تُركت القيم الافتراضية للمعاملات الداخلية للمُحسِّن دون تغيير، نظرًا لأنها أبدت أداءً جيدًا باستمرار وهي موصى بها عمومًا في الأدبيات وإرشادات التطبيق.
الحصول على الدعم
إذا كنت بحاجة إلى مساعدة، يمكنك إرسال بريد إلكتروني إلى qpo.support@globaldataquantum.com. في رسالتك، أدرج معرّف وظيفة الدالة.
الخطوات التالية
- اقرأ ورقة البحث المرتبطة.
- اطلب الوصول إلى الدالة عن طريق ملء هذا النموذج.
- جرّب درس تحسين المحفظة الاستثمارية الديناميكي.