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

C# للتداول الخوارزمي

ما هو C#

C# هي لغة برمجة كائنية التوجه تُستخدم لبناء مجموعة واسعة من الخدمات والتطبيقات. تجعل بنيتها النحوية الواضحة والمنظمة من السهل تعلمها وقراءتها، حتى بالنسبة للمبتدئين، مع توفير نهج منظم لكتابة كود مدمج وقابل لإعادة الاستخدام.

خوارزميات C# في دقيقة واحدة!

  • حتى إذا لم تكن قد عملت مع C# من قبل، فإن إنشاء ونشر روبوت التداول الأول الخاص بك أو المؤشر يستغرق بضع دقائق فقط.
  • نظرًا لسهولة استخدام C#، يمكنك بسرعة إعادة كتابة أي مقتطفات برمجية من هذه الوثائق لتناسب احتياجاتك.
  • عند استخدام C#، يمكنك الوصول إلى عدد كبير من المكتبات التي تحتوي على فئات وطرق محددة مسبقًا. يمكن لهذه الطرق التعامل بكفاءة مع المهام الشائعة، مما يتيح لك حرية حل مشكلات التداول المعقدة.
  • في C#، يمكنك كتابة كود لا يعيق مسارات الخادم عند التنفيذ. بعبارة أخرى، يمكنك بدء مهام معينة بالتزامن مع المهام الأخرى.

ما هو .NET؟

لتشغيل برامج C#، يجب تجميع الكود المصدري إلى لغة وسيطة (IL). يتبع كود IL هذا مواصفات البنية التحتية للغة المشتركة (CLI) ويتم تجميعه لاحقًا إلى تعليمات الجهاز الأصلية في وقت التشغيل. يوفر إطار عمل .NET بيئة تنفيذ افتراضية مبنية على مكتبات فئات واسعة النطاق ووقت تشغيل اللغة المشتركة (CLR)، وهو تطبيق Microsoft لـ CLI.

دون الخوض في التعقيدات التقنية، يؤدي .NET الوظائف التالية:

  • تسهيل تطوير وتنفيذ التطبيقات: تحتوي مجموعة تطوير البرامج .NET بالفعل على العديد من المترجمات ومحركات البناء المدمجة، مما يلغي الحاجة إلى إنشاء أي حلول مخصصة.
  • توفير مكتبات وقت التشغيل: عند إضافة أنواع بيانات أو مجموعات جديدة إلى الكود الخاص بك، ستجد غالبًا أن .NET يقدم بالفعل فئات وطرق مناسبة للمهمة.

أساسيات C#

أنواع البيانات وإعلانات المتغيرات

أنواع البيانات هي وسيلة لتصنيف البيانات بحيث تعرف C# بالضبط كيفية التعامل مع المتغيرات والخصائص. في إعلانات المتغيرات/الخصائص، تسبق أنواع البيانات دائمًا اسم المتغير/الخاصية.

1
string developer = "I am developing cBots, plugins, and indicators!";

بدلاً من ذلك، يمكنك استخدام الكلمة الأساسية var لتجنب تحديد نوع البيانات.

1
var developer = "I am developing cBots, plugins, and indicators!";

الكائنات والفئات

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

نظرًا لأن C# هي لغة كائنية التوجه، يمكن للفئات أيضًا أن ترث الخصائص والطرق من الفئات الأخرى. ضع في اعتبارك المثال التالي الذي نعلن فيه عن فئة NewBot جديدة ترث من فئة Robot. كما نحدد بعض خصائص الفئة الجديدة.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/* We use the colon sign to designate inheritance.
Additionally, we used expressions in square brackets to
specify the parameters that apply to the entire class */
[Robot(AccessRights = AccessRights.None)]
public class NewBot : Robot
{
    /* We declare a custom class property and make it
    read-only. */
    public string CustomProperty { get; }

    /* In this declaration, we define the default value of a
    custom parameter. */
    [Parameter("BotName", DefaultValue = "Traders First!")]

    /* We declare the BotName property which is changeable via
    the "BotName" parameter. */
    public string BotName { get; }

    /* We also declare the BotComment parameter.
    It can be both read and set. */
    [Parameter("BotComment", DefaultValue = "Our super-duper bot!")]
    public string BotComment { get; set; }
}

أنواع البيانات

نظرًا لأن C# هي لغة ذات أنواع قوية، من الضروري تحديد أنواع البيانات عند إعلان المتغيرات وخصائص الفئة. باختصار، تشكل أنواع البيانات فئات فريدة ذات مجموعات مختلفة من السلوكيات. ضع في اعتبارك الأمثلة التالية التي يتم فيها تحديد أنواع بيانات مختلفة لخصائص الفئة المختلفة والمعلمات ذات الصلة.

1
2
[Parameter("Price")]
public DataSeries Source { get; }

في الكود أعلاه، يمثل نوع البيانات DataSeries قائمة للقراءة فقط من القيم، وبالتالي يُستخدم عادةً لتمثيل أسعار السوق.

عندما تكون هناك حاجة لإنشاء معلمات متعددة الخيارات، يمكنك استخدام نوع البيانات المدمج enum كما هو مفصل أدناه. يمكنك التفكير في enum كفئات خاصة تحتوي على ثوابت مختلفة.

1
2
3
4
5
6
7
8
9
public enum Option
{
    First,
    Second,
    Third
}

[Parameter("Option", DefaultValue = Option.Third)]
public Option SelectedOption { get; set; }

للوصول إلى ثابت موجود في enum، استخدم بناء الجملة التالي.

1
var newOption = Option.First;

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

1
2
[Parameter("MA Periods", DefaultValue = 14, MinValue = 1, MaxValue = 20)]
public int Periods { get; set; }

أخيرًا، يمثل النوع bool عادةً إدخال نعم أو لا. تتوافق القيم نعم ولا مع true و false على التوالي.

1
2
[Parameter("Message", DefaultValue = true)]
public bool DisplayChartMessage { get; set; }

مساحات الأسماء

تعمل مساحات الأسماء كمجموعات مخصصة من الفئات. بمجرد تعيين فئة إلى مساحة أسماء، يمكن الوصول إليها لاحقًا باستخدام التدوين Namespace.ClassName. سنقوم بتعيين NewBot الخاص بنا إلى مساحة الأسماء CoolTradingBots.

1
2
3
4
5
6
7
8
namespace CoolTradingBots
{
    [Robot(AccessRights = AccessRights.None)]
    public class NewBot : Robot
    {
        // ...
    }
}

طرق الفئة

يتم تعريف طرق الفئة بعد إعلان الفئة. ستتمكن جميع كائنات فئة NewBot الخاصة بنا من استدعاء طريقة CustomTradeOperation(). تأخذ وسيطين، وهما كائن Symbol وكائن double. من المفترض أن تأخذ طريقتنا رمزًا وتنفذ نوعًا من إجراءات التداول للحجم المحدد

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
namespace CoolTradingBots
{
    [Robot(AccessRights = AccessRights.None)]
    public class NewBot : Robot
    {
        // ... Defining the class parameters.

        // We declare the CustomTradeOperation method. 
        protected override void CustomTradeOperation(string symbolName, double volume)

        {
            // This space is for declaring the method logic. 
        }
    }
}

مكتبات الفئة

يمكن الوصول إلى مكتبات الفئة (وبالتالي طرق الفئة) عن طريق مساحة الأسماء الخاصة بها كما هو موضح في المثال أدناه.

1
CoolTradingBots.NewBot.CustomTradeOperation(symbolName, 10000)

بدلاً من ذلك، يمكنك كتابة الكلمة الأساسية using في بداية التعليمات البرمجية الخاصة بك لتعيين مساحات أسماء معينة وتجنب التكرار. انظر إلى مقتطف الشفرة التالي.

1
2
3
using CoolTradingBots;

NewBot.CustomTradeOperation(symbolName, 10000)

العبارات الشرطية

لاستخدام العبارات الشرطية، استخدم كلمة أساسية متبوعة بتعبير بين قوسين. يستخدم المثال أدناه الكلمة الأساسية if لإنهاء طريقة CustomTradingOperation() الخاصة بنا. للقيام بذلك، نستخدم طريقة EvaluateMarket() المعرفة في مساحة الأسماء Analytics.Actions.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
namespace CoolTradingBots
{
    [Robot(AccessRights = AccessRights.None)]
    public class NewBot : Robot
    {
        // ... Defining the class parameters.

        protected override void CustomTradeOperation(string symbolName, double volume)
        {
            // We declare and initialize the 'result' variable.
            var result = Analytics.Action.EvaluateMarket();

            // We use a conditional statement based on the IsSuccessful property.
            if (result.IsSuccessful)
            {
                Print("Operation successful!")
            }
        }
    }
}

المجموعات

يتم تعريف المجموعات على أنها حاويات يمكنها تخزين كائن واحد أو أكثر من فئة معينة.

المجموعات قابلة للفهرسة بالكامل، مما يعني أنه يمكن الوصول إلى أعضائها عن طريق تمرير قيمة integer معينة في أقواس مربعة. انظر إلى المثال التالي حيث تقوم طريقة Calculate() بطباعة خصائص شريط تم الوصول إليه عبر فهرسه.

1
2
3
4
5
public override void Calculate(int index)
{
       var bar = Bars[index];
       Print($"{bar.Open} | {bar.High} | {bar.Low} | {bar.Close}");
}

إنشاء امتدادات cTrader

في المقتطف أدناه، نقوم بإنشاء روبوت تداول أساسي باستخدام المعرفة المغطاة في الأقسام أعلاه فقط.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System; 

namespace Spotware.cBots
{
    [Robot(AccessRights = AccessRights.None)]
    public class SuperAwesomeBot : Robot
    {

        /* In the below method, we define the operation(s) that our bot should
        perform when it is launched. */
        protected override void OnStart()
        {
            var result = ExecuteMarketOrder(TradeType.Buy, symbolName, 10000);

            /* We use a conditional statement using the IsSuccessful property of the
            TradeResult object. */
            if (result.IsSuccessful)
            {
                var position = result.Position;
                Print ("Position entry price is {0}", position.EntryPrice);
            } 
        }
    }
}

العمليات المتزامنة وغير المتزامنة

كما ذكرنا سابقًا، تدعم C# بالكامل العمليات غير المتزامنة. يوضح الرسم البياني أدناه مثالاً أساسيًا لكيفية تنفيذ أنشطة التداول في التنفيذ المتزامن.

graph TD
    A(مواجهة إشارة فنية) ==> B(تنفيذ أمر السوق)
    B ==> C(جني الأرباح/إيقاف الخسارة <br>تم الوصول إليه)
    C ==> D(إغلاق المركز)
    D ==> A

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

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

graph TD
    A([مواجهة إشارة فنية]) ==> B([إدراج أمر شراء]) & C([إدراج أمر بيع للتحوط]) ==> D([وصول الأمر إلى جني<br> الأرباح/إيقاف الخسارة])
    D ==> E([إغلاق المركز])
    E ==> A

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

لاحظ أن التنفيذ غير المتزامن يختلف عن تعدد المسارات:

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

لا يقوم cTrader أبدًا باستدعاء طرقك بالتوازي لذلك لا داعي للقلق بشأن مشكلات تعدد المسارات.

Image title