Zum Inhalt

Erweiterte Operationen mit Indikatoren

Dieser Artikel ergänzt unsere umfangreiche Liste von Indikator-Codebeispielen. Wir erweitern einige in diesen Codebeispielen erwähnte Konzepte und diskutieren mehrere erweiterte Funktionen, die Sie beim Erstellen neuer Indikatoren implementieren können.

Das Cloud-Attribut

Sie haben wahrscheinlich transparente Wolken auf Handelscharts gesehen.

Image title

Sie können Wolken zu Ihren Indikatorausgaben hinzufügen, indem Sie das Klassenattribut CloudAttribute wie im folgenden Beispiel gezeigt verwenden:

 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
    }
}

Der Konstruktor CloudAttribute nimmt zwei Ausgabeliniennamen. Danach zeichnet er automatisch die Wolke so, dass sie dem Raum zwischen diesen beiden Ausgaben entspricht.

Sie können auch die Deckkraft der Wolke festlegen, indem Sie die Eigenschaft Opacity verwenden. Um die Farbe der Wolke festzulegen, verwenden Sie die Eigenschaft FirstColor. Standardmäßig entspricht die Farbe der Wolke der Farbe der ersten Linie in der Indikatorausgabe.

Mit Farben arbeiten

Die Algo-API enthält das Color enum, das verwendet werden kann, um die Farben für Chart-Objekte, Chart-Steuerelemente und Ausgaben zu konfigurieren.

Die Werte des Color enum repräsentieren häufig verwendete Farben. Sie können sie verwenden, ohne sich mit hexadezimalen oder ARGB-Farbcodes befassen zu müssen.

Beim Anpassen von Ausgaben können Sie deren Farben festlegen, indem Sie die String-Eigenschaft LineColor verwenden. Wie unten gezeigt, akzeptiert sie sowohl benannte Farben als auch hexadezimale Farbcodes.

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; }

Hinweis

Farben können auch als anpassbare Parameter behandelt werden. Um Benutzern die Auswahl benutzerdefinierter Farben zu ermöglichen (z. B. die Farben der von einem Indikator gezeichneten Linien), deklarieren Sie einen Parameter vom Typ Color.

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

Im folgenden Beispiel erstellen wir einen einfachen (High Minus Low) Indikator, der nach der Initialisierung Text auf dem Handelschart anzeigt, an den er angehängt ist.

 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);
        }
    }
}

Ausgabetypen

Es gibt mehrere verschiedene Ausgabetypen, die für benutzerdefinierte Indikatoren verfügbar sind:

  • Line - eine durchgehende Linie.
  • DiscontinuousLine - eine nicht durchgehende Linie, die für Fälle nützlich ist, in denen Ihr Indikator nicht immer einen Berechnungswert hat.
  • Points - ein Punkt oder ein Punkt für jeden Balken.
  • Histogram - eine Reihe von vertikalen Balken. Wenn Sie diesen Typ verwenden, setzen Sie die Eigenschaft IsOverlay Ihres Indikators auf false.

Um einen Ausgabetyp festzulegen, verwenden Sie die Eigenschaft PlotType wie unten gezeigt.

 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; }

Enum-Parameter

Der Typ enum wird benötigt, um Parameter zu erstellen, die mehrere vordefinierte Optionen haben, aus denen Benutzer wählen können. Wir verwenden den Typ enum im folgenden Beispiel:

 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; }

Wenn Sie diesen Parameter zu einem Indikator oder cBot hinzufügen, sehen Sie ein interaktives Menü mit mehreren Optionen, mit dem Sie einen der angegebenen enum-Werte auswählen können.

Mit Zeit arbeiten

Plattform- und Serverzeit

Sie können die aktuelle Serverzeit abrufen, indem Sie entweder auf die Eigenschaften Server.Time oder Server.TimeInUtc zugreifen.

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

Die Eigenschaft Server.Time repräsentiert die aktuelle Zeit in der Zeitzone Ihres Indikators oder cBots, die über die Eigenschaft TimeZone festgelegt wurde.

Balkenöffnungszeit

Verwenden Sie die Sammlung Bars.OpenTime, um die Balkenöffnungszeiten abzurufen. Die Zeitzone basiert auf der Zeitzone, die Sie im Klassenattribut TimeZone angegeben haben.

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

Plattformzeit-Offset

Verwenden Sie die Eigenschaft Application.UserTimeOffset, um die Zeitzone der Plattform des Benutzers abzurufen. Dies wird hauptsächlich verwendet, um die Zeit Ihres Indikators in die Zeitzone des Benutzers zu konvertieren.

1
var userPlatformTimeOffset = Application.UserTimeOffset;

Die Eigenschaft Application.UserTimeOffset gibt ein TimeSpan-Objekt zurück, das den vom Benutzer in seiner cTrader-Plattform festgelegten Zeitversatz im Vergleich zur UTC-Zeit darstellt.

Sie können sich auch benachrichtigen lassen, wenn ein Benutzer den Zeitversatz seiner Plattform ändert. Verwenden Sie dazu das Ereignis 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;
}

Zeit mit einem Parameter abrufen

cTrader unterstützt dedizierte Datums- und Zeitparametertypen, mit denen Sie stark typisierte Datums- und Zeitwerte als Eingabe für Ihre Algos erhalten können, anstatt den Parametertyp string zu verwenden.

Durch die Verwendung der neuen Datums- und Zeitparametertypen können Sie Werte in der Zeitzone Ihres Algos mit integrierter Mindest- und Höchstwertvalidierung und vollständiger Optimierungsunterstützung erhalten, genau wie bei anderen Parametertypen.

Um einen bestimmten Zeitwert über einen anpassbaren Parameter zu erhalten, können Sie diese C#-Typen verwenden:

  • DateTime
  • DateOnly
  • TimeSpan

Nachfolgend finden Sie ein Beispiel, wie dies durchgeführt werden kann:

 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