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

كيفية إنشاء روبوت تداول في Python

تقدم هذه المقالة والفيديو تعليمات خطوة بخطوة لإنشاء روبوت تداول في Python.

ملاحظة

cTrader هي منصة التداول الرئيسية الوحيدة التي تدعم Python بشكل أصلي، مما يتيح لك كتابة الكود بلغة Python وبناء الروبوتات والمؤشرات التقنية والأدوات مباشرة في cTrader على نظامي Windows أو Mac. لا حاجة إلى محول أو حل معقد.

إنشاء روبوت تداول

في علامة التبويب cBots في تطبيق Algo، انقر فوق الزر جديد لبدء إنشاء روبوت تداول جديد.

أعطِ cBot اسمًا وحدد Python كلغة البرمجة.

ملاحظة

يوفر cTrader العديد من الخوارزميات الجاهزة بلغة Python التي تغطي مجموعة واسعة من الاستراتيجيات وإجراءات التداول الآلي. تحتوي قوالب الخوارزميات هذه بالفعل على منطق تداول ومعلمات قابلة للتخصيص وجاهزة للتشغيل بمجرد حفظها وبنائها.

حدد استخدام قالب كطريقة الإنشاء، واختر عينة الشبكة، ثم انقر فوق إنشاء.

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

دعونا نبني cBot الخاص بنا للتحقق من صحة الكود.

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

اضغط على Cmd+B أو انقر فوق أيقونة بناء.

إضافة مؤشر

دعونا ندمج مؤشرًا في روبوت التداول الخاص بنا لتحسين دقته.

يعد مؤشر القوة النسبية (RSI) مؤشرًا شائعًا يشير إلى حالات الشراء المفرط أو البيع المفرط في السوق. يمكن أن يساعد هذا المؤشر cBot الخاص بنا على تجنب فتح مراكز جديدة عندما يكون السوق ممتدًا في اتجاه واحد.

دمج RSI في منطق الروبوت. قم بتهيئة المؤشر بفترة افتراضية قدرها 14 وحدد مستويات الشراء المفرط والبيع المفرط عند 70 و30 على التوالي. استخدم أسعار الإغلاق للرمز لإنشاء RSI.

1
2
3
4
self.rsi_period = getattr(api, "RsiPeriod", 14)
self.rsi_overbought = getattr(api, "RsiOverbought", 70)
self.rsi_oversold = getattr(api, "RsiOversold", 30)
self.rsi = api.Indicators.RelativeStrengthIndex(api.Bars.ClosePrices, self.rsi_period)

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

1
2
3
4
5
6
if len(self.get_grid_positions()) == 0:
    # self.open_position()
    if self.passes_rsi_filter():
        self.open_position()
    else:
        api.Print("RSI filter blocked initial entry (RSI={:.2f})".format(self.get_rsi_value()))

اكتب الكود الذي يضمن فتح مركز الشبكة فقط إذا تحرك السعر بما فيه الكفاية وكانت قيمة RSI ضمن نطاق محايد. استخدم قيمة RSI للشمعة الأخيرة المغلقة للاستقرار واطبع رسالة عند الحظر بواسطة فلتر RSI.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
if distance >= api.StepPips:
    # self.open_position()
    if self.passes_rsi_filter():
        self.open_position()
    else:
        api.Print("RSI filter: no new entry (RSI={:.2f}, range {}-{})"
                    .format(self.get_rsi_value(), self.rsi_oversold, self.rsi_overbought))

def get_rsi_value(self):
    # Use the last CLOSED bar for stability
    return self.rsi.Result.Last(1)

def passes_rsi_filter(self):
    r = self.get_rsi_value()
    return (r > self.rsi_oversold) and (r < self.rsi_overbought)

اضبط منطق الحساب للمسافة بالنقاط بين سعر السوق الحالي وسعر دخول المركز.

1
2
3
4
5
6
7
def get_distance_in_pips(self, position):
    # return (position.EntryPrice - api.Symbol.Ask if position.TradeType == TradeType.Buy else api.Symbol.Bid - position.EntryPrice) / api.Symbol.PipSize
    if position.TradeType == TradeType.Buy:
        diff = position.EntryPrice - api.Symbol.Ask
    else:
        diff = api.Symbol.Bid - position.EntryPrice
    return diff / api.Symbol.PipSize

يمكنك نسخ كود Python الكامل مع مؤشر RSI المدمج أدناه:

 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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import clr

clr.AddReference("cAlgo.API")

# Import cAlgo API types
from cAlgo.API import *

# Import trading wrapper functions
from robot_wrapper import *

class SupercBot():
    def on_start(self):
        self.volumeInUnits = api.Symbol.QuantityToVolumeInUnits(api.VolumeInLots)
        self.enoughMoney = True

        self.rsi_period = getattr(api, "RsiPeriod", 14)
        self.rsi_overbought = getattr(api, "RsiOverbought", 70)
        self.rsi_oversold = getattr(api, "RsiOversold", 30)
        self.rsi = api.Indicators.RelativeStrengthIndex(api.Bars.ClosePrices, self.rsi_period)

        if len(self.get_grid_positions()) == 0:
            if self.passes_rsi_filter():
                self.open_position()
            else:
                api.Print("RSI filter blocked initial entry (RSI={:.2f})".format(self.get_rsi_value()))

    def on_tick(self):
        grid_positions = self.get_grid_positions()
        net_profit_sum = sum([p.NetProfit for p in grid_positions])
        if net_profit_sum >= api.TargetProfit:
            api.Print("Target profit is reached. Closing all grid positions")
            self.close_grid_positions()
            api.Print("All grid positions are closed. Stopping cBot")
            api.Stop()

        if len(grid_positions) > 0 and self.enoughMoney == True:
            position_with_highest_pips = sorted(grid_positions, key=lambda pos: pos.Pips, reverse=True)[0]
            distance = self.get_distance_in_pips(position_with_highest_pips)          
            if distance >= api.StepPips:
                if self.passes_rsi_filter():
                    self.open_position()
                else:
                    api.Print("RSI filter: no new entry (RSI={:.2f}, range {}-{})"
                              .format(self.get_rsi_value(), self.rsi_oversold, self.rsi_overbought))

    def get_rsi_value(self):
        # Use the last CLOSED bar for stability
        return self.rsi.Result.Last(1)

    def passes_rsi_filter(self):
        r = self.get_rsi_value()
        return (r > self.rsi_oversold) and (r < self.rsi_overbought)

    def get_grid_positions(self):
        return [pos for pos in api.Positions if pos.SymbolName == api.SymbolName and pos.TradeType == api.TradeType]

    def open_position(self):
        result = api.ExecuteMarketOrder(api.TradeType, api.SymbolName, self.volumeInUnits, "Grid")
        if result.Error == ErrorCode.NoMoney:
            self.enoughMoney = False
            api.Print("Not enough money to open additional positions")

    def close_grid_positions(self):
        for position in self.get_grid_positions():
            position.Close()

        if len(self.get_grid_positions()) > 0:
            self.close_grid_positions()

    def get_distance_in_pips(self, position):
        if position.TradeType == TradeType.Buy:
            diff = position.EntryPrice - api.Symbol.Ask
        else:
            diff = api.Symbol.Bid - position.EntryPrice
        return diff / api.Symbol.PipSize

بدء مثيل

دعونا نعود إلى cBot الخاص بنا ونقوم ببنائه. الآن، انقر فوق أيقونة بدء cBot لأي مثيل، وسيبدأ روبوت التداول في التشغيل.

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

من خلال إضافة وتخصيص مثيلات جديدة، يمكنك تشغيل cBot في وقت واحد على رموز أو فترات أو معلمات مختلفة.

تشغيل الروبوت في مكان آخر

مع تمكين المزامنة السحابية، يظهر cBot تلقائيًا في جميع تطبيقات cTrader حيث يكون cTID الخاص بك نشطًا. يمكننا بدء نفس روبوت التداول في السحابة في أي تطبيق cTrader، بما في ذلك cTrader Mobile وWeb.

في cTrader Algo، ابدأ تشغيل cBot.

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

Image title