Langkau tajuk talian

Objek carta dan lukisan

Objek carta (lukisan) membolehkan melukis garis atau bentuk geometri pada carta cTrader. Dengan menggunakannya, anda boleh melukis corak atau menunjukkan peristiwa tertentu pada carta berdasarkan data cBot atau indikator anda.

Objek carta menggunakan koordinat X dan Y untuk penempatan.

  • Paksi X mewakili masa carta atau indeks bar.
  • Paksi Y ialah harga simbol.

Semua objek carta diperoleh daripada kelas asas ChartObject, bermakna bahawa semuanya mewarisi ciri asas tertentu.

Sampel kod objek carta

Lukis dalam tetingkap indikator

Apabila mencipta objek carta, anda tidak terhad kepada carta simbol utama. Sebenarnya, anda boleh melukis objek carta di dalam mana-mana tetingkap yang mengandungi output indikator.

Kelas Chart mempunyai koleksi IndicatorAreas. Ia mengandungi semua tetingkap bukan tindihan atau berasingan di mana indikator boleh memaparkan outputnya.

Anda juga boleh mengakses kawasan indikator semasa anda dengan menggunakan sifat IndicatorArea kelas Indicator anda.

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

Apabila anda menjalankan contoh indikator di atas, anda sepatutnya melihat garis merah dalam tetingkap indikator yang berasingan. Apabila mencipta carta dalam kawasan indikator berasingan, anda boleh menggunakan semua kaedah lukisan kerana kedua-dua Chart dan IndicatorArea mewarisi daripada kelas asas ChartArea.

Teks statik

Bukannya menggunakan koordinat X dan Y untuk penempatan, teks statik menggunakan penjajaran mendatar dan menegak yang statik. Untuk menunjukkan atau melukis teks statik, gunakan kaedah DrawStaticText().

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

Jika anda melampirkan objek carta ini kepada indikator dan menjalankan contoh, anda akan melihat teks berikut dalam carta utama.

Image title

Garis menegak

Gunakan kaedah DrawVerticalLine() untuk melukis garis menegak.

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

Garis mendatar

Gunakan kaedah DrawHorizontalLine() untuk melukis garis mendatar.

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

Garis trend

Garis trend bermula dari titik tertentu dalam carta dan berakhir di titik lain. Garis trend berguna untuk mencipta bentuk yang berbeza atau corak kompleks.

Untuk melukis garis trend gunakan kaedah 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);

Segi empat tepat

Gunakan kaedah DrawRectangle() untuk melukis segi empat tepat.

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

Segi tiga

Gunakan kaedah DrawTriangle() untuk melukis segi tiga.

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

Objek carta lain

Demi ringkasan, kami tidak menyebut beberapa objek carta lain dalam cebisan kod di atas. Objek-objek ini termasuk tetapi tidak terhad kepada yang berikut:

  • Elips
  • Ikon
  • Andrews Pitchfork
  • Saluran Sama Jarak
  • Pengembangan Fibonacci
  • Kipas Fibonacci
  • Penjejakan semula Fibonacci

Semua objek ini boleh dilukis menggunakan kaedah Draw...() yang dinamakan serupa yang menerima parameter yang serupa.

Risiko-ganjaran

Antara muka ChartRiskReward menyediakan jenis yang membolehkan anda mencipta dan menguruskan objek risiko-ganjaran secara programatik pada carta.

Kod di bawah menunjukkan kepada anda cara untuk mencipta penunjuk yang melukis objek risiko-ganjaran:

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

Tetapan objek utama

Menamakan objek carta

Apabila anda cuba melukis objek carta, anda perlu memberikan namanya sebagai hujah untuk kaedah lukisan.

Semua nama objek carta mestilah unik. Jika keperluan ini tidak dipenuhi, anda berisiko objek carta mengatasi objek carta dengan nama yang sama bergantung pada masa pelaksanaan mereka. Anda boleh menggunakan nilai indeks bar semasa atau masa semasa untuk menjana nama unik bagi setiap objek.

Mengakses objek carta

Semua objek carta terkandung dalam koleksi Objects. Koleksi ini termasuk objek yang dilukis oleh pengguna. Hasilnya, koleksi Objects boleh diakses untuk membuang objek dari carta atau mengubah suai sifat-sifatnya.

Contoh di bawah mengakses ahli koleksi 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)
        {
        }
    }
}

Peristiwa

Objek carta mempunyai beberapa peristiwa yang boleh anda gunakan untuk mengetahui objek mana yang dilukis, dikemas kini atau dibuang:

  • ObjectsAdded - dicetuskan apabila satu atau lebih objek carta ditambah pada carta.
  • ObjectsRemoved - dicetuskan apabila satu atau lebih objek carta dibuang dari carta.
  • ObjectsUpdated - dicetuskan apabila satu atau lebih objek carta dikemas kini (salah satu sifatnya diubah oleh pengguna atau penunjuk atau cBot aktif).
  • ObjectsSelectionChanged - dicetuskan apabila satu atau lebih objek carta dipilih oleh pengguna.
  • ObjectHoverChanged - dicetuskan apabila kursor tetikus berada di atas objek carta.

Contoh berikut menggunakan kelima-lima jenis peristiwa:

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

Objek interaktif dan bukan interaktif

Apabila bekerja dengan objek interaktif, pengguna boleh mengubah sifat-sifatnya seperti kedudukan objek, warna, komen, dan sebagainya. Semua objek yang dilukis oleh pengguna adalah interaktif secara lalai.

Nota

Sifat ChartStaticText tidak boleh diubah tanpa mengira sama ada objek yang berkaitan dengannya adalah interaktif.

Untuk menjadikan objek interaktif, tetapkan sifat IsInteractive kepada true seperti yang ditunjukkan di bawah:

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

Semua objek carta mempunyai sifat IsInteractive. Nilai lalainya ialah false.

Jika objek carta adalah interaktif, ia tidak akan dibuang apabila contoh penunjuk atau cBot dibuang atau dihentikan. Sebaliknya, objek bukan interaktif dibuang secara automatik apabila penunjuk atau cBot berhenti berfungsi.

Untuk mengelakkan kekacauan, pastikan untuk membersihkan objek interaktif selepas contoh yang berkaitan dibuang dengan menggunakan kaedah Destroy penunjuk atau kaedah OnStop cBot.

Jika objek carta tidak interaktif, ia juga akan tidak kelihatan dalam senarai dan koleksi objek carta.

Objek terkunci dan tidak terkunci

Mengunci objek carta menghalang pengguna daripada mengubah suai atau mengemaskininya. Anda boleh melakukannya melalui kotak Trader (Sifat carta) atau dengan menetapkan sifat IsLocked kepada true. Nilai lalai ialah false.

Anda boleh menggunakan penguncian untuk menjadikan objek interaktif tetapi pada masa yang sama menghalang pengguna daripada mengemaskininya. Contoh berikut mengunci objek garis menegak:

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

Tunjuk dan sembunyi

Anda boleh melukis objek pada carta dan, kemudiannya, menyembunyikannya. Walaupun objek itu masih ada pada carta, ia akan menjadi sama sekali tidak kelihatan.

Untuk berbuat demikian, tetapkan sifat IsHidden kepada 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)
        {
        }
    }
}

Penggunaan sumber adalah pertimbangan utama untuk menggunakan ciri ini. Jika terdapat objek yang sepatutnya kerap muncul pada carta (tetapi tidak sepanjang masa), adalah lebih baik untuk menyembunyikannya daripada membuang dan melukis semula setiap kali ia diperlukan.

Pemilihan objek dan indeks penampilan (ZIndex)

Secara semula jadi, mungkin ada kes di mana beberapa objek bersilang antara satu sama lain pada carta, menjadikan pemilihan satu objek tertentu sukar atau mustahil sama sekali. Hanya objek yang dilukis terakhir akan boleh dipilih apabila anda meletakkan kursor tetikus di atas sekumpulan objek carta yang bersilang.

Untuk mengubah tingkah laku ini anda boleh menggunakan sifat ZIndex. Ia boleh membantu apabila cuba memaparkan corak kompleks objek carta.

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

Sebaik sahaja dilampirkan pada carta, penunjuk di atas akan memaparkan garis menegak merah dan bukannya kuning. Oleh kerana nilai sifat ZIndex garis pertama adalah lebih tinggi daripada nilai yang sepadan dengan garis kedua, ia mengambil keutamaan berbanding garis kedua (kuning).

Dengan kata lain, sifat ZIndex menentukan objek carta mana yang dipaparkan dahulu apabila mereka bertindih. Semua objek carta yang dilukis diberikan nilai tertentu untuk sifat ZIndex secara automatik.

Ketahui sama ada objek dibuang

Semua objek carta mewarisi sifat IsAlive daripada kelas asas ChartObject. Nilai sifat ini adalah true selagi objek ada pada carta (tanpa mengira sama ada ia kelihatan atau tidak kelihatan). Nilai ditetapkan kepada false sebaik sahaja objek dibuang dari carta.

Jika anda menyimpan rujukan kepada objek carta dan objek ini dibuang oleh pengguna, anda boleh memeriksa sifat IsAlive untuk memeriksa sama ada objek itu hidup atau mati.

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

Jika anda menjalankan contoh penunjuk ini, klik kanan pada garis merah dan buangnya. Log kemudian harus mengeluarkan mesej "Object reference removed".

Jika anda menyimpan rujukan kepada objek carta (mati), kebocoran memori akan berlaku. Semasa pengumpulan sampah, objek anda masih akan dianggap hidup, bermakna ia akan terselamat daripada proses pengumpulan.

Untuk mengelakkan masalah ini, gunakan peristiwa ObjectsRemoved bersama dengan sifat IsAlive.

Indeks bar atau masa

Apabila mengekod objek carta, anda boleh menggunakan sama ada masa carta atau indeks bar untuk paksi X.

Pada pendapat kami, masa carta adalah pilihan yang lebih baik. Apabila menggunakan indeks bar, anda tidak boleh merancang untuk nilai masa hadapan (kerana indeks yang diperlukan belum wujud) dan tidak boleh mengambil kira sebarang ruang antara bar. Walau bagaimanapun, indeks bar mungkin lebih mudah digunakan, terutamanya dalam kes objek carta yang agak mudah.

Semua kaedah Chart.Draw mempunyai overload yang berbeza untuk indeks bar dan masa carta.