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

كيفية أتمتة إستراتيجية التداول اليدوي

يوفر التداول الآلي أو الخوارزمي العديد من المزايا مقارنة بالتداول اليدوي:

  • تُلغي الأنظمة الآلية اتخاذ القرارات العاطفية وتنفذ الصفقات بدقة وسرعة وكفاءة متزايدة.
  • تنفذ الخوارزميات باستمرار استراتيجيات التداول المتقدمة بينما يتم تطبيق تدابير إدارة المخاطر بشكل موثوق.
  • تُمكّن الخوارزميات من إجراء الاختبار العكسي للاستراتيجيات باستخدام البيانات التاريخية والتنويع عبر أصول وأسواق متعددة في وقت واحد.

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

تحديد أنماط الاستراتيجية اليدوية

لتطوير خوارزمية، دعنا نفترض أننا نتداول يدويًا نمط hammer للدخول في صفقات شراء ونمط hanging man للدخول في صفقات بيع.

يحدث نمط hammer خلال اتجاه هبوطي ويشير إلى احتمال انعكاس صعودي. يُستخدم نمط hammer لتحديد نقاط دخول الشراء.

يظهر نمط hanging man خلال اتجاه صعودي ويشير إلى احتمال انعكاس هبوطي. يُستخدم نمط hanging man لتحديد نقاط دخول البيع.

تطوير cBot لتداول الاستراتيجية اليدوية

في Algo الخاص بـ cTrader، دعنا ننشئ خوارزمية تنفذ الاستراتيجية الموضحة في القسم السابق.

انقر على زر New تحت علامة التبويب cBot. اكتب Patterns Strategy في حقل الاسم وانقر على Create.

في طريقة OnBarClosed()، نقوم بتنفيذ المنطق الخاص باستراتيجيتنا. يجب أن تستوفي نقاط دخولنا هذين الشرطين:

  • يتطابق سعر الإغلاق مع السعر المرتفع.
  • حجم الشمعة أكبر بخمس مرات على الأقل من جسم الشمعة.

نبدأ بتحديد معلمات Volume وStopLoss وTakeProfit.

1
2
3
4
5
6
7
8
[Parameter(DefaultValue = 1000)]
public double Volume { get; set; }

[Parameter(DefaultValue = 10)]
public double StopLoss { get; set; }

[Parameter(DefaultValue = 10)]
public double TakeProfit { get; set; }

ثم نكتب مقطعًا برمجيًا لتنفيذ صفقة شراء عند استيفاء الشروط المطلوبة.

1
2
3
4
5
if (Bars.Last(0).Close == Bars.Last(0).High &&
            (Bars.Last(0).Close - Bars.Last(0).Open) < (Bars.Last(0).Close - Bars.Last(0).Low) * 0.2)
{
    ExecuteMarketOrder(TradeType.Buy, SymbolName, Volume, InstanceId, StopLoss, TakeProfit);
}
1
2
3
bar = api.Bars.Last(0)
if bar.Close == bar.High and (bar.Close - bar.Open) < (bar.Close - bar.Low) * 0.2:
    api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, api.Volume, api.InstanceId, api.StopLoss, api.TakeProfit)

على الجانب الآخر، هذه هي الشروط التي يجب استيفاؤها لنقاط دخول البيع لدينا:

  • يتطابق سعر الإغلاق مع السعر المنخفض.
  • حجم الشمعة أكبر بخمس مرات على الأقل من جسم الشمعة.

وبالمثل، نكتب مقطعًا برمجيًا لتنفيذ صفقة بيع عند استيفاء الشروط المطلوبة.

1
2
3
4
5
if (Bars.Last(0).Close == Bars.Last(0).Low &&
                (Bars.Last(0).Open - Bars.Last(0).Close) < (Bars.Last(0).High - Bars.Last(0).Close) * 0.2)
{
    ExecuteMarketOrder(TradeType.Sell, SymbolName, Volume, InstanceId, StopLoss, TakeProfit);
}
1
2
if bar.Close == bar.Low and (bar.Open - bar.Close) < (bar.High - bar.Close) * 0.2:
    api.ExecuteMarketOrder(TradeType.Sell, api.SymbolName, api.Volume, api.InstanceId, api.StopLoss, api.TakeProfit)

يمكنك نسخ الكود الكامل أدناه:

 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
37
38
39
40
41
42
43
44
45
46
47
using System;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None, AddIndicators = true)]
    public class PatternsStrategy : Robot
    {
        [Parameter(DefaultValue = 1000)]
        public double Volume { get; set; }

        [Parameter(DefaultValue = 10)]
        public double StopLoss { get; set; }

        [Parameter(DefaultValue = 10)]
        public double TakeProfit { get; set; }

        protected override void OnStart()
        {

        }

        protected override void OnBarClosed()
        {
            if (Bars.Last(0).Close == Bars.Last(0).High &&
            (Bars.Last(0).Close - Bars.Last(0).Open) < (Bars.Last(0).Close - Bars.Last(0).Low) * 0.2)
            {
                ExecuteMarketOrder(TradeType.Buy, SymbolName, Volume, InstanceId, StopLoss, TakeProfit);
            }

            if (Bars.Last(0).Close == Bars.Last(0).Low &&
            (Bars.Last(0).Open - Bars.Last(0).Close) < (Bars.Last(0).High - Bars.Last(0).Close) * 0.2)
            {
                ExecuteMarketOrder(TradeType.Sell, SymbolName, Volume, InstanceId, StopLoss, TakeProfit);
            }

        }

        protected override void OnStop()
        {

        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import clr
clr.AddReference("cAlgo.API")
from cAlgo.API import *
from robot_wrapper import *

class PatternsStrategy():
    def on_start(self):
        pass

    def on_bar_closed(self):
        bar = api.Bars.Last(0)

        if bar.Close == bar.High and (bar.Close - bar.Open) < (bar.Close - bar.Low) * 0.2:
            api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, api.Volume, api.InstanceId, api.StopLoss, api.TakeProfit)

        if bar.Close == bar.Low and (bar.Open - bar.Close) < (bar.High - bar.Close) * 0.2:
            api.ExecuteMarketOrder(TradeType.Sell, api.SymbolName, api.Volume, api.InstanceId, api.StopLoss, api.TakeProfit)

    def on_stop(self):
        pass

لبناء cBot، اضغط على Ctrl+B أو انقر على Build.

لإجراء الاختبار العكسي لـ cBot، نضيف أولاً مثيلاً. حدد خيار Locally، وحدد المعلمات المفضلة لديك وانقر على زر Add instance.

ثم ننتقل إلى علامة التبويب Backtesting، ونحدد فترة لعملية الاختبار العكسي ونبدأ الاختبار العكسي.

بمجرد اكتمال عملية الاختبار العكسي، يمكننا فحص الصفقات. سترى أن شروط الدخول قد تم استيفاؤها قبل دخول كل صفقة مباشرة.

مع النجاح في أتمتة استراتيجيتنا، يمكننا توظيف cBot لإجراء الصفقات نيابة عنا.

تنفيذ إستراتيجية انعكاس RSI

في مثالنا الثاني، نريد تنفيذ إستراتيجية تعتمد على انعكاس مؤشر القوة النسبية (RSI). في هذه الاستراتيجية، ندخل في مراكز متوقعين أن ينعكس اتجاه RSI ونتبع هذه القواعد:

  • عندما تنخفض قيمة RSI دون عتبة شراء RSI، ندخل في مركز شراء.
  • عندما ترتفع قيمة RSI فوق عتبة بيع RSI، ندخل في مركز بيع.

دعنا ننشئ cBot جديدًا، وندخل RSI Reversal Strategy كاسم له وننقر على Create.

بمجرد ظهور محرر التعليمات البرمجية، أضف System.Linq إلى أعلى التعليمات البرمجية كمرجع.

1
using System.Linq;

دعنا نضيف معلمتين ستسمحان لنا بتعديل العتبات قبل تشغيل cBot.

1
2
3
4
5
[Parameter(DefaultValue = 30)]
public int BuyLevel { get; set; }

[Parameter(DefaultValue = 70)]
public int SellLevel { get; set; }

نعلن ونهيئ مؤشر القوة النسبية الخاص بنا.

1
2
3
4
5
6
private RelativeStrengthIndex _rsi;

protected override void OnStart()
{
    _rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, 14);
}
1
2
3
class RSIReversalStrategy():
    def on_start(self):
        self._rsi = api.Indicators.RelativeStrengthIndex(api.Bars.ClosePrices, 14)

ثم نقوم بتنفيذ الشروط التي تحدد منطق التداول لدينا.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
protected override void OnBarClosed()
{

    if (_rsi.Result.LastValue < BuyLevel)
    {
        if (Positions.Count == 0)
            ExecuteMarketOrder(TradeType.Buy, SymbolName, 1000);
        foreach (var position in Positions.Where(p => p.TradeType == TradeType.Sell))
        {
            position.Close();
        }

    }
    else if (_rsi.Result.LastValue > SellLevel)
    {
        if (Positions.Count == 0)
            ExecuteMarketOrder(TradeType.Sell, SymbolName, 1000);
        foreach (var position in Positions.Where(p => p.TradeType == TradeType.Buy))
        {
            position.Close();
        }
    }

}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
def on_bar_closed(self):
    rsi_value = self._rsi.Result.LastValue

    if rsi_value < api.BuyLevel:
        if api.Positions.Count == 0:
            api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, 1000)
        for position in api.Positions:
            if position.TradeType == TradeType.Sell:
                position.Close()

    elif rsi_value > api.SellLevel:
        if api.Positions.Count == 0:
            api.ExecuteMarketOrder(TradeType.Sell, api.SymbolName, 1000)
        for position in api.Positions:
            if position.TradeType == TradeType.Buy:
                position.Close()

يمكنك نسخ الكود الكامل أدناه:

 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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None, AddIndicators = true)]
    public class RSIReversalStrategy : Robot
    {
        [Parameter(DefaultValue = 30)]
        public int BuyLevel { get; set; }

        [Parameter(DefaultValue = 70)]
        public int SellLevel { get; set; }

        private RelativeStrengthIndex _rsi;

        protected override void OnStart()
        {
            _rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, 14);
        }

        protected override void OnBarClosed()
        {

            if (_rsi.Result.LastValue < BuyLevel)
            {
                if (Positions.Count == 0)
                    ExecuteMarketOrder(TradeType.Buy, SymbolName, 1000);
                foreach (var position in Positions.Where(p => p.TradeType == TradeType.Sell))
                {
                    position.Close();
                }

            }
            else if (_rsi.Result.LastValue > SellLevel)
            {
                if (Positions.Count == 0)
                    ExecuteMarketOrder(TradeType.Sell, SymbolName, 1000);
                foreach (var position in Positions.Where(p => p.TradeType == TradeType.Buy))
                {
                    position.Close();
                }
            }

        }

        protected override void OnStop()
        {

        }
    }
}
 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
import clr
clr.AddReference("cAlgo.API")
from cAlgo.API import *
from robot_wrapper import *

class RSIReversalStrategy():
    def on_start(self):
        self._rsi = api.Indicators.RelativeStrengthIndex(api.Bars.ClosePrices, 14)

    def on_bar_closed(self):
        rsi_value = self._rsi.Result.LastValue

        if rsi_value < api.BuyLevel:
            if api.Positions.Count == 0:
                api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, 1000)
            for position in api.Positions:
                if position.TradeType == TradeType.Sell:
                    position.Close()

        elif rsi_value > api.SellLevel:
            if api.Positions.Count == 0:
                api.ExecuteMarketOrder(TradeType.Sell, api.SymbolName, 1000)
            for position in api.Positions:
                if position.TradeType == TradeType.Buy:
                    position.Close()

    def on_stop(self):
        pass

دعنا نبني استراتيجيتنا، ونضيف مثيلاً ونجري اختبارًا عكسيًا، كما فعلنا مع الاستراتيجية السابقة.

يمكننا فحص ومراجعة بعض الصفقات مرة أخرى لرؤية استيفاء شروط الدخول قبل دخول الصفقة مباشرة.

أظهرت هذه المقالة كيفية تحديد استراتيجية يدوية وتحويلها إلى استراتيجية آلية، مما يسمح بعمليات التداول الخوارزمي.

Image title