Перейти к содержанию

TradeWatch Tab Sample

Обзор

Плагин TradeWatch Tab Sample добавляет новую вкладку в Обзор сделок, отображая актуальную статистику и торговые действия для инструмента на активном графике. Он предоставляет следующие ключевые функции:

  • Автоматически добавляет плагин в качестве новой вкладки в Обзор сделок.
  • Отображает актуальную торговую статистику.
  • Позволяет исполнять рыночные ордера для текущего инструмента графика.
  • Автоматически обновляется при изменении инструмента активного графика.

Плагин работает через выделенную вкладку в Обзоре сделок, которая отражает активный график. Он остается активным, пока запущен cTrader Windows или Mac, и автоматически освобождает системные ресурсы при остановке.

Создание плагина

Узнайте, как создавать плагины на C# или Python, в наших пошаговых руководствах.

Код плагина TradeWatch Tab Sample доступен в наших публичных репозиториях C# и Python. Тот же код предоставляется в качестве шаблона в мастере создания алгоритмов в cTrader Windows или Mac, или вы можете просто скопировать и использовать фрагмент ниже:

 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});

Параметры настройки

Этот плагин связывает контекст графика в реальном времени с исполнением сделок через панель Обзор сделок. В таблице ниже описаны его ключевые компоненты и их функции:

Параметр Описание Возможные значения
TradeWatch.AddTab Настройка вкладки для панели Обзор сделок. Active chart symbol stats
StackPanel.Orientation Определяет направление расположения элементов интерфейса. Vertical или horizontal
HorizontalAlignment Определяет горизонтальное выравнивание панели во вкладке. Center, left, right и т. д.
SymbolStatsControl.Margin Задает отступ вокруг элемента управления статистикой инструмента. 10, 12, 14 и т. д.
TradeControl.Margin Задает отступ вокруг элемента управления сделкой. 10, 12, 14 и т. д.
SymbolStatsControl.Symbol Привязывает элемент управления статистикой инструмента к определенному инструменту графика. chartframe.symbol, eurusd, gbpjpy и т. д.
TradeControl.Symbol Связывает TradeControl с инструментом для выполнения торговых действий. chartframe.symbol, eurusd, gbpjpy и т. д.
ChartManager.ActiveFrameChanged Событие, которое запускает обновление статистики инструмента при изменении фрейма графика. _ => setsymbolstats()
TradeControl.Trade Событие, которое запускается при выполнении торгового действия с панели управления. tradecontrolontrade или null
ExecuteMarketOrder Выполняет сделку при вызове. e.tradetype, e.symbolname, e.volume

Варианты использования

Плагин TradeWatch Tab Sample предоставляет простой способ улучшить cTrader, связывая контекст графика в режиме реального времени с исполнением сделок. Он поддерживает практические приложения, которые упрощают торговые процессы. Ниже приведены практические примеры использования, которые демонстрируют, как плагин может улучшить торговый опыт.

Пример использования Сценарий Значение
Фиксация инструмента Настройте вкладку плагина так, чтобы всегда отображался фиксированный инструмент, например EURUSD, вместо обновления при каждом переключении графика. Помогает отслеживать и торговать одним инструментом последовательно, независимо от контекста графика.
Торговая панель, связанная с графиком Синхронизируйте плагин с инструментом активного графика, чтобы всегда отображать соответствующую статистику и торговые опции. Позволяет быстро реагировать на анализ графика без переключения инструментов или панелей.
Сделка с фиксированным объемом Настройте объем по умолчанию в обработчике ордеров на фиксированный или предпочтительный размер лота. Упрощает исполнение, устраняя необходимость каждый раз корректировать объем.
Терминал быстрых действий Расположите элементы управления горизонтально и выровняйте по центру для упрощенной торговой панели. Обеспечивает более быстрый доступ как к статистике, так и к кнопкам сделок в компактных настройках.

Обзор

TradeWatch Tab Sample упрощает торговые процессы, объединяя статистику в режиме реального времени и элементы управления сделками в отдельной вкладке в Обзоре сделок. Он автоматически обновляется вместе с активным графиком, а его макет, поведение инструмента и настройки сделок можно настроить в соответствии с различными торговыми стилями или областями фокуса.

Для получения дополнительной информации о разработке обратитесь к нашей документации по плагинам.