Langkau tajuk talian

Sampel kod indikator

Halaman ini menyediakan beberapa contoh kod Python dan C# untuk mencipta indikator teknikal yang digunakan untuk dagangan manual atau algoritma.

Repositori sampel indikator

Sampel kod indikator yang komprehensif, termasuk templat sedia untuk dijalankan untuk pelbagai jenis indikator dan alat analisis teknikal, tersedia dalam repositori Python dan C# yang berasingan di GitHub.

Indikator mudah

Indikator tinggi tolak rendah mengira perbezaan antara harga tinggi dan rendah bar semasa dan memaparkannya dalam siri output. Siri ini dilukis pada carta sebagai garis yang menghubungkan nilai yang terhasil dalam setiap bar.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None, ScalePrecision = 5)]
public class HighMinusLow : Indicator
{
    [Output("Main", LineColor = "Orange")]
    public IndicatorDataSeries Result { get; set; }

    public override void Calculate(int index)
    {
        Result[index] = Bars.HighPrices[index] - Bars.LowPrices[index];
    }
}

Nota

Indikator Python menggunakan parameter yang boleh disesuaikan yang diisytiharkan dalam fail .cs mereka.

1
2
3
4
5
6
7
from System import Action

class HighMinusLow():
    def calculate(self, index):
        # In Python you have to declare parameters and outputs in your algo C# file like C# algos
        # So Result here is already declared in C# file of this indicator and here we can use it
        api.Result[index] = api.Bars.HighPrices[index] - api.Bars.LowPrices[index]

Pengisytiharan [Indicator...] termasuk beberapa parameter yang ditakrifkan seperti berikut:

  • IsOverlay - boolean yang menentukan sama ada garis akan ditindih pada carta atau dipaparkan dalam panel UI yang berasingan.
  • TimeZone - medan kelas TimeZones yang menentukan zon masa data indikator dan masa pelayan.
  • AccessRights - medan kelas AccessRights yang menentukan hak akses yang diperuntukkan kepada indikator anda.
  • ScalePrecision - int yang menetapkan ketepatan skala output indikator.

Seperti yang anda pelajari sebelum ini semasa mengedit kod indikator, atribut Output diisytiharkan untuk menandakan sifat sebagai output indikator. Sifat ini mestilah public supaya ia boleh dirujuk oleh kelas lain.

Output indikator mestilah sentiasa jenis data IndicatorDataSeries yang merupakan senarai nombor perpuluhan yang boleh diindeks seperti tatasusunan. Oleh itu, nilai pada setiap [index] dalam senarai Result boleh ditetapkan dalam kaedah Calculate seperti berikut.

1
2
3
4
public override void Calculate(int index)
{
   Result[index] = Bars.HighPrices[index] - Bars.LowPrices[index];
}
1
2
def calculate(self, index):
    api.Result[index] = api.Bars.HighPrices[index] - api.Bars.LowPrices[index]

Indikator dengan parameter

Dalam kebanyakan kes, output indikator boleh berbeza bergantung pada input pengguna. Cara parameter yang boleh disesuaikan ditetapkan untuk indikator adalah serupa dengan cara ini dilakukan untuk cBot.

Indikator purata bergerak mudah di bawah direka untuk menerima sumber harga dan tempoh sebagai parameter yang boleh disesuaikan. Parameter sedemikian (Source dan Periods dalam contoh tertentu ini) mesti didahului oleh atribut Parameter.

Serupa dengan atribut [Indicator()] dan [Output()] yang dibincangkan sebelum ini, atribut [Parameter()] boleh menentukan ciri-ciri tertentu yang digunakan pada input pengguna.

1
[Parameter("MA Periods", DefaultValue = 14, MinValue = 1, MaxValue = 20)]

Nota

Indikator Python menggunakan parameter yang boleh disesuaikan yang diisytiharkan dalam fail .cs mereka.

Di atas, kita menentukan ciri-ciri berikut:

  • Nama yang dipaparkan untuk menandakan parameter ini dalam UI cTrader ("MA Periods").
  • Nilai lalai parameter; ia boleh diubah oleh pengguna semasa menyesuaikan contoh (DefaultValue = 14)
  • Nilai minimum dan maksimum parameter (MinValue = 1, MaxValue = 20)

Dalam cebisan berikut, kita tunjukkan bagaimana parameter yang boleh disesuaikan boleh diintegrasikan ke dalam kod indikator.

 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
[Indicator(IsOverlay = false, ScalePrecision = 5)]
public class SimpleMovingAverage : Indicator
{
    [Parameter("Price")]
    public DataSeries Source { get; set; }

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

    [Parameter("MA Periods", DefaultValue = 14, MinValue = 1, MaxValue = 20)]
    public int Periods { get; set; }

    [Parameter("Message", DefaultValue = true)]
    public bool DisplayChartMessage { get; set; }

    [Output("Main", LineColor = "Red")]
    public IndicatorDataSeries Result { get; set; }

    public override void Calculate(int index)
    {
        double sum = 0;

        for (var i = index - Periods + 1; i <= index; i++)
        {
            sum += Source[i];
        }
        Result[index] = sum / Periods;
    }
}

Nota

Indikator Python menggunakan parameter yang boleh disesuaikan yang diisytiharkan dalam fail .cs mereka.

1
2
3
4
5
6
7
8
class SimpleMovingAverage():
    def calculate(self, index):
        sum = 0
        # Periods, Source and Result are declared in the C# file
        for i in range(index - api.Periods + 1, index):
            sum += api.Source[i]

        api.Result[index] = sum / api.Periods

Indikator tersarang

Indikator tersarang ditakrifkan sebagai indikator yang nilainya bergantung pada hasil pengiraan yang dilakukan oleh indikator lain. Ia berguna apabila menulis jenis sambungan tertentu seperti indikator DeMark 9. Pertimbangkan kod sampel berikut:

 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
[Indicator(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class SampleDeMarker : Indicator
{
    [Parameter(DefaultValue = 14)]
    public int Periods { get; set; }

    [Output("DMark", Color = Colors.Turquoise)]
    public IndicatorDataSeries DMark { get; set; }

    private IndicatorDataSeries deMin;
    private IndicatorDataSeries deMax;
    private MovingAverage deMinMA;
    private MovingAverage deMaxMA;

    protected override void Initialize()
    {
        deMin = CreateDataSeries();
        deMax = CreateDataSeries();
        deMinMA = Indicators.MovingAverage(deMin, Periods, MovingAverageType.Simple);
        deMaxMA = Indicators.MovingAverage(deMax, Periods, MovingAverageType.Simple);
    }

    public override void Calculate(int index)
    {
        deMin[index] = Math.Max(Bars.LowPrices[index - 1] - Bars.LowPrices[index], 0);
        deMax[index] = Math.Max(Bars.HighPrices[index] - Bars.HighPrices[index - 1], 0);

        var min = deMinMA.Result[index];
        var max = deMaxMA.Result[index];

        DMark[index] = max / (min + max);
    }
}

Nota

Indikator Python menggunakan parameter yang boleh disesuaikan yang diisytiharkan dalam fail .cs mereka.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class SampleDeMarker():
    def initialize(self):
        self.deMin = api.CreateDataSeries()
        self.deMax = api.CreateDataSeries()
        # Periods is declared in the C# file
        self.deMinMA = api.Indicators.MovingAverage(self.deMin, api.Periods, MovingAverageType.Simple)
        self.deMaxMA = api.Indicators.MovingAverage(self.deMax, api.Periods, MovingAverageType.Simple)

    def calculate(self, index):
        self.deMin[index] = max(api.Bars.LowPrices[index - 1] - api.Bars.LowPrices[index], 0)
        self.deMax[index] = max(api.Bars.HighPrices[index] - api.Bars.HighPrices[index - 1], 0)

        minValue = self.deMinMA.Result[index]
        maxValue = self.deMaxMA.Result[index]

        # DMark Output is declared in the C# file
        api.DMark[index] = maxValue / (minValue + maxValue)

Dalam contoh di atas, deMinMA dan deMaxMA adalah dua pembolehubah yang digunakan untuk mengira nilai indikator DeMarker kita.

Indikator tersarang perlu ditakrifkan dalam kaedah Initialize(). Sebagai contoh, deMinMA ditakrifkan sebagai purata bergerak mudah siri deMin.

1
deMinMA = Indicators.MovingAverage(deMin, Periods, MovingAverageType.Simple);
1
self.deMinMA = api.Indicators.MovingAverage(self.deMin, api.Periods, MovingAverageType.Simple)

deMin, seterusnya, ditakrifkan dalam kaedah Calculate() sebagai maksimum dua nilai harga rendah terakhir.

1
deMin[index] = Math.Max(Bars.LowPrices[index - 1] - Bars.LowPrices[index], 0);
1
self.deMin[index] = max(api.Bars.LowPrices[index - 1] - api.Bars.LowPrices[index], 0)

Untuk memudahkan bekerja dengan indikator tersarang, IntelliSense secara automatik mengisi senarai semua indikator terbina dalam apabila anda menaip Indicators diikuti dengan titik ke dalam editor kod. Ia juga akan memaparkan semua parameter input yang berkaitan sebaik sahaja anda memilih indikator tertentu daripada senarai ini.

Image title

Pemuatan malas

cTrader Algo menggunakan pemuatan malas apabila anda menggunakan indikator yang dirujuk. Nilai yang dibekalkan oleh indikator yang dirujuk tidak dikira sehingga kod anda mula menggunakannya secara aktif.

Jika anda mengakses data Outputs indikator yang dirujuk, cTrader akan mula memuat data indikator dengan memanggil kaedah Calculate() pada bar masa lalu dan masa depan. Dalam kes lain, indikator yang dirujuk akan kekal terbiar dan, oleh itu, tidak akan menggunakan sebarang sumber sistem.

Ini juga bermakna jika indikator anda tidak mempunyai sebarang Output atau jika anda cuba mengakses mana-mana sifat awamnya, anda akan mendapat nilai lalai sifat yang berkenaan. Untuk menyelesaikan isu ini, panggil kaedah Calculate() indikator tersuai anda daripada kaedah Calculate() indikator semasa.

Pengayun dan atribut aras

Istilah "pengayun" merangkumi semua indikator yang berayun di sekitar pemboleh ubah malar tertentu.

Apabila membuat pengayun, adalah berguna untuk terlebih dahulu melukis garis mendatar atau "aras" pada nilai malar tersebut; indikator kemudiannya akan berayun di sekitar garis ini. Dalam kebanyakan kes, nilai malar bersamaan dengan sifar.

Dalam contoh di bawah, kita menentukan pengayun momentum. Ia biasanya berayun di sekitar nilai 100. Kita menambah garis aras pada nilai ini menggunakan atribut Levels yang diisytiharkan sebelum atribut indikator.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[Levels(100)]
[Indicator()]
public class MomentumOscillator : Indicator
{
    [Parameter()]
    public DataSeries Source { get; set; }

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

    [Output("Main", LineColor = "Green")]
    public IndicatorDataSeries Result { get; set; }

    public override void Calculate(int index)
    {
        Result[index] = 100 * Source[index] / Source[index - Periods];
    }
}

Nota

Indikator Python menggunakan parameter yang boleh disesuaikan yang diisytiharkan dalam fail .cs mereka.

1
2
3
4
class MomentumOscillator():
    def calculate(self, index):
        # Result, Source, and Periods are declared in the C# file
        api.Result[index] = 100 * api.Source[index] / api.Source[index - api.Periods]

Perhatikan bahawa atribut Levels hanya boleh digunakan jika indikator tidak ditindih pada carta, bermakna sifat IsOverlay tidak ditetapkan kepada true. Secara lalai, nilai IsOverlay ialah false. Jika atribut ini ditinggalkan daripada kod anda, Levels sepatutnya berfungsi dengan betul.

Jika anda perlu menetapkan beberapa garis "aras", tambah senarai nilai yang dipisahkan dengan koma dalam tanda kurung seperti yang dipaparkan di bawah.

1
[Levels(0, 50, 100)] 
1
[Levels(50.5, 50.75)] 
1
[Levels(0.001, 0.002)] 

Aras dalam Indikator Python

Dalam Python anda mengisytiharkan Aras dalam fail indikator C# anda sama seperti indikator C#.

Sifat IsLastBar

Dalam sesetengah kes, anda mungkin ingin membuat indikator yang perlu dikira hanya untuk bar terakhir dalam carta dagangan. Untuk memudahkannya, sifat IsLastBar boleh digunakan untuk memeriksa sama ada parameter indeks kaedah Calculate() adalah untuk bar terakhir.

Indikator di bawah adalah berdasarkan masa UTC; walau bagaimanapun, ia boleh memaparkan masa buka terakhir di New York dan Tokyo.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC)]
public class TimeInDifferentParts : Indicator
{
    public override void Calculate(int index)
    {
        if (IsLastBar)
            DisplayTime(index);
    }

    protected void DisplayTime(int index)
    {
        var nyDateTime = Bars.OpenTimes[index].AddHours(-5);
        var tokyoDateTime = Bars.OpenTimes[index].AddHours(7);

        var nyTime = nyDateTime.ToShortTimeString();
        var tokyoTime = tokyoDateTime.ToShortTimeString();

        Chart.DrawStaticText("Title", "Last Bar OpenTime \n NY " + nyTime + "\n" + "Tokyo " + tokyoTime, VerticalAlignment.Top, HorizontalAlignment.Left, Color.Lime);
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class TimeInDifferentParts():
    def calculate(self, index):
        if api.IsLastBar:
            self.display_time(index)

    def display_time(self, index):
        nyDateTime = api.Bars.OpenTimes[index].AddHours(-5)
        tokyoDateTime = api.Bars.OpenTimes[index].AddHours(7)

        nyTime = nyDateTime.ToShortTimeString()
        tokyoTime = tokyoDateTime.ToShortTimeString()

        api.Chart.DrawStaticText("Title", f"Last Bar OpenTime\nNY {nyTime}\nTokyo {tokyoTime}", VerticalAlignment.Top, HorizontalAlignment.Left, Color.Lime)

Menggabungkan indikator

cTrader membolehkan penggabungan beberapa indikator dalam panel yang sama atau dalam carta yang sama.

Indikator berikut menggabungkan indikator Aroon, RSI dan sistem pergerakan berarah dalam satu.

 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
[Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, ScalePrecision = 5)]
public class Aroon_RSI_DMS : Indicator
{
    private Aroon aroon;
    private RelativeStrengthIndex rsi;
    private DirectionalMovementSystem dms;

    [Parameter()]
    public DataSeries Source { get; set; }

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

    [Output("Aroon Up", LineColor = "LightSkyBlue")]
    public IndicatorDataSeries AroonUp { get; set; }

    [Output("Aroon Down", LineColor = "Red")]
    public IndicatorDataSeries AroonDn { get; set; }

    [Output("Rsi", LineColor = "Green")]
    public IndicatorDataSeries Rsi { get; set; }

    [Output("DI Plus", LineColor = "DarkGreen")]
    public IndicatorDataSeries DmsDIPlus { get; set; }

    [Output("DI Minus", LineColor = "DarkRed")]
    public IndicatorDataSeries DmsDIMinus { get; set; }

    [Output("ADX", LineColor = "Blue")]
    public IndicatorDataSeries DmsADX { get; set; }

    protected override void Initialize()
    {
        // Initialize and create nested indicators
        aroon = Indicators.Aroon(Periods);
        rsi = Indicators.RelativeStrengthIndex(Source, Periods);
        dms = Indicators.DirectionalMovementSystem(Periods);
    }

    public override void Calculate(int index)
    {
        AroonUp[index] = aroon.Up[index];
        AroonDn[index] = aroon.Down[index];

        Rsi[index] = rsi.Result[index];

        DmsADX[index] = dms.ADX[index];
        DmsDIMinus[index] = dms.DIMinus[index];
        DmsDIPlus[index] = dms.DIPlus[index];
    }
}

Nota

Indikator Python menggunakan parameter yang boleh disesuaikan yang diisytiharkan dalam fail .cs mereka.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class Aroon_RSI_DMS():
    def initialize(self):
        # Initialize and create nested indicators
        # Periods and Source parameters are declared in the C# file
        self.aroon = api.Indicators.Aroon(Periods)
        self.rsi = api.Indicators.RelativeStrengthIndex(Source, Periods)
        self.dms = api.Indicators.DirectionalMovementSystem(Periods)

    def calculate(self, index):
        # AroonUp, AroonDn, Rsi, DmsADX, DmsDIMinus, and DmsDIPlus
        # outputs are declared in the C# file
        api.AroonUp[index] = self.aroon.Up[index]
        api.AroonDn[index] = self.aroon.Down[index]

        api.Rsi[index] = self.rsi.Result[index]

        api.DmsADX[index] = self.dms.ADX[index]
        api.DmsDIMinus[index] = self.dms.DIMinus[index]
        api.DmsDIPlus[index] = self.dms.DIPlus[index]

Pelbagai tempoh masa

  • Menggunakan pelbagai tempoh masa

    Contoh berikut memaparkan indikator moving average pada tempoh masa yang berbeza.

     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
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC)]
    public class MultiTF_MA : Indicator
    {
        [Parameter(DefaultValue = 50)]
        public int Period { get; set; }
    
        [Output("MA", LineColor = "Yellow")]
        public IndicatorDataSeries MA { get; set; }
    
        [Output("MA5", LineColor = "Orange")]
        public IndicatorDataSeries MA5 { get; set; }
    
        [Output("MA10", LineColor = "Red")]
        public IndicatorDataSeries MA10 { get; set; }
    
        private Bars bars5;
        private Bars bars10;
    
        private MovingAverage ma;
        private MovingAverage ma5;
        private MovingAverage ma10;
    
        protected override void Initialize()
        {
            bars5 = MarketData.GetBars(TimeFrame.Minute5);
            bars10 = MarketData.GetBars(TimeFrame.Minute10);
    
            ma = Indicators.MovingAverage(Bars.ClosePrices, Period, MovingAverageType.Triangular);
            ma5 = Indicators.MovingAverage(bars5.ClosePrices, Period, MovingAverageType.Triangular);
            ma10 = Indicators.MovingAverage(bars10.ClosePrices, Period, MovingAverageType.Triangular);
        }
    
        public override void Calculate(int index)
        {
            MA[index] = ma.Result[index];
    
            var index5 = bars5.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]);
            if (index5 != -1)
                MA5[index] = ma5.Result[index5];
    
            var index10 = bars10.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]);
    
            if (index10 != -1)
                MA10[index] = ma10.Result[index10];
        }
    }
    

    Nota

    Indikator Python menggunakan parameter yang boleh disesuaikan yang diisytiharkan dalam fail .cs mereka.

     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
    class MultiTF_MA():
        def initialize(self):
            self.bars5 = api.MarketData.GetBars(TimeFrame.Minute5)
            self.bars10 = api.MarketData.GetBars(TimeFrame.Minute10)
    
            # Period is declared as a parameter in the C# file 
            # We use indicator time frame bars for this moving average
            self.ma = Indicators.MovingAverage(api.Bars.ClosePrices, api.Period, MovingAverageType.Triangular)
    
            # We use other two time frame bars that we created previously
            # for these two moving averages
            self.ma5 = Indicators.MovingAverage(self.bars5.ClosePrices, api.Period, MovingAverageType.Triangular)
            self.ma10 = Indicators.MovingAverage(self.bars10.ClosePrices, api.Period, MovingAverageType.Triangular)
    
        def calculate(self, index):
            # MA, MA5, and MA10 are outputs we declared in the C# file
            api.MA[index] = self.ma.Result[index]
    
            index5 = self.bars5.OpenTimes.GetIndexByTime(api.Bars.OpenTimes[index])
    
            if index5 > -1:
                api.MA5[index] = self.ma5.Result[index5]
    
            index10 = self.bars10.OpenTimes.GetIndexByTime(api.Bars.OpenTimes[index])
    
            if index10 > -1:
                api.MA10[index] = self.ma10.Result[index10]
    
  • Menggunakan pelbagai tempoh masa dan simbol

    Contoh berikut memaparkan indikator moving average pada pelbagai tempoh masa dan simbol.

     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
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC)]
    public class MultiSymbolMA : Indicator
    {
        private MovingAverage ma1, ma2, ma3;
        private Bars bars2, bars3;
        private Symbol symbol2, symbol3;
    
        [Parameter(DefaultValue = "EURCHF")]
        public string Symbol2 { get; set; }
    
        [Parameter(DefaultValue = "EURCAD")]
        public string Symbol3 { get; set; }
    
        [Parameter(DefaultValue = 14)]
        public int Period { get; set; }
    
        [Parameter(DefaultValue = MovingAverageType.Simple)]
        public MovingAverageType MaType { get; set; }
    
        [Output("MA Symbol 1", LineColor = "Magenta")]
        public IndicatorDataSeries Result1 { get; set; }
    
        [Output("MA Symbol 2", LineColor = "Magenta")]
        public IndicatorDataSeries Result2 { get; set; }
    
        [Output("MA Symbol 3", LineColor = "Magenta")]
        public IndicatorDataSeries Result3 { get; set; }
    
        protected override void Initialize()
        {
            symbol2 = Symbols.GetSymbol(Symbol2);
            symbol3 = Symbols.GetSymbol(Symbol3);
    
            bars2 = MarketData.GetBars(TimeFrame, symbol2.Name);
            bars3 = MarketData.GetBars(TimeFrame, symbol3.Name);
    
            ma1 = Indicators.MovingAverage(Bars.ClosePrices, Period, MaType);
            ma2 = Indicators.MovingAverage(bars2.ClosePrices, Period, MaType);
            ma3 = Indicators.MovingAverage(bars3.ClosePrices, Period, MaType);
        }
    
        public override void Calculate(int index)
        {
            ShowOutput(Symbol, Result1, ma1, Bars, index);
            ShowOutput(symbol2, Result2, ma2, bars2, index);
            ShowOutput(symbol3, Result3, ma3, bars3, index);
        }
    
        private void ShowOutput(Symbol symbol, IndicatorDataSeries result, MovingAverage movingAverage, Bars bars, int index)
        {
            var index2 = bars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]);
            result[index] = movingAverage.Result[index2];
    
            string text = string.Format("{0} {1}", symbol.Name, Math.Round(result[index], symbol.Digits));
            Chart.DrawStaticText(symbol.Name, text, VerticalAlignment.Top, HorizontalAlignment.Right, Color.Yellow);
        }
    }
    

    Nota

    Indikator Python menggunakan parameter yang boleh disesuaikan yang diisytiharkan dalam fail .cs mereka.

     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
    class MultiSymbolMA():
        def initialize(self):
            # Symbol2 and Symbol3 are declared as parameters in the C# file
            self.symbol2 = api.Symbols.GetSymbol(api.Symbol2)
            self.symbol3 = api.Symbols.GetSymbol(api.Symbol3)
    
            self.bars2 = api.MarketData.GetBars(api.TimeFrame, self.symbol2.Name)
            self.bars3 = api.MarketData.GetBars(api.TimeFrame, self.symbol3.Name)
    
            self.ma1 = api.Indicators.MovingAverage(api.Bars.ClosePrices, api.Period, api.MaType)
            self.ma2 = api.Indicators.MovingAverage(self.bars2.ClosePrices, api.Period, api.MaType)
            self.ma3 = api.Indicators.MovingAverage(self.bars3.ClosePrices, api.Period, api.MaType)
    
        def calculate(self, index):
            # Result1, Result2, and Result3 are declared as outputs in the C# file
            self.show_output(api.Symbol, api.Result1, self.ma1, api.Bars, index)
            self.show_output(self.symbol2, api.Result2, self.ma2, self.bars2, index)
            self.show_output(self.symbol3, api.Result3, self.ma3, self.bars3, index)
    
        def show_output(self, symbol, result, movingAverage, bars, index):
            index2 = bars.OpenTimes.GetIndexByTime(api.Bars.OpenTimes[index])
    
            result[index] = movingAverage.Result[index2]
    
            text = f"{symbol.Name} {round(result[index], symbol.Digits)}"
    
            api.Chart.DrawStaticText(symbol.Name, text, VerticalAlignment.Top, HorizontalAlignment.Right, Color.Yellow)
    

Image title