Skip to content

Plugin placements in cTrader UI

A plugin's creation method determines its available placement options, and this article covers both web-based and native plugins. Web-based plugins are built using HTML, CSS, JavaScript and the plugin SDK, targeting all cTrader apps. Native plugins are built using C# or Python via Algo API, targeting cTrader Windows and Mac.

  • Web technology – the web-based plugin can display content in supported UI areas in all cTrader applications. Specify your preferred placements when building the plugin.
  • Algo API – the desktop-based plugin can display content in supported UI areas in cTrader Windows and Mac. Specify your preferred placements directly in the C# or Python code of the plugin.

Mobile

Note

Only plugins created using Web technology support content placement in cTrader Mobile. Choose your preferred mobile UI areas when building the plugin.

Trade app

When traders pull down in the Trade app, the plugin panel containing all enabled plugins appear, and this behaviour cannot be configured or changed.

When traders tap the plugin in the panel, the bottom sheet is displayed.

Symbol overview

The expanded view of the plugin is displayed in the Overview tab of any symbol.

Desktop

Note

cTrader Windows and Mac allow placements in all possible desktop UI areas, while cTrader Web supports only placements available when building the plugin.

ASP

Active Symbol Panel is located to the right of the chart display, and it allows plugins to display content in child blocks and tabs.

ASP block is a collapsible and expandable section in the Symbol tab.

ASP tab is a separate tab next to Symbol, DoM and others.

Choose Block in Active Symbol Panel, Tab in Active Symbol Panel or both when building the plugin.

You can code your plugin to add custom elements using the following options:

  • As an AspTab. When this option is used, the plugin displays custom elements in separate tabs alongside Symbol, DoM and others.
  • As an AspBlock. When this option is used, the plugin displays custom elements in the Symbol tab in new collapsible and expandable sections with customisable titles and positions.

<!-- !!! example "Use cases"

Here are some ideas for plugins displaying custom elements in an ASP block:

* A small calculator of protection levels for a given symbol.
* A grid displaying additional information about the currently active symbol.

The following ideas would function best when embedded as an ASP tab:

* A list containing custom analytics about all currently open positions.
* A WebView of a financial news outlet. -->

To add custom elements as an ASP block, use the Asp.SymbolTab.AddBlock(string title) method.

1
2
3
var child = ... // Insert the contents you want the block to have here
AspBlock aspBlock = Asp.SymbolTab.AddBlock("Cool Plugin");
aspBlock.Child = child; 

To add custom elements as an ASP tab, use the Asp.AddTab(string title) method.

1
2
3
var child = ... // Insert the contents you want the tab to have here
AspTab pluginTab = Asp.AddTab("Another Cool Plugin");
pluginTab.Child = child;

To determine the order in which a block or tab appears in ASP, use the Index property of AspBlock and AspTab, respectively.

Warning

Note that no custom tabs can be placed before the Symbol tab. You also cannot embed your block higher than the New Order section in the Symbol tab. As a result, the smallest possible index for a block embedded into ASP is 1.

Trade Watch

Trade Watch is located just below the chart area.

Choose Tab in Trade Watch and provide the necessary details when building the plugin.

To add custom elements as a new tab in Trade Watch display, use the Trade Watch.AddTab(string title) method.

1
2
3
var child = ... // Insert the contents you want the plugin to have here
Trade WatchTab Trade WatchTab = Trade Watch.AddTab("Yet Another Cool Plugin");
Trade WatchTab.Child = child;

Similar to ASP blocks and tabs, you can use the Index property of a Trade WatchTab to define its position relative to other tabs in Trade Watch display.

Note

All custom tabs placed into Trade Watch appear to the far right of the default tabs included in the cTrader UI upon launch. Subsequently, the the Index of these tabs must be 1 or greater; the index only determines the relative position of plugin tabs compared to other plugin tabs.

Chart and custom frame

Note

Chart or custom frame placement is possible only via Algo API.

Here is a custom chart frame with a WebView next to a regular chart.

Use cases

The following ideas would look and work at their best when embedded in a custom frame:

  • A WebView of another charting service.
  • A large-scale custom trading panel.
  • A WebView of a generative AI service that a trader may consult with when deciding how to react to market movements.

To add a new custom frame, use the ChartManager.AddCustomFrame(string title) method.

1
2
3
var child = ... // Insert the contents you want the plugin to have here
var newCustomFrame = ChartManager.AddCustomFrame("Best Plugin");
newCustomFrame.Child = child;

For your plugin to open a new chart, use the ChartManager.AddChartFrame(string symbolName, TimeFrame timeFrame) method.

1
var newChart = ChartManager.AddChartFrame("EURUSD", TimeFrame.Day2);

Note

Once a plugin adds a new custom frame or chart, cTrader switches to the multi-chart mode, even if the single chart mode or the free-chart mode was enabled previously.

Separate window

This is how a plugin displays a separate window:

Depending on the cTrader desktop application where the plugin operates, users may be able to resize, minimise or maximise the window.

Choose Separate window and provide the necessary details when building the plugin.

This is the C# code of a plugin that displays the cTrader Store in a separate, adjustable window:

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

namespace cAlgo.Plugins
{
    [Plugin(AccessRights = AccessRights.FullAccess)]
    public class WebsiteWindowPlugin : Plugin
    {
        private Window _window;

        protected override void OnStart()
        {
            // Create a new independent window
            _window = new Window
            {
                Title = "cTrader Official Website",
                Width = 1024,
                Height = 768
            };

            var webView = new WebView();
            webView.Loaded += _ =>
            {
                webView.NavigateAsync("http://ctrader.com");
            };

            // Add the WebView to the window and display it
            _window.Child = webView;
            _window.Show();
        }

    }
}

Note

Main menu placement is possible only via Algo API.

Plugins can be coded to add custom sections to the main menu UI, in addition to existing sections such as Trade, Algo, Copy and Analyze. Any added custom section can hold websites, dashboards, buttons, tools and more.

Here is the code for a simple plugin that adds a cTrader Store custom section, which houses the cTrader Store website, to the main menu:

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

namespace cAlgo
{
    [Plugin(AccessRights = AccessRights.None)]
    public class CTraderStorePlugin : Plugin
    {
        private MainMenuOwnCustomItem _storeItem;

        private const string StoreIconSvg = @"
        <svg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'>
          <path fill='white' d='M7 7V6a5 5 0 0 1 10 0v1h2a1 1 0 0 1 1 1l-1 11a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2L4 8a1 1 0 0 1 1-1h2zm2 0h6V6a3 3 0 0 0-6 0v1z' />
        </svg>";

        protected override void OnStart()
        {
            _storeItem = MainMenu.AddItem("cTrader Store", new SvgIcon(StoreIconSvg));

            var webView = new WebView();
            webView.Loaded += _ =>
            {
                webView.NavigateAsync("http://ctrader.com");
            };

            _storeItem.Child = webView;

            MainMenu.SelectedItemChanged += OnSelectedItemChanged;
        }

        private void OnSelectedItemChanged(MainMenuSelectedItemChangedEventArgs args)
        {
            if (args.NewItem == _storeItem)
            {
                MainMenu.IsExpanded = true;
            }
        }

        protected override void OnStop()
        {
            MainMenu.SelectedItemChanged -= OnSelectedItemChanged;

            if (_storeItem != null)
            {
                MainMenu.RemoveItem(_storeItem);
                _storeItem = null;
            }
        }
    }
}

Selecting cTrader Store navigates to the custom section, revealing its content as shown below.

Multiple areas

A plugin can display content in multiple UI areas across cTrader applications.

Choose several placements and provide details when building the plugin, and your plugin will display content in multiple UI areas simultaneously.

Entering the same URL across placement options leads to identical content in those UI areas. If you want your plugin to show unique content per UI area, provide different URLs (under the same domain) for the placements.

Example

https://ctrader.com/bots/ and https://ctrader.com/indicators/ lead to different pages, each with its own content, yet both exist under the https://ctrader.com/ domain.

The following plugin adds custom elements to several locations of the cTrader UI at once:

  • The plugin displays the sum of commissions for all currently open positions in an ASP block.
  • In Trade Watch, the plugin shows the cumulative volume of all open positions.
  • The plugin also shows a WebView of ctrader.com in a custom chart frame.
 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
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 PluginPlacementTest : Plugin
    {

        private TextBlock _commissionsText;
        private TextBlock _volumeText;
        private WebView _cTraderWebView;

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

            _commissionsText = new TextBlock
            {
                Text = ShowCommissions(),
                FontSize = 100,
                TextAlignment = TextAlignment.Center,
                FontWeight = FontWeight.ExtraBold,
            };

            _volumeText = new TextBlock
            {
                Text = ShowVolume(),
                FontSize = 100,
                TextAlignment = TextAlignment.Center,
                FontWeight = FontWeight.ExtraBold,
            };

            ChartManager.AddCustomFrame("cTrader.com").Child = _cTraderWebView;
            Asp.SymbolTab.AddBlock("Commissions").Child = _commissionsText;
            TradeWatch.AddTab("Volume").Child = _volumeText;
            Timer.Start(TimeSpan.FromSeconds(0.5));

        }

        protected void ShowWebsite(WebViewLoadedEventArgs args)
        {
            _cTraderWebView.NavigateAsync("https://ctrader.com");
        }

        protected string ShowCommissions()
        {
            double commissionsCounter = 0;
            foreach (var position in Positions)
            {
                commissionsCounter += position.Commissions;
            }
            return commissionsCounter.ToString();
        }

        protected string ShowVolume() 
        {
            double volumeCounter = 0;
            foreach (var position in Positions) 
            {
                volumeCounter += position.VolumeInUnits;
            }
            return volumeCounter.ToString();
        }

        protected override void OnTimer()
        {
            _commissionsText.Text = ShowCommissions();
            _volumeText.Text = ShowVolume();
        }
    }
}

Image title