Saltar a contenido

Operaciones avanzadas con indicadores

Este artículo complementa nuestra extensa lista de ejemplos de código de indicadores. Ampliamos algunos conceptos mencionados en estos ejemplos de código y discutimos varias características avanzadas que puede implementar al crear nuevos indicadores.

El atributo cloud

Probablemente haya visto nubes transparentes en los gráficos de operaciones.

Image title

Puede agregar nubes a las salidas de su indicador utilizando el atributo de clase CloudAttribute como se muestra en el ejemplo a continuación:

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

namespace cAlgo
{
    /// <summary>
    /// This indicator shows how to make a built-in cTrader indicator multi time frame and how to use cloud attribute
    /// </summary>
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None), Cloud("Top", "Bottom", Opacity = 0.2)]
    public class BollingerBandsMTFCloudSample : Indicator
    {
        private BollingerBands _bollingerBands;

        private Bars _baseBars;

        [Parameter("Base TimeFrame", DefaultValue = "Daily")]
        public TimeFrame BaseTimeFrame { get; set; }

        [Parameter("Source", DefaultValue = DataSeriesType.Close)]
        public DataSeriesType DataSeriesType { get; set; }

        [Parameter("Periods", DefaultValue = 14, MinValue = 0)]
        public int Periods { get; set; }

        [Parameter("Standard Deviation", DefaultValue = 2, MinValue = 0)]
        public double StandardDeviation { get; set; }

        [Parameter("MA Type", DefaultValue = MovingAverageType.Simple)]
        public MovingAverageType MaType { get; set; }

        [Output("Main", LineColor = "Yellow", PlotType = PlotType.Line, Thickness = 1)]
        public IndicatorDataSeries Main { get; set; }

        [Output("Top", LineColor = "Red", PlotType = PlotType.Line, Thickness = 1)]
        public IndicatorDataSeries Top { get; set; }

        [Output("Bottom", LineColor = "Red", PlotType = PlotType.Line, Thickness = 1)]
        public IndicatorDataSeries Bottom { get; set; }

        protected override void Initialize()
        {
            _baseBars = MarketData.GetBars(BaseTimeFrame);

            var baseSeries = GetBaseSeries();

            _bollingerBands = Indicators.BollingerBands(baseSeries, Periods, StandardDeviation, MaType);
        }

        public override void Calculate(int index)
        {
            var baseIndex = _baseBars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]);

            Main[index] = _bollingerBands.Main[baseIndex];
            Top[index] = _bollingerBands.Top[baseIndex];
            Bottom[index] = _bollingerBands.Bottom[baseIndex];
        }

        private DataSeries GetBaseSeries()
        {
            switch (DataSeriesType)
            {
                case DataSeriesType.Open:
                    return _baseBars.OpenPrices;

                case DataSeriesType.High:
                    return _baseBars.HighPrices;

                case DataSeriesType.Low:
                    return _baseBars.LowPrices;

                case DataSeriesType.Close:
                    return _baseBars.ClosePrices;
                default:

                    throw new ArgumentOutOfRangeException("DataSeriesType");
            }
        }
    }

    public enum DataSeriesType
    {
        Open,
        High,
        Low,
        Close
    }
}

El constructor CloudAttribute toma dos nombres de líneas de salida. Después, traza automáticamente la nube para que coincida con el espacio entre estas dos salidas.

También puede establecer la opacidad de la nube utilizando la propiedad Opacity. Para configurar el color de la nube, use la propiedad FirstColor. Por defecto, el color de la nube coincidirá con el color de la primera línea en la salida del indicador.

Trabajar con colores

La API de Algo incluye el enum Color que se puede utilizar para configurar los colores de los objetos Chart, controles de gráficos y salidas.

Los valores del enum Color representan colores comúnmente utilizados. Puede usarlos sin tener que lidiar con códigos de color hexadecimales o ARGB.

Al personalizar las salidas, puede establecer sus colores utilizando la propiedad de cadena LineColor. Como se muestra a continuación, acepta tanto colores nombrados como códigos de color hexadecimales.

1
2
3
4
_ = Chart.DrawStaticText("NamedColor", "This is text using Color class color name properties", VerticalAlignment.Center, HorizontalAlignment.Center, Color.Red);
_ = Chart.DrawStaticText("HexadecimalColor", "This is text using Hexadecimal color", VerticalAlignment.Bottom, HorizontalAlignment.Center, Color.FromHex("#FF5733"));
_ = Chart.DrawStaticText("ARGBColor", "This is text using ARGB color", VerticalAlignment.Top, HorizontalAlignment.Center, Color.FromArgb(255, 200, 100, 60));
_ = Chart.DrawStaticText("ParsedNameColor", "This is text using color name by parsing it from string", VerticalAlignment.Center, HorizontalAlignment.Left, Color.FromName("Yellow"));
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
var stackPanel = new StackPanel
{
    Orientation = Orientation.Vertical,
    HorizontalAlignment = HorizontalAlignment.Center,
    VerticalAlignment = VerticalAlignment.Center
};

stackPanel.AddChild(new TextBlock { Text = "Red Color property", BackgroundColor = Color.Red });
stackPanel.AddChild(new TextBlock { Text = "Hexadecimal Color code", BackgroundColor = Color.FromHex("#FF5733") });
stackPanel.AddChild(new TextBlock { Text = "ARGB Color", BackgroundColor = Color.FromArgb(200, 100, 40, 80) });
stackPanel.AddChild(new TextBlock { Text = "Color Name", BackgroundColor = Color.FromName("Green") });

Chart.AddControl(stackPanel);
1
2
3
4
5
[Output("Hexadecimal", LineColor = "#FF5733", PlotType = PlotType.Line, Thickness = 1)]
public IndicatorDataSeries Hexadecimal { get; set; }

[Output("Name", LineColor = "Red", PlotType = PlotType.Line, Thickness = 1)]
public IndicatorDataSeries Name { get; set; }

Nota

Los colores también pueden tratarse como parámetros personalizables. Para permitir que los usuarios seleccionen colores personalizados (por ejemplo, los colores de las líneas dibujadas por un indicador), declare un parámetro del tipo Color.

1
2
[Parameter("Drawing Color", DefaultValue = "#f54242")]
public Color DrawingColor { get; set; }

En el ejemplo a continuación, creamos un indicador simple (alto menos bajo) que, al inicializarse, muestra texto en el gráfico de operaciones al que está adjunto.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Collections;
using cAlgo.API.Internals;

namespace cAlgo
{
    [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class HighMinusLowColor: Indicator
    {
        [Parameter("Text Color", DefaultValue="#f54242")]
        public Color TextColor { get; set; }

        public override void Initialize()
        {
            var staticText = Chart.DrawStaticText("static", "This text shows how color parameters work", VerticalAlignment.Center, HorizontalAlignment.Center, TextColor);
        }
    }
}

Tipos de salida

Hay varios tipos diferentes de salida disponibles para indicadores personalizados:

  • Line - una línea continua.
  • DiscontinuousLine - una línea no continua que es útil para casos en los que su indicador no siempre tiene un valor de cálculo.
  • Points - un punto o un punto para cada barra.
  • Histogram - una serie de barras verticales. Al usar este tipo, establezca la propiedad IsOverlay de su indicador en false.

Para establecer un tipo de salida, use la propiedad PlotType como se demuestra a continuación.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[Output("Line", PlotType = PlotType.Line)]
public IndicatorDataSeries Line { get; set; }

[Output("Discontinuous Line", PlotType = PlotType.DiscontinuousLine)]
public IndicatorDataSeries DiscontinuousLine { get; set; }

[Output("Points", PlotType = PlotType.Points)]
public IndicatorDataSeries Points { get; set; }

[Output("Histogram", PlotType = PlotType.Histogram)]
public IndicatorDataSeries Histogram { get; set; }

Parámetros enum

El tipo enum es necesario para crear parámetros que tienen varias opciones predefinidas entre las que los usuarios pueden elegir. Usamos el tipo enum en el siguiente ejemplo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public enum Options
{
    First,
    Second,
    Third,
    Fourth
}

[Parameter("Options", DefaultValue = Options.Third)]
public Options OptionsParameter { get; set; }

Si agrega este parámetro a un indicador o cBot, verá un menú interactivo de múltiples opciones que le permite elegir uno de los valores enum especificados.

Trabajar con el tiempo

Tiempo de la plataforma y del servidor

Puede obtener la hora actual del servidor accediendo a las propiedades Server.Time o Server.TimeInUtc.

1
2
var currentServerTimeInIndicatorTimeZone = Server.Time;
var currentServerTimeInUtc = Server.TimeInUtc;

La propiedad Server.Time representa la hora actual en la zona horaria de su indicador o cBot establecida a través de la propiedad TimeZone.

Tiempo de apertura de la barra

Use la colección Bars.OpenTime para obtener los tiempos de apertura de las barras. La zona horaria se basará en la zona horaria que haya especificado en el atributo de clase TimeZone.

1
2
3
4
public override void Calculate(int index)
{
    var barTime = Bars.OpenTimes[index];
}

Desplazamiento de tiempo de la plataforma

Use la propiedad Application.UserTimeOffset para obtener la zona horaria de la plataforma del usuario. Esto se usa principalmente para convertir el tiempo de su indicador a la zona horaria del usuario.

1
var userPlatformTimeOffset = Application.UserTimeOffset;

La propiedad Application.UserTimeOffset devuelve un objeto TimeSpan que representa el desplazamiento de tiempo establecido por el usuario en su plataforma cTrader en comparación con la hora UTC.

También puede optar por recibir notificaciones cuando un usuario cambia el desplazamiento de tiempo de su plataforma. Para hacerlo, use el evento Application.UserTimeOffsetChanged.

1
2
3
4
5
6
7
8
9
protected override void Initialize()
{
    Application.UserTimeOffsetChanged += Application_UserTimeOffsetChanged;
}

private void Application_UserTimeOffsetChanged(UserTimeOffsetChangedEventArgs obj)
{
    var platformTimeOffset = obj.UserTimeOffset;
}

Obtener tiempo con un parámetro

cTrader admite tipos de parámetros dedicados de fecha y hora que le permiten obtener valores de fecha y hora fuertemente tipados como entrada para sus algos en lugar de usar el tipo de parámetro string.

Al utilizar los nuevos tipos de parámetros de fecha y hora, puede obtener valores en la zona horaria de su algoritmo con validación mínima y máxima incorporada y soporte de optimización completo, al igual que otros tipos de parámetros.

Para obtener un valor de tiempo determinado a través de un parámetro personalizable, puede utilizar estos tipos de C#:

  • DateTime
  • DateOnly
  • TimeSpan

A continuación se muestra un ejemplo de cómo se puede hacer esto:

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

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class Sample : Indicator
    {
        [Parameter("DateTime Parameter", MinValue = "1970-01-01T00:00:00", MaxValue = "2025-11-01T00:00:00", DefaultValue = "2025-01-01T10:00:00")]
        public DateTime DateTimeParameter { get; set; }

        [Parameter("DateOnly Parameter", MinValue = "1970-01-01", MaxValue = "2025-11-01", DefaultValue = "2025-01-01")]
        public DateOnly DateOnlyParameter { get; set; }

        [Parameter("TimeSpan Parameter", MinValue = "00:00:00", MaxValue = "23:59:59", DefaultValue = "04:10:20")]
        public TimeSpan TimeSpanParameter { get; set; }

        protected override void Initialize()
        {
            Print($"DateTimeParameter: {DateTimeParameter:o}");
            Print($"DateOnlyParameter: {DateOnlyParameter:o}");
            Print($"TimeSpanParameter: {TimeSpanParameter}");
        }

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

Image title