إنشاء وسيط مخصص
استخدم وسيطًا مخصصًا لربط AQE بجهة تنفيذ. يتولى مهايئك الاتصال ونقل البيانات ورصد الحساب وتنفيذ الأوامر. وتحتفظ الاستراتيجية بملكية إشاراتها التداولية؛ ويتلقى الوسيط طلبات أوامر غير قابلة للتغيير بدلًا من شجرة الإشارات التداولية الكاملة للاستراتيجية.
يتبع هذا الدليل واجهات AQE 0.2.0. تأكّد من توافق تطبيقك مع السمات في نسخة شيفرة AQE التي تستخدمها استراتيجيتك. ابدأ بطبقة اتصال محاكية أو ببيئة الاختبار المعزولة لجهة التنفيذ، لا بحساب تداول مباشر ممول.
1. تنفيذ الاتصال وإدارة الأوامر
Section titled “1. تنفيذ الاتصال وإدارة الأوامر”أنشئ نوع Rust ينفّذ aq_engine::core::broker::traits::{Broker, OrderManagementProvider}. يجب أن يكون Send + Sync وأن يمتلك اتصاله وذاكراته المؤقتة وقائمة انتظار أحداثه.
| السمة | الدوال المطلوبة | المسؤولية |
|---|---|---|
Broker | connect, disconnect, is_connected | إدارة دورة حياة النقل والتنظيف حتى بعد إلغاء محاولة اتصال. |
Broker | get_name, get_account_type | تعريف المهايئ وبيئة الحساب بدقة. |
OrderManagementProvider | submit_order, cancel_order | إرسال BrokerOrderRequest وإلغاء أمر وسيط بمعرّفه. |
OrderManagementProvider | update_take_profit, update_stop_loss | تعديل الحماية بالسعر والكمية المقدَّمَين. |
OrderManagementProvider | close_position, close_all_positions | طلب إغلاق المراكز وإدارة الحماية المتبقية. |
OrderManagementProvider | get_orders, get_order | إعادة سجلات Order في AQE بهويات الوسيط وحالاته الحقيقية. |
OrderManagementProvider | get_positions, get_position | إعادة سجلات Position؛ وتأخذ دالة المركز الواحد رمزًا. |
OrderManagementProvider | get_account | إعادة Account يتضمن الأرصدة والعملة والقوة الشرائية والحدود. |
OrderManagementProvider | drain_trade_events_bounded, has_pending_trade_events | إتاحة قائمة انتظار أحداث مرتبة وغير حاجبة. |
OrderManagementProvider | subscribe_to_trade_stream, unsubscribe_from_trade_stream | إدارة دوال استدعاء التداول ودورة حياتها. |
تتطلب عدة دوال صراحةً قيمًا مستقبلية تحقق قيد Send، بما فيها connect وتعديلات الأوامر الفردية وget_orders وget_positions وget_account. اتبع توقيعات السمات بدقة؛ يصلح تنفيذ async fn عندما تحقق قيمته المستقبلية قيد Send. لا تحتفظ أبدًا بحارس قفل غير Send عبر .await، ولا تنفّذ عمليات اتصال حاجبة على خيط عمل تابع لبيئة التشغيل.
بالنسبة إلى جهة لا تدعم دفع الأحداث، خطط لكيفية إنتاج الاستطلاع الدوري لأحداث دورة الحياة ودعمه لعقد الاشتراك المطلوب. لا تعلن TradeEventStream إلا إذا كان الوسيط يوفّر الأحداث فعلًا دون استطلاع AQE الدوري.
إعلان القدرات الأصلية
Section titled “إعلان القدرات الأصلية”أعِد تعريف Broker::get_features() بشريحة ثابتة من قيم BrokerFeature. لا تعلن إلا الميزات التي يدعمها المهايئ فعلًا، مثل MarketOrder أو LimitOrder أو PartialClose أو BrokerManagedOco. أعلن AmendLimitPrice وAmendStopPrice كلًا على حدة عندما تدعم الجهة تعديل أسعار الدخول المقابلة في أمر لم يُنفَّذ بعد.
أبلِغ عن القوة الشرائية باتساق: تعني BuyingPowerLeveraged أن القوة الشرائية المعادة تتضمن الرافعة المالية بالفعل. اربط الحدود القصوى المدعومة بـAccount.max_total_orders وAsset.max_total_size؛ أما حجم الأمر الفردي فموضعه Asset.max_order_size. لا تختلق حدودًا للوسيط أو تعلن تقديرات موثوقة تعتمد فقط على حسابات عامة للقيمة الاسمية.
لأي عملية غير مدعومة، أعِد BrokerError::UnsupportedOperation قبل أي تعديل عبر النقل. لا تستبدل نوع أمر آخر بصمت، ولا تُعِد نجاحًا.
2. تحويل الطلبات مع الحفاظ على معرّفاتها
Section titled “2. تحويل الطلبات مع الحفاظ على معرّفاتها”تتلقى submit_order كائن BrokerOrderRequest. طابق رمزه واتجاهه وكميته ونوع الأمر وفئته وأسعار الحد والوقف ومستويات الحماية والوقف المتحرك مع التمثيل المدعوم لدى الجهة.
احتفظ بـclient_order_id للربط، واستخدمه معرّف أمر العميل لدى الجهة عند دعمه. يظل ثابتًا عبر إعادة المحاولات أو استرداد نية الدخول نفسها؛ وليس دليلًا على أن الجهة أنشأت أمرًا. أعِد معرّف أمر الوسيط الفعلي في Order الناتج.
حافظ على التمييز بين هذه النتائج:
| النتيجة | سلوك المهايئ |
|---|---|
| غير مدعوم قبل الإرسال | إعادة UnsupportedOperation؛ لم يحدث أي تعديل. |
| رفض مثبت قبل استدعاء تعديل الوسيط | استخدام SubmissionRejected مع السبب. |
| انتهاء مهلة النقل بعد الإرسال | الحفاظ على عدم اليقين. لا تدّعِ الرفض ولا تُعِد الإرسال دون تحقق. |
| طلب مقبول | إعادة حالة الأمر المرصودة لدى الوسيط؛ فالقبول وحده لا يعني التنفيذ. |
| تنفيذ أو رفض أو إلغاء أو إغلاق لاحق | إصدار بيانات تثبت الحدث في دورة الحياة، مع الأمر والحدث المقابلَين. |
الدالة replace_order اختيارية وتعيد افتراضيًا خطأ عدم الدعم. أعِد تعريفها لاستبدال سعر أو كمية دخول معلّق. وهي ليست بديلًا عن update_take_profit أو update_stop_loss.
الدالة amend_entry_prices(order_id, limit_price, stop_price) دالة اختيارية منفصلة لتغيير مكوّن الحد أو سعر تفعيل الوقف لدخول معلّق دون تغيير كميته. يعيد تطبيقها الافتراضي خطأ عدم الدعم. نفّذها قبل إعلان أي من قدرتَي التعديل. لا توجّه تعديل سعر تفعيل الوقف إلى update_stop_loss، التي تتحكم في أوامر الوقف الوقائية.
تعبئة سجلات الحساب والأوامر والمراكز
Section titled “تعبئة سجلات الحساب والأوامر والمراكز”يجب أن تتضمن صيغ إنشاء هياكل Rust كل حقل في النوع الحالي، بما في ذلك الحقول الاختيارية. تساعد #[serde(default)] على قراءة السجلات القديمة المحفوظة بصيغة تسلسلية؛ لكنها لا تجعل إدراج الحقل اختياريًا عند إنشاء هيكل في Rust.
| السجل والحقول | متطلبات المهايئ |
|---|---|
Account.account_id, currency, accrued_commission, max_total_orders | أبقِ عمليات الرصد مرتبطة بالحساب الفعلي وعملته. املأ العمولة المستحقة استنادًا إلى أدلة الوسيط، والحد الأقصى للأوامر المعلّقة عند الإبلاغ عنه. القيم الافتراضية القديمة ليست دليلًا على غياب التكاليف أو الحدود. |
Position.order_id | حقل اختياري جديد لتذكرة التنفيذ أو المركز الدقيقة المرتبطة بالدخول. استخدم Some(...) فقط عندما يستطيع المهايئ إثبات الارتباط؛ واستخدم None للسجلات القديمة أو المجمّعة حسب الرمز ذات المالكين المتعددين. لا تختلق هوية من الرمز أبدًا. |
Position.entry_commission | احتفظ بعمولة دخول المركز مستقلةً عن أرباحه وخسائره التداولية غير المحققة. لا تحتسب الرسم نفسه مرة أخرى عند الإبلاغ عن المحاسبة النهائية. |
Order.filled_qty, realized_pnl, commission, swap | استخدم كميات التنفيذ التراكمية للدخول في لقطة الدخول، لكن استخدم فقط الكمية المنفّذة في عملية الخروج المعنية عند الإبلاغ عن حدث خروج. احتفظ بقيم التنفيذ والقيم النقدية التي يبلّغ عنها الوسيط؛ فالقبول ليس تنفيذًا. |
Order.position_accounting, OrderLifecycleCloseDetails.position_accounting | أدلة PositionCloseAccounting اختيارية لمركز يمكن إثبات ملكيته. أبقِها None عند عدم الدعم أو الغموض؛ فهي ليست مطلوبة لمجرد تنفيذ إرسال الأوامر. |
BrokerLifecycleSnapshot.snapshot_complete, captured_at | لا تضع علامة الاكتمال إلا بعد حصر كامل بيانات دورة الحياة المعنية، واحتفظ بوقت رصدها. لا يمكن للقطة فارغة وغير مكتملة أن تثبت اختفاء أمر أو مركز. |
عند إنشاء Order، احتفظ بمعرّفات الإشارة التداولية والاستراتيجية إلى جانب معرّف أمر الوسيط الحقيقي. أعِد البيانات الوصفية الحالية لـAsset مع الأوامر والمراكز، بما في ذلك قواعد التداول وجدوله ورسومه عند معرفتها. راجع البيانات الوصفية لمصدر البيانات المخصص للاطلاع على حقول الأداة المالية.
البحث عن المراكز بهوية الدخول الدقيقة
Section titled “البحث عن المراكز بهوية الدخول الدقيقة”قد تعرض get_position(symbol) بيانات مجمّعة. تجري الدالة الأحدث get_position_by_order_id(order_id, symbol) بحثًا دقيقًا غير متزامن وتعيد Result<Option<Position>, BrokerError>. يفحص تنفيذها الافتراضي get_positions() ويرفض هوية الأمر الغامضة أو المفقودة بدلًا من اختيار مركز عشوائي على الرمز نفسه. أعِد تعريفها إذا احتاجت جهة التنفيذ إلى بحث مخصص بالتذكرة.
للمحاكاة الدقيقة في الذاكرة أو لذاكرة مؤقتة مخصصة، يمكن أن تعيد position_snapshot_reader كائن PositionSnapshotReader: دالة استدعاء مملوكة وآمنة للاستخدام عبر الخيوط، تأخذ معرّف الأمر والرمز. أبقِها خالية من عمليات النقل. لا تُعِد Ok(None) إلا عند رصد غياب المركز؛ وأعِد خطأً عندما تكون البيانات غير متاحة أو يتعذر إثبات الهوية المطلوبة. تستخدم قرارات الاستراتيجية المباشرة ذاكرة لقطات AQE المؤقتة ذات الطوابع الزمنية، لا طلب شبكة إضافيًا من دالة استدعاء الإشارة التداولية.
3. تسليم أحداث دورة الحياة بموثوقية
Section titled “3. تسليم أحداث دورة الحياة بموثوقية”احتفظ بقائمة انتظار من (Order, TradeUpdateEvent) بترتيب المصدر. تزيل drain_trade_events_bounded(max_events) ذلك العدد من الأحداث كحد أقصى وتترك الباقي في القائمة. لا يزيل حد مقداره صفر أي شيء. لا تُفرغ القائمة كاملةً ثم تقتطع المتجه المُعاد.
توضّح هذه الدالة المساعدة كيفية التعامل مع قائمة الانتظار دون فرض مكتبة أقفال معينة. استدعِها أثناء حماية قائمة انتظار المهايئ بحارس قفل قصير العمر:
use aq_engine::core::broker::types::{Order, TradeUpdateEvent};use std::collections::VecDeque;
pub fn take_trade_events( queue: &mut VecDeque<(Order, TradeUpdateEvent)>, max_events: usize,) -> Vec<(Order, TradeUpdateEvent)> { let count = max_events.min(queue.len()); queue.drain(..count).collect()}تتحقق has_pending_trade_events من جاهزية القائمة دون عمليات إدخال وإخراج للشبكة أو قاعدة البيانات. نفّذ دوال الاستدعاء خارج الأقفال وأبقِها قصيرة. انشر أحداث التنفيذ الجزئي وتحديثات الأوامر الوقائية التابعة بدقة، وعالج رسائل المزوّد المكررة أو الواردة خارج ترتيبها بدلًا من اختلاق حالات نهائية.
تولّد أغلفة الأحداث الافتراضية المحايدة تجاه الوسيط معرّفات أحداث بتوقيت مصدر غير معروف. أعِد تعريف subscribe_to_broker_event_stream ومعالجة أغلفة البيانات المرتبطة بها عندما يستطيع مهايئك توفير هويات وأرقام تسلسلية وطوابع زمنية موثوقة لـBrokerOrderEvent.
4. معالجة الحماية والاسترداد
Section titled “4. معالجة الحماية والاسترداد”تتولى close_position إدارة أوامر الحماية عند الإغلاق: يلغي الإغلاق الكامل الأوامر الأصلية التابعة المتبقية، ويحافظ الإغلاق الجزئي على الحماية أو يعدّل حجمها بما يناسب التعرّض المتبقي. تؤكد Ok(true) استلام الأمر، لا إتمام الإغلاق. أرسل بيانات تثبت النتيجة النهائية للتداول بصورة منفصلة.
تحسّن نقاط الاستدعاء الاختيارية الإشراف والاسترداد:
| نقطة الاستدعاء | متى تنفّذها |
|---|---|
get_cached_account | إعادة أحدث لقطة حساب دون إدخال وإخراج عبر النقل. |
get_cached_positions | توفير مراكز دون نقل للتنفيذ الحتمي في الذاكرة، لا كبديل للتحديثات المباشرة ذات الطوابع الزمنية. |
get_cached_lifecycle_snapshot | توفير عرض كامل وموثوق لدورة الحياة دون إدخال وإخراج؛ وإعادة None حتى يتوفر. |
estimate_order_margin | الحصول على تقدير موثوق للطلب الدقيق دون وضعه. |
reconcile_submission | البحث عن الحساب وأمر العميل المحددَين دون إعادة إرساله. |
reconcile_order_lifecycle | حسم معرّفات الأوامر باستخدام سجل الأوامر وهوية المركز بعد إعادة التشغيل. |
lifecycle_reconciler | توفير Arc<dyn OrderLifecycleReconciler> مملوك للاسترداد بعد إعادة التشغيل. |
get_position_by_order_id, position_snapshot_reader | تحديد تذكرة الدخول الدقيقة، مع الفصل بين التحديث غير المتزامن والبحث الخالي من عمليات النقل. |
pending_cancellation_recovery, retry_cancellation | دعم الاسترداد القائم على الأدلة لإلغاء غير محسوم، عبر عامل الأوامر ذي الحالة الدائمة. |
execution_fill_history_reader | توفير سجل تنفيذ محدود وللقراءة فقط لحساب وأمر دخول ورمز محددة بدقة. |
position_valuation_reader | توفير تقييمات بعملة الحساب وللقراءة فقط للمراكز الفعلية المحددة بدقة، لا تقدير شامل للرمز. |
account_cash_flow_reader | توفير سجلات تمويل الحساب وتسوياته للقراءة فقط، مع هوية المصدر والتسلسل ونطاق التغطية. |
configure_live_session, configure_asset_metadata | قبول سياق الجلسة وقواعد الأصول عندما يحتاجهما المهايئ. |
تعيد آلية التحقق الافتراضية من نتيجة الإرسال Unsupported. وتستخدم آلية التحقق الافتراضية من دورة الحياة get_orders()، وتُرجع Unknown للمعرّفات التي لم تجدها؛ ولا يمكنها إثبات إغلاق المركز الناتج عن أمر منفّذ. لا تفسّر أبدًا غياب أمر أو وجود لقطة غير مكتملة أو انتهاء مهلة على أنه دليل على الإلغاء أو الإغلاق.
استرداد الإلغاءات دون إعادة إرسال الأوامر
Section titled “استرداد الإلغاءات دون إعادة إرسال الأوامر”توفّر pending_cancellation_recovery(account, order) دليلًا للقراءة فقط على أن الإلغاء غير المحسوم لا يزال يستهدف أمرًا معلّقًا. تعيد افتراضيًا None، وهو ليس دليلًا على حالة نهائية. لا يجوز استدعاء retry_cancellation إلا من عامل الأوامر ذي الحالة الدائمة، وبعد تسجيل محاولة استرداد. يجب ألا ترسل نقطة الاستدعاء هذه أمرًا أو تغلقه أو تستبدله؛ بل يجب أن تحصل على دليل موثوق على الإلغاء، وأن تمرّره عبر آلية اختزال أحداث الوسيط المعتادة. تنفيذها الافتراضي غير مدعوم. لا تضف مؤقّتًا مستقلًا لإعادة المحاولة يتجاوز هذه العملية.
إبقاء التحليلات اختيارية وللقراءة فقط
Section titled “إبقاء التحليلات اختيارية وللقراءة فقط”تعيد نقاط استدعاء قراءة السجل والتقييم والتدفقات النقدية None افتراضيًا. يمكن لمهايئ التنفيذ الاحتفاظ بهذه القيم الافتراضية عندما يتعذر عليه توفير الأدلة. يجب أن تظل التحليلات غير المدعومة غير متاحة، لا أن تُستبدل بسجل فارغ مختلق أو محفظة بلا مراكز مفتوحة أو تدفق نقدي صفري.
- تعيد
ExecutionFillHistoryReader::read(account_id, entry_order_id, symbol)كائنExecutionFillHistoryلمركز يمكن إثبات ارتباطه بأمر دخول واحد. احتفظ بمعرّفات عمليات التنفيذ وتوقيتها لدى المصدر؛ ويمكن أن تضيفposition_snapshotتحققًا من الكمية مستندًا إلى رصد مستقل. لا يُعدّ السجل المفقود أو المجمّع بالمقاصة دليلًا على عدم وجود عمليات تنفيذ. - تعيد
PositionValuationReader::read_positions(account_id, symbol, position_ids)كائنPositionValuationsلدفعة محدودة من المراكز المحددة بدقة. احتفظ بعملة الحساب وas_of_usوتوقيت عرض السعر والأرباح والخسائر التداولية وعوائد الاحتفاظ وتكاليفه، وبأساس صريح للقيمة الاسمية أو سبب عدم توفره. تمثلNotOpenرصدًا لغياب المركز، لا تنفيذ إغلاق أو إذنًا بإغلاق إشارة تداولية. - تعيد
AccountCashFlowReader::read(account_id, source_id, after_sequence)كائنAccountCashFlowPageيتضمن هوية المصدر والعملة والتغطية الزمنية ومؤشر التسلسل والسجلات. سجّل التمويل أو التسويات الفعلية؛ ولا تستنتج إيداعات أو سحوبات من تغيّرات حقوق ملكية الحساب أو عمليات التنفيذ أو حالة الإشارة التداولية.
تعيد الدوال الثلاث نتيجة اختيارية داخل Result. تختلف القراءة غير المتاحة والخطأ عن رصد كامل وموثوق لا يحتوي على سجلات مطابقة. ويجب ألا تضع هذه الدوال أوامر أبدًا أو تجري مطابقة لدورة الحياة كأثر جانبي لقراءة التحليلات.
5. الجمع بين التنفيذ والبيانات
Section titled “5. الجمع بين التنفيذ والبيانات”يقبل UnifiedBroker نوع التنفيذ الخاص بك مباشرةً. تعمل هذه الدالة المساعدة مع أي وسيط ومصدر بيانات متوافقَين؛ ويجب أن يكون كلا المهايئَين قد نفّذ سماته الخاصة بالفعل:
use aq_engine::core::broker::{ traits::{Broker, DataFeed, DataProvider, OrderManagementProvider}, UnifiedBroker,};
pub fn live_with<E, D>(execution: E, datafeed: D) -> UnifiedBroker<E, D>where E: Broker + OrderManagementProvider, D: DataFeed + DataProvider,{ UnifiedBroker::new(execution, datafeed)}استخدم PaperBroker مع UnifiedBroker::new_backtest للمحاكي التاريخي المدمج. لا يؤدي تنفيذ سمات الوسيط المباشر وحدها إلى تحويل جهة تنفيذ بعيدة إلى ذلك المحاكي. دعم أداة اختيار الاتصالات في AQS تكامل مستقل لسطح المكتب، وليس نتيجة تلقائية لتنفيذ السمات.
6. التحقق قبل الاستخدام المباشر
Section titled “6. التحقق قبل الاستخدام المباشر”- اختبر فشل الاتصال والإلغاء وإعادة الاتصال والإيقاف الكامل.
- اختبر كل نوع أمر معلَن وقاعدة دقة وحد للسعة.
- تحقّق من التنفيذ الجزئي والإلغاء وتحديثات الحماية والإغلاق الجزئي وإلغاء الحماية المتبقية عند الإغلاق الكامل.
- اختبر سحب الأحداث المحدود بحدود صفر وواحد وعدة أحداث؛ وتأكّد من الحفاظ على الترتيب والأحداث المتبقية.
- حاكِ انتهاء مهلة إرسال بعد قبول الجهة. تأكّد من أن الاسترداد لا يكرّر الأمر.
- أعِد التشغيل مع أوامر معلّقة ومراكز مفتوحة؛ وتحقّق من استمرار التمييز بين النتائج غير المعروفة والنتائج المؤكدة.
- قارن عمليات رصد الحساب والأوامر والمراكز بسجلات بيئة الاختبار المعزولة للجهة قبل التفكير في الاستخدام المباشر.
- أبقِ عمليتَي دخول على الرمز نفسه منفصلتين. اختبر البحث بالتذكرة الدقيقة والهوية غير المعروفة واللقطات غير المكتملة، بدلًا من اختيار أول مركز يطابق الرمز.
- حاكِ إلغاءً غير محسوم يمتد عبر إعادة تشغيل، وتحقّق من أن مسار الاسترداد ذي الحالة الدائمة وحده يستطيع إعادة محاولة الإلغاء.
- اختبر دوال القراءة الاختيارية ببيانات غير مدعومة وغير مكتملة ومتقادمة وتابعة لحساب آخر. تأكّد من أن قراءات التحليلات لا تستطيع إرسال أوامر أو اختلاق أدلة محاسبية.
مرجع المصدر
Section titled “مرجع المصدر”في نسخة AQE المحلية، ابدأ بما يلي:
src/core/broker/mod.rs: سمات التنفيذ والقيم الافتراضية والتركيب.src/core/broker/commands.rs:BrokerOrderRequestوSubmissionResolution.src/core/broker/types/mod.rs: أنواع الحساب والأمر والمركز ودورة الحياة والأخطاء.src/core/broker/features.rs: علامات القدرات الأصلية.src/core/broker/fill_history.rsوposition_valuation.rsوaccount_cash_flow.rs: عقود التحليلات الاختيارية المخصّصة للقراءة فقط.live-sync-protocol/src/position_accounting.rsوposition_valuation.rs: الأدلة المحاسبية والتحقق من صحة التقييم.src/core/broker/mt5_broker.rsوsrc/core/broker/paper_broker.rs: التطبيقان المباشر والمحاكى.
التالي: إنشاء مصدر بيانات مخصص أو التشغيل المباشر.
نستخدم ملفات تعريف الارتباط والتخزين الضروريين لتسجيل الدخول وحماية الحساب وحفظ تفضيلات المظهر وهذا الإشعار، ولجمع مقاييس PostHog الداخلية اللازمة لقياس الاستخدام وجودة الجلسات والموثوقية. لا نستخدم ملفات تعريف ارتباط إعلانية.
