Vai al contenuto

Operazioni avanzate con gli indicatori

Questo articolo integra il nostro ampio elenco di esempi di codice per indicatori. Approfondiamo alcuni concetti menzionati in questi esempi di codice e discutiamo diverse funzionalità avanzate che puoi implementare durante la creazione di nuovi indicatori.

L'attributo cloud

Probabilmente hai visto nuvole trasparenti sui grafici di trading.

Image title

Puoi aggiungere nuvole ai tuoi output dell'indicatore utilizzando l'attributo di classe CloudAttribute come mostrato nell'esempio seguente:

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

Il costruttore CloudAttribute accetta due nomi di linee di output. Successivamente, traccia automaticamente la nuvola in modo da corrispondere allo spazio tra questi due output.

Puoi anche impostare l'opacità della nuvola utilizzando la proprietà Opacity. Per impostare il colore della nuvola, utilizza la proprietà FirstColor. Per impostazione predefinita, il colore della nuvola corrisponderà al colore della prima linea nell'output dell'indicatore.

Lavorare con i colori

L'API Algo include l'enum Color che può essere utilizzato per configurare i colori per gli oggetti Chart, i controlli del grafico e gli output.

I valori dell'enum Color rappresentano i colori comunemente utilizzati. Puoi utilizzarli senza dover gestire codici colore esadecimali o ARGB.

Quando personalizzi gli output, puoi impostare i loro colori utilizzando la proprietà stringa LineColor. Come mostrato di seguito, accetta sia colori denominati che codici colore esadecimali.

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

I colori possono anche essere trattati come parametri personalizzabili. Per consentire agli utenti di selezionare colori personalizzati (ad esempio, i colori delle linee disegnate da un indicatore), dichiara un parametro di tipo Color.

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

Nell'esempio seguente, creiamo un semplice indicatore (massimo meno minimo) che, una volta inizializzato, visualizza del testo sul grafico di trading a cui è collegato.

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

Tipi di output

Sono disponibili diversi tipi di output per gli indicatori personalizzati:

  • Line - una linea continua.
  • DiscontinuousLine - una linea non continua utile per i casi in cui il tuo indicatore non ha sempre un valore di calcolo.
  • Points - un punto o un puntino per ogni barra.
  • Histogram - una serie di barre verticali. Quando utilizzi questo tipo, imposta la proprietà IsOverlay del tuo indicatore su false.

Per impostare un tipo di output, utilizza la proprietà PlotType come dimostrato di seguito.

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

Parametri enum

Il tipo enum è necessario per creare parametri che hanno diverse opzioni predefinite tra cui gli utenti possono scegliere. Utilizziamo il tipo enum nell'esempio seguente:

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

Se aggiungi questo parametro a un indicatore o cBot, vedrai un menu interattivo a più opzioni che ti consente di scegliere uno dei valori enum specificati.

Lavora con il tempo

Ora della piattaforma e del server

Puoi ottenere l'ora corrente del server accedendo alle proprietà Server.Time o Server.TimeInUtc.

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

La proprietà Server.Time rappresenta l'ora corrente nel fuso orario del tuo indicatore o cBot stabilito tramite la proprietà TimeZone.

Ora di apertura della barra

Utilizza la raccolta Bars.OpenTime per ottenere gli orari di apertura delle barre. Il fuso orario sarà basato sul fuso orario che hai specificato nell'attributo di classe TimeZone.

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

Offset dell'ora della piattaforma

Utilizza la proprietà Application.UserTimeOffset per ottenere il fuso orario della piattaforma dell'utente. Questo viene utilizzato principalmente per convertire l'ora del tuo indicatore nel fuso orario dell'utente.

1
var userPlatformTimeOffset = Application.UserTimeOffset;

La proprietà Application.UserTimeOffset restituisce un oggetto TimeSpan che rappresenta l'offset temporale impostato dall'utente nella sua piattaforma cTrader rispetto all'ora UTC.

Puoi anche scegliere di ricevere una notifica quando un utente modifica l'offset dell'orario della propria piattaforma. Per farlo, utilizza l'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;
}

Ottieni l'orario con un parametro

cTrader supporta tipi di parametri dedicati per data e ora che ti consentono di ottenere valori di data e ora fortemente tipizzati come input per i tuoi algoritmi invece di utilizzare il tipo di parametro string.

Utilizzando i nuovi tipi di parametri per data e ora, puoi ottenere valori nel fuso orario del tuo algoritmo con convalida minima e massima integrata e supporto completo per l'ottimizzazione, proprio come altri tipi di parametri.

Per ottenere un determinato valore di orario tramite un parametro personalizzabile, puoi utilizzare questi tipi C#:

  • DateTime
  • DateOnly
  • TimeSpan

Di seguito è riportato un esempio di come è possibile farlo:

 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