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

عينات كود الإضافة

توفر هذه الصفحة العديد من أمثلة الكود بلغتي Python وC# لإنشاء إضافات أصلية، بما في ذلك أدوات للتداول اليدوي أو الخوارزمي في cTrader.

مستودعات عينات الإضافات

تتوفر عينات كود شاملة للإضافات، بما في ذلك قوالب جاهزة للتشغيل لمختلف مناطق واجهة المستخدم والوظائف، في مستودعات منفصلة لـ Python و C# على GitHub.

نصيحة

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

عرض موقع ويب في إطار رسم بياني

تعرض الإضافة التالية موقع متجر 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
25
26
27
28
29
30
31
32
33
34
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.Plugins
{
    [Plugin(AccessRights = AccessRights.None)]
    public class ForumExample : Plugin
    {
        private WebView _cTraderWebView;

        protected override void OnStart()
        {
            _cTraderWebView = new WebView();
            _cTraderWebView.Loaded += DisplayForum;

            var webViewFrame = ChartManager.AddCustomFrame("Forum");
            webViewFrame.Child = _cTraderWebView;
            webViewFrame.ChartContainer.Mode = ChartMode.Multi;
            webViewFrame.Attach();
        }


        private void DisplayForum(WebViewLoadedEventArgs args)
        {
            _cTraderWebView.NavigateAsync("https://ctrader.com/forum");
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import clr
clr.AddReference("cAlgo.API")

from cAlgo.API import *

class ForumExample():
    def on_start(self):
        self.cTraderWebView = WebView()
        self.cTraderWebView.Loaded += self.display_forum

        webViewFrame = api.ChartManager.AddCustomFrame("Forum")
        webViewFrame.Child = self.cTraderWebView
        webViewFrame.ChartContainer.Mode = ChartMode.Multi
        webViewFrame.Attach()

    def display_forum(self, args):
        self.cTraderWebView.NavigateAsync("https://ctrader.com/forum")

كتابة المعلومات في التخزين المحلي

مرة واحدة كل دقيقة، تحفظ الإضافة أدناه إجمالي الربح والخسارة (P&L) للحساب في ملف باستخدام ميزة التخزين المحلي والطابع الزمني الحالي كاسم للملف. كما تعرض نفس المعلومات في قسم منفصل في لوحة الرمز النشط (ASP).

 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
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.Plugins
{
    [Plugin(AccessRights = AccessRights.None)]
    public class GrossPnL : Plugin
    {
        private TextBlock _textBlock = new TextBlock
        {
            Text = "Starting...",
            FontSize = 15,
            FontWeight = FontWeight.ExtraBold,
            TextAlignment = TextAlignment.Center,
            Padding = new Thickness(5, 5, 5, 5),
        };

        protected override void OnStart()
        {
            var aspBlock = Asp.SymbolTab.AddBlock("Gross P&L");
            aspBlock.Child = _textBlock;
            Timer.Start(TimeSpan.FromMinutes(1));
        }

        protected override void OnTimer()
        {
            var timestamp = Server.TimeInUtc;

            string result = timestamp.ToString("HH mm ss");

            LocalStorage.SetString($"{result}", $"{Account.UnrealizedGrossProfit}", LocalStorageScope.Device);

            _textBlock.Text = $"{result}: {Account.UnrealizedGrossProfit}";
        }

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

from cAlgo.API import *

class GrossPnL():
    def on_start(self):
        self.textBlock = TextBlock()
        self.textBlock.Text = "Starting..."
        self.textBlock.FontSize = 15
        self.textBlock.FontWeight = FontWeight.ExtraBold
        self.textBlock.TextAlignment = TextAlignment.Center
        self.textBlock.Padding = Thickness(5, 5, 5, 5)

        aspBlock = api.Asp.SymbolTab.AddBlock("Gross P&L")
        aspBlock.Child = self.textBlock

        api.Timer.Start(60)

    def on_timer(self):
        timestamp = api.Server.TimeInUtc

        result = timestamp.ToString("HH mm ss")

        api.LocalStorage.SetString(result, f"{api.Account.UnrealizedGrossProfit}", LocalStorageScope.Device)

        self.textBlock.Text = f"{result}: {api.Account.UnrealizedGrossProfit}"

عرض نافذة منفصلة مع عنصر تحكم مخصص

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

 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
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.Plugins
{
    [Plugin(AccessRights = AccessRights.None)]
    public class ProtectionPlugin : Plugin
    {

        private Button _buttonAddTakeProfit;
        private Window _window;

        protected override void OnStart()
        {
            _buttonAddTakeProfit = new Button
            {
                BackgroundColor = Color.SeaGreen,
                Height = 50,
                Text = "Add Take Profit"
            };

            _buttonAddTakeProfit.Click += AddTakeProfit;
            _window = new Window
            {
                Height = 150,
                Width = 150,
                Padding = new Thickness(5, 10, 10, 5),
            };

            _window.Child = _buttonAddTakeProfit;
            _window.Show();
        }

        private void AddTakeProfit(ButtonClickEventArgs args)
        {
            foreach (var position in Positions)
            {
                if (position.TakeProfit is null)
                {
                    position.ModifyTakeProfitPips(20);
                }
            }
        }
    }
}
 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
import clr
clr.AddReference("cAlgo.API")

from cAlgo.API import *

class ProtectionPlugin():
    def on_start(self):
        self.buttonAddTakeProfit = Button()
        self.buttonAddTakeProfit.BackgroundColor = Color.SeaGreen
        self.buttonAddTakeProfit.Height = 50
        self.buttonAddTakeProfit.Text = "Add Take Profit"

        self.buttonAddTakeProfit.Click += self.On_add_take_profit_click

        self.window = Window()
        self.window.Height = 150
        self.window.Width = 150
        self.window.Padding = Thickness(5, 10, 10, 5)

        self.window.Child = self.buttonAddTakeProfit
        self.window.Show()

    def On_add_take_profit_click(self, args):
        for position in api.Positions:
            if position.TakeProfit is None:
                position.ModifyTakeProfitPips(20)

عرض معلومات حول أسعار الشموع في شاشة Trade Watch

عند بنائها، تضيف هذه الإضافة علامة تبويب جديدة إلى لوحة Trade Watch. تحتوي علامة التبويب هذه على شبكة 2×2 تعرض معلومات حول آخر أسعار شموع معروفة للإطار الزمني m1 والرمز "USDJPY".

 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
76
77
78
79
80
81
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.Plugins
{
    [Plugin(AccessRights = AccessRights.None)]
    public class BarInfo : Plugin
    {
        private Grid _grid;
        private TextBlock _lowBlock;
        private TextBlock _highBlock;
        private TextBlock _closeBlock;
        private TextBlock _openBlock;
        private Bars _bars;

        protected override void OnStart()
        {
            _bars = MarketData.GetBars(TimeFrame.Minute, "USDJPY");
            _grid = new Grid(2, 2)
            {
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
                ShowGridLines = true,
                Height = 150,
                Width = 150,
            };

            _lowBlock = new TextBlock
            {
                Text = $"Low: {_bars.LowPrices.LastValue}",
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
            };

            _highBlock = new TextBlock
            {
                Text = $"High: {_bars.HighPrices.LastValue}",
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
            };

            _closeBlock = new TextBlock
            {
                Text = $"Low: {_bars.ClosePrices.LastValue}",
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
            };

            _openBlock = new TextBlock
            {
                Text = $"Open: {_bars.OpenPrices.LastValue}",
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
            };

            _grid.AddChild(_lowBlock, 0, 0);
            _grid.AddChild(_highBlock, 0, 1);
            _grid.AddChild(_openBlock, 1, 0);
            _grid.AddChild(_closeBlock, 1, 1);

            var TradeWatchTab = TradeWatch.AddTab("Bar Info");
            TradeWatchTab.Child = _grid;
            TradeWatchTab.IsSelected = true;
            _bars.Tick += OnBarsTick;
        }

        private void OnBarsTick(BarsTickEventArgs args)
        {
            _lowBlock.Text = _bars.LowPrices.LastValue.ToString();
            _highBlock.Text = _bars.HighPrices.LastValue.ToString();
            _openBlock.Text = _bars.HighPrices.LastValue.ToString();
            _closeBlock.Text = _bars.HighPrices.LastValue.ToString();
        }
    }
}
 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
import clr
clr.AddReference("cAlgo.API")

from cAlgo.API import *

class BarInfo():
    def on_start(self):
        tradeWatchTab = api.TradeWatch.AddTab("Bar Info")
        tradeWatchTab.IsSelected = True

        grid = Grid(2, 2)
        grid.HorizontalAlignment = HorizontalAlignment.Center
        grid.VerticalAlignment = VerticalAlignment.Center
        grid.ShowGridLines = True
        grid.Height = 150
        grid.Width = 150

        self.bars = api.MarketData.GetBars(TimeFrame.Minute, "USDJPY")

        self.lowBlock = self.get_text_block(f"Low: {self.bars.LowPrices.LastValue}")
        self.highBlock = self.get_text_block(f"High: {self.bars.HighPrices.LastValue}")
        self.openBlock = self.get_text_block(f"Open: {self.bars.OpenPrices.LastValue}")
        self.closeBlock = self.get_text_block(f"Close: {self.bars.ClosePrices.LastValue}")

        grid.AddChild(self.lowBlock, 0, 0)
        grid.AddChild(self.highBlock, 0, 1)
        grid.AddChild(self.openBlock, 1, 0)
        grid.AddChild(self.closeBlock, 1, 1)

        tradeWatchTab.Child = grid

        self.bars.Tick += self.on_bars_Tick

    def on_bars_Tick(self, args):
        self.lowBlock.Text = f"Low: {self.bars.LowPrices.LastValue}"
        self.highBlock.Text = f"High: {self.bars.HighPrices.LastValue}"
        self.openBlock.Text = f"Open: {self.bars.OpenPrices.LastValue}"
        self.closeBlock.Text = f"Close: {self.bars.ClosePrices.LastValue}"

    def get_text_block(self, text):
        textblock = TextBlock()
        textblock.Text = text
        textblock.HorizontalAlignment = HorizontalAlignment.Center
        textblock.VerticalAlignment = VerticalAlignment.Center
        return textblock

الاستجابة لتغيير الإطار النشط

تكتشف الإضافة التالية أي ChartFrame نشط حاليًا. داخل كتلة مخصصة في ASP، تعرض الإضافة النسبة المئوية للفرق بين السعر الحالي للرمز الذي تم فتح ChartFrame له وسعر هذا الرمز قبل شهر واحد تقريبًا.

 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
using System;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Plugins
{
    [Plugin(AccessRights = AccessRights.None)]
    public class ActiveFrameChangedSample : Plugin
    {

        // Declaring the necessary UI elements
        private Grid _grid;
        private TextBlock _percentageTextBlock;
        private Frame _activeFrame;

        protected override void OnStart()
        {
            // Initialising the grid and the TextBlock
            // displaying the percentage difference
            _grid = new Grid(1, 1);
            _percentageTextBlock = new TextBlock
            {
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
                Text = "Monthly change: ",
            };

            _grid.AddChild(_percentageTextBlock, 0, 0);

            // Initialising a new block inside the ASP
            // and adding the grid as a child
            var block = Asp.SymbolTab.AddBlock("Monthly Change Plugin");

            block.Child = _grid;

            // Attaching a custom handler to the
            // ActiveFrameChanged event
            ChartManager.ActiveFrameChanged += ChartManager_ActiveFrameChanged;
        }

        private void ChartManager_ActiveFrameChanged(ActiveFrameChangedEventArgs obj)
        {
            if (obj.NewFrame is ChartFrame)
            {
                // Casting the Frame into a ChartFrame
                var newChartFrame = obj.NewFrame as ChartFrame;

                // Attaining market data for the symbol for which
                // the currently active ChartFrame is opened
                var dailySeries = MarketData.GetBars(TimeFrame.Daily, newChartFrame.Symbol.Name);

                // Calculating the monthly change and displaying it
                // inside the TextBlock
                double monthlyChange = (newChartFrame.Symbol.Bid - dailySeries.ClosePrices[dailySeries.ClosePrices.Count - 30]) / 100;
                _percentageTextBlock.Text = $"Monthly change: {monthlyChange}";
            }
        }
    }
}
 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
import clr
clr.AddReference("cAlgo.API")

from cAlgo.API import *

class ActiveFrameChangedSample():
    def on_start(self):
        # Initialising the grid and the TextBlock displaying the percentage difference
        grid = Grid(1, 1)
        self.percentageTextBlock = TextBlock()
        self.percentageTextBlock.HorizontalAlignment = HorizontalAlignment.Center
        self.percentageTextBlock.VerticalAlignment = VerticalAlignment.Center
        self.percentageTextBlock.Text = "Monthly change: "

        grid.AddChild(self.percentageTextBlock, 0, 0)

        # Initialising a new block inside the ASP and adding the grid as a child
        block = api.Asp.SymbolTab.AddBlock("Monthly Change Plugin")
        block.Child = grid

        # Attaching an event handler to the ActiveFrameChanged event
        api.ChartManager.ActiveFrameChanged += self.on_chart_manager_active_frame_changed

    def on_chart_manager_active_frame_changed(self, args):
        if args.NewFrame is None or isinstance(args.NewFrame.__implementation__, ChartFrame) == False:
            return

        newChartFrame = ChartFrame(args.NewFrame)

        # Attaining market data for the symbol for which the currently active ChartFrame is opened
        dailySeries = api.MarketData.GetBars(TimeFrame.Daily, newChartFrame.Symbol.Name)

        # Calculating the monthly change and displaying it inside the TextBlock
        monthlyChange = (newChartFrame.Symbol.Bid - dailySeries.ClosePrices[dailySeries.ClosePrices.Count - 30]) / 100
        self.percentageTextBlock.Text = f"Monthly change: {monthlyChange}"

Image title