Bỏ qua

Tạo chỉ báo kỹ thuật trong cTrader

Bài viết này phác thảo các bước để tạo các chỉ báo kỹ thuật tùy chỉnh, bao gồm các công cụ cho giao dịch thuật toán hoặc thao tác thủ công trong cTrader.

Trong tab Chỉ báo của ứng dụng Algo, nhấp vào nút Mới để mở trình hướng dẫn tạo thuật toán.

Nhập tên cho chỉ báo của bạn, sau đó chọn ngôn ngữ lập trình giữa C#Python.

Chọn một phương thức tạo từ:

  • Từ đầu – chỉ báo mới sẽ chỉ chứa một mẫu cơ bản.

  • Sử dụng mẫu – bạn sẽ có thể chọn một thuật toán có sẵn từ danh sách các mẫu Python# hoặc C#, bao gồm nhiều loại chỉ báo, công cụ phân tích kỹ thuật và hơn thế nữa.

Ghi chú

Các thuật toán có sẵn đã chứa logic cho các phép tính và tham số có thể tùy chỉnh. Các chỉ báo như vậy đã sẵn sàng để hiển thị trên biểu đồ sau khi bạn lưu và xây dựng chúng.

Sau khi bạn nhấp vào Tạo, trình soạn thảo mã sẽ mở ra và bạn có thể bắt đầu chỉnh sửa mã chỉ báo.

Chỉnh sửa mã

Tùy thuộc vào phương thức tạo của bạn, mẫu mã chỉ báo nên chứa một hoặc nhiều thành phần sau:

 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
[Indicator(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class SimpleIndicator : Indicator
{
    [Parameter(DefaultValue = "Hello world!")]
    public string Message { get; set; }

    [Output("Main")]
    public IndicatorDataSeries Result { get; set; }

    protected override void Initialize()
    {
    // Called once when the indicator is launched
    // Initialise variables, nested indicators or series

        Print(Message);
    }

    public override void Calculate(int index)
    {
    // Called automatically on each historical bar
    // Also called in real-time on each tick
    // Place the indicator formula and logic here
    }

    // === Custom Methods ===
    // Add helper methods below to structure your indicator logic

}

Thuộc tính Indicator, cùng với các thuộc tính tùy chọn của nó như TimeZoneAccessRights, đứng trước khai báo lớp chỉ báo (SimpleIndicator).

Các phương thức này được bao gồm trong mọi chỉ báo theo mặc định:

  • Phương thức Initialize() được gọi một lần khi chỉ báo của bạn bắt đầu. Nó thường được sử dụng để thiết lập các biến, chỉ báo lồng nhau và chuỗi cần sẵn sàng ngay từ đầu.
  • Phương thức Calculate() được gọi tự động trên mỗi nến lịch sử và trong thời gian thực trên mỗi tick mới. Đây là nơi bạn triển khai công thức của chỉ báo và xác định cách tính toán và hiển thị kết quả.

Thuộc tính [Output()] chỉ định các giá trị mà chỉ báo của bạn tạo ra và cách chúng xuất hiện trên biểu đồ. Bạn có thể tùy chỉnh tên và kiểu của mỗi đầu ra, ví dụ bằng cách đặt màu đường của nó.

Các phương thức Initialize()Calculate() tạo nên nền tảng của mọi chỉ báo tùy chỉnh và không bao giờ nên bị bỏ qua. Bạn có thể thêm các phương thức riêng của mình để mở rộng chức năng, giống như khi bạn lập trình một cBot. Để tìm hiểu thêm về thuật toán, hãy bắt đầu với hướng dẫn C# cơ bản và khám phá các ví dụ về mã chỉ báo.

Ghi chú

Tài liệu tham khảo bao gồm tất cả các lớp, sự kiện, phương thức, biến, v.v. để xây dựng thuật toán trong cTrader, trong khi các ví dụ và mẫu thuật toán đầy đủ có sẵn trong kho lưu trữ GitHub.

Áp dụng kiến thức mới của bạn để chỉnh sửa mã chỉ báo và điều chỉnh nó theo nhu cầu của bạn.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class SimpleIndicator:
    def initialize(self):
        # Called once when the indicator is launched
        # Initialise variables, nested indicators or series
        api.Print(api.Message)

    def calculate(self, index):
        # Called automatically on each historical bar
        # Also called in real-time on each tick
        # Place the indicator formula and logic here
        api.Result[index] = 100 # Example calculation

    # === Custom Methods ===
    # Add helper methods below to structure your indicator logic

Lớp SimpleIndicator định nghĩa một chỉ báo tùy chỉnh trong Python.

Các phương thức này được bao gồm trong mọi chỉ báo theo mặc định:

  • Phương thức initialize(self) được gọi một lần khi chỉ báo của bạn bắt đầu. Nó thường được sử dụng để khởi tạo các biến, chỉ báo lồng nhau và chuỗi cần sẵn sàng ngay từ đầu.
  • Phương thức calculate(self, index) được gọi tự động trên mỗi nến lịch sử và trong thời gian thực trên mỗi tick mới. Đây là nơi bạn triển khai công thức của chỉ báo và xác định cách tính toán và hiển thị kết quả.

Các phương thức initialize(self)calculate(self, index) tạo nên nền tảng của mọi chỉ báo tùy chỉnh và không bao giờ nên bị bỏ qua. Bạn cũng có thể thêm các phương thức trợ giúp riêng của mình bên trong lớp để mở rộng chức năng, giống như khi bạn lập trình một cBot. Để tìm hiểu thêm về thuật toán, hãy bắt đầu với Python cơ bản và khám phá các ví dụ về mã chỉ báo.

Áp dụng kiến thức mới của bạn để chỉnh sửa mã chỉ báo và điều chỉnh nó theo nhu cầu của bạn.

Lưu và biên dịch

Lưu mã của bạn bằng cách nhấp vào nút Lưu ở đầu trình soạn thảo mã hoặc sử dụng phím tắt Ctrl+S.

Trước khi bạn có thể sử dụng chỉ báo của mình, bạn cần xác thực mã của nó bằng cách xây dựng dự án chỉ báo. Nhấp vào nút Biên dịch ở đầu trình soạn thảo mã hoặc nhấn Ctrl+B.

Lưu mã của bạn bằng cách nhấp vào biểu tượng Lưu ở đầu trình soạn thảo mã hoặc sử dụng phím tắt Cmd+S.

Trước khi bạn có thể sử dụng chỉ báo của mình, bạn cần xác thực mã của nó bằng cách xây dựng dự án chỉ báo. Nhấp vào biểu tượng Biên dịch ở đầu trình soạn thảo mã hoặc nhấn Cmd+B.

Khi việc xây dựng thành công, bạn sẽ thấy một thông báo xác nhận trong Kết quả xây dựng. Nếu quá trình biên dịch thất bại, một bản tóm tắt tất cả các lỗi gặp phải sẽ xuất hiện thay vào đó.

Nếu có thay đổi trong mã kể từ lần biên dịch cuối cùng, một dấu sao sẽ xuất hiện bên cạnh biểu tượng Biên dịch. Trong trường hợp này, bạn nên xây dựng lại chỉ báo trước khi thêm một phiên bản của nó vào bất kỳ biểu đồ nào.

Để sử dụng hoặc hiển thị chỉ báo trên biểu đồ, thêm một phiên bản của nó, hoặc bạn có thể tiếp tục sửa đổi mã chỉ báo như đã giải thích trong các phần.

Sử dụng phép tính NaN

Các chỉ báo thực hiện các phép tính để tạo ra các hình ảnh cụ thể, và điều quan trọng là mã của bạn phải xử lý đúng các trường hợp biên và điều kiện giới hạn trong quá trình tính toán này.

Hãy xem xét đoạn mã sau từ một chỉ báo tạo ra một dao động giá phi xu hướng:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private MovingAverage movingAverage;

protected override void Initialize()
{
    movingAverage = Indicators.SimpleMovingAverage(Source, Periods);
}

public override void Calculate(int index)
{
    Result[index] = Source[index] - movingAverage.Result[index - Periods / 2 - 1];
}

Đoạn mã trên định nghĩa các quy tắc tính toán chung nhưng bỏ qua các điều kiện giới hạn. Ví dụ, nếu Periods được đặt thành 10index nằm trong khoảng 0–9, phép tính sẽ trả về NaN (Not a Number). Vấn đề này xảy ra vì chỉ báo không thể tính toán giá trị cho một biểu đồ nến với chỉ số âm.

Để giải quyết vấn đề, bạn có thể thêm một điều kiện như sau:

1
2
3
4
5
6
7
public override void Calculate(int index)
{
    if (index >= Periods + Periods / 2 + 1)
    {
        Result[index] = Source[index] - movingAverage.Result[index - Periods / 2 - 1];
    }
}

Mã cho trung bình động đơn giản cũng phải kiểm tra rằng index >= Periods. Nếu bạn sử dụng một chỉ báo lồng nhau, chẳng hạn như một loại trung bình động khác, điều kiện sẽ khác để tính đến các phép tính bổ sung.

Mặc dù bạn có thể định nghĩa các điều kiện giới hạn rõ ràng, C# cung cấp một cách thuận tiện để tránh những vấn đề này thông qua phép tính NaN. Cụ thể, kiểu dữ liệu double hỗ trợ đầy đủ các phép tính NaN. Ví dụ:

1
2
3
4
5
double result = double.NaN + 1.4; 
// result will be NaN

bool isNaN = double.IsNaN(result); 
// isNaN will be true

Tuy nhiên, khi bất kỳ toán hạng nào trong một phép tính là NaN, kết quả cũng sẽ là NaN. Vì các chỉ báo tùy chỉnh cTrader hoạt động trên kiểu DataSeries, nếu bạn cố gắng truy cập một phần tử DataSeries với chỉ số âm, nó sẽ trả về NaN, và giá trị sẽ không được vẽ trên biểu đồ giao dịch. Hành vi này cho phép chỉ báo tiếp tục hoạt động mà không gây ra ngoại lệ. Trong hầu hết các trường hợp, bạn có thể an toàn bỏ qua các điều kiện giới hạn và chỉ tập trung vào logic tính toán chung.

Thêm kiểm tra rõ ràng

Mặc dù phép tính NaN đơn giản hóa việc xử lý các điều kiện giới hạn, một số trường hợp vẫn yêu cầu kiểm tra NaN rõ ràng. Các chỉ báo đệ quy là một ví dụ phổ biến. Một chỉ báo đệ quy tính toán giá trị hiện tại của nó dựa trên giá trị đã tính toán trước đó.

Hãy xem xét việc triển khai sau đây của một trung bình động hàm mũ:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public override void Calculate(int index)
{
    var previousValue = Result[index - 1];

    if (double.IsNaN(previousValue))
    {
        Result[index] = Source[index];
    }
    else
    {
        Result[index] = Source[index] * _exp + previousValue * (1 - _exp);
    }
}

Khi chỉ báo tính toán chu kỳ đầu tiên, giá trị ban đầu phải được đặt rõ ràng thành một kiểu không phải NaN. Nếu không, tất cả các phép tính tiếp theo sẽ trả về NaN, khiến chỉ báo trở nên vô dụng.

Trong đoạn mã trên, điều này được xử lý bằng phương thức double.IsNaN(previousValue). Toán tử == không thể được sử dụng cho việc kiểm tra này (previousValue == double.NaN) vì bất kỳ phép so sánh nào của NaN với một giá trị khác, kể cả chính nó, luôn đánh giá là false.

Khi bạn hài lòng với mã chỉ báo, hãy xây dựng nó, sau đó sử dụng nó bằng cách thêm một phiên bản vào biểu đồ.

Image title