Przejdź do treści

TradeWatch Tab Sample

Przegląd

Wtyczka TradeWatch Tab Sample dodaje nową zakładkę do Trade Watch, wyświetlającą statystyki na żywo i działania handlowe dla symbolu na aktywnym wykresie. Zapewnia następujące kluczowe funkcje:

  • Automatycznie dodaje wtyczkę jako nową zakładkę w Trade Watch.
  • Wyświetla statystyki handlowe na żywo.
  • Umożliwia realizację zleceń rynkowych dla bieżącego symbolu wykresu.
  • Aktualizuje się automatycznie po zmianie symbolu aktywnego wykresu.

Wtyczka działa poprzez dedykowaną zakładkę Trade Watch, która odzwierciedla aktywny wykres. Pozostaje aktywna, gdy cTrader Windows lub Mac jest uruchomiony i automatycznie zwalnia zasoby systemowe po zatrzymaniu.

Tworzenie wtyczki

Dowiedz się, jak tworzyć wtyczki, używając C# lub Pythona, w naszych krok po kroku przewodnikach.

Kod wtyczki TradeWatch Tab Sample jest dostępny w naszych publicznych repozytoriach C# i Python. Ten sam kod jest dostarczany jako szablon w kreatorze tworzenia algorytmu w cTrader Windows lub Mac, lub możesz po prostu skopiować i użyć poniższego fragmentu:

 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
using cAlgo.API;

namespace cAlgo.Plugins
{
    [Plugin(AccessRights = AccessRights.None)]
    public class MyTradeWatchTabSample1 : Plugin
    {
        private SymbolStatsControl _symbolStatsControl;
        private TradeControl _tradeControl;

        protected override void OnStart()
        {
            var tab = TradeWatch.AddTab("Active Chart Symbol Stats");

            var panel = new StackPanel
                {Orientation = Orientation.Vertical, HorizontalAlignment = HorizontalAlignment.Center};

            _symbolStatsControl = new SymbolStatsControl {Margin = 10};
            _tradeControl = new TradeControl {Margin = 10};

            panel.AddChild(_symbolStatsControl);
            panel.AddChild(_tradeControl);

            tab.Child = panel;

            SetSymbolStats();

            _tradeControl.Trade += TradeControlOnTrade;
            ChartManager.ActiveFrameChanged += _ => SetSymbolStats();
        }

        private void TradeControlOnTrade(object sender, TradeEventArgs e)
        {
            ExecuteMarketOrder(e.TradeType, e.SymbolName, e.Volume);
        }

        private void SetSymbolStats()
        {
            if (ChartManager.ActiveFrame is not ChartFrame chartFrame)
                return;

            _tradeControl.Symbol = chartFrame.Symbol;
            _symbolStatsControl.Symbol = chartFrame.Symbol;
        }
    }
}
  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
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
import clr
clr.AddReference("cAlgo.API")

from cAlgo.API import *

class TradeWatchTabSample():
    def on_start(self):
        tab = api.TradeWatch.AddTab("Active Chart Symbol Stats")

        panel = StackPanel()
        panel.Orientation = Orientation.Vertical
        panel.HorizontalAlignment = HorizontalAlignment.Center

        self.symbolStatsControl = SymbolStatsControl()
        self.symbolStatsControl.Margin = Thickness(10)
        self.tradeControl = TradeControl(self.on_trade)
        self.tradeControl.Margin = Thickness(10)

        panel.AddChild(self.symbolStatsControl.content)
        panel.AddChild(self.tradeControl.content)

        tab.Child = panel

        self.set_symbol_stats()

        api.ChartManager.ActiveFrameChanged += lambda _ : self.set_symbol_stats()

    def on_trade(self, args):
        api.ExecuteMarketOrder(args["tradeType"], args["symbolName"], args["volume"])

    def set_symbol_stats(self):
        if api.ChartManager.ActiveFrame is None or isinstance(api.ChartManager.ActiveFrame.__implementation__, ChartFrame) == False:
            return;

        chartFrame = ChartFrame(api.ChartManager.ActiveFrame)
        self.tradeControl.set_symbol(chartFrame.Symbol)
        self.symbolStatsControl.set_symbol(chartFrame.Symbol)


class SymbolStatsControl():
    def __init__(self):
        self.__symbol__ = None
        self.content = StackPanel()
        self.content.Orientation = Orientation.Vertical

        self.symbolNameTextBlock = self.get_text_block()
        self.symbolPriceTextBlock = self.get_text_block()

        self.content.AddChild(self.wrap_in_horizontal_panel(self.symbolNameTextBlock, self.symbolPriceTextBlock))

        grid = Grid(10, 2)

        self.spreadTextBlock = self.get_text_block()

        grid.AddChild(self.get_text_block("Spread"), 0, 0)
        grid.AddChild(self.spreadTextBlock, 0, 1)

        self.unrealizedNetProfitTextBlock = self.get_text_block()

        grid.AddChild(self.get_text_block("Unrealized Net Profit"), 1, 0)
        grid.AddChild(self.unrealizedNetProfitTextBlock, 1, 1)

        self.unrealizedGrossProfitTextBlock = self.get_text_block()

        grid.AddChild(self.get_text_block("Unrealized Gross Profit"), 2, 0)
        grid.AddChild(self.unrealizedGrossProfitTextBlock, 2, 1)

        self.commissionTextBlock = self.get_text_block()

        grid.AddChild(self.get_text_block("Commission"), 3, 0)
        grid.AddChild(self.commissionTextBlock, 3, 1)

        self.content.AddChild(grid);

    def get_text_block(self, text = None):
        textBlock = TextBlock()
        textBlock.Margin = Thickness(3)
        textBlock.FontSize = 20
        textBlock.FontWeight = FontWeight.Bold
        textBlock.FontFamily = "Calibri"
        textBlock.Text = text
        return textBlock

    def wrap_in_horizontal_panel(self, *args):
        panel = StackPanel()
        panel.Orientation = Orientation.Horizontal

        for control in args:
            if control.Margin == Thickness(0):
                control.Margin = 3
            panel.AddChild(control)

        return panel

    def get_symbol(self):
        return self.__symbol__

    def set_symbol(self, symbol):
        if symbol is None or symbol == self.__symbol__:
            return

        self.update(symbol)

    def update(self, newSymbol):
        previousSymbol = self.__symbol__;
        self.__symbol__ = newSymbol;

        self.symbolNameTextBlock.Text = f"{newSymbol.Name} ({newSymbol.Description})"
        self.symbolPriceTextBlock.Text = f"Bid: {newSymbol.Bid}, Ask: {newSymbol.Ask}"
        self.spreadTextBlock.Text = f"{self.get_spread_in_pips(newSymbol)} Pips"
        self.unrealizedNetProfitTextBlock.Text = str(newSymbol.UnrealizedNetProfit)
        self.unrealizedGrossProfitTextBlock.Text = str(newSymbol.UnrealizedGrossProfit)
        self.commissionTextBlock.Text = f"{newSymbol.Commission} {newSymbol.CommissionType}"

        if previousSymbol is not None: 
            previousSymbol.Tick -= self.on_symbol_tick

        newSymbol.Tick += self.on_symbol_tick

    def get_spread_in_pips(self, symbol):
        return (symbol.Spread * pow(10, symbol.Digits)) / (symbol.PipSize / symbol.TickSize);

    def on_symbol_tick(self, args):
        self.symbolPriceTextBlock.Text = f"Bid: {args.Bid}, Ask: {args.Ask}"
        self.spreadTextBlock.Text = f"{self.get_spread_in_pips(args.Symbol)} Pips"
        self.unrealizedNetProfitTextBlock.Text = str(args.Symbol.UnrealizedNetProfit)
        self.unrealizedGrossProfitTextBlock.Text = str(args.Symbol.UnrealizedGrossProfit)

class TradeControl():
    def __init__(self, on_trade):
        self.__symbol__ = None
        self.__on_trade__ = on_trade
        self.content = Grid(10, 2)

        self.volumeTextBox = TextBox()
        self.volumeTextBox.MinWidth = 200
        self.volumeTextBox.FontFamily = "Calibri"
        self.volumeTextBox.FontSize = 20
        self.volumeTextBox.FontWeight = FontWeight.Bold
        self.volumeTextBox.Margin = Thickness(3)

        self.content.AddChild(self.get_text_block("Volume"), 0, 0)
        self.content.AddChild(self.volumeTextBox, 0, 1);

        self.tradeTypeComboBox = ComboBox()
        self.tradeTypeComboBox.MinWidth = 200
        self.tradeTypeComboBox.FontFamily = "Calibri"
        self.tradeTypeComboBox.FontSize = 20
        self.tradeTypeComboBox.FontWeight = FontWeight.Bold
        self.tradeTypeComboBox.Margin = Thickness(3)

        self.tradeTypeComboBox.AddItem("Buy")
        self.tradeTypeComboBox.AddItem("Sell")

        self.tradeTypeComboBox.SelectedItem = "Buy"

        tradeTypeTextBlock = self.get_text_block("Trade Type")

        tradeTypeTextBlock.VerticalAlignment = VerticalAlignment.Center

        self.content.AddChild(tradeTypeTextBlock, 1, 0)
        self.content.AddChild(self.tradeTypeComboBox, 1, 1)

        executeButton = Button()
        executeButton.Text = "Execute"
        executeButton.FontFamily = "Calibri"
        executeButton.BackgroundColor = Color.Red

        executeButton.Click += self.on_execute_button_click

        self.content.AddChild(executeButton, 2, 0, 1, 2);

    def get_text_block(self, text = None):
        textBlock = TextBlock()
        textBlock.Margin = Thickness(3)
        textBlock.FontSize = 20
        textBlock.FontWeight = FontWeight.Bold
        textBlock.FontFamily = "Calibri"
        textBlock.Text = text
        return textBlock

    def get_symbol(self):
        return self.__symbol__

    def set_symbol(self, symbol):
        if symbol is None or symbol == self.__symbol__:
            return

        self.__symbol__ = symbol
        self.volumeTextBox.Text = str(self.__symbol__.VolumeInUnitsMin)

    def on_execute_button_click(self, args):
        if self.__symbol__ is None:
            return;

        volume = float(self.volumeTextBox.Text)
        tradeType = TradeType.Buy if self.tradeTypeComboBox.SelectedItem == "Buy" else TradeType.Sell

        self.__on_trade__({"volume": volume, "tradeType": tradeType, "symbolName": self.__symbol__.Name});

Opcje dostosowywania

Ta wtyczka łączy kontekst wykresu w czasie rzeczywistym z realizacją transakcji poprzez panel Trade Watch. Poniższa tabela przedstawia jej kluczowe komponenty i ich funkcje:

Parametr Opis Możliwe wartości
TradeWatch.AddTab Konfiguracja zakładki dla panelu Trade Watch. Active chart symbol stats
StackPanel.Orientation Definiuje kierunek układania elementów interfejsu użytkownika. Vertical lub horizontal
HorizontalAlignment Definiuje wyrównanie poziome panelu w zakładce. Center, left, right itp.
SymbolStatsControl.Margin Ustawia margines wokół elementu kontrolnego statystyk symbolu. 10, 12, 14 itp.
TradeControl.Margin Ustawia margines wokół elementu kontrolnego transakcji. 10, 12, 14 itp.
SymbolStatsControl.Symbol Wiąże element kontrolny statystyk symbolu z konkretnym symbolem wykresu. chartframe.symbol, eurusd, gbpjpy itp.
TradeControl.Symbol Łączy TradeControl z symbolem dla działań handlowych. chartframe.symbol, eurusd, gbpjpy itp.
ChartManager.ActiveFrameChanged Zdarzenie, które wyzwala aktualizacje statystyk symbolu po zmianie ramki wykresu. _ => setsymbolstats()
TradeControl.Trade Zdarzenie wyzwalane po podjęciu działania handlowego z panelu kontrolnego. tradecontrolontrade lub null
ExecuteMarketOrder Realizuje transakcję po wywołaniu. e.tradetype, e.symbolname, e.volume

Przypadki użycia

Wtyczka TradeWatch Tab Sample zapewnia prosty sposób na ulepszenie cTrader poprzez połączenie kontekstu wykresu w czasie rzeczywistym z realizacją transakcji. Wspiera praktyczne zastosowania, które usprawniają przepływy pracy handlowej. Poniżej przedstawiono praktyczne przypadki użycia, które pokazują, jak wtyczka może ulepszyć doświadczenie handlowe.

Przypadek użycia Scenariusz Wartość
Blokada symbolu Ustaw zakładkę wtyczki tak, aby zawsze wyświetlała stały symbol, taki jak EURUSD, zamiast aktualizować się przy każdej zmianie wykresu. Pomaga śledzić i handlować jednym instrumentem konsekwentnie, niezależnie od kontekstu wykresu.
Panel handlowy zsynchronizowany z wykresem Utrzymuj wtyczkę zsynchronizowaną z symbolem aktywnego wykresu, aby zawsze pokazywać odpowiednie statystyki i opcje handlowe. Pozwala szybko reagować na analizę wykresu bez przełączania narzędzi lub paneli.
Transakcja o stałym wolumenie Dostosuj domyślny wolumen w obsłudze zleceń do stałego lub preferowanego rozmiaru lota. Upraszcza realizację, eliminując konieczność dostosowywania wolumenu za każdym razem.
Terminal szybkich działań Zmień pozycję kontrolek poziomo i wyśrodkuj je, aby uzyskać usprawniony panel handlowy. Umożliwia szybszy dostęp zarówno do statystyk, jak i przycisków handlowych w kompaktowych konfiguracjach.

Podsumowanie

TradeWatch Tab Sample upraszcza przepływy pracy handlowej, łącząc statystyki w czasie rzeczywistym i kontrolki handlowe w dedykowanej zakładce w Trade Watch. Aktualizuje się automatycznie z aktywnym wykresem, a jego układ, zachowanie symbolu i ustawienia transakcji można dostosować do różnych stylów handlowych lub obszarów zainteresowania.

Aby uzyskać więcej szczegółów dotyczących rozwoju, zapoznaj się z naszą dokumentacją wtyczek.