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

การดำเนินการขั้นสูงกับ cBots

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

ทำการเทรดสัญลักษณ์อื่น

คุณสามารถพัฒนา cBot ที่ทำการเทรดหลายสัญลักษณ์นอกเหนือจากสัญลักษณ์ที่ระบุเมื่อสร้างอินสแตนซ์ใหม่

ทำให้เป็นไปได้ Symbols เป็นคอลเลกชันของสัญลักษณ์ทั้งหมดที่มีให้สำหรับบัญชีเทรดของคุณ คุณสามารถวนซ้ำผ่านมันโดยใช้ลูป หรือคุณสามารถค้นหาผ่านมันเพื่อหาสัญลักษณ์เฉพาะ

เพื่อทำงานกับหลายสัญลักษณ์อย่างถูกต้อง cBot จำเป็นต้องทราบข้อมูลต่อไปนี้:

  • ปริมาณขั้นต่ำและสูงสุดที่อนุญาต
  • ขั้นของปริมาณ
  • ขนาด pip tick
  • มูลค่า pip tick (มูลค่าทางการเงินของหนึ่ง pip หรือ tick ในสกุลเงินฝากของบัญชี)

ข้อมูลนี้สามารถเรียนรู้ได้จากออบเจกต์ Symbol ในโค้ดด้านล่าง เราค้นหาสัญลักษณ์ที่มี "GBPUSD" เป็นชื่อ จากนั้นสร้างคำสั่ง Market สำหรับมัน เรายังใช้ปริมาณขั้นต่ำที่อนุญาตเป็นปริมาณคำสั่งด้วย

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
[Robot()]
public class Sample_cBot : Robot
{
    protected override void OnStart()
    {
        var symbol = Symbols.GetSymbol("GBPUSD");

        if (symbol is not null)
        {
            ExecuteMarketOrder(TradeType.Sell, symbol.Name, symbol.VolumeInUnitsMin);
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import clr

clr.AddReference("cAlgo.API")

# Import cAlgo API types
from cAlgo.API import *
from cAlgo.API.Internals import *

# Import trading wrapper functions
from robot_wrapper import *

class Sample_cBot():
    def on_start(self):
        symbol = api.Symbols.GetSymbol("GBPUSD")

        if symbol is not None:
            api.ExecuteMarketOrder(TradeType.Sell, symbol.Name, symbol.VolumeInUnitsMin)

แปลง pips เป็น ticks

เมื่อเขียนโค้ด cBot มักจะพบข้อผิดพลาดที่เกิดจากการที่ค่าตัวแปรบางตัวคำนวณเป็นหน่วย ในขณะที่ค่าอื่น ๆ คำนวณเป็น pips

คลาส SymbolExtensions ด้านล่างแสดงวิธีการแปลง pips เป็น ticks นอกจากนี้ยังแสดงวิธีการเพิ่ม pips ให้กับค่าราคาสัมบูรณ์

  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
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
using System;
using cAlgo.API;
using cAlgo.API.Internals;

namespace Samples
{
    [Robot(AccessRights = AccessRights.None)]
    public class Sample : Robot
    {
        protected override void OnStart()
        {
            var spreadInPips = Symbol.NormalizePips(Symbol.ToPips(Symbol.Spread));

            Print(spreadInPips);

            var spreadInTicks = Math.Round(Symbol.ToTicks(Symbol.Spread));

            Print(spreadInTicks);

            /* Calculating a long position stop loss using the
            absolute price value. */
            var stopLossInPips = 60;

            /* We use 'NormalizePips' to avoid the 'invalid decimal places'
            error in case our stop loss value has too many decimals. */
            var stopLossInPrice = Symbol.Ask - (Symbol.NormalizePips(stopLossInPips) * Symbol.PipSize);

            Print(stopLossInPrice);
        }
    }

    public static class SymbolExtensions
    {
        /// <summary>
        /// Returns a symbol pip value
        /// </summary>
        /// <param name="symbol"></param>
        /// <returns>double</returns>
        public static double GetPip(this Symbol symbol)
        {
            return symbol.TickSize / symbol.PipSize * Math.Pow(10, symbol.Digits);
        }

        /// <summary>
        /// Returns a price value in terms of pips
        /// </summary>
        /// <param name="symbol"></param>
        /// <param name="price">The price level</param>
        /// <returns>double</returns>
        public static double ToPips(this Symbol symbol, double price)
        {
            return price * symbol.GetPip();
        }

        /// <summary>
        /// Returns a price value in terms of ticks
        /// </summary>
        /// <param name="symbol"></param>
        /// <param name="price">The price level</param>
        /// <returns>double</returns>
        public static double ToTicks(this Symbol symbol, double price)
        {
            return price * Math.Pow(10, symbol.Digits);
        }

        /// <summary>
        /// Rounds a price level to the number of symbol digits
        /// </summary>
        /// <param name="symbol">The symbol</param>
        /// <param name="price">The price level</param>
        /// <returns>double</returns>
        public static double Round(this Symbol symbol, double price)
        {
            return Math.Round(price, symbol.Digits);
        }

        /// <summary>
        /// Normalize x Pips amount decimal places to something that can be used as a stop loss or take profit for an order.
        /// For example if symbol is EURUSD and you pass to this method 10.456775 it will return back 10.5
        /// </summary>
        /// <param name="symbol">The symbol</param>
        /// <param name="pips">The amount of Pips</param>
        /// <returns>double</returns>
        public static double NormalizePips(this Symbol symbol, double pips)
        {
            var currentPrice = Convert.ToDecimal(symbol.Bid);

            var pipSize = Convert.ToDecimal(symbol.PipSize);

            var pipsDecimal = Convert.ToDecimal(pips);

            var pipsAddedToCurrentPrice = Math.Round((pipsDecimal * pipSize) + currentPrice, symbol.Digits);

            var tickSize = Convert.ToDecimal(symbol.TickSize);

            var result = (pipsAddedToCurrentPrice - currentPrice) * tickSize / pipSize * Convert.ToDecimal(Math.Pow(10, symbol.Digits));

            return decimal.ToDouble(result);
        }
    }
}
 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
import clr
import math

clr.AddReference("cAlgo.API")

from cAlgo.API import *
from robot_wrapper import *


class Sample():
    def on_start(self):
        spreadInPips = SymbolExtensions.normalize_pips(api.Symbol, SymbolExtensions.to_pips(api.Symbol, api.Symbol.Spread))
        print(spreadInPips)

        spreadInTicks = round(SymbolExtensions.to_ticks(api.Symbol, api.Symbol.Spread))
        print(spreadInTicks)

        stopLossInPips = 60

        stopLossInPrice = api.Symbol.Ask - (SymbolExtensions.normalize_pips(api.Symbol, stopLossInPips) * api.Symbol.PipSize)
        print(stopLossInPrice)


class SymbolExtensions:
    @staticmethod
    def get_pip(symbol):
        return symbol.TickSize / symbol.PipSize * math.pow(10, symbol.Digits)

    @staticmethod
    def to_pips(symbol, price):
        return price * SymbolExtensions.get_pip(symbol)

    @staticmethod
    def to_ticks(symbol, price):
        return price * math.pow(10, symbol.Digits)

    @staticmethod
    def round(symbol, price):
        return round(price, symbol.Digits)

    @staticmethod
    def normalize_pips(symbol, pips):
        currentPrice = float(symbol.Bid)
        pipSize = float(symbol.PipSize)
        pipsDecimal = float(pips)

        pipsAddedToCurrentPrice = round((pipsDecimal * pipSize) + currentPrice, symbol.Digits)
        tickSize = float(symbol.TickSize)

        result = (pipsAddedToCurrentPrice - currentPrice) * tickSize / pipSize * math.pow(10, symbol.Digits)
        return round(result, 12)

รับรายละเอียดธุรกรรม

Transactions ประกอบด้วยประเภทที่ให้ข้อมูลเกี่ยวกับการฝากและถอนสำหรับบัญชี ประเภทเหล่านี้ช่วยให้คุณเข้าถึงและจัดการรายละเอียดธุรกรรมสำหรับบัญชีด้วยโปรแกรม

คุณสามารถดึงข้อมูลเกี่ยวกับประเภทธุรกรรม (ฝากหรือถอน) จำนวนเงิน เวลาที่ทำรายการ ID ธุรกรรม รายละเอียดยอดคงเหลือ คุณสมบัติของ equity ฯลฯ

cBot นี้ดึงและพิมพ์รายละเอียดธุรกรรม:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
using System;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot]
    public class TransactionsAPITEST : Robot
    {
        protected override void OnStart()
        {           
            foreach (var transaction in Transactions)
            {
                Print($"Transaction ID: {transaction.Id}, Amount: {transaction.Amount}, Type: {transaction.Type}, Date: {transaction.Time}");
            }
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import clr

clr.AddReference("cAlgo.API")

# Import cAlgo API types
from cAlgo.API import *
from cAlgo.API.Internals import *

# Import trading wrapper functions
from robot_wrapper import *

class TransactionsAPITEST():
    def on_start(self):
        for transaction in api.Transactions:
            api.Print(
                f"Transaction ID: {transaction.Id}, "
                f"Amount: {transaction.Amount}, "
                f"Type: {transaction.Type}, "
                f"Date: {transaction.Time}"
            )

รับข้อมูลคำสั่งในอดีต

cTrader มีคอลเลกชัน HistoricalOrder เพื่อให้ผู้ใช้สามารถดึงข้อมูลเกี่ยวกับคำสั่ง รวมถึงคำสั่ง Market ที่เสร็จสมบูรณ์และคำสั่งที่รอดำเนินการที่ถูกดำเนินการหรือยกเลิก รายละเอียดที่สามารถดึงได้รวมถึง ID ของคำสั่ง ประเภท ป้ายกำกับ ราคาเป้าหมาย วันหมดอายุ ฯลฯ

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

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None)]
    public class HistoricalOrdersExample : Robot
    {
        protected override void OnStart()
        {
            var historicalOrders = HistoricalOrders;
            foreach (var order in historicalOrders)
            {
                Print($"Order ID: {order.Id}");
                Print($"Type: {order.OrderType}");
                Print($"Volume: {order.VolumeInUnits}");
                Print($"Price: {order.TargetPrice}");
                Print($"Expiration: {order.ExpirationTime}");
                Print($"Comment: {order.Comment}");
                Print($"Label: {order.Label}");
                Print($"Stop Loss: {order.StopLoss}");
                Print($"Take Profit: {order.TakeProfit}");
                Print($"TradeType: {order.TradeType}");
                Print($"Quantity: {order.Quantity}");
                Print($"Label: {order.Label}");
            }
        }
    }
}

ใช้ข้อมูลการเทรดในอดีต

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

ส่วนของโค้ดด้านล่างสร้างไฟล์ .CSV ที่มีการเทรดในอดีตทั้งหมดของเราและข้อมูลการเทรดของพวกเขา

 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
using System;
using cAlgo.API;
using System.Text;
using System.IO;

namespace Samples
{
    /* We provide the access rights required for
    reading and writing in locally stored files. */
    [Robot(AccessRights = AccessRights.FullAccess)]
    public class Sample : Robot
    {
        protected override void OnStart()
        {
            var stringBuilder = new StringBuilder();

            _ = stringBuilder.AppendLine($"PositionId,TradeType,SymbolName,VolumeInUnits,EntryTime,EntryPrice,ClosingTime,ClosingPrice,NetProfit,Balance");

            // All trades are inside the 'History' collection
            foreach (var trade in History)
            {
                _ = stringBuilder.AppendLine($"{trade.PositionId},{trade.TradeType},{trade.SymbolName},{trade.VolumeInUnits},{trade.EntryTime:o},{trade.EntryPrice},{trade.ClosingTime:o},{trade.ClosingPrice},{trade.NetProfit},{trade.Balance}");
            }

            // We will save the CSV file on our desktop
            var desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);

            var filePath = Path.Combine(desktopPath, $"{Account.Number}_History.csv");

            File.WriteAllText(filePath, stringBuilder.ToString());
        }
    }
}

รับข้อมูลเกี่ยวกับดีล

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

โค้ด 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
using System;
using cAlgo.API;

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None)]
    public class DealsExample : Robot
    {
        protected override void OnStart()
        {
            var position = ExecuteMarketOrder(TradeType.Buy, "EURUSD", 10000);

            var deals = position.Position.Deals;

            foreach (var deal in deals)
            {
                Print(deal.ExecutionTime + " " + deal.Status + " " + deal.Id);
            }

            ClosePosition(position.Position, 3000);
            ClosePosition(position.Position, 7000);

            var closing_deals = History.FindByPositionId(position.Position.Id);

            foreach (var closing_deal in closing_deals)
            {
                Print(closing_deal.ClosingDeal.ExecutionTime + " " + closing_deal.ClosingDeal.VolumeInUnits);
            }
        }

        protected override void OnStop()
        {
        }
    }
}
 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
import clr

clr.AddReference("cAlgo.API")

# Import cAlgo API types
from cAlgo.API import *
from cAlgo.API.Internals import *

# Import trading wrapper functions
from robot_wrapper import *

class DealsExample():
    def on_start(self):
        position = api.ExecuteMarketOrder(TradeType.Buy, "EURUSD", 10000)

        deals = position.Position.Deals

        for deal in deals:
            api.Print(f"{deal.ExecutionTime} {deal.Status} {deal.Id}")

        api.ClosePosition(position.Position, 3000)
        api.ClosePosition(position.Position, 7000)

        closing_deals = api.History.FindByPositionId(position.Position.Id)

        for closing_deal in closing_deals:
            api.Print(f"{closing_deal.ClosingDeal.ExecutionTime} {closing_deal.ClosingDeal.VolumeInUnits}")

    def on_stop(self):
        pass

แปลงล็อตเป็นหน่วย

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

คุณสามารถแปลงล็อตเป็นหน่วยโดยใช้เมธอด Symbol.QuantityToVolumeUnits()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
using System;
using cAlgo.API;
using System.Text;
using System.IO;

namespace Samples
{
    [Robot(AccessRights = AccessRights.None)]
    public class Sample : Robot
    {
        protected override void OnStart()
        {
            var lots = 2.5;

            var volumeInUnits = Symbol.QuantityToVolumeInUnits(lots);

            ExecuteMarketOrder(TradeType.Sell, SymbolName, volumeInUnits);
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import clr

clr.AddReference("cAlgo.API")

# Import cAlgo API types
from cAlgo.API import *
from cAlgo.API.Internals import *

# Import trading wrapper functions
from robot_wrapper import *

class Sample():
    def on_start(self):
        lots = 2.5
        volume_in_units = api.Symbol.QuantityToVolumeInUnits(lots)
        api.ExecuteMarketOrder(TradeType.Sell, api.SymbolName, volume_in_units)

หรือคุณสามารถใช้เมธอด Symbol.VolumeInUnitsToQuantity() เพื่อแปลงหน่วยเป็นล็อต

ทำงานกับสี

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

1
2
[Parameter("Color", DefaultValue = "#f54242")]
public Color DrawingColor { get; set; }

หมายเหตุ

คุณสามารถใช้ทั้งรหัสสีแบบเลขฐานสิบหกและชื่อสี (เช่น red") เมื่อกำหนด DefaultValue ของพารามิเตอร์ดังกล่าว"

เพื่อแสดงวิธีการทำงานของพารามิเตอร์สี เราจะสร้าง cBot อย่างง่ายที่เมื่อเริ่มต้น จะเขียนข้อความบนแผนภูมิการเทรดที่กำลังทำงานอยู่ สีของข้อความนี้จะสามารถปรับแต่งได้ผ่านพารามิเตอร์ TextColor

 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
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 SampleColorcBot : Robot
    {
        [Parameter("Text Color", DefaultValue = "red")]
        public Color TextColor { get; set; }

        protected override void OnStart()
        {
            var staticText = Chart.DrawStaticText("static", "Sample text to demonstrate how color works", VerticalAlignment.Center, HorizontalAlignment.Center, TextColor);

        }

    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import clr

clr.AddReference("cAlgo.API")

# Import cAlgo API types
from cAlgo.API import *
from cAlgo.API.Internals import *

# Import trading wrapper functions
from robot_wrapper import *

class SampleColorcBot():
    def on_start(self):
        api.Chart.DrawStaticText(
            "static",
            "Sample text to demonstrate how color works",
            VerticalAlignment.Center,
            HorizontalAlignment.Center,
            api.TextColor
        )