Los controles permiten ciertas interacciones con cBots, indicadores y plugins. Utilizando la guÃa a continuación, puede crear fácilmente controles de interfaz de usuario básicos y avanzados directamente en un gráfico.
Si crea el indicador anterior y crea una instancia, deberÃa ver un botón gris Haz clic aquà justo en el centro del gráfico.
Diferencia entre controles y objetos de gráfico
En una sección anterior, ya hemos cubierto los objetos de gráfico. Los controles permiten a los usuarios interactuar con cBots e indicadores. Por el contrario, los objetos de gráfico dan la oportunidad de dibujar algo en el gráfico de operaciones o en una ventana de salida de indicador separada.
Los controles de gráfico derivan de la clase ControlBase mientras que los objetos de gráfico se derivan de la clase ChartObject.
De manera similar a los objetos de gráfico, los controles de gráfico se pueden agregar tanto al gráfico principal como a cualquier ventana de salida de indicador (si existen). A continuación se muestra un ejemplo de dicho posicionamiento:
El control ColorPicker permite a los operadores seleccionar su color preferido para elementos u objetos clave en cTrader. Por ejemplo, un desarrollador puede integrar el control ColorPicker en un cBot que dibuja lÃneas de tendencia para que los usuarios puedan seleccionar su color preferido para cada lÃnea de tendencia. Esta configuración facilita a los operadores distinguir entre varios tipos de lÃneas de tendencia.
Cuando los usuarios hacen clic en el cuadrado de color, aparece el selector de color. Los usuarios pueden entonces elegir entre colores estándar y personalizados.
El control DropZone permite a los operadores realizar acciones de arrastrar y soltar con cBots, indicadores o plugins. Para implementar este control en su algoritmo, utilice la clase DropZone. El control DropZone se puede manipular como cualquier otro control.
Cuando un usuario suelta un archivo o carpeta compatible en el cuadro, se genera el evento Dropped. Cuando un usuario suelta una carpeta o varias carpetas en el cuadro, solo se procesan y copian los archivos compatibles con las extensiones especificadas en FilterExtensions.
Nota
Los archivos soltados generalmente se copian y guardan en esta ubicación: ..\Documents\cAlgo\Data\{AlgoType}\{AlgoName}\Selected Files\
La ubicación para las instancias de cBot difiere de la anterior: ..\Documents\cAlgo\Data\cBots\{cBotName}\{unique-instance-number}\Selected files\
Este código de plugin le muestra cómo agregar un control DropZone a Trade Watch:
usingSystem;usingSystem.Drawing;usingcAlgo.API;usingcAlgo.API.Collections;usingcAlgo.API.Indicators;usingcAlgo.API.Internals;namespacecAlgo.Plugins{[Plugin(AccessRights = AccessRights.None)]publicclassTradeWatchTabSample:Plugin{protectedoverridevoidOnStart(){vartab=TradeWatch.AddTab("DropZone");var_border=newBorder{BorderThickness=3,BorderColor=Color.DarkGray,Opacity=0.7,HorizontalAlignment=HorizontalAlignment.Center,VerticalAlignment=VerticalAlignment.Center,Height=200,Width=350,BackgroundColor=Color.LightGray};var_textBlock=newTextBlock{Text="Drag your files here",Opacity=1,ForegroundColor=Color.DarkGray,FontSize=16,VerticalAlignment=VerticalAlignment.Center,HorizontalAlignment=HorizontalAlignment.Center};var_dropzone=newDropZone{FilterExtensions=newstring[]{"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;}privatevoidDropped_file(DroppedEventArgsobj){Print("File has been added!");}}}
ProgressBar
El control ProgressBar muestra la progresión de una operación en curso. Las barras de progreso hacen que los algoritmos sean más fáciles de usar y ayudan a gestionar las expectativas de los operadores con respecto al tiempo de espera de ciertas operaciones.
La API de cTrader Algo permite a los desarrolladores agregar dos tipos de controles ProgressBar: control infinito y control determinado.
Control infinito
Es posible que desee utilizar el control infinito en las siguientes situaciones:
No puede determinar el tiempo de espera de una operación.
No puede detectar la progresión de una operación.
No desea indicar cuánto tiempo tardará una operación.
Control determinado
Es posible que desee utilizar este control cuando pueda determinar el tiempo de espera de una operación y desee que los usuarios vean un indicador basado en ese tiempo.
Para mostrar el progreso de la operación, utilice la propiedad Value para establecer una cifra. Para establecer el porcentaje de la barra de progreso, utilice las propiedades Minimum y Maximum.
El código de plugin a continuación le muestra cómo crear una barra de progreso utilizando controles infinitos y determinados (verde):
La API de cTrader Algo proporciona la interfaz OpenFileDialog para permitir a los usuarios seleccionar un archivo para un algoritmo. Cuando un usuario selecciona un archivo en la ventana resultante, el archivo se copia a la carpeta Selected files del algoritmo. Un algoritmo puede trabajar con archivos dentro de su carpeta Selected files sin restricciones.
Consejo
Utilice la funcionalidad OpenFileDialog cuando necesite cargar archivos de datos importantes, archivos de respaldo o configuración, indicadores personalizados o scripts.
El código a continuación le muestra cómo utilizar el diálogo OpenFileDialog en un indicador:
La API de cTrader Algo proporciona la interfaz OpenFolderDialog para permitir a los usuarios especificar una carpeta para un algoritmo. Cuando un usuario selecciona una carpeta en la ventana resultante, todos los archivos y carpetas con archivos dentro de la carpeta seleccionada se copian a la carpeta Selected files del algoritmo.
Consejo
Utilice la funcionalidad OpenFolderDialog cuando necesite cargar una carpeta que contenga archivos de datos crÃticos, archivos de respaldo o configuración, indicadores personalizados o scripts.
Los archivos y carpetas seleccionados generalmente se copian a la carpeta Selected files porque un algoritmo puede trabajar con elementos dentro de esa carpeta incluso cuando su AccessRights está configurado como None.
Nota
La carpeta Selected files de un algoritmo generalmente se encuentra en esta ruta: ..\Documents\cAlgo\Data\{AlgoType}\{AlgoName}\Selected files\
La carpeta Selected files para una instancia de cBot difiere de la anterior: ..\Documents\cAlgo\Data\cBots\{cBotName}\{Instance-Id}\Selected files\
El código a continuación le muestra cómo utilizar el diálogo OpenFolderDialog en un indicador:
usingSystem;usingcAlgo.API;namespacecAlgo{[Indicator(AccessRights = AccessRights.None, IsOverlay = true)]publicclassOpenFolderDialogExample:Indicator{privateOpenFolderDialog_openFolderDialog;protectedoverridevoidInitialize(){_openFolderDialog=newOpenFolderDialog(){InitialDirectory=Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),Title="My Open Folder Dialog Title"};varshowOpenFolderDialog=newButton{Text="Show Open Folder Dialog"};showOpenFolderDialog.Click+=showOpenFolderDialog_Click;varpanel=newStackPanel{Orientation=Orientation.Vertical,HorizontalAlignment=HorizontalAlignment.Center,VerticalAlignment=VerticalAlignment.Center};panel.AddChild(showOpenFolderDialog);Chart.AddControl(panel);}privatevoidshowOpenFolderDialog_Click(ButtonClickEventArgsobj){varresult=_openFolderDialog.ShowDialog();Print($"Result: {result} | FolderName: {_openFolderDialog.FolderName}");}publicoverridevoidCalculate(intindex){}}}
SaveFileDialog
La API de cTrader Algo proporciona la interfaz SaveFileDialog para permitir a los usuarios guardar archivos (localmente) en sus computadoras. Cuando aparece la ventana correspondiente, un usuario selecciona la carpeta en la que desea guardar el archivo e ingresa un nombre para el archivo. Luego, el archivo se guarda en la ubicación especificada.
Consejo
Utilice la funcionalidad SaveFileDialog cuando necesite hacer cualquiera de las siguientes acciones:
Guardar informes de rendimiento, resultados de backtesting, archivos de configuración o datos de optimización.
Exportar registros de operaciones, diarios de operaciones o datos de actividad general del usuario.
Almacenar indicadores personalizados, datos para gráficos y visualizaciones o parámetros para una estrategia.
El código a continuación le muestra cómo utilizar el diálogo SaveFileDialog en un indicador:
usingSystem;usingcAlgo.API;usingSystem.Text;namespacecAlgo{[Indicator(AccessRights = AccessRights.None, IsOverlay = true)]publicclassSaveFileDialogExample:Indicator{privateSaveFileDialog_saveFileDialog;protectedoverridevoidInitialize(){_saveFileDialog=newSaveFileDialog(){InitialDirectory=Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),Title="My Save File Dialog Title"};varshowSaveFileDialogText=newButton{Text="Show Save File Dialog (Set Content as text)"};varshowSaveFileDialogBytes=newButton{Text="Show Save File Dialog (Set Content as bytes)"};showSaveFileDialogText.Click+=showSaveFileDialogText_Click;showSaveFileDialogBytes.Click+=showSaveFileDialogBytes_Click;varpanel=newStackPanel{Orientation=Orientation.Vertical,HorizontalAlignment=HorizontalAlignment.Center,VerticalAlignment=VerticalAlignment.Center};panel.AddChild(showSaveFileDialogText);panel.AddChild(showSaveFileDialogBytes);Chart.AddControl(panel);}privatevoidshowSaveFileDialogText_Click(ButtonClickEventArgsobj){varresult=_saveFileDialog.ShowDialog();Print($"Result: {result}");if(result!=FileDialogResult.Cancel){_saveFileDialog.WriteToFile("Test in text");}}privatevoidshowSaveFileDialogBytes_Click(ButtonClickEventArgsobj){varresult=_saveFileDialog.ShowDialog();Print($"Result: {result}");if(result!=FileDialogResult.Cancel){_saveFileDialog.WriteToFile(Encoding.UTF8.GetBytes("Test in bytes"));}}publicoverridevoidCalculate(intindex){}}}
Controles arrastrables
Control arrastrable del área del gráfico
Las interfaces ChartDraggable y ChartDraggables proporcionan tipos que le permiten agregar un control arrastrable capaz de alojar otros controles y diferentes elementos a un gráfico. Estos controles arrastrables facilitan a los usuarios la interacción con varios elementos del gráfico.
Nota
Un control arrastrable solo se puede mover o reposicionar dentro del gráfico donde se ha agregado.
Este código le muestra cómo crear un indicador que agrega dos controles que se pueden mover dentro de un gráfico:
usingSystem;usingcAlgo.API;usingcAlgo.API.Collections;usingcAlgo.API.Indicators;usingcAlgo.API.Internals;namespacecAlgo{[Indicator(AccessRights = AccessRights.None)]publicclassDragControl:Indicator{protectedoverridevoidInitialize(){vardraggable=Chart.Draggables.Add();vardraggable2=IndicatorArea.Draggables.Add();draggable.Child=GetDraggableChildWebView();draggable2.Child=GetDraggableChildText();draggable.LocationChanged+=draggable_LocationChanged;draggable2.LocationChanged+=draggable2_LocationChanged;}publicoverridevoidCalculate(intindex){// Calculate value at specified index// Result[index] = }privateStackPanelGetDraggableChildWebView(){varstackPanel=newStackPanel{HorizontalAlignment=HorizontalAlignment.Center,VerticalAlignment=VerticalAlignment.Center,BackgroundColor=Color.Gold};varwebView=newWebView(){Height=500,Width=300};webView.Loaded+=webView_Loaded;stackPanel.AddChild(webView);returnstackPanel;}privateStackPanelGetDraggableChildText(){varstackPanel=newStackPanel{HorizontalAlignment=HorizontalAlignment.Center,VerticalAlignment=VerticalAlignment.Center,BackgroundColor=Color.Gold};vartext_block=newTextBlock{Text="Testing draggable controls",Margin=5,ForegroundColor=Color.Black,FontWeight=FontWeight.ExtraBold};stackPanel.AddChild(text_block);returnstackPanel;}privatevoidwebView_Loaded(WebViewLoadedEventArgsobj){obj.WebView.NavigateAsync("https://www.youtube.com/");}privatevoiddraggable_LocationChanged(ChartDraggableLocationChangedEventArgsobj){Print($"Draggable '{obj.Draggable.Id}' location changed to: ({obj.Draggable.X}, {obj.Draggable.Y})");}privatevoiddraggable2_LocationChanged(ChartDraggableLocationChangedEventArgsobj){Print($"Draggable '{obj.Draggable.Id}' location changed to: ({obj.Draggable.X}, {obj.Draggable.Y})");}}}
Control arrastrable de la ventana de la aplicación
Las interfaces ApplicationDraggable y ApplicationDraggables proporcionan los tipos utilizados para agregar controles flotantes que se pueden mover individualmente por toda la ventana de la aplicación cTrader. Estos controles le permiten crear interfaces de usuario interactivas y dinámicas.
Nota
De los tres tipos de algoritmos, solo los plugins pueden implementar controles arrastrables en toda la aplicación.
Este código le muestra cómo crear un plugin que agrega un componente WebView y un bloque de texto en dos ventanas separadas, que se pueden mover por toda la interfaz de usuario de cTrader:
La clase TabControl proporciona tipos que le permiten crear múltiples pestañas para un algoritmo. Estas pestañas se pueden utilizar para mantener juntos elementos relacionados o presentar vistas separadas para funcionalidades.
Este código le muestra cómo usar pestañas en un plugin agregado al Panel de sÃmbolo activo:
Un control personalizado es un control que, en esencia, está construido por varios controles predefinidos. En otras palabras, es un control para el cual otros controles constituyen su contenido.
Los controles personalizados actúan como clases reutilizables de manera similar a los controles integrados.
usingcAlgo.API;namespaceChartControlsTest{[Indicator(IsOverlay = true, AccessRights = AccessRights.None)]publicclassChartControls:Indicator{[Parameter("# Of Text Areas", DefaultValue = 4)]publicintNumberOfTextAreas{get;set;}protectedoverridevoidInitialize(){varpanel=newWrapPanel{Orientation=Orientation.Horizontal,HorizontalAlignment=HorizontalAlignment.Center,VerticalAlignment=VerticalAlignment.Center};for(inti=0;i<NumberOfTextAreas;i++){vartextArea=newTextArea{HorizontalAlignment=HorizontalAlignment.Right,VerticalAlignment=VerticalAlignment.Stretch,Margin=5,};panel.AddChild(textArea);}Chart.AddControl(panel);}publicoverridevoidCalculate(intindex){}}publicclassTextArea:CustomControl{privatereadonlyTextBox_textBox;publicTextArea(){_textBox=newTextBox{TextAlignment=TextAlignment.Left,TextWrapping=TextWrapping.Wrap,AcceptsReturn=true,AcceptsTab=true,Width=300,Height=200,};AddChild(_textBox);}}}
Una instancia de este indicador deberÃa mostrar cuatro cuadros de texto directamente en el centro del gráfico principal.
Organizar controles con paneles
Para hacer que el trabajo con controles sea más conveniente, es posible que desee colocar varios controles en un grupo distinto con su propia posición en la interfaz de usuario. Para hacer esto, puede usar la clase Panels y sus derivados.
Piense en un panel como un control con otros controles como su contenido. cTrader admite cinco clases diferentes que heredan de la clase base Panels (que a su vez hereda de la clase Control):
Canvas
DockPanel
Grid
StackPanel
WrapPanel
Cada una de las clases anteriores utiliza diferentes diseños de panel y estrategias de posicionamiento, como se explica a continuación.
Canvas
El canvas es un panel que permite posicionar controles basándose en ciertas coordenadas X e Y.
En la mayorÃa de los casos, la clase Canvas se utiliza para agrupar solo un pequeño número de controles.
Panel de acoplamiento
La clase DockPanel se utiliza para acoplar (colocar) un control en una ubicación estática en el gráfico. Hay cuatro posiciones de acoplamiento posibles:
Arriba
Abajo
Izquierda
Derecha
Cada control tiene una propiedad Dock. Al utilizar la clase DockPanel, puede usar esta propiedad para posicionar un control dentro de un DockPanel. Esto se ilustra en el siguiente ejemplo:
usingcAlgo.API;namespaceChartControlsTest{[Indicator(IsOverlay = true, AccessRights = AccessRights.None)]publicclassChartControls:Indicator{[Parameter(DefaultValue = Dock.Top)]publicDockTextBoxDock{get;set;}[Parameter(DefaultValue = Dock.Bottom)]publicDockButtonDock{get;set;}privateTextBox_textBox;protectedoverridevoidInitialize(){_textBox=newTextBox{Margin=5,Text="Write here...",ForegroundColor=Color.Yellow,Dock=TextBoxDock,Width=200};varbutton=newButton{Text="Tell what I wrote?",Dock=ButtonDock,Width=200};button.Click+=Button_Click;vardockPanel=newDockPanel{HorizontalAlignment=HorizontalAlignment.Center,VerticalAlignment=VerticalAlignment.Center,};dockPanel.AddChild(_textBox);dockPanel.AddChild(button);Chart.AddControl(dockPanel);}privatevoidButton_Click(ButtonClickEventArgsobj){obj.Button.Text=$"You wrote: {_textBox.Text}";}publicoverridevoidCalculate(intindex){}}}
Al crear una instancia de este indicador, deberÃa ver un panel de acoplamiento en el centro del gráfico que contiene un campo de texto y un botón en el que se puede hacer clic.
Tenga en cuenta que los paneles de acoplamiento pueden poblarse horizontal o verticalmente. No puede utilizar ambas alineaciones al mismo tiempo. La orientación del panel de acoplamiento se establece automáticamente al configurar el primer control en un DockPanel. Si la propiedad Dock del primer control se establece en Top o Bottom, todo el DockPanel se orientará verticalmente, y viceversa.
Panel de pila
Los paneles de pila son uno de los controles más utilizados debido a su simplicidad y usabilidad. Los paneles de pila alinean los controles secundarios horizontal o verticalmente uno por uno. Como se muestra a continuación, solo tiene que configurar su orientación y la clase gestionará el resto:
Piense en las cuadrÃculas como hojas de cálculo con un número determinado de columnas y filas. Al utilizar cuadrÃculas, puede añadir controles a cada celda separada.
Como se demuestra a continuación, cuando crea una instancia de la clase Grid, pasa el número de sus filas y columnas como argumentos integer. Al añadir nuevos hijos o controles, de manera similar tiene que especificar el número de filas y columnas secundarias.
El número de controles raÃz que se pueden añadir en un gráfico está limitado a 100 debido a posibles problemas de rendimiento. Esta limitación se aplica solo a una instancia de algoritmo y a los controles adjuntos a precios y barras.
Propiedades de relleno y margen
La propiedad Margin define el espacio entre los bordes de un objeto Control y su padre (un gráfico, un panel, un borde, etc.).
A su vez, la propiedad Padding determina el espacio entre el contenido del control y sus bordes. Puede variar los valores de la propiedad para que sean todos diferentes para diferentes lados.
usingcAlgo.API;namespaceChartControlsTest{[Indicator(IsOverlay = true, AccessRights = AccessRights.None)]publicclassChartControls:Indicator{[Parameter(DefaultValue = "Click Me")]publicstringText{get;set;}[Parameter(DefaultValue = 0)]publicdoubleLeft{get;set;}[Parameter(DefaultValue = 0)]publicdoubleTop{get;set;}[Parameter(DefaultValue = 0, Group = "Margin")]publicdoubleLeftMargin{get;set;}[Parameter(DefaultValue = 0, Group = "Margin")]publicdoubleTopMargin{get;set;}[Parameter(DefaultValue = 0, Group = "Margin")]publicdoubleRightMargin{get;set;}[Parameter(DefaultValue = 0, Group = "Margin")]publicdoubleBottomMargin{get;set;}[Parameter(DefaultValue = 5, Group = "Padding")]publicdoubleLeftPadding{get;set;}[Parameter(DefaultValue = 5, Group = "Padding")]publicdoubleTopPadding{get;set;}[Parameter(DefaultValue = 5, Group = "Padding")]publicdoubleRightPadding{get;set;}[Parameter(DefaultValue = 5, Group = "Padding")]publicdoubleBottomPadding{get;set;}protectedoverridevoidInitialize(){varbutton=newButton{Text=Text,Left=Left,Top=Top,Margin=newThickness(LeftMargin,TopMargin,RightMargin,BottomMargin),Padding=newThickness(LeftPadding,TopPadding,RightPadding,BottomPadding)};button.Click+=Button_Click;varcanvas=newCanvas();canvas.AddChild(button);Chart.AddControl(canvas);}privatevoidButton_Click(ButtonClickEventArgsobj){obj.Button.Text="You clicked me, thanks";}publicoverridevoidCalculate(intindex){}}}
Una instancia de este indicador creará un botón gris Haz clic aquà en la esquina superior izquierda del gráfico. Modifique los parámetros en las ventanas Añadir instancia o Modificar parámetros para ver exactamente cómo diferentes valores de margen y relleno cambian la forma en que se muestra el control.
Estilos
Al utilizar estilos, puede dar un aspecto similar a varios tipos diferentes de controles. Esto es particularmente útil cuando se trata de un gran número (cinco o más) de controles.
La clase Style permite establecer valores para diferentes propiedades de controles como Margin o BackgroundColor. Posteriormente, puede reutilizar estos valores como una plantilla para múltiples otros controles.
usingcAlgo.API;namespaceChartControlsTest{[Indicator(IsOverlay = true, AccessRights = AccessRights.None)]publicclassChartControls:Indicator{protectedoverridevoidInitialize(){vartextBoxStyle=newStyle();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 textboxtextBoxStyle.Set(ControlProperty.ForegroundColor,Color.Yellow,ControlState.Hover);varfirstTextBox=newTextBox{Text="Type...",Style=textBoxStyle};varsecondTextBox=newTextBox{Text="Type...",Style=textBoxStyle};varthirdTextBox=newTextBox{Text="Type...",Style=textBoxStyle};varpanel=newStackPanel{Orientation=Orientation.Vertical,HorizontalAlignment=HorizontalAlignment.Center,VerticalAlignment=VerticalAlignment.Center};panel.AddChild(firstTextBox);panel.AddChild(secondTextBox);panel.AddChild(thirdTextBox);Chart.AddControl(panel);}publicoverridevoidCalculate(intindex){}}}
Imagen
El control Image puede utilizarse para mostrar una imagen almacenada localmente. El control Image utiliza la clase Bitmap de .NET, lo que significa que admite la mayorÃa de los formatos de imagen populares, como los siguientes:
.PNG
.JPG
.BMP
.GIF
.TIFF
Consulte la documentación de la clase Bitmap de .NET para obtener más información al respecto.
Para utilizar un control Image, establezca su propiedad Source en los datos de archivo de imagen en una matriz de bytes (byte[]).