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

วงจรชีวิตของ cBot

ในบทความนี้และวิดีโอที่เกี่ยวข้อง เราจะอธิบายโครงสร้างโค้ดและตรรกะเบื้องหลังเหตุการณ์และวงจรชีวิตของ cTrader cBot

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

ตีความเทมเพลตพื้นฐาน

หลังจากสร้าง cBot ใหม่ คุณควรเห็นโครงสร้างพื้นฐานต่อไปนี้ในหน้าต่างตัวแก้ไขโค้ด

 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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        [Parameter(DefaultValue = "Hello world!")]
        public string Message { get; set; }

        protected override void OnStart()
        {
            // To learn more about cTrader Algo visit our Help Center:
            // https://help.ctrader.com/ctrader-algo

            Print(Message);
        }

        protected override void OnTick()
        {
            // Handle price updates here
        }

        protected override void OnStop()
        {
            // Handle cBot stop here
        }
    }
}

โปรดทราบว่ามีเพียงสามเหตุการณ์ที่แสดงในเทมเพลตพื้นฐาน เหตุการณ์เหล่านี้จัดการโดยเมธอด OnStart(), OnTick() และ OnStop() เราจะเพิ่มอีกสองเมธอด (OnBar() และ OnException()) และอธิบายวิธีการทำงานในภายหลัง ก่อนอื่นเราจะพูดถึงเมธอด OnStart()

ใช้เมธอด OnStart()

เมธอด OnStart() จะถูกเรียกเมื่อ cBot เริ่มต้นครั้งแรก มันใช้เพื่อเริ่มต้นตัวแปรใดๆ ที่คุณวางแผนจะใช้ใน cBot ของคุณ รวมถึงอินดิเคเตอร์ ตัวนับ ตัวจัดการเหตุการณ์ หรือตัวจับเวลา

หมายเหตุ

เทมเพลตโค้ดเริ่มต้นมีคำสั่งโค้ดเพื่อพิมพ์ข้อความลงในบันทึกเมื่อ cBot เริ่มต้นอยู่แล้ว ดังที่คุณเห็น cBot ของเรามีพารามิเตอร์ Message และเมธอด OnStart() ส่งค่าของพารามิเตอร์นี้ไปยังเมธอด Print()

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

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

ใช้เมธอด OnTick()

เมธอด OnTick() จะถูกเรียกทุกครั้งที่ราคา bid หรือ ask ของสัญลักษณ์เปลี่ยนแปลง ภายในเมธอดนี้ คุณสามารถเขียนโปรแกรมเงื่อนไขการเข้าและออกจากตำแหน่งรวมถึงฟังก์ชันเสริมอื่นๆ ที่คุณต้องการให้ทำงานเมื่อมีข้อมูล tick ใหม่เข้ามา

เราจะเพิ่มโค้ดต่อไปนี้ลงในเมธอด OnTick() เพื่อให้พิมพ์ข้อความลงในบันทึก

1
Print("OnTick. Bid: ", Symbol.Bid, ", Ask: ", Symbol.Ask);

ดังที่คุณเห็นด้านล่าง cBot ของเราจะพิมพ์ราคา bid และ ask ลงในบันทึกทุกครั้งที่ราคาเปลี่ยนแปลง

ใช้เมธอด OnBar()

เมธอด OnBar() ไม่ได้รวมอยู่ในเทมเพลตโค้ด cBot เริ่มต้น ดังนั้นเราจะเพิ่มส่วนของโค้ดต่อไปนี้เพื่อเพิ่มมัน

1
2
3
4
protected override void OnBar() 
{
    Print("OnBar");
}

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

วิธีการที่เมธอด OnBar() ถูกเรียก

หากคุณมีแผนภูมิ H1 แท่งใหม่จะถูกสร้างขึ้นทุกชั่วโมง ซึ่งหมายความว่าเมธอด OnBar() จะถูกเรียกหนึ่งครั้งต่อชั่วโมง หากคุณมีแผนภูมิ m1 เมธอดเดียวกันจะถูกเรียกหนึ่งครั้งต่อนาที

เมธอด OnBar() ของเราจะพิมพ์ "OnBar" ในทุกแท่ง/แท่งเทียนใหม่ เพื่อแสดงวิธีการทำงาน เราจะแนบ cBot ของเราเข้ากับแผนภูมิ m1 และดูที่บันทึก

ใช้เมธอด OnStop()

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

เราจะเพิ่มโค้ดต่อไปนี้ลงในเมธอด OnStop() ของเรา - เช่นเคย cBot ของเราจะพิมพ์ค่าของพารามิเตอร์ Message เมื่อมันหยุดทำงาน

1
Print(Message);

ในภาพหน้าจอด้านล่าง เราเปิดและหยุดอินสแตนซ์ของ cBot ของเราเพื่อแสดงวิธีการทำงานทั้งหมด

ใช้เมธอด OnException()

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

1
2
3
4
protected override void OnException(Exception exception) 
{
    Print("Ooops, unhandled exception! No worries, cBot still alive");            
}

เพื่อเรียกใช้เมธอด OnException() เราจะเขียนโค้ดบางส่วนเพื่อจับข้อยกเว้นที่เกิดขึ้นเมื่อเราพยายามเข้าถึงข้อมูลเกี่ยวกับการเทรดที่ไม่มีอยู่แล้ว เราจะเพิ่มโค้ดด้านล่างนี้ลงในเมธอด OnStart() ของเรา

1
ExecuteMarketOrder(TradeType.Buy, SymbolName, 1000, "my label");

โค้ดที่เราได้เขียนในเมธอด OnStart() จะดำเนินการคำสั่ง Market โดยมีพารามิเตอร์ที่กำหนดค่าได้ดังต่อไปนี้

  • ประเภทการเทรดจะเป็นคำสั่งซื้อ
  • การเทรดจะดำเนินการสำหรับสัญลักษณ์ปัจจุบันของกราฟที่ cBot ถูกแนบ
  • ปริมาณคำสั่งจะเป็น 1,000 หน่วย
  • ป้ายกำกับที่ไม่ซ้ำกันที่แนบกับคำสั่งจะเป็น "my label"

เราจะเพิ่มโค้ดต่อไปนี้ลงในเมธอด OnTick() ด้วย

1
2
3
var position = Positions.Find("my label");
if (Positions.Find("my label") != null) Print("PositionId: ", position.Id);
Print("Message below");

โค้ดที่เราได้เขียนในเมธอด OnTick() จะค้นหาโพสิชันที่ถูกเปิดในเมธอด OnStart() โดยใช้ชื่อป้ายกำกับ "my label"

หากพบโพสิชันที่มีป้ายกำกับเดียวกัน มันจะพิมพ์ ID ของโพสิชันของการเทรดที่เปิดอยู่ลงในบันทึก นอกจากนี้ยังจะพิมพ์ข้อความอื่นที่เรียกว่า "Message below" เป็นบรรทัดถัดไปของโค้ดที่ถูกดำเนินการ

เมื่อ cBot ของเราถูกเปิดใช้งานและเมธอด OnTick() ถูกเรียกและพบคำสั่ง cBot จะพิมพ์ ID ของคำสั่งลงในบันทึกและหลังจาก ID ของคำสั่ง มันจะพิมพ์ข้อความ "Message below"

ดังที่คุณเห็น ไม่มีข้อยกเว้นเกิดขึ้นและ cBot ของเราทำงานได้อย่างสมบูรณ์แบบ

อย่างไรก็ตาม ตอนนี้เราจะปิดโพสิชันที่เปิดโดย cBot ด้วยตนเองและทำการเปลี่ยนแปลงเล็กน้อยกับโค้ดเพื่อให้แน่ใจว่าจะเกิดข้อยกเว้นขึ้น ในเมธอด OnStart() เราจะเปลี่ยนป้ายกำกับคำสั่งเป็น "cTrader" ในเมธอด OnTick() เราจะคอมเมนต์เงื่อนไขที่ตรวจสอบว่ามีโพสิชันที่มีป้ายกำกับ "my label" อยู่หรือไม่

นี่คือโค้ดสุดท้ายของ cBot ของเรา - โปรดทราบว่าโค้ดนี้จะทริกเกอร์ข้อยกเว้นเสมอ

 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
namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None)]
    public class LifecycleTest : Robot
    {
        [Parameter(DefaultValue = "cTrader rocks!")]
        public string Message { get; set; }

        protected override void OnStart()
        {
            ExecuteMarketOrder(TradeType.Buy, SymbolName, 1000, "cTrader");
        }

        protected override void OnTick()
        {
            var position = Positions.Find("my label");
            //if (Positions.Find("my label") != null) 
            Print("PositionId: ", position.Id);
            Print("Message below");
        }

        protected override void OnStop()
        {
            Print(Message);
        }

        protected override void OnException(Exception exception) 
        {
            Print("Ooops, unhandled exception! No worries, cBot still alive");            
        }
    }
}

เราจะรัน cBot อีกครั้งและดูว่าเกิดอะไรขึ้น

สิ่งที่เกิดขึ้นคือคำสั่ง Market ใหม่ถูกสร้างขึ้นเมื่อ cBot เริ่มต้น ป้ายกำกับที่แนบกับคำสั่งนี้คือ "cTrader" ในเมธอด OnTick() โค้ดพยายามที่จะรับโพสิชันที่มีป้ายกำกับ "my label" และเนื่องจากเราได้คอมเมนต์บรรทัดของโค้ดที่มีเงื่อนไข จากนั้นจึงพยายามพิมพ์ ID ของโพสิชันลงในบันทึก

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

สรุป

วงจรชีวิตของ cBot ประกอบด้วยเหตุการณ์สำคัญหลายอย่างที่คุณสามารถจัดการผ่านเมธอด OnStart(), OnTick(), OnStop(), OnBar() และ OnException() โดยการปรับแต่งวิธีที่ cBot ของคุณตอบสนองต่อเหตุการณ์สำคัญ คุณสามารถทำให้แน่ใจได้ว่าอัลกอริทึมของคุณทำงานได้ตรงตามที่คาดหวังไว้