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

วิธีเพิ่มเมธอดให้กับ API ของ cTrader

เมธอดส่วนขยายเป็นเครื่องมือที่สำคัญหากคุณต้องการเพิ่มฟังก์ชันการทำงานใหม่ให้กับ API ของ cTrader โดยใช้ไวยากรณ์ที่ค่อนข้างง่าย คุณสามารถเพิ่มพฤติกรรมใหม่ให้กับคลาส API ที่กำหนดไว้ล่วงหน้า เช่น Symbol หรือ Position หลังจากที่คุณกำหนดเมธอดส่วนขยาย คุณสามารถเรียกใช้มันจากวัตถุใดๆ ของคลาสที่คุณขยาย

ใช้กรณีสำหรับเมธอดส่วนขยาย

ก่อนอื่น เราจะทำการสาธิตอย่างรวดเร็วว่าทำไมคุณอาจต้องการใช้เมธอดส่วนขยาย

โดยใช้ cBot เราต้องการเข้าถึงขนาดของโพสิชันที่กำหนดในล็อต เนื่องจากข้อมูลนี้ส่งผลโดยตรงต่อกลยุทธ์การเทรดที่เราต้องการ เพื่อทำเช่นนั้น เราสามารถลองเริ่มต้นตัวแปรของคลาส Position แล้วพยายามเข้าถึงเมธอด Lots() ของมัน

1
2
Position position = Positions.Last();
Print(position.Lots());

หากเราเพียงแค่พิมพ์โค้ดตามที่เป็นอยู่ เราจะได้รับข้อผิดพลาดที่บอกว่าตัวเข้าถึง Lots() ไม่มีอยู่ใน API แต่ถ้ามีวิธีเพิ่มเมธอดใหม่ให้กับสมาชิก API ที่มีอยู่โดยไม่ส่งผลกระทบต่อฟังก์ชันการทำงานอื่น ๆ ล่ะ?

สมมติว่าเมธอดนี้มีอยู่ เราสามารถสร้าง cBot อย่างง่ายที่ในทุก ๆ แท่งเทียน จะวนซ้ำผ่านรายการของโพสิชันปัจจุบันทั้งหมดและพิมพ์ขนาดของพวกมันเป็นล็อตในบันทึก เราจะกำหนดเมธอด OnBar() ดังต่อไปนี้

1
2
3
4
5
6
protected override void OnBar()
{
    foreach (var position in Positions) {
        Print(position.Lots());
    }
}

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

วิธีการทำงานของเมธอดส่วนขยาย

เมื่อทำงานกับเมธอดส่วนขยาย โปรดคำนึงถึงกฎต่อไปนี้

  • เมธอดส่วนขยายเป็นแบบ static เสมอ

ในการประกาศเมธอด static ทั้งหมดที่คุณต้องทำคือใช้คีย์เวิร์ด static ด้านล่างนี้ ประกาศเมธอด Lots() ที่มีเนื้อหาว่างเปล่า

1
2
3
4
public static class MyExtensions {
    public static double Lots() {}

}
  • เมธอดส่วนขยายสามารถมีอาร์กิวเมนต์ได้จำนวนเท่าใดก็ได้ แต่อาร์กิวเมนต์แรกต้องระบุประเภทข้อมูล/คลาสที่เมธอดนั้นจะถูกเรียกใช้ โดยนำหน้าด้วยคีย์เวิร์ด this เสมอ

เราจะเพิ่มวัตถุของคลาส Position เป็นอาร์กิวเมนต์แรกและอาร์กิวเมนต์เดียวของเมธอด Lots() เนื่องจากวัตถุ Position ยังมีข้อมูลเกี่ยวกับสัญลักษณ์ที่โพสิชันถูกเปิดด้วย เราจึงไม่จำเป็นต้องมีอาร์กิวเมนต์อื่นใด

1
2
3
public static class MyExtensions {
    public static double Lots(this Position position) {}
}
  • เมธอดส่วนขยายสามารถมีตรรกะใด ๆ ที่เหมาะสมกับอาร์กิวเมนต์ที่ให้มา

ไม่จำเป็นต้องใช้ไวยากรณ์พิเศษเมื่อกำหนดเนื้อหาของเมธอดส่วนขยาย เราสามารถปฏิบัติกับมันเหมือนเมธอดอื่น ๆ และดังนั้นจึงสามารถกำหนดเนื้อหาของมันได้ดังนี้

1
2
3
4
5
public static class MyExtensions {
    public static double Lots(this Position position) {
        return position.VolumeInUnits / position.Symbol.LotSize;
    }
}
  • เมธอดส่วนขยายสามารถถูกเรียกเป็นเมธอดของอินสแตนซ์หรือเมธอด static ได้

มีสองวิธีที่เป็นไปได้ในการเรียกเมธอดส่วนขยายของเราในโค้ดของ cBot

เมื่อใช้ไวยากรณ์เมธอดของอินสแตนซ์ เราเรียกเมธอดจากวัตถุที่เหมาะสมใด ๆ ของประเภท Position

1
2
var position = Positions.Last();
Print(position.Lots());

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

1
2
var position = Positions.Last();
Print(MyExtensions.Lots(position));

ขึ้นอยู่กับคุณที่จะกำหนดว่าวิธีใดในการเรียกเมธอดส่วนขยายที่สะดวกที่สุด

ลายเซ็นของเมธอด

เมื่อใช้ไวยากรณ์อินสแตนซ์ ให้หลีกเลี่ยงกรณีที่เมธอดส่วนขยายของคุณมีลายเซ็นเดียวกันกับเมธอด API ที่มีอยู่แล้ว (เช่น Position.Close()) ในสถานการณ์เหล่านี้ เมธอดที่มีอยู่แล้วจะถูกเรียกทุกครั้งที่คุณพยายามเรียกเมธอดส่วนขยายที่มีลายเซ็นตรงกัน

IntelliSense

เมื่อเราพยายามเรียกเมธอดส่วนขยาย IntelliSense จะใช้ไอคอนพิเศษเพื่อแยกความแตกต่างจากสมาชิก API ที่มีอยู่แล้ว

เพื่อสาธิตเมธอดใหม่ของเราในการทำงาน เราสามารถสร้าง cBot ที่ส่งคำสั่งสามคำสั่งเมื่อเริ่มต้น แต่ละคำสั่งมีปริมาณที่แตกต่างกัน ในทุก ๆ แท่งเทียน cBot จะพิมพ์ปริมาณของโพสิชันที่เปิดอยู่ทั้งหมดเป็นล็อต

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
protected override void OnStart()
{
    ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000);
    ExecuteMarketOrder(TradeType.Buy, SymbolName, 100000);
    ExecuteMarketOrder(TradeType.Buy, SymbolName, 50000);
}

protected override void OnBar()
{
    foreach (var position in Positions) {
        Print(position.Lots());
    }
}

หลังจากสร้างและเปิดใช้งาน cBot ของเรา เราควรเห็นค่าที่ถูกต้องถูกพิมพ์ในบันทึก

ใช้เมธอดส่วนขยายใน cBots

ตอนนี้เราจะลองสร้าง cBot ที่ซับซ้อนมากขึ้น ในทุก ๆ แท่งเทียน อัลกอริทึมของเราจะตรวจสอบรายการของโพสิชันที่เปิดอยู่ในปัจจุบันและปรับระดับ Stop-Loss ของพวกมันให้อยู่ที่จุดคุ้มทุน เพื่อทำเช่นนั้น เราจะต้องสร้างเมธอดส่วนขยาย BreakEven() สำหรับคลาส Position

เราสร้าง cBot ใหม่และเปลี่ยนชื่อมัน หลังจากนั้น เราลบโค้ดทั้งหมดที่เราไม่ต้องการและเพิ่มคลาส MyExtensions

1
2
3
public static class MyExtensions {

}

โค้ดของเราสำหรับเมธอด BreakEven() ค่อนข้างง่าย เราตรวจสอบว่าโพสิชันมี Stop Loss หรือไม่ กำไรขั้นต้นมากกว่าศูนย์หรือไม่ และ Stop Loss ที่ตั้งไว้ในปัจจุบันไม่เท่ากับราคาเข้าของโพสิชันหรือไม่ หากเงื่อนไขเหล่านี้ทั้งหมดเป็นจริง เราจะแก้ไข Stop Loss ของโพสิชันให้เท่ากับราคาเข้าของโพสิชัน

1
2
3
4
5
6
7
public static class MyExtensions {
    public static void BreakEven(this Position position) {
        if (position.StopLoss is not null && position.GrossProfit > 0 && position.StopLoss != position.EntryPrice) {
            position.ModifyStopLossPrice(position.EntryPrice);
        }
    }
}

ใน cBot เอง เราไม่จำเป็นต้องใช้เมธอดอื่นนอกจาก OnBar() ในทุก ๆ แท่งเทียน เราขอให้ cBot ทำการดำเนินการอย่างง่าย นั่นคือวนซ้ำผ่านคอลเลกชัน Positions และเรียกเมธอด BreakEven() ใหม่สำหรับแต่ละองค์ประกอบในนั้น

1
2
3
4
5
6
protected override void OnBar() 
{
    foreach (var position in Positions) {
        position.BreakEven();
    }
}

หลังจากที่เราสร้างและเปิดใช้งาน cBot ของเรา เราสามารถเห็นมันทำงานได้ มันสามารถเป็นผู้ช่วยการเทรดที่มีประโยชน์ โดยเฉพาะอย่างยิ่งเมื่อจัดการกับโพสิชันที่เปิดอยู่จำนวนมาก

ใช้เมธอดส่วนขยายในอินดิเคเตอร์

เราจะสร้างอินดิเคเตอร์ที่มีประโยชน์ซึ่งอาศัยเมธอดส่วนขยายด้วย อินดิเคเตอร์จะวัดความผันผวนโดยการพล็อตเปอร์เซ็นต์ที่ราคาของสัญลักษณ์เปลี่ยนแปลงในแต่ละแท่งเทียนเมื่อเทียบกับราคาเปิดของแท่งเทียนนั้น

เพื่อทำเช่นนั้น เราจะสร้างอินดิเคเตอร์ใหม่และเปลี่ยนชื่อมัน ในหน้าต่างตัวแก้ไขโค้ด เราจะสร้างคลาส MyExtensions เพื่อขยายคลาส Bar

1
2
3
public static class MyExtensions {

}

เราจะเพิ่มเมธอด PercentageChange() ด้วย ในตัวแปร priceChange เราลบราคาปิดของแท่งเทียนออกจากราคาเปิดของมัน เมธอดนี้คืนค่าการเปลี่ยนแปลงราคาของเราหารด้วยราคาเปิดและคูณด้วย 100

1
2
3
4
5
6
7
8
public static class MyExtensions 
{
    public static double PercentageChange(this Bar bar) 
    {
        var priceChange = bar.Open - bar.Close;
        return priceChange / bar.Open * 100;
    }
}

ในโค้ดอินดิเคเตอร์เอง เราไม่จำเป็นต้องใช้เมธอด Initialize() และพารามิเตอร์ที่ไม่จำเป็น ในเนื้อหาของเมธอด Calculate() เราเพียงแค่เรียกเมธอด PercentageChange() ใหม่ของเราในทุกแท่งเทียน

1
2
3
4
5
6
7
8
[Output("Main")]
public IndicatorDataSeries Result { get; set; }


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

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

สรุป

สรุปได้ว่า เมธอดส่วนขยายเป็นเครื่องมือที่มีคุณค่าหากคุณต้องการสร้างโค้ดที่นำกลับมาใช้ใหม่ได้ซึ่งเพิ่มฟังก์ชันการทำงานใหม่ให้กับ cTrader API เราขอแนะนำอย่างยิ่งให้ทดลองใช้เมธอดส่วนขยาย เนื่องจากสามารถทำให้อัลกอของคุณมีประสิทธิภาพมากขึ้นและง่ายต่อการบำรุงรักษา