Zum Inhalt

Wie man eine manuelle Handelsstrategie automatisiert

Automatisierter oder algorithmischer Handel bietet mehrere Vorteile gegenüber manuellem Handeln:

  • Automatisierte Systeme eliminieren emotionale Entscheidungsfindung und führen Transaktionen mit erhöhter Präzision, Geschwindigkeit und Effizienz aus.
  • Algorithmen setzen fortgeschrittene Handelsstrategien konsistent um, während Risikomanagementmaßnahmen zuverlässig durchgesetzt werden.
  • Algorithmen ermöglichen das Backtesting von Strategien anhand historischer Daten und die Diversifizierung über mehrere Vermögenswerte und Märkte gleichzeitig.

Die cTrader Algo API ermöglicht es Händlern, komplexe manuelle Strategien zu automatisieren und so die vielen Vorteile des algorithmischen Handels zu nutzen. In diesem Artikel und dem dazugehörigen Video erfahren Sie, wie Sie komplexe manuelle Strategien automatisieren und Abfolgen von Operationen in Algorithmen umwandeln.

Muster der manuellen Strategie identifizieren

Um einen Algorithmus zu entwickeln, nehmen wir an, dass wir das Hammer-Muster für Long-Einstiege und das Hanging-Man-Muster für Short-Einstiege manuell handeln.

Ein Hammer tritt während eines Abwärtstrends auf und deutet auf eine mögliche bullische Umkehr hin. Das Hammer-Muster wird verwendet, um Kauf-Einstiege zu identifizieren.

Ein Hanging Man erscheint während eines Aufwärtstrends und zeigt eine mögliche bärische Umkehr an. Das Hanging-Man-Muster wird verwendet, um Verkaufs-Einstiege zu identifizieren.

Einen cBot entwickeln, um die manuelle Strategie zu handeln

Lassen Sie uns in cTrader Algo einen Algorithmus erstellen, der die im vorherigen Abschnitt beschriebene Strategie umsetzt.

Klicken Sie auf die Schaltfläche Neu unter der Registerkarte cBot. Geben Sie Patterns Strategy in das Namensfeld ein und klicken Sie auf Erstellen.

In der Methode OnBarClosed() implementieren wir die Logik für unsere Strategie. Unsere Einstiege müssen diese beiden Bedingungen erfüllen:

  • Der Schlusskurs entspricht dem Höchstkurs.
  • Die Kerzengröße ist mindestens fünfmal größer als der Kerzenkörper.

Wir beginnen mit der Definition der Parameter Volume, StopLoss und TakeProfit.

1
2
3
4
5
6
7
8
[Parameter(DefaultValue = 1000)]
public double Volume { get; set; }

[Parameter(DefaultValue = 10)]
public double StopLoss { get; set; }

[Parameter(DefaultValue = 10)]
public double TakeProfit { get; set; }

Dann schreiben wir ein Snippet, um eine Kauf-Transaktion auszuführen, wenn die erforderlichen Bedingungen erfüllt sind.

1
2
3
4
5
if (Bars.Last(0).Close == Bars.Last(0).High &&
            (Bars.Last(0).Close - Bars.Last(0).Open) < (Bars.Last(0).Close - Bars.Last(0).Low) * 0.2)
{
    ExecuteMarketOrder(TradeType.Buy, SymbolName, Volume, InstanceId, StopLoss, TakeProfit);
}
1
2
3
bar = api.Bars.Last(0)
if bar.Close == bar.High and (bar.Close - bar.Open) < (bar.Close - bar.Low) * 0.2:
    api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, api.Volume, api.InstanceId, api.StopLoss, api.TakeProfit)

Auf der anderen Seite sind dies die Bedingungen, die für unsere Verkaufs-Einstiege erfüllt sein müssen:

  • Der Schlusskurs entspricht dem Tiefstkurs.
  • Die Kerzengröße ist mindestens fünfmal größer als der Kerzenkörper.

Ebenso schreiben wir ein Snippet, um eine Verkaufs-Transaktion auszuführen, wenn die erforderlichen Bedingungen erfüllt sind.

1
2
3
4
5
if (Bars.Last(0).Close == Bars.Last(0).Low &&
                (Bars.Last(0).Open - Bars.Last(0).Close) < (Bars.Last(0).High - Bars.Last(0).Close) * 0.2)
{
    ExecuteMarketOrder(TradeType.Sell, SymbolName, Volume, InstanceId, StopLoss, TakeProfit);
}
1
2
if bar.Close == bar.Low and (bar.Open - bar.Close) < (bar.High - bar.Close) * 0.2:
    api.ExecuteMarketOrder(TradeType.Sell, api.SymbolName, api.Volume, api.InstanceId, api.StopLoss, api.TakeProfit)

Sie können den vollständigen Code unten kopieren:

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

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None, AddIndicators = true)]
    public class PatternsStrategy : Robot
    {
        [Parameter(DefaultValue = 1000)]
        public double Volume { get; set; }

        [Parameter(DefaultValue = 10)]
        public double StopLoss { get; set; }

        [Parameter(DefaultValue = 10)]
        public double TakeProfit { get; set; }

        protected override void OnStart()
        {

        }

        protected override void OnBarClosed()
        {
            if (Bars.Last(0).Close == Bars.Last(0).High &&
            (Bars.Last(0).Close - Bars.Last(0).Open) < (Bars.Last(0).Close - Bars.Last(0).Low) * 0.2)
            {
                ExecuteMarketOrder(TradeType.Buy, SymbolName, Volume, InstanceId, StopLoss, TakeProfit);
            }

            if (Bars.Last(0).Close == Bars.Last(0).Low &&
            (Bars.Last(0).Open - Bars.Last(0).Close) < (Bars.Last(0).High - Bars.Last(0).Close) * 0.2)
            {
                ExecuteMarketOrder(TradeType.Sell, SymbolName, Volume, InstanceId, StopLoss, TakeProfit);
            }

        }

        protected override void OnStop()
        {

        }
    }
}
 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")
from cAlgo.API import *
from robot_wrapper import *

class PatternsStrategy():
    def on_start(self):
        pass

    def on_bar_closed(self):
        bar = api.Bars.Last(0)

        if bar.Close == bar.High and (bar.Close - bar.Open) < (bar.Close - bar.Low) * 0.2:
            api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, api.Volume, api.InstanceId, api.StopLoss, api.TakeProfit)

        if bar.Close == bar.Low and (bar.Open - bar.Close) < (bar.High - bar.Close) * 0.2:
            api.ExecuteMarketOrder(TradeType.Sell, api.SymbolName, api.Volume, api.InstanceId, api.StopLoss, api.TakeProfit)

    def on_stop(self):
        pass

Um den cBot zu erstellen, drücken Sie Ctrl+B oder klicken Sie auf Build.

Um den cBot zu testen, fügen wir zunächst eine Instanz hinzu. Wählen Sie die Option Lokal, geben Sie Ihre bevorzugten Parameter an und klicken Sie auf die Schaltfläche Instanz hinzufügen.

Wir navigieren dann zur Registerkarte Backtesting, geben einen Zeitraum für den Backtesting-Vorgang an und starten das Backtesting.

Sobald der Backtesting-Prozess abgeschlossen ist, können wir die Transaktionen überprüfen. Sie werden sehen, dass die Einstiegsbedingungen kurz vor jeder Transaktion erfüllt sind.

Mit der erfolgreichen Automatisierung unserer Strategie können wir den cBot einsetzen, um in unserem Namen Transaktionen durchzuführen.

Die RSI-Umkehrstrategie implementieren

In unserem zweiten Beispiel möchten wir eine Strategie implementieren, die auf der Umkehr des Relative Strength Index (RSI)-Indikators basiert. In dieser Strategie eröffnen wir Positionen in der Erwartung, dass der RSI seine Richtung umkehrt, und befolgen diese Regeln:

  • Wenn der RSI-Wert unter den RSI-Kaufschwellenwert fällt, eröffnen wir eine Kaufposition.
  • Wenn der RSI-Wert über den RSI-Verkaufsschwellenwert steigt, eröffnen wir eine Verkaufsposition.

Lassen Sie uns einen neuen cBot erstellen, RSI Reversal Strategy als Namen eingeben und auf Erstellen klicken.

Sobald der Code-Editor erscheint, fügen Sie System.Linq oben im Code als Referenz hinzu.

1
using System.Linq;

Fügen wir zwei Parameter hinzu, die es uns ermöglichen, die Schwellenwerte zu ändern, bevor wir den cBot ausführen.

1
2
3
4
5
[Parameter(DefaultValue = 30)]
public int BuyLevel { get; set; }

[Parameter(DefaultValue = 70)]
public int SellLevel { get; set; }

Wir deklarieren und initialisieren unseren Relative-Strength-Indikator.

1
2
3
4
5
6
private RelativeStrengthIndex _rsi;

protected override void OnStart()
{
    _rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, 14);
}
1
2
3
class RSIReversalStrategy():
    def on_start(self):
        self._rsi = api.Indicators.RelativeStrengthIndex(api.Bars.ClosePrices, 14)

Wir implementieren dann die Bedingungen, die unsere Handelslogik definieren.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
protected override void OnBarClosed()
{

    if (_rsi.Result.LastValue < BuyLevel)
    {
        if (Positions.Count == 0)
            ExecuteMarketOrder(TradeType.Buy, SymbolName, 1000);
        foreach (var position in Positions.Where(p => p.TradeType == TradeType.Sell))
        {
            position.Close();
        }

    }
    else if (_rsi.Result.LastValue > SellLevel)
    {
        if (Positions.Count == 0)
            ExecuteMarketOrder(TradeType.Sell, SymbolName, 1000);
        foreach (var position in Positions.Where(p => p.TradeType == TradeType.Buy))
        {
            position.Close();
        }
    }

}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
def on_bar_closed(self):
    rsi_value = self._rsi.Result.LastValue

    if rsi_value < api.BuyLevel:
        if api.Positions.Count == 0:
            api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, 1000)
        for position in api.Positions:
            if position.TradeType == TradeType.Sell:
                position.Close()

    elif rsi_value > api.SellLevel:
        if api.Positions.Count == 0:
            api.ExecuteMarketOrder(TradeType.Sell, api.SymbolName, 1000)
        for position in api.Positions:
            if position.TradeType == TradeType.Buy:
                position.Close()

Sie können den vollständigen Code unten kopieren:

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

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None, AddIndicators = true)]
    public class RSIReversalStrategy : Robot
    {
        [Parameter(DefaultValue = 30)]
        public int BuyLevel { get; set; }

        [Parameter(DefaultValue = 70)]
        public int SellLevel { get; set; }

        private RelativeStrengthIndex _rsi;

        protected override void OnStart()
        {
            _rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, 14);
        }

        protected override void OnBarClosed()
        {

            if (_rsi.Result.LastValue < BuyLevel)
            {
                if (Positions.Count == 0)
                    ExecuteMarketOrder(TradeType.Buy, SymbolName, 1000);
                foreach (var position in Positions.Where(p => p.TradeType == TradeType.Sell))
                {
                    position.Close();
                }

            }
            else if (_rsi.Result.LastValue > SellLevel)
            {
                if (Positions.Count == 0)
                    ExecuteMarketOrder(TradeType.Sell, SymbolName, 1000);
                foreach (var position in Positions.Where(p => p.TradeType == TradeType.Buy))
                {
                    position.Close();
                }
            }

        }

        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
import clr
clr.AddReference("cAlgo.API")
from cAlgo.API import *
from robot_wrapper import *

class RSIReversalStrategy():
    def on_start(self):
        self._rsi = api.Indicators.RelativeStrengthIndex(api.Bars.ClosePrices, 14)

    def on_bar_closed(self):
        rsi_value = self._rsi.Result.LastValue

        if rsi_value < api.BuyLevel:
            if api.Positions.Count == 0:
                api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, 1000)
            for position in api.Positions:
                if position.TradeType == TradeType.Sell:
                    position.Close()

        elif rsi_value > api.SellLevel:
            if api.Positions.Count == 0:
                api.ExecuteMarketOrder(TradeType.Sell, api.SymbolName, 1000)
            for position in api.Positions:
                if position.TradeType == TradeType.Buy:
                    position.Close()

    def on_stop(self):
        pass

Lassen Sie uns unsere Strategie erstellen, eine Instanz hinzufügen und sie testen, wie wir es mit der vorherigen Strategie getan haben.

Wir können einige Transaktionen erneut überprüfen und prüfen, um zu sehen, dass die Einstiegsbedingungen kurz vor einer Transaktion erfüllt sind.

Dieser Artikel hat gezeigt, wie man eine manuelle Strategie identifiziert und in eine automatisierte umwandelt, um Algo-Trading-Operationen zu ermöglichen.

Image title