انتقل إلى المحتوى الرئيسي

محسِّن المحفظة الكمية: دالة 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 لتخصيص عملية التحسين.

الاسمالنوعالوصفمطلوبالافتراضيمثال
assetsjsonقاموس بأسعار الأصولنعم--
qubo_settingsjsonإعدادات QUBOنعم-انظر الأمثلة في الجدول أدناه
ansatz_settingsjsonإعدادات الـ ansatzلاNoneانظر الأمثلة في الجدول أدناه.
optimizer_settingsjsonإعدادات المُحسِّنلاNoneانظر الأمثلة في الجدول أدناه.
backendstrاسم Backend وحدة QPUلا-"ibm_torino"
previous_session_idlist of strقائمة بمعرّفات الجلسات لاسترجاع البيانات من تشغيلات سابقة (*)لاقائمة فارغة["session_id_1", "session_id_2"]
apply_postprocessboolتطبيق المعالجة اللاحقة المدركة للضجيج باستخدام SQDلاTrueTrue
tagslist 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 — أو بتغيير القيم الافتراضية الأخرى.

الاسمالنوعالوصفمطلوبالافتراضيمثال
ntintعدد الخطوات الزمنيةنعم-4
nqintعدد Qubit الدقةنعم-4
max_investmentfloatالحد الأقصى لعدد وحدات العملة المستثمرة عبر جميع الأصولنعم-10
dt*intالنافذة الزمنية المُعتبَرة في كل خطوة زمنية. الوحدة تتطابق مع الفترات الزمنية بين المفاتيح في بيانات الأصوللا30-
risk_aversionfloatمعامل النفور من المخاطرةلا1000-
transaction_feefloatمعامل رسوم المعاملةلا0.01-
restriction_coefffloatمضاعف لاغرانج المستخدم لفرض قيد المشكلة ضمن صياغة QUBOلا1-

ansatz_settings

لتعديل الخيارات الافتراضية، أنشئ قاموساً لمعامل ansatz_settings بالمفاتيح التالية. يُضبَط الـ ansatz افتراضياً على "real_amplitudes"، ويُضبَط كلا الخياران الإضافيان (انظر الجدول التالي) على False.

الاسمالنوعالوصفمطلوبالافتراضي
ansatz*strالـ ansatz المراد استخدامهلا"real_amplitudes"
multiple_passmanager**boolيُمكِّن روتين passmanager المتعدد (غير متاح لـ Tailored ansatz)لاFalse
dd_enableboolيضيف Dynamical DecouplingلاFalse

* الـ ansatz المتاحة

  • real_amplitudes
  • cyclic
  • optimized_real_amplitudes
  • tailored (متاح فقط لـ ibm_torino backend، و7 أصول، و4 خطوات زمنية، و4 Qubit دقة)

** إذا كان multiple_passmanager مضبوطاً على False، تستخدم الدالة مدير التمرير الافتراضي لـ Qiskit مع optimization_level=3. أما إذا كان مضبوطاً على True، فإن روتين multiple_passmanager يقارن بين ثلاثة مديري تمرير: مدير التمرير الافتراضي السابق لـ Qiskit، ومدير تمرير يُعيِّن الـ Qubit على سلسلة الجيران الأولى لوحدة QPU، وخدمات AI transpiler. ثم يُختار مدير التمرير ذو الخطأ التراكمي المُقدَّر الأدنى.

optimizer_settings

هذا المعامل هو قاموس يحتوي على بعض الخيارات القابلة للضبط في عملية التحسين.

الاسمالنوعالوصفمطلوبالافتراضي
primitive_optionsjsonإعدادات العنصر الأساسي (primitive)لا-
optimizerstrالمُحسِّن الكلاسيكي المختارلا"differential_evolution"
optimizer_optionsjsonتكوين المُحسِّنلا-
ملاحظة

حالياً، خيار المُحسِّن الوحيد المتاح هو "differential_evolution".

نضبط تحت مفاتيح primitive_options وoptimizer_options قواميساً بالمعاملات التالية:

primitive_options

الاسمالنوعالوصفمطلوبالافتراضيمثال
sampler_shotsintعدد لقطات الـ Sampler.لا100000-
estimator_shotsintعدد لقطات الـ Estimator.لا25000-
estimator_precisionfloatالدقة المطلوبة للقيمة المتوقعة. إذا حُدِّدت، ستُستخدَم الدقة بدلاً من estimator_shots.لاNone0.015625 · (1 / sqrt(4096))
max_timeint أو strالحد الأقصى لوقت بقاء جلسة التشغيل مفتوحة قبل إغلاقها قسراً. يمكن تحديده بالثواني (int) أو كسلسلة نصية مثل "2h 30m 40s". يجب أن يكون أقل من الحد الأقصى المفروض من النظام.لاNone"1h 15m"

optimizer_options

الاسمالنوعالوصفمطلوبالافتراضي
num_generationsintعدد الأجياللا20
population_sizeintحجم المجتمع (population)لا20
mutation_rangelistالحد الأقصى والأدنى لمعامل الطفرةلا[0, 0.25]
recombinationfloatمعامل إعادة التركيبلا0.4
max_parallel_jobsintالحد الأقصى لعدد وظائف QPU المنفَّذة بالتوازيلا3
max_batchsizeintالحد الأقصى لحجم الدُّفعة (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" الذي يحتوي على بيانات من جميع النتائج المتحصَّل عليها خلال عملية التحسين إلى جانب مقاييسها المعنية.

يركّز القاموس الأول على الحل الأفضل أداءً، بينما يوفر القاموس الثاني معلومات تفصيلية حول جميع الحلول، بما في ذلك تكاليف الهدف والمقاييس الأخرى ذات الصلة.

قواميس المُخرَجات:

الاسمالنوعالوصفمثال
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]قاموس مفاتيحه تمثيلات بتية لحلول مُعيَّنة وقيمه عدد تكراراتها.{"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]]
countslist[int]عدد مرات أخذ عيّنة لكل مسار استثماري. يتطابق الفهرس مع investment_trajectories.[5, 3]
objective_costslist[float]قيمة دالة الهدف لكل مسار استثماري، مرتبةً من الأدنى إلى الأعلى.[0.98, 1.25]
sharpe_ratioslist[float]الأداء المُعدَّل وفق المخاطرة (نسبة شارب) لكل مسار استثماري. مُوافِق للفهرس.[1.1, 0.7]
returnslist[float]العائد المتوقع لكل مسار استثماري. مُوافِق للفهرس.[0.15, 0.10]
rest_breacheslist[float]الحد الأقصى لانتهاك القيود ضمن كل مسار استثماري. مُوافِق للفهرس.[0.0, 0.25]
transaction_costslist[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). راجع مزيدًا من التفاصيل في الجدول التالي.

المجموعةالتاريخالأصول
المجموعة 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. نسبة شارب، التي تلتقط العائد المعدَّل بالمخاطر لكل محفظة، مما يوفّر رؤية حول الأداء المالي للحلول.

يقيس كلا المقياسين معًا الجوانب الحسابية والمالية للمحافظ المولَّدة كميًا كمعيار مرجعي.

المثالالكيوبتاتالـ Ansatzالعمقاستخدام وقت التشغيل (ث)إجمالي الاستخدام (ث)تكلفة الهدفشاربتكلفة هدف Gurobiشارب Gurobi
أصول مختلطة (المجموعة 1، 4 خطوات زمنية، 4 بت)112Tailored831273513095-3.7824.82-4.2524.71
أصول مختلطة (المجموعة 1، 4 خطوات زمنية، 4 خطوات زمنية، 4 بت)112Real Amplitudes3591173911903-3.3923.64-4.2524.71
مشتقات النفط (المجموعة 2، 4 خطوات زمنية، 3 بت)84Optimized Real Amplitudes7861806350-3.7319.13-4.1921.71
IBEX35 (المجموعة 3، 4 خطوات زمنية، 2 بت)56Optimized Real Amplitudes9633143523-3.6714.48-4.1116.44

تُظهر النتائج أن المُحسِّن الكمومي، باستخدام الـ ansatz المتخصص في المسألة، يُحدّد بفعالية استراتيجيات استثمارية كفؤة عبر أنواع محافظ مختلفة. نُفصّل أدناه كلًا من حجم المجتمع وعدد الأجيال المحددَين في قاموس optimizer_options. وقد جرى ضبط جميع المعاملات الأخرى على قيمها الافتراضية.

المثالpopulation_sizenum_generations
محفظة الأصول المختلطة9020
محفظة الأصول المختلطة9220
محفظة مشتقات النفط12020
محفظة IBEX354020

تم ضبط عدد الأجيال على 20، إذ تبيّن أن هذه القيمة كافية للوصول إلى التقارب. علاوة على ذلك، تُركت القيم الافتراضية للمعاملات الداخلية للمُحسِّن دون تغيير، نظرًا لأنها أبدت أداءً جيدًا باستمرار وهي موصى بها عمومًا في الأدبيات وإرشادات التطبيق.

الحصول على الدعم

إذا كنت بحاجة إلى مساعدة، يمكنك إرسال بريد إلكتروني إلى qpo.support@globaldataquantum.com. في رسالتك، أدرج معرّف وظيفة الدالة.

الخطوات التالية

توصيات