Langkau tajuk talian

Sampel kod plugin

Halaman ini menyediakan beberapa contoh kod Python dan C# untuk mencipta plugin natif, termasuk alat untuk dagangan manual atau algoritma dalam cTrader.

Repositori sampel plugin

Sampel kod plugin yang komprehensif, termasuk templat sedia untuk dijalankan bagi pelbagai kawasan UI dan fungsi, boleh didapati dalam repositori Python dan C# yang berasingan di GitHub.

Petua

Gunakan parameter tersuai dalam kedua-dua plugin C# dan Python untuk mencapai fleksibiliti yang lebih besar. Parameter tersuai untuk plugin C# diisytiharkan dalam kod C# biasa, manakala plugin Python memerlukan parameter tersuai diisytiharkan dalam fail .cs mereka.

Paparkan laman web dalam bingkai carta

Plugin berikut memaparkan laman web cTrader Store dalam bingkai carta yang berasingan.

 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")

Tulis maklumat ke storan setempat

Sekali setiap minit, plugin di bawah menyimpan jumlah untung dan rugi (P&L) akaun ke dalam fail menggunakan ciri storan setempat dan cap masa semasa sebagai nama fail. Ia juga memaparkan maklumat yang sama dalam bahagian berasingan dalam Panel Simbol Aktif (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}"

Paparkan tetingkap berasingan dengan kawalan tersuai

Plugin di bawah menambah butang tersuai ke tetingkap yang dipisahkan. Apabila diklik, kawalan tersebut menambah tahap ambilan untung untuk semua posisi terbuka tetapi hanya jika posisi tersebut tidak mempunyai ambilan untung yang ditetapkan sebelumnya.

 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)

Paparkan maklumat tentang harga bar dalam paparan Pantau Dagangan

Apabila dibina, plugin ini menambah tab baharu ke panel Pantau Dagangan. Tab ini mengandungi grid dua kali dua yang memaparkan maklumat tentang harga bar terakhir yang diketahui untuk rangka masa m1 dan simbol "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

Bertindak balas terhadap perubahan bingkai aktif

Plugin berikut mengesan ChartFrame yang sedang aktif. Di dalam blok tersuai dalam ASP, plugin menunjukkan perbezaan peratusan antara harga semasa simbol yang ChartFrame ini dibuka untuknya dan harga simbol ini kira-kira sebulan yang lalu.

 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