انتقل إلى المحتوى

دورة حياة cBot

في هذه المقالة والفيديو المصاحب لها، نستعرض هيكل الكود ونشرح المنطق وراء الأحداث ودورة حياة خوارزمية cBot في cTrader.

للتذكير، يمكنك الوصول إلى خوارزميات cBot الخاصة بك في تطبيق Algo في cTrader. لإنشاء خوارزمية cBot جديدة، ما عليك سوى النقر على زر خوارزمية cBot جديدة أو تحديد هذا الخيار في القائمة المنسدلة الموضحة أدناه.

تفسير القالب الأساسي

بعد إنشاء cBot جديد، يجب أن ترى الهيكل الأساسي التالي في نافذة محرر الكود.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        [Parameter(DefaultValue = "Hello world!")]
        public string Message { get; set; }

        protected override void OnStart()
        {
            // To learn more about cTrader Algo visit our Help Center:
            // https://help.ctrader.com/ctrader-algo

            Print(Message);
        }

        protected override void OnTick()
        {
            // Handle price updates here
        }

        protected override void OnStop()
        {
            // Handle cBot stop here
        }
    }
}

لاحظ أنه يتم عرض ثلاثة أحداث فقط في القالب الأساسي؛ تتم معالجة هذه الأحداث بواسطة الطرق OnStart() وOnTick() وOnStop(). سنضيف طريقتين إضافيتين (OnBar() وOnException()) ونشرح كيفية عملهما لاحقًا؛ أولاً، سنناقش طريقة OnStart().

استخدام طريقة OnStart()

يتم تشغيل طريقة OnStart() عند بدء cBot لأول مرة. تُستخدم لتهيئة أي متغيرات تخطط لاستخدامها في cBot الخاص بك، بما في ذلك المؤشرات والعدادات ومعالجات الأحداث أو المؤقتات.

ملاحظة

يتضمن قالب الكود الأولي بالفعل عبارة كود لطباعة رسالة في السجل عند بدء cBot. كما ترى، يحتوي cBot الخاص بنا على المعلمة Message، وتمرر طريقة OnStart() قيمة هذه المعلمة إلى طريقة Print().

يمكننا توضيح كيفية عمل طريقة OnStart() ببساطة عن طريق بدء مثيل cBot في تطبيق Trade وفتح علامة التبويب Log لرؤية النتيجة.

يمكننا أيضًا إيقاف cBot في أي وقت، وتغيير قيمة المعلمة Message في علامة التبويب Parameters، وإعادة تشغيل المثيل الخاص بنا. عند البدء، سيتم طباعة رسالتنا الجديدة في السجل.

استخدام طريقة OnTick()

يتم تشغيل طريقة OnTick() في كل مرة يتغير فيها سعر العرض أو الطلب للرمز. داخل هذه الطريقة، يمكنك عادةً برمجة شروط دخول وخروج المركز بالإضافة إلى أي وظائف مساعدة أخرى تحتاج إلى تشغيلها عند وصول بيانات جديدة.

سنضيف الكود التالي إلى طريقة OnTick() بحيث تطبع رسالة في السجل.

1
Print("OnTick. Bid: ", Symbol.Bid, ", Ask: ", Symbol.Ask);

كما ترى أدناه، يقوم cBot الخاص بنا الآن بطباعة أسعار العرض والطلب في السجل عند كل تغيير في السعر.

استخدام طريقة OnBar()

لا يتم تضمين طريقة OnBar() في قالب كود cBot الافتراضي لذلك سنضيف مقتطف الكود التالي لإضافتها.

1
2
3
4
protected override void OnBar() 
{
    Print("OnBar");
}

يتم تشغيل طريقة OnBar() كلما تم رسم شريط أو شمعة جديدة على الرسم البياني الذي تم إرفاق cBot به. بشكل مماثل لطريقة OnTick()، يمكنك استخدام طريقة OnBar() لبرمجة شروط دخول وخروج المركز بالإضافة إلى أي منطق آخر يحتاج إلى تنفيذه عند تشكيل كل شريط جديد.

كيفية تشغيل طريقة OnBar()

إذا كان لديك رسم بياني H1، يتم تشكيل شريط جديد كل ساعة، مما يعني أنه سيتم استدعاء طريقة OnBar() مرة واحدة في الساعة. إذا كان لديك رسم بياني m1، فسيتم استدعاء نفس الطريقة مرة واحدة في الدقيقة.

ستقوم طريقة OnBar() الخاصة بنا بطباعة "OnBar" عند كل شريط/شمعة جديدة. لتوضيح كيفية عملها، سنقوم بإرفاق cBot الخاص بنا برسم بياني m1 وإلقاء نظرة على السجل.

استخدام طريقة OnStop()

يتم استدعاء طريقة OnStop() عند توقف cBot إما بواسطة المستخدم أو عبر الكود. عندما يحدث ذلك، يتم تنفيذ أي كود داخل طريقة OnStop(). يمكن استخدام هذا لإجراء العمليات النهائية، مثل إغلاق المراكز.

سنضيف الكود التالي إلى طريقة OnStop() الخاصة بنا - كالمعتاد، سيقوم cBot الخاص بنا بطباعة قيمة المعلمة Message عند إيقافه.

1
Print(Message);

في لقطة الشاشة أدناه، نقوم بتشغيل وإيقاف مثيل من cBot الخاص بنا لتوضيح كيفية عمل كل شيء.

استخدام طريقة OnException()

توفر طريقة OnException() تحملًا للأخطاء من خلال التقاط الاستثناءات غير المعالجة، مما يتيح لك تحديد كيفية التعامل معها. لا يتم تضمينها في قالب الكود الافتراضي لذلك سنضيفها بأنفسنا باستخدام المقتطف التالي.

1
2
3
4
protected override void OnException(Exception exception) 
{
    Print("Ooops, unhandled exception! No worries, cBot still alive");            
}

لتشغيل طريقة OnException()، سنكتب بعض الكود لالتقاط استثناء يحدث عندما نحاول الوصول إلى معلومات حول تداول لم يعد موجودًا. سنضيف الكود أدناه إلى طريقة OnStart() الخاصة بنا.

1
ExecuteMarketOrder(TradeType.Buy, SymbolName, 1000, "my label");

سيقوم الكود الذي كتبناه في طريقة OnStart() بتنفيذ أمر سوق بالمعلمات القابلة للتكوين التالية.

  • سيكون نوع التداول أمر شراء.
  • سيتم تنفيذ التداول للرمز الحالي للرسم البياني الذي تم إرفاق cBot به.
  • سيكون حجم الأمر 1,000 وحدة.
  • سيكون التسمية الفريدة المرفقة بالأمر هي "my label".

سنضيف أيضًا الكود التالي إلى طريقة OnTick().

1
2
3
var position = Positions.Find("my label");
if (Positions.Find("my label") != null) Print("PositionId: ", position.Id);
Print("Message below");

سيقوم الكود الذي كتبناه في طريقة OnTick() بالعثور على المركز الذي تم فتحه في طريقة OnStart() باستخدام اسم التسمية "my label".

إذا تم العثور على المركز بنفس التسمية، فسيقوم بطباعة معرف المركز للتداول المفتوح في السجل. سيقوم أيضًا بطباعة رسالة أخرى تسمى "Message below" كسطر التالي من الكود الذي يتم تنفيذه.

عندما يتم إطلاق cBot الخاص بنا واستدعاء طريقة OnTick() والعثور على الأمر، سيقوم cBot بطباعة معرف الأمر في السجل، وبعد معرف الأمر، سيقوم بطباعة رسالة "Message below".

كما ترى، لا تنشأ أي استثناءات ويقوم cBot الخاص بنا بعمله بشكل مثالي.

الآن، ومع ذلك، سنقوم بإغلاق المركز الذي تم فتحه بواسطة cBot يدويًا وإجراء تغييرات صغيرة على الكود بحيث يكون حدوث استثناء مضمونًا. في طريقة OnStart()، سنقوم بتغيير تسمية الأمر إلى "cTrader". في طريقة OnTick()، سنقوم بالتعليق على الشرط الذي يتحقق مما إذا كان هناك مركز موجود بتسمية "my label".

هنا الكود النهائي لـ cBot الخاص بنا - لاحظ أن هذا الكود سيؤدي دائمًا إلى حدوث استثناء.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None)]
    public class LifecycleTest : Robot
    {
        [Parameter(DefaultValue = "cTrader rocks!")]
        public string Message { get; set; }

        protected override void OnStart()
        {
            ExecuteMarketOrder(TradeType.Buy, SymbolName, 1000, "cTrader");
        }

        protected override void OnTick()
        {
            var position = Positions.Find("my label");
            //if (Positions.Find("my label") != null) 
            Print("PositionId: ", position.Id);
            Print("Message below");
        }

        protected override void OnStop()
        {
            Print(Message);
        }

        protected override void OnException(Exception exception) 
        {
            Print("Ooops, unhandled exception! No worries, cBot still alive");            
        }
    }
}

سنقوم بتشغيل cBot مرة أخرى ونرى ماذا يحدث.

ما حدث هو أنه تم إنشاء أمر سوق جديد عند بدء cBot. كانت التسمية المرفقة بهذا الأمر هي "cTrader". في طريقة OnTick()، حاول الكود الحصول على مركز بتسمية "my label" وبما أننا قمنا بالتعليق على سطر الكود مع الشرط. ثم حاول طباعة معرف المركز في السجل.

تسبب هذا في حدوث خطأ استثناء كان من شأنه أن يوقف cBot في الإصدارات السابقة من cTrader، ولكن مع طريقة OnException() الجديدة، يمكننا الآن التقاط هذا ومعالجة الخطأ. سيستمر cBot في التشغيل ويمكننا تسجيل الخطأ حتى يمكن إصلاحه.

الملخص

تتكون دورة حياة cBot من عدة أحداث رئيسية يمكنك التعامل معها عبر طرق OnStart() وOnTick() وOnStop() وOnBar() وOnException(). من خلال تخصيص كيفية استجابة cBot الخاص بك للأحداث الرئيسية، يمكنك ضمان أن خوارزمياتك تتصرف بالضبط كما هو متوقع.