ตัวอย่างโค้ดอินดิเคเตอร์
หน้านี้แสดงตัวอย่างโค้ด Python และ C# หลายตัวอย่างสำหรับการสร้างอินดิเคเตอร์ทางเทคนิคที่ใช้สำหรับการเทรดด้วยตนเองหรือแบบอัลกอริทึม
ที่เก็บตัวอย่างอินดิเคเตอร์
ตัวอย่างโค้ดอินดิเคเตอร์ที่ครอบคลุม รวมถึงเทมเพลตพร้อมใช้งานสำหรับประเภทอินดิเคเตอร์ต่างๆ และเครื่องมือวิเคราะห์ทางเทคนิค มีอยู่ในที่เก็บแยกต่างหากสำหรับ Python และ C# ใน GitHub
อินดิเคเตอร์อย่างง่าย
อินดิเคเตอร์ High Minus Low คำนวณความแตกต่างระหว่างราคาสูงสุดและต่ำสุดของแท่งเทียนปัจจุบันและแสดงผลในชุดผลลัพธ์ ชุดนี้จะถูกวาดบนกราฟเป็นเส้นที่เชื่อมต่อค่าที่ได้ในแต่ละแท่งเทียน
1 2 3 4 5 6 7 8 9 10 11 | |
หมายเหตุ
อินดิเคเตอร์ Python ใช้พารามิเตอร์ที่ปรับแต่งได้ที่ประกาศในไฟล์ .cs
1 2 3 4 5 6 7 | |
การประกาศ [Indicator...] ประกอบด้วยพารามิเตอร์หลายตัวซึ่งกำหนดไว้ดังนี้:
IsOverlay- บูลีนที่กำหนดว่าเส้นจะถูกซ้อนทับบนกราฟหรือแสดงในพาเนล UI แยกต่างหากTimeZone- ฟิลด์คลาสTimeZonesที่ระบุโซนเวลาของข้อมูลอินดิเคเตอร์และเวลาของเซิร์ฟเวอร์AccessRights- ฟิลด์คลาสAccessRightsที่กำหนดสิทธิ์การเข้าถึงที่จัดสรรให้กับอินดิเคเตอร์ของคุณScalePrecision- int ที่ตั้งค่าความแม่นยำของสเกลของผลลัพธ์อินดิเคเตอร์
ตามที่คุณได้เรียนรู้ก่อนหน้านี้เมื่อแก้ไขโค้ดอินดิเคเตอร์ แอตทริบิวต์ Output ถูกประกาศเพื่อทำเครื่องหมายคุณสมบัติเป็นผลลัพธ์ของอินดิเคเตอร์ คุณสมบัตินี้ควรเป็น public เพื่อให้สามารถอ้างอิงได้โดยคลาสอื่น
ผลลัพธ์ของอินดิเคเตอร์ควรเป็นประเภทข้อมูล IndicatorDataSeries เสมอ ซึ่งเป็นรายการของ double ที่สามารถอินเด็กซ์ได้เหมือนอาร์เรย์ ดังนั้น ค่าที่ [index] แต่ละตัวในรายการ Result สามารถกำหนดได้ในเมธอด Calculate ดังนี้
1 2 3 4 | |
1 2 | |
อินดิเคเตอร์ที่มีพารามิเตอร์
ในกรณีส่วนใหญ่ ผลลัพธ์ของอินดิเคเตอร์สามารถแตกต่างกันไปขึ้นอยู่กับอินพุตของผู้ใช้ วิธีการตั้งค่าพารามิเตอร์ที่ปรับแต่งได้สำหรับอินดิเคเตอร์นั้นคล้ายกับวิธีการทำสำหรับ cBot
อินดิเคเตอร์ Simple Moving Average ด้านล่างนี้ถูกออกแบบมาเพื่อรับแหล่งที่มาของราคาและช่วงเวลาเป็นพารามิเตอร์ที่ปรับแต่งได้ พารามิเตอร์ดังกล่าว (Source และ Periods ในตัวอย่างนี้) ต้องนำหน้าด้วยแอตทริบิวต์ Parameter
เช่นเดียวกับแอตทริบิวต์ [Indicator()] และ [Output()] ที่กล่าวถึงก่อนหน้านี้ แอตทริบิวต์ [Parameter()] สามารถกำหนดลักษณะบางอย่างที่ใช้กับอินพุตของผู้ใช้
1 | |
หมายเหตุ
อินดิเคเตอร์ 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 | |
หมายเหตุ
อินดิเคเตอร์ Python ใช้พารามิเตอร์ที่ปรับแต่งได้ที่ประกาศในไฟล์ .cs
1 2 3 4 5 6 7 8 | |
อินดิเคเตอร์ซ้อนกัน
อินดิเคเตอร์ซ้อนกันคือ อินดิเคเตอร์ที่ค่าของมันขึ้นอยู่กับผลลัพธ์การคำนวณที่ดำเนินการโดยอินดิเคเตอร์อื่น ๆ อินดิเคเตอร์เหล่านี้มีประโยชน์เมื่อเขียนส่วนขยายบางประเภท เช่น อินดิเคเตอร์ 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 | |
หมายเหตุ
อินดิเคเตอร์ Python ใช้พารามิเตอร์ที่ปรับแต่งได้ที่ประกาศในไฟล์ .cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
ในตัวอย่างข้างต้น deMinMA และ deMaxMA เป็นตัวแปรสองตัวที่ใช้ในการคำนวณค่าของอินดิเคเตอร์ DeMarker ของเรา
อินดิเคเตอร์ซ้อนกันจำเป็นต้องถูกกำหนดในเมธอด Initialize() ตัวอย่างเช่น deMinMA ถูกกำหนดให้เป็นค่าเฉลี่ยเคลื่อนที่แบบง่ายของอนุกรม deMin
1 | |
1 | |
ส่วน deMin ถูกกำหนดในเมธอด Calculate() ให้เป็นค่าสูงสุดของค่าต่ำสุดสองค่าล่าสุด
1 | |
1 | |
เพื่อให้การทำงานกับอินดิเคเตอร์ซ้อนกันง่ายขึ้น IntelliSense จะเติมรายการของอินดิเคเตอร์ในตัวทั้งหมดโดยอัตโนมัติเมื่อคุณพิมพ์ Indicators ตามด้วยจุดลงในตัวแก้ไขโค้ด นอกจากนี้ยังจะแสดงพารามิเตอร์อินพุตที่เกี่ยวข้องทั้งหมดเมื่อคุณเลือกอินดิเคเตอร์บางตัวจากรายการนี้

การโหลดแบบ 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 | |
หมายเหตุ
อินดิเคเตอร์ Python ใช้พารามิเตอร์ที่ปรับแต่งได้ที่ประกาศในไฟล์ .cs
1 2 3 4 | |
โปรดทราบว่าแอตทริบิวต์ Levels สามารถใช้ได้เฉพาะเมื่ออินดิเคเตอร์ไม่ได้ซ้อนทับบนกราฟ ซึ่งหมายความว่าคุณสมบัติ IsOverlay ไม่ได้ถูกตั้งค่าเป็น true โดยค่าเริ่มต้น ค่าของ IsOverlay คือ false หากแอตทริบิวต์นี้ถูกละเว้นจากโค้ดของคุณ Levels ควรทำงานได้อย่างถูกต้อง
หากคุณต้องการกำหนดเส้น "ระดับ" หลายเส้น ให้เพิ่มรายการค่าที่คั่นด้วยเครื่องหมายจุลภาคภายในวงเล็บดังที่แสดงด้านล่าง
1 | |
1 | |
1 | |
ระดับในอินดิเคเตอร์ 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 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
การรวมอินดิเคเตอร์
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 | |
หมายเหตุ
อินดิเคเตอร์ Python ใช้พารามิเตอร์ที่ปรับแต่งได้ที่ประกาศในไฟล์ .cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
กรอบเวลาหลายรูปแบบ
-
การใช้กรอบเวลาหลายรูปแบบ
ตัวอย่างต่อไปนี้แสดงอินดิเคเตอร์ค่าเฉลี่ยเคลื่อนที่บนกรอบเวลาที่ต่างกัน
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)
