Zum Inhalt

Multi-Timeframe-Strategien programmieren

Häufig müssen automatisierte Strategien Informationen aus verschiedenen Zeitrahmen berücksichtigen, bevor sie eine Handelsentscheidung treffen. Glücklicherweise bietet cTrader viele Tools, die es Algos ermöglichen, einfach auf Daten aus mehreren Zeitrahmen zuzugreifen. In diesem Video und dem dazugehörigen Artikel erklären wir, wie Sie diese Tools verwenden können, um einen effektiven cBot zu erstellen.

cBot-Parameter deklarieren

Wir beginnen mit der Deklaration der notwendigen Parameter für einen Moving Average. Wir benötigen die Periode, den Zeitrahmen und den Moving-Average-Typ.

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; }

Dann können wir den Moving Average definieren.

1
private MovingAverage _ma1;

Wir können den Moving Average in der Methode OnStart() initialisieren. Wir verwenden die Methode MarketData.GetBars(), um die Balken des ersten Moving Average zu erhalten und sie an den Indikator-Konstruktor zu übergeben. Die Methode GetBars() ist nützlich, um Balkendaten für jeden benötigten Zeitrahmen und jedes Symbol zu erhalten.

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

Wir wiederholen den Vorgang für die anderen beiden Moving Averages. Sie können den folgenden Code einfach kopieren und einfügen, um fortzufahren.

 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);
}

Handelslogik implementieren

An diesem Punkt können wir die Handelslogik implementieren. Unsere Strategie hält eine Kauf-Position, wenn alle Moving Averages steigen, und eine Verkauf-Position, wenn die Moving Averages fallen. Hier ist der Code für die gesamte Kauf-Logik.

 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();
    }
}

Und hier ist der Code für die Verkauf-Logik.

 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();
    }
}

Multi-Timeframe-Strategie backtesten

Abschließend sollten wir unseren neuen cBot backtesten. Wir können sehen, dass der cBot Positionen eingeht, wenn die Moving Averages in dieselbe Richtung synchronisiert sind, und außerhalb des Marktes bleibt, wenn jeder Indikator in eine andere Richtung zeigt.