Vai al contenuto

Oggetti e disegni del grafico

Gli oggetti del grafico (disegni) consentono di tracciare linee o forme geometriche sui grafici di cTrader. Utilizzandoli, puoi disegnare pattern o mostrare determinati eventi sui grafici in base ai dati del tuo cBot o indicatore.

Gli oggetti del grafico utilizzano le coordinate X e Y per il posizionamento.

  • L'asse X rappresenta il tempo del grafico o gli indici delle barre.
  • L'asse Y è il prezzo del simbolo.

Tutti gli oggetti del grafico derivano dalla classe base ChartObject, il che significa che tutti ereditano determinate funzionalità di base.

Esempi di codice degli oggetti del grafico

Disegnare all'interno delle finestre degli indicatori

Quando crei oggetti del grafico non sei limitato al grafico del simbolo principale. Infatti, puoi disegnare oggetti del grafico all'interno di qualsiasi finestra contenente output di indicatori.

La classe Chart ha la collezione IndicatorAreas. Contiene tutte le finestre non sovrapposte o separate in cui gli indicatori possono visualizzare i loro output.

Puoi anche accedere all'area dell'indicatore corrente utilizzando la proprietà IndicatorArea della tua classe Indicator.

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

namespace NewIndicator
{
    [Indicator(IsOverlay = false, AccessRights = AccessRights.None)]
    public class NewIndicator : Indicator
    {
        protected override void Initialize()
        {
            var verticalLine = IndicatorArea.DrawVerticalLine("line", Chart.LastVisibleBarIndex, Color.Red);
        }

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

Quando esegui un'istanza dell'indicatore sopra riportato, dovresti vedere una linea rossa in una finestra indicatore separata. Quando crei grafici in aree indicatore separate, puoi utilizzare tutti i metodi di disegno poiché sia Chart che IndicatorArea ereditano dalla classe base ChartArea.

Testo statico

Invece di utilizzare le coordinate X e Y per il posizionamento, il testo statico utilizza allineamenti orizzontali e verticali statici. Per mostrare o disegnare un testo statico, utilizza il metodo DrawStaticText().

1
var staticText = Chart.DrawStaticText("static", "This is the text that will be shown", VerticalAlignment.Center, HorizontalAlignment.Center, Color.Red);

Se alleghi questo oggetto grafico a un indicatore ed esegui un'istanza, vedrai il seguente testo nel grafico principale.

Image title

Linea verticale

Utilizza il metodo DrawVerticalLine() per disegnare una linea verticale.

1
2
3
var verticalLine = Chart.DrawVerticalLine("line", Chart.LastVisibleBarIndex, Color.Red);
// Or
var verticalLine = Chart.DrawVerticalLine("line", Bars.OpenTimes[Chart.LastVisibleBarIndex], Color.Red);

Linea orizzontale

Utilizza il metodo DrawHorizontalLine() per disegnare una linea orizzontale.

1
2
3
/* We use the maximum of the high prices
of the last ten bars as the Y coordinate. */ 
var horizontalLine = Chart.DrawHorizontalLine("line", Bars.HighPrices.Maximum(10), Color.Red);

Linea di tendenza

Una linea di tendenza parte da un certo punto del grafico e termina in un altro punto. Le linee di tendenza sono utili per creare forme diverse o pattern complessi.

Per disegnare una linea di tendenza utilizza il metodo DrawTrendLine().

1
2
3
4
5
6
7
/* We draw a line from the low price
 of the first visible bar to the high price
 of the last visible bar on the chart. */
var trendLine = Chart.DrawTrendLine("line", Chart.FirstVisibleBarIndex, Bars.LowPrices[Chart.FirstVisibleBarIndex], Chart.LastVisibleBarIndex, Bars.HighPrices[Chart.LastVisibleBarIndex], Color.Red);

// Alternatively, consider the following.
var trendLine = Chart.DrawTrendLine("line", Bars.OpenTimes[Chart.FirstVisibleBarIndex], Bars.LowPrices[Chart.FirstVisibleBarIndex], Bars.OpenTimes[Chart.LastVisibleBarIndex], Bars.HighPrices[Chart.LastVisibleBarIndex], Color.Red);

Rettangolo

Utilizza il metodo DrawRectangle() per disegnare un rettangolo.

1
2
3
4
5
6
7
var rectangle = Chart.DrawRectangle("rectangle", Chart.FirstVisibleBarIndex + 1, Bars.LowPrices[Chart.FirstVisibleBarIndex + 1], Chart.LastVisibleBarIndex, Bars.HighPrices[Chart.LastVisibleBarIndex], Color.Red);

/* We fill the rectangle with a transparent color.
By using its current color, we only change the alpha
channel. */
rectangle.IsFilled = true;
rectangle.Color = Color.FromArgb(80, rectangle.Color);

Triangolo

Utilizza il metodo DrawTriangle() per disegnare un triangolo.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
var middleX = Chart.FirstVisibleBarIndex + (Chart.LastVisibleBarIndex - Chart.FirstVisibleBarIndex) / 2;
var middleY = Bars.LowPrices[Chart.FirstVisibleBarIndex] + (Bars.HighPrices[Chart.LastVisibleBarIndex] - Bars.LowPrices[Chart.FirstVisibleBarIndex]) / 2;

var triangle = Chart.DrawTriangle("triangle", Chart.FirstVisibleBarIndex, Bars.LowPrices[Chart.FirstVisibleBarIndex], middleX, middleY, Chart.LastVisibleBarIndex, Bars.LowPrices[Chart.FirstVisibleBarIndex], Color.Red);

// We fill the triangle with a transparent color
// by using it's current color, we change only the alpha channel

/* We fill the triangle with a transparent color.
By using its current color, we only change the alpha
channel. */
triangle.IsFilled = true;
triangle.Color = Color.FromArgb(80, triangle.Color);

Altri oggetti del grafico

Per motivi di brevità, non abbiamo menzionato diversi altri oggetti del grafico nei frammenti di codice sopra riportati. Questi oggetti includono, ma non sono limitati ai seguenti:

  • Ellisse
  • Icona
  • Andrews Pitchfork
  • Canale equidistante
  • Espansione di Fibonacci
  • Ventaglio di Fibonacci
  • Ritracciamento di Fibonacci

Tutti questi oggetti possono essere disegnati utilizzando metodi Draw...() con nomi simili che accettano parametri simili.

Rischio/rendimento

L'interfaccia ChartRiskReward fornisce tipi che ti consentono di creare e gestire oggetti rischio/rendimento in modo programmatico sui grafici.

Il codice seguente mostra come creare un indicatore che disegna un oggetto rischio/rendimento:

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

namespace cAlgo
{
    [Indicator(AccessRights = AccessRights.None, IsOverlay = true)]
    public class SimpleRiskReward : Indicator
    {
        protected override void Initialize()
        {
            var type = new ChartRiskRewardFixedRiskType(
                ChartRiskRewardAmountType.BalancePercentage, 
                1                                            
            );
            var tradeType = TradeType.Buy;
            var orderType = OrderType.Market;

            var entryPrice = Chart.Bars.LastBar.Close;
            var time1 = Chart.LastVisibleBarIndex - 20; 
            var time2 = Chart.LastVisibleBarIndex;      

            var rr = Chart.DrawRiskReward(
                "SimpleRR",     
                time1,           
                time2,            
                entryPrice,       
                orderType,        
                tradeType,        
                type              
            );

            rr.IsInteractive = true;

            rr.RiskColor = Color.Yellow;
            rr.RiskLineStyle = LineStyle.DotsRare;
            rr.RiskThickness = 3;

            rr.RewardColor = Color.Blue;
            rr.RewardLineStyle = LineStyle.LinesDots;
            rr.RewardThickness = 2;

            PrintRRInfo(rr);
        }

        private void PrintRRInfo(ChartRiskReward rr)
        {
            Print($"Name: {rr.Name} | Type: {rr.Type.GetType().Name} | Order Type: {rr.OrderType} | Trade Type: {rr.TradeType} | Time 1: {rr.Time1:o} | Time 2: {rr.Time2:o} | Entry: {rr.EntryPrice} | SL: {rr.StopLossPrice} | TP: {rr.TakeProfitPrice} | RR: {rr.RiskRewardRatio} | Volume: {rr.VolumeInUnits}");
        }

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

Impostazioni chiave degli oggetti

Denominazione degli oggetti del grafico

Ogni volta che provi a disegnare un oggetto del grafico, devi fornire il suo nome come argomento per il metodo di disegno.

Tutti i nomi degli oggetti del grafico devono essere univoci. Se questo requisito non viene soddisfatto, rischi che gli oggetti del grafico sovrascrivano oggetti del grafico con gli stessi nomi a seconda dei loro tempi di esecuzione. Puoi utilizzare il valore dell'indice della barra corrente o l'ora corrente per generare nomi univoci per ciascun oggetto.

Accesso agli oggetti del grafico

Tutti gli oggetti del grafico sono contenuti nella raccolta Objects. Questa raccolta include oggetti disegnati dall'utente. Di conseguenza, è possibile accedere alla raccolta Objects per rimuovere oggetti dai grafici o modificare le loro proprietà.

L'esempio seguente accede ai membri della raccolta Objects:

 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
using cAlgo.API;
using System.Linq;
namespace NewIndicator
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class NewIndicator : Indicator
    {
        protected override void Initialize()
        {
            foreach (var chartObject in Chart.Objects)
            {
                /* If the object is a trend line 
                we change its Y1/2 properties */
                if (chartObject is ChartTrendLine trendLine)
                {
                    trendLine.Y1 = Chart.BottomY;
                    trendLine.Y2 = Chart.TopY;
                }
            }

            /* Here, we filter all objects of the 'ChartRectangle'
            type. */
            var rectangles = from chartObject in Chart.Objects
                             where chartObject is ChartRectangle
                             select chartObject as ChartRectangle;

            /* We select only the chart objects with a name that
            begins with "MyObjects". */
            var myObjects = from chartObject in Chart.Objects
                            where chartObject.Name.StartsWith("MyObjects", System.StringComparison.OrdinalIgnoreCase)
                            select chartObject;

            /* We select only interactive objects. If an object
            is interactive, it will not be removed when the 
            indicator is removed or reloaded. */
            var interactiveObjects = from chartObject in Chart.Objects
                                     where chartObject.IsInteractive
                                     select chartObject;

            /* We remove all objects with a name 
            that begins with "ToRemove". */
            var chartObjectsCopy = Chart.Objects.ToArray();

            foreach (var chartObject in chartObjectsCopy)
            {
                if (chartObject.Name.StartsWith("ToRemove", System.StringComparison.OrdinalIgnoreCase))
                {
                    /* Chart 'RemoveObject' gets the object name
                    as a parameter. */
                    Chart.RemoveObject(chartObject.Name);
                }

            }
        }

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

Eventi

Gli oggetti del grafico hanno diversi eventi che puoi utilizzare per sapere quali oggetti vengono disegnati, aggiornati o rimossi:

  • ObjectsAdded - viene attivato quando uno o più oggetti del grafico vengono aggiunti a un grafico.
  • ObjectsRemoved - viene attivato quando uno o più oggetti del grafico vengono rimossi da un grafico.
  • ObjectsUpdated - viene attivato quando uno o più oggetti del grafico vengono aggiornati (una delle loro proprietà viene modificata dall'utente o dall'indicatore attivo o dal cBot).
  • ObjectsSelectionChanged - viene attivato quando uno o più oggetti del grafico vengono selezionati dall'utente.
  • ObjectHoverChanged - viene attivato quando il cursore del mouse passa sopra un oggetto del grafico.

L'esempio seguente utilizza tutti e cinque i tipi di evento:

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

namespace NewIndicator
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class NewIndicator : Indicator
    {
        protected override void Initialize()
        {
            Chart.ObjectsAdded += Chart_ObjectsAdded;
            Chart.ObjectsRemoved += Chart_ObjectsRemoved;
            Chart.ObjectsUpdated += Chart_ObjectsUpdated;
            Chart.ObjectsSelectionChanged += Chart_ObjectsSelectionChanged;
            Chart.ObjectHoverChanged += Chart_ObjectHoverChanged;
        }

        private void Chart_ObjectHoverChanged(ChartObjectHoverChangedEventArgs obj) => throw new System.NotImplementedException();

        private void Chart_ObjectsSelectionChanged(ChartObjectsSelectionChangedEventArgs obj) => throw new System.NotImplementedException();

        private void Chart_ObjectsUpdated(ChartObjectsUpdatedEventArgs obj) => throw new System.NotImplementedException();

        private void Chart_ObjectsRemoved(ChartObjectsRemovedEventArgs obj) => throw new System.NotImplementedException();

        private void Chart_ObjectsAdded(ChartObjectsAddedEventArgs obj) => throw new System.NotImplementedException();

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

Oggetti interattivi e non interattivi

Quando si lavora con oggetti interattivi, gli utenti possono modificare le loro proprietà come la posizione dell'oggetto, il colore, il commento, ecc. Tutti gli oggetti disegnati dall'utente sono interattivi per impostazione predefinita.

Nota

La proprietà ChartStaticText non può essere modificata indipendentemente dal fatto che il relativo oggetto sia interattivo.

Per rendere un oggetto interattivo, imposta la sua proprietà IsInteractive su true come mostrato di seguito:

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

namespace NewIndicator
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class NewIndicator : Indicator
    {
        protected override void Initialize()
        {
            var verticalLine = Chart.DrawVerticalLine("line", Chart.LastVisibleBarIndex, Color.Red);

            verticalLine.IsInteractive = true;
        }

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

Tutti gli oggetti del grafico hanno la proprietà IsInteractive. Il suo valore predefinito è false.

Se un oggetto del grafico è interattivo, non verrà rimosso quando un'istanza di indicatore o cBot viene rimossa o arrestata. Al contrario, gli oggetti non interattivi vengono rimossi automaticamente quando un indicatore o un cBot smette di funzionare.

Per evitare confusione, assicurati di pulire gli oggetti interattivi dopo che la relativa istanza è stata rimossa utilizzando il metodo Destroy dell'indicatore o il metodo OnStop del cBot.

Se un oggetto del grafico non è interattivo, sarà anche invisibile negli elenchi e nelle raccolte di oggetti del grafico.

Oggetti bloccati e sbloccati

Il blocco di un oggetto del grafico impedisce all'utente di modificarlo o aggiornarlo. Puoi farlo tramite la casella Trader (proprietà del grafico) o impostando la proprietà IsLocked su true. Il valore predefinito è false.

Puoi utilizzare il blocco per rendere un oggetto interattivo ma allo stesso tempo impedire all'utente di aggiornarlo. L'esempio seguente blocca un oggetto linea verticale:

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

namespace NewIndicator
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class NewIndicator : Indicator
    {
        protected override void Initialize()
        {
            var verticalLine = Chart.DrawVerticalLine("line", Chart.LastVisibleBarIndex, Color.Red);

            verticalLine.IsLocked = true;
        }

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

Mostra e nascondi

Puoi disegnare un oggetto sul grafico e, successivamente, nasconderlo. Sebbene l'oggetto sarà ancora presente sul grafico, sarà completamente invisibile.

Per farlo, imposta la proprietà IsHidden su true.

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

namespace NewIndicator
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class NewIndicator : Indicator
    {
        protected override void Initialize()
        {
            var verticalLine = Chart.DrawVerticalLine("line", Chart.LastVisibleBarIndex, Color.Red);

            verticalLine.IsHidden = true;
        }

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

L'utilizzo delle risorse è la considerazione principale per l'utilizzo di questa funzione. Se c'è un oggetto che dovrebbe apparire frequentemente sul grafico (ma non sempre), è meglio nasconderlo invece di rimuoverlo e ridisegnarlo ogni volta che è necessario.

Selezione degli oggetti e indice di apparenza (ZIndex)

Naturalmente, potrebbero esserci casi in cui diversi oggetti si intersecano tra loro su un grafico, rendendo difficile o addirittura impossibile selezionare un oggetto specifico. Solo l'oggetto che è stato disegnato per ultimo sarà selezionabile passando il cursore del mouse su un gruppo di oggetti del grafico che si intersecano.

Per modificare questo comportamento puoi utilizzare la proprietà ZIndex. Può essere utile quando si tenta di visualizzare pattern complessi di oggetti del grafico.

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

namespace NewIndicator
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class NewIndicator : Indicator
    {
        protected override void Initialize()
        {
            var firstVerticalLine = Chart.DrawVerticalLine("line1", Chart.LastVisibleBarIndex, Color.Red);

            firstVerticalLine.IsInteractive = true;

            var secondVerticalLine = Chart.DrawVerticalLine("line2", Chart.LastVisibleBarIndex, Color.Yellow);

            secondVerticalLine.IsInteractive = true;

            firstVerticalLine.ZIndex = secondVerticalLine.ZIndex + 1;
        }

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

Una volta allegato a un grafico, l'indicatore sopra riportato visualizzerà una linea verticale rossa anziché gialla. Poiché il valore della proprietà ZIndex della prima linea è superiore al valore corrispondente della seconda linea, ha la precedenza sulla seconda linea (gialla).

In altre parole, la proprietà ZIndex determina quali oggetti del grafico vengono visualizzati per primi quando si sovrappongono. A tutti gli oggetti del grafico disegnati viene assegnato automaticamente un determinato valore per la proprietà ZIndex.

Sapere se un oggetto è stato rimosso

Tutti gli oggetti del grafico ereditano la proprietà IsAlive dalla classe base ChartObject. Il valore di questa proprietà è true finché un oggetto è presente sul grafico (indipendentemente dal fatto che sia visibile o invisibile). Il valore viene impostato su false non appena un oggetto viene rimosso dal grafico.

Se salvi un riferimento a un oggetto del grafico e questo oggetto viene rimosso dall'utente, puoi controllare la proprietà IsAlive per verificare se un oggetto è vivo o morto.

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

namespace NewIndicator
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class NewIndicator : Indicator
    {
        private ChartVerticalLine _verticalLine;

        protected override void Initialize()
        {
            _verticalLine = Chart.DrawVerticalLine("line1", Chart.LastVisibleBarIndex, Color.Red);
            _verticalLine.IsInteractive = true;

            Chart.ObjectsRemoved += Chart_ObjectsRemoved;

            Print(_verticalLine.IsAlive);
        }

        private void Chart_ObjectsRemoved(ChartObjectsRemovedEventArgs obj)
        {
            Print(_verticalLine.IsAlive);

            /* If the object is removed, we should rid of its
            reference. Otherwise, it will remain in memory. */
            if (_verticalLine.IsAlive is false)
            {
                _verticalLine = null;

                Print("Object reference removed");
            }
        }

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

Se esegui un'istanza di questo indicatore, fai clic con il pulsante destro del mouse sulla linea rossa e rimuovila. Il registro dovrebbe quindi restituire il messaggio "Object reference removed".

Se mantieni un riferimento a un oggetto del grafico (morto), si verificherà una perdita di memoria. Durante la garbage collection, il tuo oggetto sarà ancora considerato vivo, il che significa che sopravviverà al processo di raccolta.

Per evitare questo problema, utilizza l'evento ObjectsRemoved in combinazione con la proprietà IsAlive.

Indice della barra o tempo

Quando codifichi oggetti del grafico, puoi utilizzare il tempo del grafico o l'indice della barra per l'asse X.

A nostro avviso, il tempo del grafico è l'opzione migliore. Quando utilizzi gli indici delle barre, non puoi pianificare valori futuri (perché gli indici richiesti non esistono ancora) e non puoi tenere conto di eventuali spazi tra le barre. Tuttavia, gli indici delle barre possono essere più facili da usare, in particolare nel caso di oggetti del grafico relativamente semplici.

Tutti i metodi Chart.Draw hanno diversi overload per gli indici delle barre e il tempo del grafico.