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

C# สำหรับการเทรดด้วยอัลกอริทึม

C# คืออะไร

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

อัลกอริทึม C# ในหนึ่งนาที!

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

.NET คืออะไร?

สำหรับโปรแกรม C# ที่จะทำงานได้ โค้ดต้นฉบับของพวกเขาต้องถูกคอมไพล์เป็น Intermediate Language (IL) โค้ด IL นี้เป็นไปตามข้อกำหนด Common Language Infrastructure (CLI) และจะถูกคอมไพล์เป็นคำสั่งเครื่องเนทีฟในขณะรันไทม์ เฟรมเวิร์ก .NET จัดเตรียมสภาพแวดล้อมการทำงานเสมือนที่สร้างขึ้นบนไลบรารีคลาสที่กว้างขวางและ Common Language Runtime (CLR) ซึ่งเป็นการใช้งาน CLI ของ Microsoft

โดยไม่ต้องลงลึกในรายละเอียดทางเทคนิค .NET ทำหน้าที่ดังต่อไปนี้:

  • อำนวยความสะดวกในการพัฒนาและการทำงานของแอปพลิเคชัน: .NET SDK มีคอมไพเลอร์และเครื่องมือสร้างในตัวหลายตัว ทำให้ไม่จำเป็นต้องสร้างโซลูชันแบบกำหนดเอง
  • จัดเตรียมไลบรารีรันไทม์: เมื่อเพิ่มชนิดข้อมูลหรือคอลเลกชันใหม่ลงในโค้ดของคุณ คุณมักจะพบว่า .NET มีคลาสและเมธอดที่เหมาะสมสำหรับงานนั้นอยู่แล้ว

พื้นฐานของ C#

ชนิดข้อมูลและการประกาศตัวแปร

ชนิดข้อมูลเป็นวิธีการจัดหมวดหมู่ข้อมูลเพื่อให้ C# รู้ว่าจะจัดการกับตัวแปรและคุณสมบัติอย่างไร ในการประกาศตัวแปร/คุณสมบัติ ชนิดข้อมูลจะอยู่หน้าชื่อตัวแปร/คุณสมบัติเสมอ

1
string developer = "I am developing cBots, plugins, and indicators!";

หรือคุณสามารถใช้คีย์เวิร์ด var เพื่อหลีกเลี่ยงการระบุชนิดข้อมูล

1
var developer = "I am developing cBots, plugins, and indicators!";

วัตถุและคลาส

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

เนื่องจาก C# เป็นภาษาเชิงวัตถุ คลาสยังสามารถสืบทอดคุณสมบัติและเมธอดจากคลาสอื่นได้ พิจารณาตัวอย่างต่อไปนี้ซึ่งเราประกาศคลาส NewBot ใหม่ที่สืบทอดมาจากคลาส Robot เรายังกำหนดคุณสมบัติคลาสใหม่บางอย่างด้วย

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/* We use the colon sign to designate inheritance.
Additionally, we used expressions in square brackets to
specify the parameters that apply to the entire class */
[Robot(AccessRights = AccessRights.None)]
public class NewBot : Robot
{
    /* We declare a custom class property and make it
    read-only. */
    public string CustomProperty { get; }

    /* In this declaration, we define the default value of a
    custom parameter. */
    [Parameter("BotName", DefaultValue = "Traders First!")]

    /* We declare the BotName property which is changeable via
    the "BotName" parameter. */
    public string BotName { get; }

    /* We also declare the BotComment parameter.
    It can be both read and set. */
    [Parameter("BotComment", DefaultValue = "Our super-duper bot!")]
    public string BotComment { get; set; }
}

ชนิดข้อมูล

เนื่องจาก C# เป็นภาษาที่มีการกำหนดชนิดข้อมูลอย่างเข้มงวด จึงจำเป็นต้องระบุชนิดข้อมูลเมื่อประกาศตัวแปรและคุณสมบัติของคลาส โดยสรุป ชนิดข้อมูลประกอบด้วยคลาสที่ไม่ซ้ำกันซึ่งมีชุดพฤติกรรมที่แตกต่างกัน พิจารณาตัวอย่างต่อไปนี้ซึ่งมีการระบุชนิดข้อมูลต่างๆ สำหรับคุณสมบัติคลาสและพารามิเตอร์ที่เกี่ยวข้อง

1
2
[Parameter("Price")]
public DataSeries Source { get; }

ในโค้ดด้านบน ชนิดข้อมูล DataSeries แสดงถึงรายการค่าแบบอ่านอย่างเดียว และโดยทั่วไปจะใช้แสดงราคาตลาด

เมื่อต้องการสร้างพารามิเตอร์แบบหลายตัวเลือก คุณสามารถใช้ชนิดข้อมูล enum ในตัวตามที่แสดงด้านล่าง คุณสามารถคิดว่า enum เป็นคลาสพิเศษที่มีค่าคงที่ต่างๆ

1
2
3
4
5
6
7
8
9
public enum Option
{
    First,
    Second,
    Third
}

[Parameter("Option", DefaultValue = Option.Third)]
public Option SelectedOption { get; set; }

ในการเข้าถึงค่าคงที่ที่อยู่ใน enum ให้ใช้ไวยากรณ์ต่อไปนี้

1
var newOption = Option.First;

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

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

สุดท้าย ชนิด bool โดยทั่วไปแสดงถึงอินพุตแบบใช่หรือไม่ ค่าใช่และไม่สอดคล้องกับ true และ false ตามลำดับ

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

เนมสเปซ

เนมสเปซทำหน้าที่เป็นคอลเลกชันของคลาสที่กำหนดไว้ เมื่อคุณกำหนดคลาสให้กับเนมสเปซ คลาสนั้นสามารถเข้าถึงได้ในภายหลังโดยใช้สัญกรณ์ Namespace.ClassName เราจะกำหนด NewBot ของเราให้กับเนมสเปซ CoolTradingBots

1
2
3
4
5
6
7
8
namespace CoolTradingBots
{
    [Robot(AccessRights = AccessRights.None)]
    public class NewBot : Robot
    {
        // ...
    }
}

เมธอดของคลาส

เมธอดของคลาสถูกกำหนดหลังจากการประกาศคลาส วัตถุทั้งหมดของคลาส NewBot ของเราจะสามารถเรียกเมธอด CustomTradeOperation() ได้ มันรับอาร์กิวเมนต์สองตัว คือวัตถุ Symbol และวัตถุ double เมธอดของเราควรรับสัญลักษณ์และดำเนินการเทรดบางอย่างสำหรับปริมาณที่ระบุ

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
namespace CoolTradingBots
{
    [Robot(AccessRights = AccessRights.None)]
    public class NewBot : Robot
    {
        // ... Defining the class parameters.

        // We declare the CustomTradeOperation method. 
        protected override void CustomTradeOperation(string symbolName, double volume)

        {
            // This space is for declaring the method logic. 
        }
    }
}

ไลบรารีคลาส

ไลบรารีคลาส (และต่อมาคือเมธอดของคลาส) สามารถเข้าถึงได้โดยเนมสเปซของพวกมันตามที่แสดงในตัวอย่างด้านล่าง

1
CoolTradingBots.NewBot.CustomTradeOperation(symbolName, 10000)

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

1
2
3
using CoolTradingBots;

NewBot.CustomTradeOperation(symbolName, 10000)

ประโยคเงื่อนไข

ในการใช้ประโยคเงื่อนไข ให้ใช้คีย์เวิร์ดตามด้วยนิพจน์ในวงเล็บกลม ตัวอย่างด้านล่างใช้คีย์เวิร์ด if เพื่อสรุปเมธอด CustomTradingOperation() ของเรา เพื่อทำเช่นนั้น เราใช้เมธอด EvaluateMarket() ซึ่งถูกกำหนดไว้ในเนมสเปซ Analytics.Actions

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
namespace CoolTradingBots
{
    [Robot(AccessRights = AccessRights.None)]
    public class NewBot : Robot
    {
        // ... Defining the class parameters.

        protected override void CustomTradeOperation(string symbolName, double volume)
        {
            // We declare and initialize the 'result' variable.
            var result = Analytics.Action.EvaluateMarket();

            // We use a conditional statement based on the IsSuccessful property.
            if (result.IsSuccessful)
            {
                Print("Operation successful!")
            }
        }
    }
}

คอลเลกชัน

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

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

1
2
3
4
5
public override void Calculate(int index)
{
       var bar = Bars[index];
       Print($"{bar.Open} | {bar.High} | {bar.Low} | {bar.Close}");
}

สร้างส่วนขยาย cTrader

ในส่วนด้านล่างนี้ เราสร้างหุ่นยนต์เทรดพื้นฐานโดยใช้เพียงความรู้ที่ครอบคลุมในส่วนด้านบน

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System; 

namespace Spotware.cBots
{
    [Robot(AccessRights = AccessRights.None)]
    public class SuperAwesomeBot : Robot
    {

        /* In the below method, we define the operation(s) that our bot should
        perform when it is launched. */
        protected override void OnStart()
        {
            var result = ExecuteMarketOrder(TradeType.Buy, symbolName, 10000);

            /* We use a conditional statement using the IsSuccessful property of the
            TradeResult object. */
            if (result.IsSuccessful)
            {
                var position = result.Position;
                Print ("Position entry price is {0}", position.EntryPrice);
            } 
        }
    }
}

การดำเนินการแบบซิงโครนัสและอะซิงโครนัส

ตามที่กล่าวไว้ก่อนหน้านี้ C# รองรับการดำเนินการแบบอะซิงโครนัสอย่างเต็มที่ แผนภาพด้านล่างกำหนดตัวอย่างพื้นฐานของวิธีการดำเนินกิจกรรมการเทรดในการดำเนินการแบบซิงโครนัส

graph TD
    A(พบสัญญาณทางเทคนิค) ==> B(ดำเนินการคำสั่ง Market) 
    B ==> C(ถึง Take Profit/Stop Loss) 
    C ==> D(ปิดโพสิชัน)
    D ==> A

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

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

graph TD
    A([พบสัญญาณทางเทคนิค]) ==> B([ส่งคำสั่งซื้อ]) & C([ส่งคำสั่งขายเพื่อ Hedging]) ==> D([คำสั่งถึงจุด <br>Take Profit/Stop Loss]) 
    D ==> E([ปิดสถานะ])
    E ==> A

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

โปรดทราบว่าการดำเนินการแบบอะซิงโครนัสแตกต่างจากการทำงานแบบหลายเธรด:

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

cTrader ไม่เรียกใช้เมธอดของคุณแบบขนานดังนั้นคุณไม่ต้องกังวลเกี่ยวกับปัญหาการทำงานแบบหลายเธรด

Image title