Bỏ qua

Lập mã cho chiến lược đa khung thời gian

Thường xuyên, các chiến lược tự động cần xem xét thông tin từ các khung thời gian khác nhau trước khi đưa ra quyết định giao dịch. May mắn thay, cTrader cung cấp nhiều công cụ cho phép các thuật toán dễ dàng truy cập dữ liệu từ nhiều khung thời gian. Trong video này và bài viết tương ứng, chúng tôi sẽ giải thích cách bạn có thể sử dụng các công cụ này để tạo ra một cBot hiệu quả.

Khai báo tham số cBot

Chúng ta sẽ bắt đầu bằng cách khai báo các tham số cần thiết cho một đường trung bình di động. Chúng ta sẽ cần chu kỳ, khung thời gian và loại trung bình di động.

1
2
3
4
5
6
7
8
[Parameter("MA 1 Period", DefaultValue = 14, Group = "Moving Averages")]
        public int MA1Period { get; set; }

[Parameter("MA 1 Timeframe", DefaultValue = "Hour", Group = "Moving Averages")]
public TimeFrame MA1Timeframe { get; set; }

[Parameter("MA 1 Type", Group = "Moving Averages")]
public MovingAverageType MA1Type { get; set; }

Sau đó, chúng ta có thể định nghĩa đường trung bình di động.

1
private MovingAverage _ma1;

Chúng ta có thể khởi tạo đường trung bình di động trong phương thức OnStart(). Chúng ta sẽ sử dụng phương thức MarketData.GetBars() để lấy các nến của đường trung bình di động đầu tiên và truyền chúng vào hàm tạo chỉ báo. Phương thức GetBars() hữu ích để lấy dữ liệu nến cho bất kỳ khung thời gian và ký hiệu nào bạn cần.

1
_ma1 = Indicators.MovingAverage(MarketData.GetBars(MA1Timeframe).ClosePrices, MA1Period, MA1Type);

Chúng ta sẽ lặp lại quá trình này cho hai đường trung bình di động còn lại. Bạn có thể đơn giản sao chép và dán mã dưới đây để tiếp tục.

 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
Parameter("MA 1 Period", DefaultValue = 14, Group = "Moving Averages")]
public int MA1Period { get; set; }

[Parameter("MA 1 Timeframe", DefaultValue = "Hour", Group = "Moving Averages")]
public TimeFrame MA1Timeframe { get; set; }

[Parameter("MA 1 Type", Group = "Moving Averages")]
public MovingAverageType MA1Type { get; set; }

[Parameter("MA 2 Period", DefaultValue = 14, Group = "Moving Averages")]
public int MA2Period { get; set; }

[Parameter("MA 2 Timeframe", DefaultValue = "Hour2", Group = "Moving Averages")]
public TimeFrame MA2Timeframe { get; set; }

[Parameter("MA 2 Type", Group = "Moving Averages")]
public MovingAverageType MA2Type { get; set; }

[Parameter("MA 3 Period", DefaultValue = 14, Group = "Moving Averages")]
public int MA3Period { get; set; }

[Parameter("MA 3 Timeframe", DefaultValue = "Hour4", Group = "Moving Averages")]
public TimeFrame MA3Timeframe { get; set; }

[Parameter("MA 3 Type", Group = "Moving Averages")]
public MovingAverageType MA3Type { get; set; }

private MovingAverage _ma1;
private MovingAverage _ma2;
private MovingAverage _ma3;

protected override void OnStart()
{
    _ma1 = Indicators.MovingAverage(MarketData.GetBars(MA1Timeframe).ClosePrices, MA1Period, MA1Type);
    _ma2 = Indicators.MovingAverage(MarketData.GetBars(MA2Timeframe).ClosePrices, MA2Period, MA2Type);
    _ma3 = Indicators.MovingAverage(MarketData.GetBars(MA3Timeframe).ClosePrices, MA3Period, MA3Type);
}

Triển khai logic giao dịch

Tại thời điểm này, chúng ta có thể triển khai logic giao dịch. Chiến lược của chúng ta sẽ giữ vị thế mua khi tất cả các đường trung bình di động đang tăng và vị thế bán khi các đường trung bình di động đang giảm. Đây là mã cho tất cả logic phía mua.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
if (_ma1.Result.IsRising() && _ma2.Result.IsRising() && _ma3.Result.IsRising())
{
    if (Positions.Count(p => p.SymbolName == SymbolName && p.TradeType == TradeType.Buy) == 0)
        ExecuteMarketOrder(TradeType.Buy, SymbolName, 100000);
}
else
{
    foreach (var position in Positions.Where(p => p.SymbolName == SymbolName && p.TradeType == TradeType.Buy))
    {
        position.Close();
    }
}

Và đây là mã cho logic phía bán.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
if (_ma1.Result.IsFalling() && _ma2.Result.IsFalling() && _ma3.Result.IsFalling())
{
    if (Positions.Count(p => p.SymbolName == SymbolName && p.TradeType == TradeType.Sell) == 0)
        ExecuteMarketOrder(TradeType.Sell, SymbolName, 100000);
}
else
{
    foreach (var position in Positions.Where(p => p.SymbolName == SymbolName && p.TradeType == TradeType.Sell))
    {
        position.Close();
    }
}

Backtest chiến lược đa khung thời gian

Cuối cùng, chúng ta nên backtest cBot mới của mình. Chúng ta có thể thấy rằng cBot mở vị thế khi các đường trung bình di động được đồng bộ hóa theo cùng một hướng và tránh thị trường khi mỗi chỉ báo chỉ ra một hướng khác nhau.