ข้ามไปที่เนื้อหา

ตัวอย่างโค้ดอินดิเคเตอร์

หน้านี้แสดงตัวอย่างโค้ด Python และ C# หลายตัวอย่างสำหรับการสร้างอินดิเคเตอร์ทางเทคนิคที่ใช้สำหรับการเทรดด้วยตนเองหรือแบบอัลกอริทึม

ที่เก็บตัวอย่างอินดิเคเตอร์

ตัวอย่างโค้ดอินดิเคเตอร์ที่ครอบคลุม รวมถึงเทมเพลตพร้อมใช้งานสำหรับประเภทอินดิเคเตอร์ต่างๆ และเครื่องมือวิเคราะห์ทางเทคนิค มีอยู่ในที่เก็บแยกต่างหากสำหรับ Python และ C# ใน GitHub

อินดิเคเตอร์อย่างง่าย

อินดิเคเตอร์ High Minus Low คำนวณความแตกต่างระหว่างราคาสูงสุดและต่ำสุดของแท่งเทียนปัจจุบันและแสดงผลในชุดผลลัพธ์ ชุดนี้จะถูกวาดบนกราฟเป็นเส้นที่เชื่อมต่อค่าที่ได้ในแต่ละแท่งเทียน

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

หมายเหตุ

อินดิเคเตอร์ Python ใช้พารามิเตอร์ที่ปรับแต่งได้ที่ประกาศในไฟล์ .cs

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]

การประกาศ [Indicator...] ประกอบด้วยพารามิเตอร์หลายตัวซึ่งกำหนดไว้ดังนี้:

  • IsOverlay - บูลีนที่กำหนดว่าเส้นจะถูกซ้อนทับบนกราฟหรือแสดงในพาเนล UI แยกต่างหาก
  • TimeZone - ฟิลด์คลาส TimeZones ที่ระบุโซนเวลาของข้อมูลอินดิเคเตอร์และเวลาของเซิร์ฟเวอร์
  • AccessRights - ฟิลด์คลาส AccessRights ที่กำหนดสิทธิ์การเข้าถึงที่จัดสรรให้กับอินดิเคเตอร์ของคุณ
  • ScalePrecision - int ที่ตั้งค่าความแม่นยำของสเกลของผลลัพธ์อินดิเคเตอร์

ตามที่คุณได้เรียนรู้ก่อนหน้านี้เมื่อแก้ไขโค้ดอินดิเคเตอร์ แอตทริบิวต์ Output ถูกประกาศเพื่อทำเครื่องหมายคุณสมบัติเป็นผลลัพธ์ของอินดิเคเตอร์ คุณสมบัตินี้ควรเป็น public เพื่อให้สามารถอ้างอิงได้โดยคลาสอื่น

ผลลัพธ์ของอินดิเคเตอร์ควรเป็นประเภทข้อมูล IndicatorDataSeries เสมอ ซึ่งเป็นรายการของ double ที่สามารถอินเด็กซ์ได้เหมือนอาร์เรย์ ดังนั้น ค่าที่ [index] แต่ละตัวในรายการ Result สามารถกำหนดได้ในเมธอด Calculate ดังนี้

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]

อินดิเคเตอร์ที่มีพารามิเตอร์

ในกรณีส่วนใหญ่ ผลลัพธ์ของอินดิเคเตอร์สามารถแตกต่างกันไปขึ้นอยู่กับอินพุตของผู้ใช้ วิธีการตั้งค่าพารามิเตอร์ที่ปรับแต่งได้สำหรับอินดิเคเตอร์นั้นคล้ายกับวิธีการทำสำหรับ cBot

อินดิเคเตอร์ Simple Moving Average ด้านล่างนี้ถูกออกแบบมาเพื่อรับแหล่งที่มาของราคาและช่วงเวลาเป็นพารามิเตอร์ที่ปรับแต่งได้ พารามิเตอร์ดังกล่าว (Source และ Periods ในตัวอย่างนี้) ต้องนำหน้าด้วยแอตทริบิวต์ Parameter

เช่นเดียวกับแอตทริบิวต์ [Indicator()] และ [Output()] ที่กล่าวถึงก่อนหน้านี้ แอตทริบิวต์ [Parameter()] สามารถกำหนดลักษณะบางอย่างที่ใช้กับอินพุตของผู้ใช้

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

หมายเหตุ

อินดิเคเตอร์ Python ใช้พารามิเตอร์ที่ปรับแต่งได้ที่ประกาศในไฟล์ .cs

ด้านบน เราระบุลักษณะต่อไปนี้:

  • ชื่อที่แสดงเพื่อระบุพารามิเตอร์นี้ในส่วนติดต่อผู้ใช้ของ cTrader ("MA Periods")
  • ค่าเริ่มต้นของพารามิเตอร์ ซึ่งผู้ใช้สามารถเปลี่ยนแปลงได้เมื่อปรับแต่งอินสแตนซ์ (DefaultValue = 14)
  • ค่าต่ำสุดและสูงสุดของพารามิเตอร์ (MinValue = 1, MaxValue = 20)

ในส่วนต่อไปนี้ เราแสดงวิธีการรวมพารามิเตอร์ที่ปรับแต่งได้เข้ากับโค้ดอินดิเคเตอร์

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

หมายเหตุ

อินดิเคเตอร์ Python ใช้พารามิเตอร์ที่ปรับแต่งได้ที่ประกาศในไฟล์ .cs

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

อินดิเคเตอร์ซ้อนกัน

อินดิเคเตอร์ซ้อนกันคือ อินดิเคเตอร์ที่ค่าของมันขึ้นอยู่กับผลลัพธ์การคำนวณที่ดำเนินการโดยอินดิเคเตอร์อื่น ๆ อินดิเคเตอร์เหล่านี้มีประโยชน์เมื่อเขียนส่วนขยายบางประเภท เช่น อินดิเคเตอร์ DeMark 9 พิจารณาโค้ดตัวอย่างต่อไปนี้:

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

หมายเหตุ

อินดิเคเตอร์ Python ใช้พารามิเตอร์ที่ปรับแต่งได้ที่ประกาศในไฟล์ .cs

 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)

ในตัวอย่างข้างต้น deMinMA และ deMaxMA เป็นตัวแปรสองตัวที่ใช้ในการคำนวณค่าของอินดิเคเตอร์ DeMarker ของเรา

อินดิเคเตอร์ซ้อนกันจำเป็นต้องถูกกำหนดในเมธอด Initialize() ตัวอย่างเช่น deMinMA ถูกกำหนดให้เป็นค่าเฉลี่ยเคลื่อนที่แบบง่ายของอนุกรม deMin

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

ส่วน deMin ถูกกำหนดในเมธอด Calculate() ให้เป็นค่าสูงสุดของค่าต่ำสุดสองค่าล่าสุด

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)

เพื่อให้การทำงานกับอินดิเคเตอร์ซ้อนกันง่ายขึ้น IntelliSense จะเติมรายการของอินดิเคเตอร์ในตัวทั้งหมดโดยอัตโนมัติเมื่อคุณพิมพ์ Indicators ตามด้วยจุดลงในตัวแก้ไขโค้ด นอกจากนี้ยังจะแสดงพารามิเตอร์อินพุตที่เกี่ยวข้องทั้งหมดเมื่อคุณเลือกอินดิเคเตอร์บางตัวจากรายการนี้

Image title

การโหลดแบบ Lazy

cTrader Algo ใช้การโหลดแบบ Lazy เมื่อคุณใช้อินดิเคเตอร์ที่อ้างอิง ค่าที่ให้โดยอินดิเคเตอร์ที่อ้างอิงจะไม่ถูกคำนวณจนกว่าโค้ดของคุณจะเริ่มใช้งานอย่างจริงจัง

หากคุณเข้าถึงข้อมูล Outputs ของอินดิเคเตอร์ที่อ้างอิง cTrader จะเริ่มโหลดข้อมูลอินดิเคเตอร์โดยเรียกเมธอด Calculate() ของมันบนแท่งเทียนในอดีตและอนาคต ในกรณีอื่น ๆ อินดิเคเตอร์ที่อ้างอิงจะยังคงอยู่ในสถานะไม่ทำงาน และดังนั้นจึงไม่ใช้ทรัพยากรระบบใด ๆ

นี่ยังหมายความว่าหากอินดิเคเตอร์ของคุณไม่มี Output ใด ๆ หรือหากคุณพยายามเข้าถึงคุณสมบัติสาธารณะใด ๆ ของมัน คุณจะได้รับค่าเริ่มต้นของคุณสมบัตินั้น ๆ เพื่อแก้ไขปัญหานี้ ให้เรียกเมธอด Calculate() ของอินดิเคเตอร์ที่กำหนดเองของคุณจากเมธอด Calculate() ของอินดิเคเตอร์ปัจจุบัน

ออสซิลเลเตอร์และแอตทริบิวต์ระดับ

คำว่า "ออสซิลเลเตอร์" ครอบคลุมถึงอินดิเคเตอร์ทั้งหมดที่แกว่งรอบตัวแปรคงที่บางค่า

เมื่อสร้างออสซิลเลเตอร์ มักจะเป็นประโยชน์ที่จะวาดเส้นแนวนอนหรือเส้น "ระดับ" ที่ค่าคงที่นั้นก่อน จากนั้นอินดิเคเตอร์จะแกว่งรอบเส้นนี้ ในหลายกรณี ค่าคงที่เท่ากับศูนย์

ในตัวอย่างด้านล่าง เรากำหนดออสซิลเลเตอร์โมเมนตัม โดยปกติแล้วมันจะแกว่งรอบค่า 100 เราเพิ่มเส้นระดับที่ค่านี้โดยใช้แอตทริบิวต์ Levels ซึ่งถูกประกาศก่อนแอตทริบิวต์ของอินดิเคเตอร์

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

หมายเหตุ

อินดิเคเตอร์ Python ใช้พารามิเตอร์ที่ปรับแต่งได้ที่ประกาศในไฟล์ .cs

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]

โปรดทราบว่าแอตทริบิวต์ Levels สามารถใช้ได้เฉพาะเมื่ออินดิเคเตอร์ไม่ได้ซ้อนทับบนกราฟ ซึ่งหมายความว่าคุณสมบัติ IsOverlay ไม่ได้ถูกตั้งค่าเป็น true โดยค่าเริ่มต้น ค่าของ IsOverlay คือ false หากแอตทริบิวต์นี้ถูกละเว้นจากโค้ดของคุณ Levels ควรทำงานได้อย่างถูกต้อง

หากคุณต้องการกำหนดเส้น "ระดับ" หลายเส้น ให้เพิ่มรายการค่าที่คั่นด้วยเครื่องหมายจุลภาคภายในวงเล็บดังที่แสดงด้านล่าง

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

ระดับในอินดิเคเตอร์ Python

ใน Python คุณประกาศระดับในไฟล์ C# ของอินดิเคเตอร์เช่นเดียวกับอินดิเคเตอร์ C#

คุณสมบัติ IsLastBar

ในบางกรณี คุณอาจต้องการสร้างอินดิเคเตอร์ที่ต้องคำนวณเฉพาะสำหรับแท่งเทียนสุดท้ายในกราฟการเทรดเท่านั้น เพื่อทำให้ง่ายขึ้น คุณสมบัติ IsLastBar สามารถใช้เพื่อตรวจสอบว่าพารามิเตอร์ดัชนีของเมธอด Calculate() เป็นของแท่งเทียนสุดท้ายหรือไม่

อินดิเคเตอร์ด้านล่างนี้อิงตามเวลา UTC อย่างไรก็ตาม มันสามารถแสดงเวลาเปิดล่าสุดในนิวยอร์กและโตเกียวได้

 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)

การรวมอินดิเคเตอร์

cTrader อนุญาตให้รวมอินดิเคเตอร์หลายตัวในแผงเดียวกันหรือภายในกราฟเดียวกัน

อินดิเคเตอร์ต่อไปนี้รวม Aroon, RSI และระบบการเคลื่อนไหวแบบมีทิศทางเข้าด้วยกัน

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

หมายเหตุ

อินดิเคเตอร์ Python ใช้พารามิเตอร์ที่ปรับแต่งได้ที่ประกาศในไฟล์ .cs

 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]

กรอบเวลาหลายรูปแบบ

  • การใช้กรอบเวลาหลายรูปแบบ

    ตัวอย่างต่อไปนี้แสดงอินดิเคเตอร์ค่าเฉลี่ยเคลื่อนที่บนกรอบเวลาที่ต่างกัน

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

    หมายเหตุ

    อินดิเคเตอร์ Python ใช้พารามิเตอร์ที่ปรับแต่งได้ซึ่งประกาศในไฟล์ **.cs ของพวกเขา

     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]
    
  • การใช้กรอบเวลาและสัญลักษณ์หลายรูปแบบ

    ตัวอย่างต่อไปนี้แสดงอินดิเคเตอร์ค่าเฉลี่ยเคลื่อนที่บนหลายกรอบเวลาและสัญลักษณ์

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

    หมายเหตุ

    อินดิเคเตอร์ Python ใช้พารามิเตอร์ที่ปรับแต่งได้ซึ่งประกาศในไฟล์ **.cs ของพวกเขา

     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