cTrader에서 플러그인 만들기 이 문서는 cTrader 생태계에서 알고리즘 트레이딩 또는 수동 작업을 위한 도구를 포함한 네이티브 플러그인을 만드는 단계를 설명합니다.
또한 사용자 정의 프레임 및 사용자 정의 창 플러그인을 만드는 방법을 배우거나, 활성 심벌 패널 (ASP) , 트레이드 워치 (TW) 또는 차트 도구 모음 과 같은 UI 영역에 나타나는 플러그인을 개발할 수도 있습니다.
Algo 앱의 플러그인 탭에서 새로 만들기 버튼을 클릭하여 알고리즘 생성 마법사를 엽니다.
플러그인의 이름을 입력한 다음, C# 과 Python 중 하나의 프로그래밍 언어를 선택합니다.
생성 방법을 선택하세요:
처음부터 – 새 플러그인에는 기본 템플릿만 포함됩니다.
템플릿 사용 – Python# 또는 C# 템플릿 목록에서 사전 제작된 알고리즘을 선택할 수 있으며, 다양한 플러그인 배치 및 기능을 다룹니다.
참고
사전 제작된 플러그인에는 배치 및 기능 로직이 이미 포함되어 있습니다. 이러한 플러그인은 저장하고 빌드하면 바로 사용할 수 있습니다.
생성 을 클릭하면 코드 편집기 가 열리고 플러그인 코드 편집을 시작할 수 있습니다.
코드 편집 플러그인 소개 에서 플러그인이 활성 심벌 패널 (ASP), 트레이드 워치 , 차트 영역 및 사용자 정의 창을 포함한 cTrader UI에 새로운 요소를 추가할 수 있음을 보여주었습니다. 플러그인 배치 튜토리얼 은 이러한 영역에서 플러그인을 배치하는 방법을 설명합니다. 코드를 작성하기 전에 플러그인의 정보 또는 컨트롤 배치를 결정하세요.
참고
배치를 결정할 때 플러그인의 출력을 가장 적합한 UI 영역에 맞추세요. 차트 프레임은 큰 WebView에 적합하며, 활성 심벌 패널은 컴팩트한 패널에 더 적합하고, 트레이드 워치는 반복적인 메시지에 강력한 옵션입니다.
생성 방법에 따라 플러그인 코드에는 다음 중 하나 이상이 포함됩니다:
C# Python
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 [Plugin(AccessRights = AccessRights.None)]
public class SimplePlugin : Plugin
{
const string WebViewUrl = "https://ctrader.com" ;
protected override void OnStart ()
{
var icon = new SvgIcon ( @"
<svg class='w-6 h-6 text-gray-800 dark:text-white' aria-hidden='true' xmlns='http://www.w3.org/2000/svg' width='15' height='15' fill='none' viewBox='0 0 24 24'>
<path stroke='#BFBFBF' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M11 6.5h2M11 18h2m-7-5v-2m12 2v-2M5 8h2a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1Zm0 12h2a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1Zm12 0h2a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1h-2a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1Zm0-12h2a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1h-2a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1Z'/>
</svg>
" );
Commands . Add ( CommandType . ChartContainerToolbar , OnIconClicked , icon );
}
private CommandResult OnIconClicked ( CommandArgs args )
{
var buttonStyle = new Style ();
buttonStyle . Set ( ControlProperty . Margin , new Thickness ( 0 , 5 , 0 , 0 ));
buttonStyle . Set ( ControlProperty . Width , 150 );
var stackPanel = new StackPanel ();
var showMessageBoxButton = new Button { Text = "show MessageBox" , Style = buttonStyle };
showMessageBoxButton . Click += args =>
{
MessageBox . Show ( "Some message" , "Caption" , MessageBoxButton . YesNo );
};
stackPanel . AddChild ( showMessageBoxButton );
var showCustomWindowButton = new Button { Text = "show Custom Window" , Style = buttonStyle };
showCustomWindowButton . Click += args =>
{
var window = new Window ();
var webView = new WebView ();
window . Child = webView ;
window . Show ();
webView . NavigateAsync ( WebViewUrl );
};
stackPanel . AddChild ( showCustomWindowButton );
var blockCounter = 1 ;
var addAspBlockButton = new Button { Text = "add ASP Block" , Style = buttonStyle };
addAspBlockButton . Click += args =>
{
var newBlock = Asp . SymbolTab . AddBlock ( "One more block " + blockCounter );
newBlock . IsExpanded = true ;
newBlock . Height = 600 ;
blockCounter ++ ;
var webView = new WebView ();
newBlock . Child = webView ;
webView . NavigateAsync ( WebViewUrl );
};
stackPanel . AddChild ( addAspBlockButton );
var aspTabCounter = 1 ;
var addAspTabButton = new Button { Text = "add ASP Tab" , Style = buttonStyle };
addAspTabButton . Click += args =>
{
var tab = Asp . AddTab ( "ASP tab " + aspTabCounter );
tab . Index = aspTabCounter ;
aspTabCounter ++ ;
var webView = new WebView ();
tab . Child = webView ;
webView . NavigateAsync ( WebViewUrl );
};
stackPanel . AddChild ( addAspTabButton );
var tradewatchTabCounter = 1 ;
var addTradeWatchTabButton = new Button { Text = "add TradeWatch Tab" , Style = buttonStyle };
addTradeWatchTabButton . Click += args =>
{
var tab = TradeWatch . AddTab ( "Tab " + tradewatchTabCounter );
tab . Index = tradewatchTabCounter ;
tradewatchTabCounter ++ ;
tab . IsSelected = true ;
var webView = new WebView ();
tab . Child = webView ;
webView . NavigateAsync ( WebViewUrl );
};
stackPanel . AddChild ( addTradeWatchTabButton );
var addCustomFrameButton = new Button { Text = "add Custom Frame" , Style = buttonStyle };
var customFrameCounter = 1 ;
addCustomFrameButton . Click += args =>
{
var frame = ChartManager . AddCustomFrame ( "Custom Frame " + customFrameCounter );
customFrameCounter ++ ;
var webView = new WebView ();
frame . Child = webView ;
webView . NavigateAsync ( WebViewUrl );
};
stackPanel . AddChild ( addCustomFrameButton );
var customizeActiveChartButton = new Button { Text = "customize Active Chart" , Style = buttonStyle };
customizeActiveChartButton . Click += args =>
{
var activeFrame = ChartManager . ActiveFrame ;
if ( activeFrame is ChartFrame chartFrame )
{
var chart = chartFrame . Chart ;
chart . ColorSettings . BackgroundColor = Color . DarkBlue ;
chart . DisplaySettings . TickVolume = false ;
chart . ZoomLevel = 10 ;
}
};
stackPanel . AddChild ( customizeActiveChartButton );
var border = new Border ();
border . Padding = 5 ;
border . BackgroundColor = "#1A1A1A" ;
border . CornerRadius = 3 ;
border . BorderThickness = 1 ;
border . BorderColor = "525252" ;
border . Child = stackPanel ;
border . Width = 170 ;
border . Height = 190 ;
return new CommandResult ( border );
}
}
Plugin 속성과 AccessRights와 같은 선택적 속성은 플러그인 클래스 (SimplePlugin) 선언 위에 나타납니다.
이 플러그인은 플러그인이 로드될 때 호출되는 OnStart() 메서드를 사용합니다. 이 아이콘은 Commands.Add를 사용하여 차트 도구 모음에 사용자 정의 아이콘을 추가합니다.
When clicked, the icon triggers a user-defined handler (OnIconClicked) that opens a panel with several UI controls.
These are main actions available in the UI:
Show message box - opens a standard message box with Yes/No buttons. 사용자 정의 창 표시 - 외부 페이지를 로드하는 WebView가 포함된 새로운 플로팅 창을 엽니다. ASP 블록 추가 - 활성 심벌 패널 (ASP)에 새로운 확장 가능한 블록을 추가하고 WebView를 내장합니다. ASP 탭 추가 - ASP에 새로운 탭을 삽입하고 WebView를 로드합니다. 트레이드 워치 탭 추가 - 트레이드 워치에 새로운 탭을 추가하고 WebView를 로드합니다. 사용자 정의 프레임 추가 - 차트 위에 사용자 정의 차트 프레임을 생성하고 WebView로 채웁니다. 활성 차트 사용자 정의 - 현재 활성 차트의 모양과 설정을 변경합니다 (예: 배경색, 확대/축소 수준, Tick Volume 가시성). 패널의 각 버튼은 Style 객체를 사용하여 스타일이 지정되고 세로 StackPanel에 추가됩니다. 패널 자체는 스타일이 지정된 Border로 감싸져 있으며, 이는 도구 모음 명령의 결과로 반환됩니다.
C# 기본 또는 Python 기본 을 공부하고 플러그인 코드 예제 를 검토하면 cTrader에서 알고리즘 개발에 대한 이해를 깊이할 수 있습니다.
참고
참조 에는 cTrader에서 플러그인을 구축하기 위한 모든 클래스, 이벤트, 메서드, 변수 등이 포함되어 있으며, 전체 알고리즘 예제와 템플릿은 GitHub 저장소 에서 사용할 수 있습니다."
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 class SimplePlugin ():
def on_start ( self ):
api . Commands . Add ( CommandType . ChartContainerToolbar , Func [ CommandArgs , CommandResult ]( self . command_handler ), COMMANDSVGICON );
def command_handler ( self , args ):
buttonStyle = Style ()
buttonStyle . Set ( ControlProperty . Margin , Thickness ( 0 , 5 , 0 , 0 ))
buttonStyle . Set ( ControlProperty . Width , 150 )
stackPanel = StackPanel ()
showMessageBoxButton = Button ()
showMessageBoxButton . Text = "show MessageBox"
showMessageBoxButton . Style = buttonStyle
showMessageBoxButton . Click += lambda _ : MessageBox . Show ( "Some message" , "Caption" , MessageBoxButton . YesNo )
stackPanel . AddChild ( showMessageBoxButton )
showCustomWindowButton = Button ()
showCustomWindowButton . Text = "show Custom Window"
showCustomWindowButton . Style = buttonStyle
showCustomWindowButton . Click += self . on_show_window_button_clicked
stackPanel . AddChild ( showCustomWindowButton )
self . blockCounter = 1
addAspBlockButton = Button ()
addAspBlockButton . Text = "add ASP Block"
addAspBlockButton . Style = buttonStyle
addAspBlockButton . Click += self . on_add_asp_block_button_clicked
stackPanel . AddChild ( addAspBlockButton )
self . aspTabCounter = 1
addAspTabButton = Button ()
addAspTabButton . Text = "add ASP Tab"
addAspTabButton . Style = buttonStyle
addAspTabButton . Click += self . on_add_asp_tab_button_clicked
stackPanel . AddChild ( addAspTabButton )
self . tradewatchTabCounter = 1
addTradeWatchTabButton = Button ()
addTradeWatchTabButton . Text = "add TradeWatch Tab"
addTradeWatchTabButton . Style = buttonStyle
addTradeWatchTabButton . Click += self . on_add_trade_watch_tab_button
stackPanel . AddChild ( addTradeWatchTabButton )
self . customFrameCounter = 1 ;
addCustomFrameButton = Button ()
addCustomFrameButton . Text = "add Custom Frame"
addCustomFrameButton . Style = buttonStyle
addCustomFrameButton . Click += self . on_add_custom_frame_button_clicked
stackPanel . AddChild ( addCustomFrameButton );
self . mainMenuItemCounter = 1 ;
addMainMenuItemButton = Button ()
addMainMenuItemButton . Text = "add Main Menu Item"
addMainMenuItemButton . Style = buttonStyle
addMainMenuItemButton . Click += self . on_add_main_menu_item_button_clicked
stackPanel . AddChild ( addMainMenuItemButton );
self . mainMenuBottomItemCounter = 1 ;
addMainMenuBottomItemButton = Button ()
addMainMenuBottomItemButton . Text = "add Main Menu Bottom Item"
addMainMenuBottomItemButton . Style = buttonStyle
addMainMenuBottomItemButton . Click += self . on_add_main_menu_bottom_item_button_clicked
stackPanel . AddChild ( addMainMenuBottomItemButton );
customizeActiveChartButton = Button ()
customizeActiveChartButton . Text = "customize Active Chart"
customizeActiveChartButton . Style = buttonStyle
customizeActiveChartButton . Click += self . on_customize_active_chart_button_clicked
stackPanel . AddChild ( customizeActiveChartButton );
border = Border ()
border . Padding = Thickness ( 5 )
border . BackgroundColor = Color . FromHex ( "#1A1A1A" )
border . CornerRadius = CornerRadius ( 3 )
border . BorderThickness = Thickness ( 1 )
border . BorderColor = Color . FromHex ( "#525252" )
border . Child = stackPanel
border . Width = 170
border . Height = 250
return CommandResult ( border );
def on_show_window_button_clicked ( self , args ):
window = Window ()
webView = WebView ()
window . Child = webView
window . Show ()
webView . NavigateAsync ( WEBVIEWURL )
def on_add_asp_block_button_clicked ( self , args ):
newBlock = api . Asp . SymbolTab . AddBlock ( f "One more block { self . blockCounter } " )
newBlock . IsExpanded = True
newBlock . Height = 600
self . blockCounter += 1
webView = WebView ()
newBlock . Child = webView
webView . NavigateAsync ( WEBVIEWURL )
def on_add_asp_tab_button_clicked ( self , args ):
tab = api . Asp . AddTab ( f "ASP tab { self . aspTabCounter } " )
tab . Index = self . aspTabCounter
self . aspTabCounter += 1
webView = WebView ()
tab . Child = webView
webView . NavigateAsync ( WEBVIEWURL )
def on_add_trade_watch_tab_button ( self , args ):
tab = api . TradeWatch . AddTab ( f "Tab { self . tradewatchTabCounter } " )
tab . Index = self . tradewatchTabCounter
self . tradewatchTabCounter += 1
tab . IsSelected = True
webView = WebView ()
tab . Child = webView
webView . NavigateAsync ( WEBVIEWURL )
def on_add_custom_frame_button_clicked ( self , args ):
frame = api . ChartManager . AddCustomFrame ( f "Custom Frame { self . customFrameCounter } " )
self . customFrameCounter += 1
webView = WebView ()
frame . Child = webView
webView . NavigateAsync ( WEBVIEWURL )
def on_customize_active_chart_button_clicked ( self , args ):
activeFrame = api . ChartManager . ActiveFrame
if activeFrame is None or isinstance ( activeFrame . __implementation__ , ChartFrame ) == False :
return
chartFrame = ChartFrame ( activeFrame )
chart = chartFrame . Chart
chart . ColorSettings . BackgroundColor = Color . DarkBlue
chart . DisplaySettings . TickVolume = False
chart . ZoomLevel = 10
def on_add_main_menu_item_button_clicked ( self , args ):
item = api . MainMenu . AddItem ( f "Item { self . mainMenuItemCounter } " , MAINMENUITEMSVGICON )
self . mainMenuItemCounter += 1
webView = WebView ()
webView . Loaded += lambda _ : webView . NavigateAsync ( "https://help.ctrader.com/" )
item . Child = webView
def main_menu_bottom_item_handler ( self ):
api . Print ( "Main menu bottom item triggered!" )
def on_add_main_menu_bottom_item_button_clicked ( self , args ):
item = api . MainMenu . AddBottomItem ( f "Item { self . mainMenuBottomItemCounter } " , MAINMENUBOTTOMITEMSVGICON )
self . mainMenuBottomItemCounter += 1
item . Handler = Action ( self . main_menu_bottom_item_handler )
WEBVIEWURL = "https://ctrader.com" ;
COMMANDSVGICON = SvgIcon ( "<svg class='w-6 h-6 text-gray-800 dark:text-white' aria-hidden='true' xmlns='http://www.w3.org/2000/svg' width='15' height='15' fill='none' viewBox='0 0 24 24'><path stroke='#BFBFBF' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M11 6.5h2M11 18h2m-7-5v-2m12 2v-2M5 8h2a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1Zm0 12h2a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1Zm12 0h2a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1h-2a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1Zm0-12h2a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1h-2a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1Z'/></svg>" )
MAINMENUITEMSVGICON = SvgIcon ( "<svg width= \" 800px \" height= \" 800px \" viewBox= \" 0 0 1024 1024 \" class= \" icon \" version= \" 1.1 \" xmlns= \" http://www.w3.org/2000/svg \" ><path d= \" M819.9 747.6H204.1c-21.8 0-39.5-17.7-39.5-39.5V278.4c0-21.8 17.7-39.5 39.5-39.5h615.7c21.8 0 39.5 17.7 39.5 39.5v429.7c0.1 21.9-17.6 39.5-39.4 39.5z \" fill= \" #FFD632 \" /><path d= \" M819.9 753.1H204.1c-24.8 0-45-20.2-45-45V278.4c0-24.8 20.2-45 45-45h615.7c24.8 0 45 20.2 45 45v429.7c0.1 24.9-20.1 45-44.9 45zM204.1 244.4c-18.7 0-34 15.3-34 34v429.7c0 18.7 15.3 34 34 34h615.7c18.7 0 34-15.3 34-34V278.4c0-18.7-15.3-34-34-34H204.1z \" fill= \" #333336 \" /><path d= \" M296.5 766.6h58.3v39.9c0 10.1-8.2 18.4-18.4 18.4h-21.6c-10.1 0-18.4-8.2-18.4-18.4v-39.9z \" fill= \" #FFC86B \" /><path d= \" M336.4 830.4h-21.6c-13.2 0-23.9-10.7-23.9-23.9v-45.4h69.3v45.4c0.1 13.2-10.6 23.9-23.8 23.9zM302 772.1v34.4c0 7.1 5.8 12.9 12.9 12.9h21.6c7.1 0 12.9-5.8 12.9-12.9v-34.4H302z \" fill= \" #333336 \" /><path d= \" M441 315.3v-62.1c0-29.4-23.9-53.3-53.3-53.3H263.6c-29.4 0-53.3 23.9-53.3 53.3v62.1c0 24.7 7.8 47.6 21 66.4 6.5 9.2 9.9 20.3 9.9 31.5v160.2c0 11.3-3.4 22.3-9.9 31.5-13.2 18.8-21 41.7-21 66.4v63.1c0 28.9 23.4 52.3 52.3 52.3h126.2c28.9 0 52.3-23.4 52.3-52.3v-63.1c0-24.7-7.7-47.5-20.9-66.2-6.5-9.3-10-20.4-10-31.8v-160c0-11.4 3.4-22.5 10-31.8 13-18.8 20.8-41.6 20.8-66.2z \" fill= \" #68A240 \" /><path d= \" M388.7 792.1H262.6c-31.8 0-57.8-25.9-57.8-57.8v-63.1c0-25.1 7.6-49.1 22-69.5 5.8-8.2 8.9-18 8.9-28.4V413.2c0-10.3-3.1-20.1-8.9-28.4-14.4-20.4-22-44.5-22-69.5v-62.1c0-32.4 26.4-58.8 58.8-58.8h124.1c32.4 0 58.8 26.4 58.8 58.8v62.1c0 25-7.6 49-21.9 69.4-5.9 8.3-9 18.2-9 28.7v159.9c0 10.4 3.1 20.3 9 28.7 14.3 20.4 21.9 44.4 21.9 69.4v63.1c0 31.7-25.9 57.6-57.8 57.6zM263.6 205.4c-26.3 0-47.8 21.4-47.8 47.8v62.1c0 22.8 6.9 44.6 20 63.2 7.1 10.1 10.9 22.1 10.9 34.7v160.2c0 12.6-3.8 24.6-10.9 34.7-13.1 18.6-20 40.4-20 63.2v63.1c0 25.8 21 46.8 46.8 46.8h126.2c25.8 0 46.8-21 46.8-46.8v-63.1c0-22.7-6.9-44.5-19.9-63.1-7.2-10.2-11-22.3-11-35V413.3c0-12.7 3.8-24.8 11-35 13-18.5 19.9-40.3 19.9-63.1v-62.1c0-26.3-21.4-47.8-47.8-47.8H263.6z \" fill= \" #333336 \" /><path d= \" M780.6 437.5H495.4c-8 0-14.5-6.5-14.5-14.5V317.6c0-8 6.5-14.5 14.5-14.5h285.2c8 0 14.5 6.5 14.5 14.5V423c0 8-6.5 14.5-14.5 14.5z \" fill= \" #D8A128 \" /><path d= \" M780.6 443H495.4c-11 0-20-9-20-20V317.6c0-11 9-20 20-20h285.2c11 0 20 9 20 20V423c0 11-8.9 20-20 20zM495.4 308.6c-5 0-9 4-9 9V423c0 5 4 9 9 9h285.2c5 0 9-4 9-9V317.6c0-5-4-9-9-9H495.4zM476.9 889.6c-2.1 0-4-1.2-5-3.2-0.8-1.6-19.7-39-79-19.6-23.1 7.5-41.3 6.6-54.3-2.8-18.3-13.2-18.5-38-18.5-39.1 0-3 2.5-5.5 5.5-5.5s5.5 2.5 5.5 5.5c0 0.3 0.3 20.4 14 30.2 10 7.2 24.9 7.6 44.4 1.2 19.6-6.4 48.1-11 71.8 3.8 14.5 9 20.3 21 20.5 21.5 1.3 2.7 0.1 6-2.6 7.3-0.8 0.5-1.6 0.7-2.3 0.7z m-145.7-64.7z \" fill= \" #333336 \" /><path d= \" M550 570.9h-57.3c-4.7 0-8.6-3.8-8.6-8.6V505c0-4.7 3.8-8.6 8.6-8.6H550c4.7 0 8.6 3.8 8.6 8.6v57.3c-0.1 4.7-3.9 8.6-8.6 8.6z \" fill= \" #D5D9CF \" /><path d= \" M550 576.4h-57.3c-7.8 0-14.1-6.3-14.1-14.1V505c0-7.8 6.3-14.1 14.1-14.1H550c7.8 0 14.1 6.3 14.1 14.1v57.3c-0.1 7.8-6.4 14.1-14.1 14.1z m-57.3-74.5c-1.7 0-3.1 1.4-3.1 3.1v57.3c0 1.7 1.4 3.1 3.1 3.1H550c1.7 0 3.1-1.4 3.1-3.1V505c0-1.7-1.4-3.1-3.1-3.1h-57.3z \" fill= \" #333336 \" /><path d= \" M667.3 570.9H610c-4.7 0-8.6-3.8-8.6-8.6V505c0-4.7 3.8-8.6 8.6-8.6h57.3c4.7 0 8.6 3.8 8.6 8.6v57.3c0 4.7-3.8 8.6-8.6 8.6z \" fill= \" #D5D9CF \" /><path d= \" M667.3 576.4H610c-7.8 0-14.1-6.3-14.1-14.1V505c0-7.8 6.3-14.1 14.1-14.1h57.3c7.8 0 14.1 6.3 14.1 14.1v57.3c0 7.8-6.3 14.1-14.1 14.1zM610 501.9c-1.7 0-3.1 1.4-3.1 3.1v57.3c0 1.7 1.4 3.1 3.1 3.1h57.3c1.7 0 3.1-1.4 3.1-3.1V505c0-1.7-1.4-3.1-3.1-3.1H610z \" fill= \" #333336 \" /><path d= \" M784.7 570.9h-57.3c-4.7 0-8.6-3.8-8.6-8.6V505c0-4.7 3.8-8.6 8.6-8.6h57.3c4.7 0 8.6 3.8 8.6 8.6v57.3c0 4.7-3.9 8.6-8.6 8.6z \" fill= \" #D5D9CF \" /><path d= \" M784.7 576.4h-57.3c-7.8 0-14.1-6.3-14.1-14.1V505c0-7.8 6.3-14.1 14.1-14.1h57.3c7.8 0 14.1 6.3 14.1 14.1v57.3c0 7.8-6.3 14.1-14.1 14.1z m-57.3-74.5c-1.7 0-3.1 1.4-3.1 3.1v57.3c0 1.7 1.4 3.1 3.1 3.1h57.3c1.7 0 3.1-1.4 3.1-3.1V505c0-1.7-1.4-3.1-3.1-3.1h-57.3z \" fill= \" #333336 \" /><path d= \" M550 691.6h-57.3c-4.7 0-8.6-3.8-8.6-8.6v-57.3c0-4.7 3.8-8.6 8.6-8.6H550c4.7 0 8.6 3.8 8.6 8.6V683c-0.1 4.8-3.9 8.6-8.6 8.6z \" fill= \" #D5D9CF \" /><path d= \" M550 697.1h-57.3c-7.8 0-14.1-6.3-14.1-14.1v-57.3c0-7.8 6.3-14.1 14.1-14.1H550c7.8 0 14.1 6.3 14.1 14.1V683c-0.1 7.8-6.4 14.1-14.1 14.1z m-57.3-74.4c-1.7 0-3.1 1.4-3.1 3.1v57.3c0 1.7 1.4 3.1 3.1 3.1H550c1.7 0 3.1-1.4 3.1-3.1v-57.3c0-1.7-1.4-3.1-3.1-3.1h-57.3z \" fill= \" #333336 \" /><path d= \" M667.3 691.6H610c-4.7 0-8.6-3.8-8.6-8.6v-57.3c0-4.7 3.8-8.6 8.6-8.6h57.3c4.7 0 8.6 3.8 8.6 8.6V683c0 4.8-3.8 8.6-8.6 8.6z \" fill= \" #D5D9CF \" /><path d= \" M667.3 697.1H610c-7.8 0-14.1-6.3-14.1-14.1v-57.3c0-7.8 6.3-14.1 14.1-14.1h57.3c7.8 0 14.1 6.3 14.1 14.1V683c0 7.8-6.3 14.1-14.1 14.1zM610 622.7c-1.7 0-3.1 1.4-3.1 3.1v57.3c0 1.7 1.4 3.1 3.1 3.1h57.3c1.7 0 3.1-1.4 3.1-3.1v-57.3c0-1.7-1.4-3.1-3.1-3.1H610z \" fill= \" #333336 \" /><path d= \" M784.7 691.6h-57.3c-4.7 0-8.6-3.8-8.6-8.6v-57.3c0-4.7 3.8-8.6 8.6-8.6h57.3c4.7 0 8.6 3.8 8.6 8.6V683c0 4.8-3.9 8.6-8.6 8.6z \" fill= \" #68A240 \" /><path d= \" M784.7 697.1h-57.3c-7.8 0-14.1-6.3-14.1-14.1v-57.3c0-7.8 6.3-14.1 14.1-14.1h57.3c7.8 0 14.1 6.3 14.1 14.1V683c0 7.8-6.3 14.1-14.1 14.1z m-57.3-74.4c-1.7 0-3.1 1.4-3.1 3.1v57.3c0 1.7 1.4 3.1 3.1 3.1h57.3c1.7 0 3.1-1.4 3.1-3.1v-57.3c0-1.7-1.4-3.1-3.1-3.1h-57.3z \" fill= \" #333336 \" /></svg>" )
MAINMENUBOTTOMITEMSVGICON = SvgIcon ( "<svg width= \" 800px \" height= \" 800px \" viewBox= \" 0 0 1024 1024 \" class= \" icon \" version= \" 1.1 \" xmlns= \" http://www.w3.org/2000/svg \" ><path d= \" M819 234l-48-13 48-13 13-48 13 48 48 13-48 13-13 48-13-48zM867 287l-19-5 19-4 4-19 4 19 19 4-19 5-4 19-4-19z \" fill= \" #FDCD60 \" /><path d= \" M130 472l-21-5 21-5 5-21 5 21 21 5-21 5-5 20-5-20z \" fill= \" #FDCD60 \" /><path d= \" M208 246m-9 0a9 9 0 1 0 18 0 9 9 0 1 0-18 0Z \" fill= \" #5546CB \" /><path d= \" M824 804a25 25 0 1 1 25-25 25 25 0 0 1-25 25z m0-36a10 10 0 1 0 10 10 10 10 0 0 0-10-9z \" fill= \" #5546CB \" /><path d= \" M166 728h78v77.34h-78z \" fill= \" #FDCD60 \" /><path d= \" M452 509v43h128v-43a19 19 0 0 1 14-18H438a19 19 0 0 1 14 18z \" fill= \" #F97744 \" /><path d= \" M661 489h1a19 19 0 0 1 19 19v43h32v114a74 74 0 0 1-74 74H387a73 73 0 0 1-73-73V552h38v-43a19 19 0 0 1 19-19h1a116 116 0 0 1-83-50v337a31 31 0 0 0 31 31h386a31 31 0 0 0 31-31V440a116 116 0 0 1-76 49z \" fill= \" #F97744 \" /><path d= \" M334 666a53 53 0 0 0 53 53h251a54 54 0 0 0 54-54v-93h-32a30 30 0 0 1-30 25 30 30 0 0 1-30-25H432a30 30 0 0 1-30 25 30 30 0 0 1-30-25h-38z \" fill= \" #FFFFFF \" /><path d= \" M580 553H452a19 19 0 0 1-19 19h166a19 19 0 0 1-19-19z \" fill= \" #5546CB \" /><path d= \" M662 572h30v93a54 54 0 0 1-54 54H387a53 53 0 0 1-53-53v-94h37a19 19 0 0 1-19-19h-38v113a73 73 0 0 0 73 73h251a74 74 0 0 0 74-74V552h-32a19 19 0 0 1-18 20z \" fill= \" #5546CB \" /><path d= \" M289 375a96 96 0 0 0 83 95v-70a30 30 0 0 1 30-30 30 30 0 0 1 30 30v71h168v-71a30 30 0 0 1 30-30 30 30 0 0 1 30 30v69a96 96 0 0 0 76-94V266a31 31 0 0 0-31-31H320a31 31 0 0 0-31 31v109z \" fill= \" #FDCD60 \" /><path d= \" M402 597a30 30 0 0 0 30-25h-59a30 30 0 0 0 29 25zM372 510h60v41.48h-60zM630 597a30 30 0 0 0 30-25h-59a30 30 0 0 0 29 25zM600 510h60v41.48h-60z \" fill= \" #5546CB \" /><path d= \" M438 491h-67a19 19 0 0 0-19 19v43a19 19 0 0 0 19 19h63a19 19 0 0 0 19-19v-44a19 19 0 0 0-15-18z m-6 61h-60v-42h60zM662 490h-67a19 19 0 0 0-14 18v43a19 19 0 0 0 19 19h63a19 19 0 0 0 19-19v-42a19 19 0 0 0-20-19z m-1 61h-61v-41h60z \" fill= \" #FDCD60 \" /><path d= \" M786 524h-29v148h29a24 24 0 0 0 24-24V548a24 24 0 0 0-24-24z \" fill= \" #AFBCF3 \" /><path d= \" M786 504h-29V266a51 51 0 0 0-51-51h-78a116 116 0 0 0-230 0h-78a51 51 0 0 0-51 51v240l-8-2h-30a44 44 0 0 0-44 44v100a44 44 0 0 0 44 44h30l8-2v87a51 51 0 0 0 51 51h386a51 51 0 0 0 51-51v-85h29a44 44 0 0 0 44-44V548a44 44 0 0 0-44-44zM260 672h-29a24 24 0 0 1-24-24V548a24 24 0 0 1 24-24h29z m253-536a96 96 0 0 1 95 79H418a96 96 0 0 1 95-79zM289 266a31 31 0 0 1 31-31h386a31 31 0 0 1 31 31v109a96 96 0 0 1-76 94v-69a30 30 0 0 0-30-30 30 30 0 0 0-30 30v71H432v-71a30 30 0 0 0-30-30 30 30 0 0 0-30 30v70a96 96 0 0 1-83-95V266z m417 542H320a31 31 0 0 1-31-31V440a116 116 0 0 0 83 50h289a116 116 0 0 0 76-49v336a31 31 0 0 1-31 31z m104-160a24 24 0 0 1-24 24h-29V524h29a24 24 0 0 1 24 24z \" fill= \" #5546CB \" /><path d= \" M208 548v100a24 24 0 0 0 24 24h29V524h-30a24 24 0 0 0-23 24z \" fill= \" #AFBCF3 \" /></svg>" )
SimplePlugin 클래스는 Python으로 작성된 플러그인을 나타내며, Algo API를 사용하여 플랫폼 인터페이스를 사용자 정의 컨트롤 및 상호 작용으로 확장합니다.
on_start() 메서드는 플러그인이 초기화될 때 호출되는 진입점입니다. 이 메서드는 차트 도구 모음에 사용자 정의 SVG 아이콘을 추가합니다.
When clicked, the icon triggers the command_handler method, which returns a styled panel (CommandResult) containing multiple interactive buttons.
Each button performs a distinct platform interaction:
Show message box - opens a standard message box with yes and no buttons. 사용자 정의 창 표시 - 외부 페이지를 로드하는 WebView가 포함된 새로운 플로팅 창을 엽니다. ASP 블록 추가 - 활성 심벌 패널 (ASP)에 새로운 확장 가능한 블록을 추가하고 WebView를 내장합니다. ASP 탭 추가 - ASP 영역에 새로운 탭을 삽입하고 WebView를 로드합니다. 트레이드 워치 탭 추가 - 트레이드 워치에 새로운 탭을 추가하고 기본적으로 선택합니다. 사용자 정의 프레임 추가 - 플로팅 차트 프레임을 생성하고 WebView를 삽입합니다. 메인 메뉴 항목 추가 - 메인 상단 메뉴에 새로운 항목을 추가하고 cTrader 도움말 사이트를 가리키는 WebView를 엽니다. 메인 메뉴 하단 항목 추가 - 메인 메뉴 하단에 항목을 추가하고 클릭 시 메시지를 출력합니다. 활성 차트 사용자 정의 - 현재 활성 차트의 배경색을 변경하고 Tick Volume을 숨기며 확대/축소 수준을 조정합니다. 이러한 버튼은 세로로 쌓인 레이아웃 (StackPanel)에 추가되고 스타일이 지정된 Border로 감싸져 있으며, 이는 크기, 패딩, 배경, 테두리 두께 및 색상을 정의합니다. 패널은 CommandResult로 반환되어 차트 UI에 표시됩니다.
Python 기본 을 공부하고 플러그인 코드 예제 를 검토하면 cTrader에서 알고리즘 개발에 대한 이해를 깊이할 수 있습니다.
참고
참조 에는 cTrader에서 플러그인을 구축하기 위한 모든 클래스, 이벤트, 메서드, 변수 등이 포함되어 있으며, 전체 알고리즘 예제와 템플릿은 GitHub 저장소 에서 사용할 수 있습니다."
새로운 지식을 적용하여 플러그인 코드를 편집하고 필요에 맞게 조정하세요.
저장 및 빌드 Windows Mac
코드 편집기 상단의 저장 버튼을 클릭하거나 Ctrl + S 단축키를 사용하여 코드를 저장하세요.
플러그인을 사용하기 전에 코드를 검증하기 위해 플러그인 프로젝트를 빌드해야 합니다. 코드 편집기 상단의 빌드 버튼을 클릭하거나 Ctrl + B 를 누르세요.
코드 편집기 상단의 저장 아이콘을 클릭하거나 Cmd + S 단축키를 사용하여 코드를 저장하세요.
지표를 사용하기 전에 지표 프로젝트를 빌드하여 코드를 검증해야 합니다. 코드 편집기 상단의 빌드 아이콘을 클릭하거나 Cmd + B 를 누르세요.
빌드가 성공하면 빌드 결과 에 확인 메시지가 표시됩니다. 빌드가 실패하면 발생한 모든 오류 요약이 대신 표시됩니다.
마지막 빌드 이후 코드에 변경 사항이 있으면 빌드 아이콘 옆에 별표가 나타납니다. 이 경우 변경 사항이 적용되도록 플러그인을 다시 빌드해야 합니다.
성공적으로 빌드되면 플러그인은 코드에 지정된 cTrader UI 영역 에 사용자 정의 요소를 즉시 추가합니다.
특수 메서드 사용 (선택 사항) cBot과 마찬가지로 플러그인은 OnStart() 메서드, OnStop() 메서드 및 Timer 객체를 사용할 수 있습니다:
OnStart() 핸들러는 새 플러그인이 초기화될 때 한 번 호출됩니다. OnStop() 핸들러는 플러그인 인스턴스가 비활성화되거나, 제거되거나, cTrader가 종료되어 중단될 때 호출됩니다. Timer 객체는 정기적으로 코드를 실행하는 데 사용됩니다. Timer 클래스의 내장 타이머를 초기화하고 시작한 후, 정의된 간격이 경과할 때마다 지정된 메서드가 실행됩니다. 예외 처리
다른 알고리즘과 마찬가지로, 플러그인은 OnException 메서드에 접근할 수 있으며, 이는 알고리즘이 오류를 처리 하는 방식을 제어하는 데 자주 사용됩니다.
위에서 언급한 메서드의 사용을 설명하기 위해, 현재 열려 있는 수익성 포지션의 총 수를 표시하는 간단한 플러그인을 고려해 보겠습니다. 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
44
45
46
47
48
49
50
51
52
53
54
55
56 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 ProfitablePositions : Plugin
{
private TextBlock _textBlock = new TextBlock
{
Text = "Starting..." ,
FontSize = 30 ,
FontWeight = FontWeight . ExtraBold ,
TextAlignment = TextAlignment . Center ,
Padding = new Thickness ( 5 , 5 , 5 , 5 ),
};
protected override void OnStart ()
{
var aspBlock = Asp . SymbolTab . AddBlock ( "Profitable Positions" );
aspBlock . IsExpanded = true ;
aspBlock . Height = 50 ;
aspBlock . Child = _textBlock ;
_textBlock . Text = GetProfitablePositions ();
Timer . Start ( TimeSpan . FromSeconds ( 1 ));
}
protected override void OnTimer ()
{
_textBlock . Text = GetProfitablePositionsCount (). toString ();
}
protected int GetProfitablePositionsCount ()
{
int count = 0 ;
foreach ( var position in Positions )
{
if ( position . GrossProfit > 0 )
{
count ++ ;
}
}
return count ;
}
}
}