콘텐츠로 이동

컨트롤

컨트롤은 cBot, 지표 및 플러그인과 관련된 특정 상호작용을 가능하게 합니다. 아래 가이드를 사용하여 차트에 직접 기본 및 고급 UI 컨트롤을 쉽게 생성할 수 있습니다.

버튼, 텍스트 블록, 텍스트 상자 및 도형과 같은 인기 있는 컨트롤을 나타내는 여러 내장 클래스가 있습니다. 그러나 사용자 정의 컨트롤을 생성할 수도 있습니다.

다음 예제를 고려하세요:

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

namespace ChartControlsTest
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        [Parameter(DefaultValue = "Click Me")]
        public string Text { get; set; }

        [Parameter(DefaultValue = HorizontalAlignment.Center)]
        public HorizontalAlignment HorizontalAlignment { get; set; }

        [Parameter(DefaultValue = VerticalAlignment.Center)]
        public VerticalAlignment VerticalAlignment { get; set; }

        protected override void Initialize()
        {
            var button = new Button
            {
                Text = Text,
                HorizontalAlignment = HorizontalAlignment,
                VerticalAlignment = VerticalAlignment
            };

            button.Click += Button_Click;

            Chart.AddControl(button);
        }

        private void Button_Click(ButtonClickEventArgs obj)
        {
            obj.Button.Text = "You clicked me, thanks";
        }

        public override void Calculate(int index)
        {
        }
    }
}

위의 지표를 빌드하고 인스턴스를 생성하면 차트 중앙에 회색 Click me 버튼이 표시됩니다.

컨트롤과 차트 객체의 차이점

이전 섹션에서 이미 차트 객체에 대해 다루었습니다. 컨트롤은 사용자가 cBot 및 지표와 상호작용할 수 있게 합니다. 반면, 차트 객체는 거래 차트 또는 분리된 지표 출력 창에 무언가를 그릴 기회를 제공합니다.

차트 컨트롤은 ControlBase 클래스에서 파생되는 반면, 차트 객체는 ChartObject 클래스에서 파생됩니다.

차트 컨트롤은 다양한 정렬 옵션을 사용하여 정적으로 위치가 지정됩니다. 차트 객체도 동일한 방식으로 위치를 지정할 수 있지만, 특정 X 및 Y 좌표에 따라 동적으로 위치가 변경될 수도 있습니다.

차트 객체와 마찬가지로, 차트 컨트롤은 메인 차트 및 모든 지표 출력 창 (존재하는 경우)에 추가될 수 있습니다. 이러한 위치 지정의 예는 아래와 같습니다:

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

namespace ChartControlsTest
{
    [Indicator(IsOverlay = false, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        [Parameter(DefaultValue = "Click Me")]
        public string Text { get; set; }

        [Parameter(DefaultValue = HorizontalAlignment.Center)]
        public HorizontalAlignment HorizontalAlignment { get; set; }

        [Parameter(DefaultValue = VerticalAlignment.Center)]
        public VerticalAlignment VerticalAlignment { get; set; }

        protected override void Initialize()
        {
            var button = new Button
            {
                Text = Text,
                HorizontalAlignment = HorizontalAlignment,
                VerticalAlignment = VerticalAlignment
            };

            button.Click += Button_Click;

            IndicatorArea.AddControl(button);
        }

        private void Button_Click(ButtonClickEventArgs obj)
        {
            obj.Button.Text = "You clicked me, thanks";
        }

        public override void Calculate(int index)
        {
        }
    }
}

지표 인스턴스를 생성한 후 지표 출력 창에 Click me 버튼이 표시됩니다.

ColorPicker

ColorPicker 컨트롤은 트레이더가 cTrader에서 주요 요소 또는 객체에 대해 선호하는 색상을 선택할 수 있게 합니다. 예를 들어, 개발자는 트레이더가 각 추세선에 대해 선호하는 색상을 선택할 수 있도록 추세선을 그리는 cBot에 ColorPicker 컨트롤을 통합할 수 있습니다. 이 설정은 트레이더가 다양한 추세선 유형을 구별하기 쉽게 합니다.

차트에 지표를 추가하는 플러그인도 ColorPicker 컨트롤을 구현할 수 있습니다. 이 기능은 사용자가 다른 지표 선에 대해 색상을 선택할 수 있게 합니다.

사용자가 색상 사각형을 클릭하면 색상 선택기가 나타납니다. 사용자는 표준 색상과 사용자 정의 색상 중에서 선택할 수 있습니다.

코드 샘플:

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

namespace cAlgo.Plugins
{
    [Plugin(AccessRights = AccessRights.None)]
    public class ColorPickerTest : Plugin
    {
        protected override void OnStart()
        {
            var aspBlock = Asp.SymbolTab.AddBlock("Color Picker");

            var colorPicker = new ColorPicker {IsStretched = true, SelectedColor = Color.Red, Height = 20, Width = 20, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center};

            aspBlock.Child = colorPicker;

            colorPicker.SelectedColorChanged += colorPicker_SelectedColorChanged;

        }

        private void colorPicker_SelectedColorChanged(ColorPickerSelectedColorChangedEventArgs obj)
        {
            Print($"colorPicker_SelectedColorChanged, NewSelectedColor: {obj.NewSelectedColor} | PreviousSelectedColor: {obj.PreviousSelectedColor}");
        }

        protected override void OnStop()
        {
            // Handle Plugin stop here
        }
    }        
}

Image title

DropZone

DropZone 컨트롤은 트레이더가 cBot, 지표 또는 플러그인과 관련된 드래그 앤 드롭 작업을 수행할 수 있게 합니다. 알고리즘에 이 컨트롤을 구현하려면 DropZone 클래스를 사용하세요. DropZone 컨트롤은 다른 컨트롤과 마찬가지로 조작할 수 있습니다.

사용자가 호환 가능한 파일 또는 폴더를 상자에 드롭하면 Dropped 이벤트가 생성됩니다. 사용자가 폴더 또는 여러 폴더를 상자에 드롭하면 FilterExtensions에 지정된 확장자를 가진 호환 가능한 파일만 처리되고 복사됩니다.

참고

드롭된 파일은 일반적으로 다음 위치에 복사되고 저장됩니다: ..\Documents\cAlgo\Data\{AlgoType}\{AlgoName}\Selected Files\

cBot 인스턴스의 위치는 위와 다릅니다: ..\Documents\cAlgo\Data\cBots\{cBotName}\{unique-instance-number}\Selected files\

이 플러그인 코드는 Trade WatchDropZone 컨트롤을 추가하는 방법을 보여줍니다:

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

namespace cAlgo.Plugins
{
    [Plugin(AccessRights = AccessRights.None)]
    public class TradeWatchTabSample : Plugin
    {
        protected override void OnStart()
        {
            var tab = TradeWatch.AddTab("DropZone");

            var _border = new Border
            {
                BorderThickness = 3,
                BorderColor = Color.DarkGray,
                Opacity = 0.7,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
                Height = 200,
                Width = 350,
                BackgroundColor = Color.LightGray
            };

            var _textBlock = new TextBlock
            {
                Text = "Drag your files here",
                Opacity = 1,
                ForegroundColor = Color.DarkGray,
                FontSize = 16,
                VerticalAlignment = VerticalAlignment.Center,
                HorizontalAlignment = HorizontalAlignment.Center
            };

            var _dropzone = new DropZone
            {
                FilterExtensions = new string[] { "txt", "algo", "csv" },
                IsDirectoryDropAllowed = true,
                IsVisible = true,
                IsEnabled = true
            };
            _border.Child = _textBlock;
            _dropzone.Child = _border;
            //   _dropzone.Child = _textBlock;
            tab.Child = _dropzone;

            _dropzone.Dropped += Dropped_file;
        }

        private void Dropped_file(DroppedEventArgs obj)
        {
            Print("File has been added!");
        }
    }
}

Image title

ProgressBar

ProgressBar 컨트롤은 진행 중인 작업의 진행 상황을 표시합니다. 진행 막대는 알고리즘을 더 사용자 친화적으로 만들고 특정 작업에 대한 대기 시간에 대한 트레이더의 기대치를 관리하는 데 도움을 줍니다.

cTrader Algo API는 개발자에게 무한 컨트롤과 결정 컨트롤 두 가지 유형의 ProgressBar 컨트롤을 추가할 수 있게 합니다.

무한 컨트롤

다음 상황에서 무한 컨트롤을 사용할 수 있습니다:

  • 작업의 대기 시간을 결정할 수 없습니다.
  • 작업의 진행 상황을 감지할 수 없습니다.
  • 작업이 얼마나 걸릴지 표시하고 싶지 않습니다.

Image title

결정 컨트롤

작업의 대기 시간을 결정할 수 있고 사용자가 해당 시간을 기반으로 한 표시기를 보고 싶을 때 이 컨트롤을 사용할 수 있습니다.

작업의 진행 상황을 표시하려면 Value 속성을 사용하여 숫자를 설정하세요. 진행 막대 백분율을 설정하려면 MinimumMaximum 속성을 사용하세요.

Image title

아래 플러그인 코드는 무한 및 결정 (녹색) 컨트롤을 모두 사용하여 진행 막대를 생성하는 방법을 보여줍니다:

 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
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 ProgressBarTest : Plugin
    {
        private ProgressBar _infiniteProgressBar;
        private ProgressBar _determinateProgressBar;

        protected override void OnStart()
        {
            var aspBlock = Asp.SymbolTab.AddBlock("Progress bar");

            var panel = new StackPanel() {Height = 200, Width = 200, Orientation = Orientation.Vertical};

            _infiniteProgressBar = new ProgressBar {IsIndeterminate = true, Height = 20};

            panel.AddChild(_infiniteProgressBar);

            _determinateProgressBar = new ProgressBar {IsIndeterminate = false, Height = 20};

            panel.AddChild(_determinateProgressBar);

            var autoProgressButton = new Button {Text = "Start"};

            autoProgressButton.Click += AutoProgressButton_Click;

            panel.AddChild(autoProgressButton);

            aspBlock.Child = panel;

        }

        private void AutoProgressButton_Click(ButtonClickEventArgs obj)
        {
            Timer.Start(1);
        }

        protected override void OnTimer()
        {
            _determinateProgressBar.Value++;

            Print($"Value: {_determinateProgressBar.Value}");
        }

        protected override void OnStop()
        {
            // Handle Plugin stop here
        }
    }        
}

대화 상자

OpenFileDialog 및 OpenFolderDialog

cTrader Algo API는 사용자가 알고리즘을 위한 파일을 선택할 수 있도록 OpenFileDialog 인터페이스를 제공합니다. 사용자가 결과 창에서 파일을 선택하면, 해당 파일은 알고리즘의 Selected files 폴더로 복사됩니다. 알고리즘은 Selected files 폴더 내의 파일을 제한 없이 작업할 수 있습니다.

중요한 데이터 파일, 백업 또는 구성 파일, 맞춤형 지표 또는 스크립트를 로드해야 할 때 OpenFileDialog 기능을 사용하세요.

아래 코드는 지표에서 OpenFileDialog 대화 상자를 사용하는 방법을 보여줍니다:

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

namespace cAlgo
{
    [Indicator(AccessRights = AccessRights.None, IsOverlay = true)]
    public class OpenFileDialogExample : Indicator
    {
        private OpenFileDialog _openFileDialog;

        protected override void Initialize()
        {
            _openFileDialog = new OpenFileDialog()
            {
                InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                Multiselect = true,
                Title = "My Open File Dialog Title"
            };

            var showOpenFileDialog = new Button { Text = "Show Open File Dialog" };
            showOpenFileDialog.Click += showOpenFileDialog_Click;

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

            panel.AddChild(showOpenFileDialog);
            Chart.AddControl(panel);
        }

        private void showOpenFileDialog_Click(ButtonClickEventArgs obj)
        {
            var result = _openFileDialog.ShowDialog();
            Print($"Result: {result} | FileName: {_openFileDialog.FileName} | FileNames: {string.Join(',', _openFileDialog.FileNames)}");
        }

        public override void Calculate(int index)
        {
        }
    }
}

Image title

cTrader Algo API는 사용자가 알고리즘을 위한 폴더를 지정할 수 있도록 OpenFolderDialog 인터페이스를 제공합니다. 사용자가 결과 창에서 폴더를 선택하면, 선택된 폴더 내의 모든 파일과 폴더가 알고리즘의 Selected files 폴더로 복사됩니다.

중요한 데이터 파일, 백업 또는 구성 파일, 맞춤형 지표 또는 스크립트가 포함된 폴더를 로드해야 할 때 OpenFolderDialog 기능을 사용하세요.

선택된 파일과 폴더는 일반적으로 Selected files 폴더로 복사됩니다. 이는 알고리즘이 AccessRightsNone으로 설정된 경우에도 해당 폴더 내의 항목을 작업할 수 있기 때문입니다.

참고

알고리즘의 Selected files 폴더는 일반적으로 이 경로에 위치합니다: ..\Documents\cAlgo\Data\{AlgoType}\{AlgoName}\Selected files\

cBot 인스턴스의 Selected files 폴더는 위와 다릅니다: ..\Documents\cAlgo\Data\cBots\{cBotName}\{Instance-Id}\Selected files\

아래 코드는 지표에서 OpenFolderDialog 대화 상자를 사용하는 방법을 보여줍니다:

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

namespace cAlgo
{
    [Indicator(AccessRights = AccessRights.None, IsOverlay = true)]
    public class OpenFolderDialogExample : Indicator
    {
        private OpenFolderDialog _openFolderDialog;

        protected override void Initialize()
        {
            _openFolderDialog = new OpenFolderDialog()
            {
                InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                Title = "My Open Folder Dialog Title"
            };

            var showOpenFolderDialog = new Button { Text = "Show Open Folder Dialog" };
            showOpenFolderDialog.Click += showOpenFolderDialog_Click;

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

            panel.AddChild(showOpenFolderDialog);
            Chart.AddControl(panel);
        }

        private void showOpenFolderDialog_Click(ButtonClickEventArgs obj)
        {
            var result = _openFolderDialog.ShowDialog();
            Print($"Result: {result} | FolderName: {_openFolderDialog.FolderName}");
        }

        public override void Calculate(int index)
        {
        }
    }
}

Image title

SaveFileDialog

cTrader Algo API는 사용자가 파일을 (로컬로) 컴퓨터에 저장할 수 있도록 SaveFileDialog 인터페이스를 제공합니다. 관련 창이 나타나면, 사용자는 파일을 저장할 폴더를 선택하고 파일 이름을 입력합니다. 그런 다음 파일은 지정된 위치에 저장됩니다.

다음 중 하나를 수행해야 할 때 SaveFileDialog 기능을 사용하세요:

  • 성능 보고서, 백테스트 결과, 구성 파일 또는 최적화 데이터를 저장합니다.
  • 트레이딩 로그, 작업 일지 또는 일반 사용자 활동 데이터를 내보냅니다.
  • 맞춤형 지표, 차트 및 시각화를 위한 데이터 또는 전략을 위한 매개변수를 저장합니다.

아래 코드는 지표에서 SaveFileDialog 대화 상자를 사용하는 방법을 보여줍니다:

 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 System.Text;

namespace cAlgo
{
    [Indicator(AccessRights = AccessRights.None, IsOverlay = true)]
    public class SaveFileDialogExample : Indicator
    {
        private SaveFileDialog _saveFileDialog;

        protected override void Initialize()
        {
            _saveFileDialog = new SaveFileDialog()
            {
                InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                Title = "My Save File Dialog Title"
            };

            var showSaveFileDialogText = new Button { Text = "Show Save File Dialog (Set Content as text)" };
            var showSaveFileDialogBytes = new Button { Text = "Show Save File Dialog (Set Content as bytes)" };

            showSaveFileDialogText.Click += showSaveFileDialogText_Click;
            showSaveFileDialogBytes.Click += showSaveFileDialogBytes_Click;

            var panel = new StackPanel
            {
                Orientation = Orientation.Vertical,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center
            };
            panel.AddChild(showSaveFileDialogText);
            panel.AddChild(showSaveFileDialogBytes);
            Chart.AddControl(panel);
        }

        private void showSaveFileDialogText_Click(ButtonClickEventArgs obj)
        {
            var result = _saveFileDialog.ShowDialog();
            Print($"Result: {result}");
            if (result != FileDialogResult.Cancel)
            {
                _saveFileDialog.WriteToFile("Test in text");
            }
        }

        private void showSaveFileDialogBytes_Click(ButtonClickEventArgs obj)
        {
            var result = _saveFileDialog.ShowDialog();
            Print($"Result: {result}");
            if (result != FileDialogResult.Cancel)
            {
                _saveFileDialog.WriteToFile(Encoding.UTF8.GetBytes("Test in bytes"));
            }
        }

        public override void Calculate(int index)
        {
        }
    }
}

드래그 가능한 컨트롤

차트 영역 드래그 가능한 컨트롤

ChartDraggableChartDraggables 인터페이스는 차트에 다른 컨트롤과 다양한 요소를 호스팅할 수 있는 드래그 가능한 컨트롤을 추가할 수 있는 타입을 제공합니다. 이러한 드래그 가능한 컨트롤은 사용자가 다양한 차트 요소와 상호 작용하기 쉽게 합니다.

참고

드래그 가능한 컨트롤은 추가된 차트 내에서만 이동하거나 재배치할 수 있습니다.

이 코드는 차트 내에서 이동할 수 있는 두 개의 컨트롤을 추가하는 지표를 만드는 방법을 보여줍니다:

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

namespace cAlgo
{
    [Indicator(AccessRights = AccessRights.None)]
    public class DragControl : Indicator
    {
        protected override void Initialize()
        {
            var draggable = Chart.Draggables.Add();
            var draggable2 = IndicatorArea.Draggables.Add();

            draggable.Child = GetDraggableChildWebView();
            draggable2.Child = GetDraggableChildText();

            draggable.LocationChanged += draggable_LocationChanged;
            draggable2.LocationChanged += draggable2_LocationChanged;
        }

        public override void Calculate(int index)
        {
            // Calculate value at specified index
            // Result[index] = 
        }

        private StackPanel GetDraggableChildWebView()
        {
            var stackPanel = new StackPanel
            {
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
                BackgroundColor = Color.Gold
            };

            var webView = new WebView() {Height = 500, Width = 300};

            webView.Loaded += webView_Loaded;

            stackPanel.AddChild(webView);

            return stackPanel;
        }

        private StackPanel GetDraggableChildText()
        {
            var stackPanel = new StackPanel
            {
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
                BackgroundColor = Color.Gold
            };
            var text_block = new TextBlock
                 {
                     Text = "Testing draggable controls",
                     Margin = 5,
                     ForegroundColor = Color.Black,
                     FontWeight = FontWeight.ExtraBold
                 };

            stackPanel.AddChild(text_block);

            return stackPanel;
        }


        private void webView_Loaded(WebViewLoadedEventArgs obj)
        {
            obj.WebView.NavigateAsync("https://www.youtube.com/");
        }

        private void draggable_LocationChanged(ChartDraggableLocationChangedEventArgs obj)
        {
            Print($"Draggable '{obj.Draggable.Id}' location changed to: ({obj.Draggable.X}, {obj.Draggable.Y})");
        }

        private void draggable2_LocationChanged(ChartDraggableLocationChangedEventArgs obj)
        {
            Print($"Draggable '{obj.Draggable.Id}' location changed to: ({obj.Draggable.X}, {obj.Draggable.Y})");
        }
    }
}

애플리케이션 창 드래그 가능한 컨트롤

ApplicationDraggableApplicationDraggables 인터페이스는 전체 cTrader 애플리케이션 창에서 개별적으로 이동할 수 있는 플로팅 컨트롤을 추가하는 데 사용되는 타입을 제공합니다. 이러한 컨트롤은 인터랙티브하고 동적인 사용자 인터페이스를 만들 수 있게 합니다.

참고

세 가지 알고리즘 타입 중 플러그인만 애플리케이션 전체에서 드래그 가능한 컨트롤을 구현할 수 있습니다.

이 코드는 전체 cTrader UI에서 이동할 수 있는 WebView 구성 요소와 텍스트 블록을 두 개의 별도 창에 추가하는 플러그인을 만드는 방법을 보여줍니다:

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

namespace cAlgo.Plugins
{
    [Plugin(AccessRights = AccessRights.None)]
    public class ApplicationLevelDraggables : Plugin
    {
        private ApplicationDraggable _webDraggable;
        private ApplicationDraggable _textDraggable;

        protected override void OnStart()
        {
            _webDraggable = Application.Draggables.Add();
            _webDraggable.Child = GetDraggableChildWebView();
            _webDraggable.LocationChanged += OnDraggableLocationChanged;

            _textDraggable = Application.Draggables.Add();
            _textDraggable.Child = GetDraggableChildText();
            _textDraggable.LocationChanged += OnDraggableLocationChanged;
        }

        private void OnDraggableLocationChanged(ApplicationDraggableLocationChangedEventArgs args)
        {
            Print($"Draggable '{args.Draggable.Id}' location changed to: ({args.Draggable.X}, {args.Draggable.Y})");
        }

        private StackPanel GetDraggableChildWebView()
        {
            var stackPanel = new StackPanel
            {
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
                BackgroundColor = Color.Gold
            };

            var webView = new WebView { Width = 300, Height = 200 };
            webView.Loaded += (args) => args.WebView.NavigateAsync("https://www.youtube.com/");

            stackPanel.AddChild(webView);

            return stackPanel;
        }

        private StackPanel GetDraggableChildText()
        {
            var stackPanel = new StackPanel
            {
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
                BackgroundColor = Color.Gold
            };

            var textBlock = new TextBlock
            {
                Text = "Testing Application-level draggable",
                Margin = 5,
                ForegroundColor = Color.Black,
                FontWeight = FontWeight.ExtraBold
            };

            stackPanel.AddChild(textBlock);

            return stackPanel;
        }
    }
}

탭 컨트롤

TabControl 클래스는 알고리즘을 위한 여러 탭을 생성할 수 있는 타입을 제공합니다. 이러한 탭은 관련 요소를 함께 유지하거나 기능에 대한 별도의 뷰를 제공하는 데 사용할 수 있습니다.

이 코드는 활성 심벌 패널에 추가된 플러그인에서 탭을 사용하는 방법을 보여줍니다:

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

namespace cAlgo.Plugins
{
    [Plugin(AccessRights = AccessRights.FullAccess)]
    public class TabControlSimple : Plugin
    {
        private TabControl _tabControl;

        protected override void OnStart()
        {
            _tabControl = new TabControl
            {
                Height = 200,
                TabStripPlacement = Dock.Left 
            };

            var firstTab = new TabItem
            {
                Header = new TextBlock { Text = "First Tab" },
                Content = new TextBlock { Text = "First Tab Content", BackgroundColor = Color.Red }
            };

            var secondTab = new TabItem
            {
                Header = new TextBlock { Text = "Second Tab" },
                Content = new TextBlock { Text = "Second Tab Content" }
            };

            _tabControl.AddTab(firstTab);
            _tabControl.AddTab(secondTab);

            _tabControl.SelectedTabChanged += TabControl_SelectedTabChanged;

            _tabControl.SelectedTab = secondTab;

            var panel = new StackPanel { Orientation = Orientation.Vertical };
            panel.AddChild(_tabControl);

            var asp = Asp.SymbolTab.AddBlock("Simple Tab Control");
            asp.Child = panel;
            asp.Height = 300;
        }

        private void TabControl_SelectedTabChanged(TabControlSelectedTabChangedEventArgs obj)
        {
            Print($"Selected tab changed to: {obj.SelectedTab?.UniqueId}");
        }

        protected override void OnStop()
        {
        }
    }
}

맞춤형 컨트롤

맞춤형 컨트롤은 기본적으로 여러 사전 정의된 컨트롤로 구성된 컨트롤입니다. 다시 말해, 다른 컨트롤이 그 내용을 구성하는 컨트롤입니다.

맞춤형 컨트롤은 내장 컨트롤과 마찬가지로 재사용 가능한 클래스로 작동합니다.

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

namespace ChartControlsTest
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        [Parameter("# Of Text Areas", DefaultValue = 4)]
        public int NumberOfTextAreas { get; set; }

        protected override void Initialize()
        {
            var panel = new WrapPanel
            {
                Orientation = Orientation.Horizontal,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center
            };

            for (int i = 0; i < NumberOfTextAreas; i++)
            {
                var textArea = new TextArea
                {
                    HorizontalAlignment = HorizontalAlignment.Right,
                    VerticalAlignment = VerticalAlignment.Stretch,
                    Margin = 5,
                };

                panel.AddChild(textArea);
            }

            Chart.AddControl(panel);
        }

        public override void Calculate(int index)
        {
        }
    }

    public class TextArea : CustomControl
    {
        private readonly TextBox _textBox;

        public TextArea()
        {
            _textBox = new TextBox
            {
                TextAlignment = TextAlignment.Left,
                TextWrapping = TextWrapping.Wrap,
                AcceptsReturn = true,
                AcceptsTab = true,
                Width = 300,
                Height = 200,
            };

            AddChild(_textBox);
        }
    }
}

이 지표의 인스턴스는 메인 차트의 정중앙에 네 개의 텍스트 상자를 표시해야 합니다.

패널로 컨트롤 구성

컨트롤 작업을 더 편리하게 하기 위해, 여러 컨트롤을 UI 내의 고유한 위치에 있는 별도의 그룹에 배치할 수 있습니다. 이를 위해 Panels 클래스와 그 파생 클래스를 사용할 수 있습니다.

패널은 다른 컨트롤을 내용으로 하는 컨트롤로 생각할 수 있습니다. cTrader는 기본 Panels 클래스(자체적으로 Control 클래스를 상속함)에서 상속된 다섯 가지 다른 클래스를 지원합니다:

  • Canvas
  • DockPanel
  • Grid
  • StackPanel
  • WrapPanel

각각의 클래스는 아래에서 논의된 것처럼 다른 패널 레이아웃과 위치 지정 전략을 사용합니다.

캔버스

캔버스는 특정 X 및 Y 좌표를 기반으로 컨트롤을 배치할 수 있는 패널입니다.

특히, X 및 Y 축은 차트 객체 또는 그림에 사용되는 것과 다릅니다. Canvas 클래스에서 사용하는 X 및 Y 좌표는 차트의 왼쪽 상단 모서리에서 시작하는 (0, 0)부터의 숫자 값입니다.

다음 예제를 고려하세요:

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

namespace ChartControlsTest
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        [Parameter(DefaultValue = "Click Me")]
        public string Text { get; set; }

        [Parameter(DefaultValue = 0)]
        public double Left { get; set; }

        [Parameter(DefaultValue = 0)]
        public double Top { get; set; }

        [Parameter(DefaultValue = 0)]
        public double Margin { get; set; }

        [Parameter(DefaultValue = 10)]
        public double Padding { get; set; }

        protected override void Initialize()
        {
            var button = new Button
            {
                Text = Text,
                Left = Left,
                Top = Top,
                Margin = Margin,
                Padding = Padding
            };

            button.Click += Button_Click;

            var canvas = new Canvas();

            /* We add our button control to the canvas
            panel. */
            canvas.AddChild(button);

            // We add our canvas panel to the chart.
            Chart.AddControl(canvas);
        }

        private void Button_Click(ButtonClickEventArgs obj)
        {
            obj.Button.Text = "You clicked me, thanks";
        }

        public override void Calculate(int index)
        {
        }
    }
}

위 지표의 인스턴스를 생성하면 차트의 왼쪽 상단 모서리에 Click me 버튼이 표시됩니다.

컨트롤의 Top 속성은 Y축에서의 위치를 결정합니다. 반면, Left 속성은 X축에서의 위치를 정의합니다.

위 코드는 또한 PaddingMargin 속성을 사용합니다. Padding은 컨트롤 내용과 외부 경계 사이의 거리를 나타냅니다. Margin은 컨트롤과 부모의 경계 사이의 거리입니다. PaddingMargin 속성은 캔버스 클래스뿐만 아니라 모든 패널에 적용됩니다. 이들은 컨트롤 간의 간격을 관리하는 데 유용합니다.

대부분의 경우, Canvas 클래스는 소수의 컨트롤만 그룹화하는 데 사용됩니다.

도크 패널

DockPanel 클래스는 차트의 정적 위치에 컨트롤을 도크(배치)하는 데 사용됩니다. 네 가지 가능한 도크 위치가 있습니다:

  • 상단
  • 하단
  • 왼쪽
  • 오른쪽

각 컨트롤은 Dock 속성을 가지고 있습니다. DockPanel 클래스를 사용할 때, 이 속성을 사용하여 DockPanel 내에 컨트롤을 배치할 수 있습니다. 이것은 다음 예제에서 설명됩니다:

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

namespace ChartControlsTest
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        [Parameter(DefaultValue = Dock.Top)]
        public Dock TextBoxDock { get; set; }

        [Parameter(DefaultValue = Dock.Bottom)]
        public Dock ButtonDock { get; set; }

        private TextBox _textBox;

        protected override void Initialize()
        {
            _textBox = new TextBox
            {
                Margin = 5,
                Text = "Write here...",
                ForegroundColor = Color.Yellow,
                Dock = TextBoxDock,
                Width = 200
            };

            var button = new Button
            {
                Text = "Tell what I wrote?",
                Dock = ButtonDock,
                Width = 200
            };

            button.Click += Button_Click;

            var dockPanel = new DockPanel
            {
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
            };

            dockPanel.AddChild(_textBox);
            dockPanel.AddChild(button);

            Chart.AddControl(dockPanel);
        }

        private void Button_Click(ButtonClickEventArgs obj)
        {
            obj.Button.Text = $"You wrote: {_textBox.Text}";
        }

        public override void Calculate(int index)
        {
        }
    }
}

이 지표의 인스턴스를 생성하면 차트의 중앙에 텍스트 필드와 클릭 가능한 버튼이 포함된 도크 패널이 표시됩니다.

도크 패널은 가로 또는 세로로 채워질 수 있습니다. 이 두 정렬을 동시에 사용할 수는 없습니다. 도크 패널의 방향은 DockPanel 내의 첫 번째 컨트롤을 설정할 때 자동으로 설정됩니다. 첫 번째 컨트롤의 Dock 속성이 Top 또는 Bottom으로 설정된 경우, 전체 DockPanel은 세로로 정렬되며, 그 반대의 경우도 마찬가지입니다.

스택 패널

스택 패널은 간단하고 사용하기 쉬운 컨트롤로 가장 자주 사용되는 컨트롤 중 하나입니다. 스택 패널은 자식 컨트롤을 가로 또는 세로로 하나씩 정렬합니다. 아래와 같이 방향만 설정하면 클래스가 나머지를 관리합니다:

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

namespace ChartControlsTest
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        [Parameter(DefaultValue = Orientation.Vertical)]
        public Orientation Orientation { get; set; }

        protected override void Initialize()
        {
            var firstNameTextBox = new TextBox
            {
                Margin = 5,
                Text = "First Name...",
                Width = 200
            };

            var lastNameTextBox = new TextBox
            {
                Margin = 5,
                Text = "Last Name...",
                Width = 200
            };

            var isMarriedCheckBox = new CheckBox
            {
                Text = "Is Married?",
                Margin = 5,
            };

            var submitButton = new Button
            {
                Text = "Submit",
                Margin = 5
            };

            var stackPanel = new StackPanel
            {
                Orientation = Orientation,
                HorizontalAlignment = HorizontalAlignment.Right,
                VerticalAlignment = VerticalAlignment.Bottom,
                BackgroundColor = Color.FromArgb(80, Color.Gold),
                Margin = 20
            };

            stackPanel.AddChild(firstNameTextBox);
            stackPanel.AddChild(lastNameTextBox);
            stackPanel.AddChild(isMarriedCheckBox);
            stackPanel.AddChild(submitButton);

            Chart.AddControl(stackPanel);
        }

        public override void Calculate(int index)
        {
        }
    }
}

지표 인스턴스를 생성한 후 메인 차트의 오른쪽 하단에 두 개의 텍스트 필드와 '제출' 버튼이 있는 가로 스택 패널이 표시되어야 합니다.

랩 패널

랩 패널은 스택 패널과 거의 동일합니다. 그러나 랩 패널의 모든 요소를 맞출 공간이 충분하지 않으면 남은 컨트롤을 Y 축의 다음 줄로 자동으로 감쌉니다.

그리드

그리드는 고정된 수의 열과 행이 있는 스프레드시트라고 생각할 수 있습니다. 그리드를 사용할 때 각각의 셀에 컨트롤을 추가할 수 있습니다.

아래에 설명된 것처럼 Grid 클래스의 인스턴스를 생성할 때 행과 열의 수를 integer 인수로 전달합니다. 새로운 자식 또는 컨트롤을 추가할 때도 마찬가지로 자식 행과 열의 수를 지정해야 합니다.

 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 ChartControlsTest
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        [Parameter("Grid Rows #", DefaultValue = 10)]
        public int GridRowsNumber { get; set; }

        [Parameter("Grid Columns #", DefaultValue = 2)]
        public int GridColumnsNumber { get; set; }

        protected override void Initialize()
        {
            var grid = new Grid(GridRowsNumber, GridColumnsNumber)
            {
                BackgroundColor = Color.Gold,
                Opacity = 0.6,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
                ShowGridLines = true
            };

            for (int iRow = 0; iRow < GridRowsNumber; iRow++)
            {
                for (int iColumn = 0; iColumn < GridColumnsNumber; iColumn++)
                {
                    grid.AddChild(new TextBlock
                    {
                        Text = string.Format("Row {0} and Column {1}", iRow, iColumn),
                        Margin = 5,
                        ForegroundColor = Color.Black,
                        FontWeight = FontWeight.ExtraBold
                    }, iRow, iColumn);
                }
            }

            Chart.AddControl(grid);
        }

        public override void Calculate(int index)
        {
        }
    }
}

위의 지표 인스턴스를 생성하면 차트의 정중앙에 10x2 그리드가 표시되어야 합니다.

가격 및 시간 좌표 내에서 컨트롤 위치 지정

패널 컨트롤 외에도 cTrader는 차트 영역에서 직접 컨트롤의 가격 및 시간 좌표를 지정할 수 있도록 합니다. AddControl()MoveControl() 메서드는 알고리즘 개발자에게 이 기능을 제공합니다.

선호에 따라 차트 컨트롤의 좌표를 관리하려면 다음 메서드 오버로드를 사용하십시오.

차트 또는 지표 영역에 절대 바 인덱스와 가격 (x, y) 좌표로 차트 컨트롤을 추가합니다.

1
void AddControl(ControlBase control, int barIndex, double y)

차트 또는 지표 영역에 절대 바 인덱스와 가격 (x, y) 좌표로 차트 컨트롤을 이동합니다.

1
void MoveControl(ControlBase control, int barIndex, double y)

차트 또는 지표 영역에 절대 시간과 가격 (x, y) 좌표로 차트 컨트롤을 추가합니다.

1
void AddControl(ControlBase control, DateTime time, double y)

차트 또는 지표 영역에 절대 시간과 가격 (x, y) 좌표로 차트 컨트롤을 이동합니다.

1
void MoveControl(ControlBase control, DateTime time, double y)

차트 또는 지표 영역에 절대 시간 (x) 좌표로 차트 컨트롤을 추가합니다.

1
void AddControl(ControlBase control, DateTime time)

차트 또는 지표 영역에 절대 시간 (x) 좌표로 차트 컨트롤을 이동합니다.

1
void MoveControl(ControlBase control, DateTime time)

차트 또는 지표 영역에 절대 바 인덱스 (x) 좌표로 차트 컨트롤을 추가합니다.

1
void AddControl(ControlBase control, int barIndex)

차트 또는 지표 영역에 절대 바 인덱스 (x) 좌표로 차트 컨트롤을 이동합니다.

1
void MoveControl(ControlBase control, int barIndex)

차트 또는 지표 영역에 절대 가격 (y) 좌표로 차트 컨트롤을 추가합니다.

1
void AddControl(ControlBase control, double y)

차트 또는 지표 영역에 절대 가격 (y) 좌표로 차트 컨트롤을 이동합니다.

1
void MoveControl(ControlBase control, double y)

ControlBase 매개변수 클래스는 위의 시그니처에 따라 호출될 메서드에 대해 다른 하위 클래스(Control, Button 등)를 포함할 수 있습니다.

다음 cBot 예제는 차트의 마지막 바 위에 Click me! 버튼을 추가합니다. 버튼은 새로운 바가 추가될 때마다 함께 앞으로 이동합니다. 버튼을 클릭하면 화면에 메시지 상자가 나타납니다.

 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
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.Robots
{
    [Robot(AccessRights = AccessRights.None)]
    public class ButtonTest : Robot
    {
        [Parameter(DefaultValue = "Hello world!")]
        public string Message { get; set; }

        Button button;

        protected override void OnStart() 
        {
            button = new Button
            {
                Text = "Click me!"
            };

            button.Click += Button_Click;

            Chart.AddControl(button, Bars.Count - 1);
        }

        protected override void OnBar() 
        {
            Chart.MoveControl(button, Bars.Count - 1);
        }

        private void Button_Click(ButtonClickEventArgs obj)
        {
            MessageBox.Show(Message, "Title/Caption");
        }
    }
}

경고

성능 문제로 인해 차트에 추가할 수 있는 루트 컨트롤의 수는 100개로 제한됩니다. 이 제한은 하나의 알고리즘 인스턴스와 가격 및 바에 연결된 컨트롤에만 적용됩니다.

패딩 및 마진 속성

Margin 속성은 Control 객체의 테두리와 그 부모(차트, 패널, 테두리 등) 사이의 공간을 정의합니다.

반면에 Padding 속성은 컨트롤 내용과 그 테두리 사이의 공간을 결정합니다. 속성 값을 다양하게 설정하여 각 면마다 다른 값을 가질 수 있습니다.

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

namespace ChartControlsTest
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        [Parameter(DefaultValue = "Click Me")]
        public string Text { get; set; }

        [Parameter(DefaultValue = 0)]
        public double Left { get; set; }

        [Parameter(DefaultValue = 0)]
        public double Top { get; set; }

        [Parameter(DefaultValue = 0, Group = "Margin")]
        public double LeftMargin { get; set; }

        [Parameter(DefaultValue = 0, Group = "Margin")]
        public double TopMargin { get; set; }

        [Parameter(DefaultValue = 0, Group = "Margin")]
        public double RightMargin { get; set; }

        [Parameter(DefaultValue = 0, Group = "Margin")]
        public double BottomMargin { get; set; }

        [Parameter(DefaultValue = 5, Group = "Padding")]
        public double LeftPadding { get; set; }

        [Parameter(DefaultValue = 5, Group = "Padding")]
        public double TopPadding { get; set; }

        [Parameter(DefaultValue = 5, Group = "Padding")]
        public double RightPadding { get; set; }

        [Parameter(DefaultValue = 5, Group = "Padding")]
        public double BottomPadding { get; set; }

        protected override void Initialize()
        {
            var button = new Button
            {
                Text = Text,
                Left = Left,
                Top = Top,
                Margin = new Thickness(LeftMargin, TopMargin, RightMargin, BottomMargin),
                Padding = new Thickness(LeftPadding, TopPadding, RightPadding, BottomPadding)
            };

            button.Click += Button_Click;

            var canvas = new Canvas();

            canvas.AddChild(button);

            Chart.AddControl(canvas);
        }

        private void Button_Click(ButtonClickEventArgs obj)
        {
            obj.Button.Text = "You clicked me, thanks";
        }

        public override void Calculate(int index)
        {
        }
    }
}

이 지표의 인스턴스는 차트의 왼쪽 상단에 회색 Click me 버튼을 생성합니다. 인스턴스 추가 또는 매개변수 수정 창에서 매개변수를 수정하여 다양한 마진 및 패딩 값이 컨트롤 표시에 어떻게 영향을 미치는지 확인하십시오.

스타일

스타일을 사용하면 여러 다른 유형의 컨트롤에 비슷한 모양을 부여할 수 있습니다. 이는 특히 많은 수(5개 이상)의 컨트롤을 다룰 때 유용합니다.

Style 클래스를 사용하면 Margin 또는 BackgroundColor와 같은 컨트롤의 다양한 속성 값을 설정할 수 있습니다. 이후 이러한 값을 여러 다른 컨트롤에 대한 템플릿으로 재사용할 수 있습니다.

Style 클래스를 전혀 사용하지 않고도 여러 컨트롤에 일관된 모양을 부여할 수 있습니다.

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

namespace ChartControlsTest
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        protected override void Initialize()
        {
            var firstTextBox = new TextBox
            {
                ForegroundColor = Color.Red,
                Margin = 5,
                FontFamily = "Cambria",
                FontSize = 12,
                Text = "Type...",
                Width = 150
            };

            var secondTextBox = new TextBox
            {
                ForegroundColor = Color.Red,
                Margin = 5,
                FontFamily = "Cambria",
                FontSize = 12,
                Text = "Type...",
                Width = 150
            };

            var thirdTextBox = new TextBox
            {
                ForegroundColor = Color.Red,
                Margin = 5,
                FontFamily = "Cambria",
                FontSize = 12,
                Text = "Type...",
                Width = 150
            };

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

            panel.AddChild(firstTextBox);
            panel.AddChild(secondTextBox);
            panel.AddChild(thirdTextBox);

            Chart.AddControl(panel);
        }

        public override void Calculate(int index)
        {
        }
    }
}

다음은 Style 클래스를 사용하여 여러 컨트롤 작업을 단순화하는 방법입니다.

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

namespace ChartControlsTest
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        protected override void Initialize()
        {
            var textBoxStyle = new Style();

            textBoxStyle.Set(ControlProperty.ForegroundColor, Color.Red);
            textBoxStyle.Set(ControlProperty.Margin, 5);
            textBoxStyle.Set(ControlProperty.FontFamily, "Cambria");
            textBoxStyle.Set(ControlProperty.FontSize, 12);
            textBoxStyle.Set(ControlProperty.Width, 150);

            var firstTextBox = new TextBox
            {
                Text = "Type...",
                Style = textBoxStyle
            };

            var secondTextBox = new TextBox
            {
                Text = "Type...",
                Style = textBoxStyle
            };

            var thirdTextBox = new TextBox
            {
                Text = "Type...",
                Style = textBoxStyle
            };

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

            panel.AddChild(firstTextBox);
            panel.AddChild(secondTextBox);
            panel.AddChild(thirdTextBox);

            Chart.AddControl(panel);
        }

        public override void Calculate(int index)
        {
        }
    }
}

위의 두 코드 스니펫은 각각의 지표 인스턴스를 실행하면 동일한 컨트롤을 표시해야 합니다.

Style 클래스를 사용하여 컨트롤의 상태에 따라 외관을 변경할 수도 있습니다.

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

namespace ChartControlsTest
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class ChartControls : Indicator
    {
        protected override void Initialize()
        {
            var textBoxStyle = new Style();

            textBoxStyle.Set(ControlProperty.ForegroundColor, Color.Red);
            textBoxStyle.Set(ControlProperty.Margin, 5);
            textBoxStyle.Set(ControlProperty.FontFamily, "Cambria");
            textBoxStyle.Set(ControlProperty.FontSize, 12);
            textBoxStyle.Set(ControlProperty.Width, 150);
            // Here we change the foreground color to Yellow if mouse hover over the textbox
            textBoxStyle.Set(ControlProperty.ForegroundColor, Color.Yellow, ControlState.Hover);

            var firstTextBox = new TextBox
            {
                Text = "Type...",
                Style = textBoxStyle
            };

            var secondTextBox = new TextBox
            {
                Text = "Type...",
                Style = textBoxStyle
            };

            var thirdTextBox = new TextBox
            {
                Text = "Type...",
                Style = textBoxStyle
            };

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

            panel.AddChild(firstTextBox);
            panel.AddChild(secondTextBox);
            panel.AddChild(thirdTextBox);

            Chart.AddControl(panel);
        }

        public override void Calculate(int index)
        {
        }
    }
}

이미지

Image 컨트롤은 로컬에 저장된 이미지를 표시하는 데 사용할 수 있습니다. Image 컨트롤은 .NET Bitmap 클래스를 사용하므로 다음과 같은 대부분의 인기 있는 이미지 형식을 지원합니다:

  • .PNG
  • .JPG
  • .BMP
  • .GIF
  • .TIFF

.NET Bitmap 클래스 문서를 참조하여 더 자세히 알아보십시오.

Image 컨트롤을 사용하려면 Source 속성을 바이트 배열(byte[])의 이미지 파일 데이터로 설정하십시오.

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

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class ImageSample : Indicator
    {
        [Parameter("Image File Path")]
        public string ImageFilePath { get; set; }

        protected override void Initialize()
        {
            if (File.Exists(ImageFilePath) is false)
            {
                Print($"Image not found: {ImageFilePath}");

                return;
            }

            var imageBytes = File.ReadAllBytes(ImageFilePath);

            var image = new Image
            {
                Source = imageBytes,
                Width = 200,
                Height = 200,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center
            };

            Chart.AddControl(image);
        }

        public override void Calculate(int index)
        {
        }
    }
}

위의 지표 인스턴스를 실행한 후 메인 차트에 새로운 것이 표시되지 않아야 합니다. 그러나 (이미지 파일 경로) 매개변수의 값으로 유효한 파일 경로를 입력하면 선택한 이미지가 화면 중앙에 표시되어야 합니다.

프로젝트 리소스를 사용하여 이미지를 저장하고 Image 컨트롤을 통해 표시할 수도 있습니다. 이렇게 하려면 Visual Studio에서 프로젝트 리소스를 열고 리소스 탭으로 전환하십시오. 그 안에서 새 리소스를 생성하고 기존 이미지를 추가하십시오. 이후 Project_Name_Space.Properties.Resources._Image_Name 속성을 통해 모든 Image 컨트롤에서 이 이미지를 소스로 사용할 수 있습니다.

예를 들어 아래 이미지를 복사하여 시스템에 "image.png"로 저장하십시오:

Image title

cTrader에서 새 지표 생성, 이름을 "Image Sample"로 설정하고 Visual Studio를 통해 엽니다. 이후 로고 지표 프로젝트를 리소스로 추가하십시오. 이렇게 하려면 프로젝트를 마우스 오른쪽 버튼으로 클릭하고 속성을 선택한 후 리소스를 클릭하고 어셈블리 리소스 생성 및 관리를 클릭하십시오. logo.png 파일을 새로 열린 탭에 복사하십시오.

아래 코드를 지표 메인 소스 코드 파일에 복사하십시오:

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

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class ImageSample : Indicator
    {
        protected override void Initialize()
        {
            var image = new Image
            {
                Source = Image_Sample.Properties.Resources.logo,
                Width = 200,
                Height = 200,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center
            };

            Chart.AddControl(image);
        }

        public override void Calculate(int index)
        {
        }
    }
}

이 지표의 인스턴스를 생성한 후 다음과 같은 출력이 표시되어야 합니다.

Image title

참고

이미지의 최대 크기는 10 MB입니다.