Zum Inhalt

Wie man Methoden zur cTrader-API hinzufügt

Erweiterungsmethoden sind ein wichtiges Werkzeug, wenn Sie der cTrader-API neue Funktionalität hinzufügen möchten. Mit einer relativ einfachen Syntax können Sie jeder vordefinierten API-Klasse, wie Symbol oder Position, neue Verhaltensweisen hinzufügen. Nachdem Sie eine Erweiterungsmethode definiert haben, können Sie sie von jedem Objekt der Klasse aufrufen, die Sie erweitert haben.

Anwendungsfall für Erweiterungsmethoden

Zunächst führen wir eine kurze Demonstration durch, warum Sie Erweiterungsmethoden verwenden möchten.

Mit einem cBot möchten wir in der Lage sein, auf die Größe einer bestimmten Position in Lots zuzugreifen, da diese Information unsere bevorzugte Handelsstrategie direkt beeinflusst. Dazu können wir versuchen, eine Variable der Position-Klasse zu initialisieren und dann versuchen, auf ihre Lots()-Methode zuzugreifen.

1
2
Position position = Positions.Last();
Print(position.Lots());

Wenn wir den Code einfach so eingeben, erhalten wir einen Fehler, der darauf hinweist, dass der Lots()-Accessor in der API nicht existiert. Aber was wäre, wenn es eine Möglichkeit gäbe, einem bestehenden API-Mitglied eine neue Methode hinzuzufügen, ohne andere Funktionalitäten zu beeinträchtigen?

Angenommen, diese Methode existierte, hätten wir einen einfachen cBot erstellen können, der bei jedem Balken über eine Liste aller aktuellen Positionen iteriert und ihre Größe in Lots im Protokoll ausgibt. Wir würden die OnBar()-Methode wie folgt definieren.

1
2
3
4
5
6
protected override void OnBar()
{
    foreach (var position in Positions) {
        Print(position.Lots());
    }
}

Erweiterungsmethoden ermöglichen es uns, die Lots()-Funktionalität in nur wenigen Codezeilen hinzuzufügen und sie dann jederzeit auf jedem Objekt der Position-Klasse wiederzuverwenden. Im Folgenden erklären wir, wie Sie eine erstellen können, und geben mehrere Beispiele für Algos, die sie verwenden.

Wie Erweiterungsmethoden funktionieren

Beachten Sie beim Arbeiten mit Erweiterungsmethoden die folgenden Regeln.

  • Erweiterungsmethoden sind immer statisch.

Um eine statische Methode zu deklarieren, müssen Sie lediglich das static-Schlüsselwort verwenden. Deklarieren Sie unten die Lots()-Methode mit einem leeren Körper.

1
2
3
4
public static class MyExtensions {
    public static double Lots() {}

}
  • Erweiterungsmethoden können eine beliebige Anzahl von Argumenten haben, aber das erste Argument muss immer den Datentyp/die Klasse bezeichnen, für die die Methode aufgerufen werden soll, dem das Schlüsselwort this vorangestellt ist.

Wir fügen ein Objekt der Position-Klasse als erstes und einziges Argument der Lots()-Methode hinzu. Da ein Position-Objekt auch Informationen über das Symbol enthält, für das die Position eröffnet wurde, benötigen wir keine weiteren Argumente.

1
2
3
public static class MyExtensions {
    public static double Lots(this Position position) {}
}
  • Erweiterungsmethoden können jede Logik enthalten, die für die bereitgestellten Argumente geeignet ist.

Es ist nicht erforderlich, beim Definieren des Körpers einer Erweiterungsmethode eine spezielle Syntax zu verwenden. Wir können sie wie jede andere Methode behandeln und daher ihren Körper wie folgt definieren.

1
2
3
4
5
public static class MyExtensions {
    public static double Lots(this Position position) {
        return position.VolumeInUnits / position.Symbol.LotSize;
    }
}
  • Erweiterungsmethoden können als Instanzmethoden oder statische Methoden aufgerufen werden.

Es gibt zwei mögliche Wege, unsere Erweiterungsmethode im Code eines cBots aufzurufen.

Bei Verwendung der Instanzmethoden-Syntax rufen wir die Methode von jedem geeigneten Objekt des Position-Typs auf.

1
2
var position = Positions.Last();
Print(position.Lots());

Bei Verwendung der statischen Methoden-Syntax können wir unsere Erweiterungsmethode aufrufen, nachdem wir ihre entsprechende statische Klasse vollständig angegeben haben.

1
2
var position = Positions.Last();
Print(MyExtensions.Lots(position));

Es liegt an Ihnen zu bestimmen, welche Methode zum Aufrufen von Erweiterungsmethoden am bequemsten ist.

Methodensignaturen

Vermeiden Sie bei Verwendung der Instanz-Syntax Fälle, in denen Ihre Erweiterungsmethoden dieselben Signaturen wie eine der integrierten API-Methoden haben (wie Position.Close()). In diesen Situationen wird jedes Mal eine integrierte Methode aufgerufen, wenn Sie versuchen, eine Erweiterungsmethode mit der übereinstimmenden Signatur aufzurufen.

IntelliSense

Wenn wir versuchen, eine Erweiterungsmethode aufzurufen, verwendet IntelliSense ein spezielles Symbol, um sie von integrierten API-Mitgliedern zu unterscheiden.

Um unsere neue Methode in Aktion zu demonstrieren, können wir einen cBot erstellen, der beim Start drei Orders platziert, jede mit einem anderen Volumen. Bei jedem Balken gibt der cBot das Volumen aller aktuell offenen Positionen in Lots aus.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
protected override void OnStart()
{
    ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000);
    ExecuteMarketOrder(TradeType.Buy, SymbolName, 100000);
    ExecuteMarketOrder(TradeType.Buy, SymbolName, 50000);
}

protected override void OnBar()
{
    foreach (var position in Positions) {
        Print(position.Lots());
    }
}

Nach dem Erstellen und Starten unseres cBots sollten wir sehen, dass die korrekten Werte im Protokoll ausgegeben werden.

Erweiterungsmethoden in cBots verwenden

Wir werden nun versuchen, einen komplexeren cBot zu erstellen. Bei jedem Balken geht unser Algo die Liste der aktuell offenen Positionen durch und passt ihre Stop-Loss-Niveaus so an, dass sie auf Break-Even liegen. Dazu müssen wir eine BreakEven()-Erweiterungsmethode für die Position-Klasse erstellen.

Wir erstellen einen neuen cBot und benennen ihn um. Anschließend löschen wir den gesamten Code, den wir nicht benötigen, und fügen die MyExtensions-Klasse hinzu.

1
2
3
public static class MyExtensions {

}

Unser Code für die BreakEven()-Methode ist relativ einfach. Wir prüfen, ob eine Position einen Stop-Loss hat, ob ihr Bruttogewinn größer als null ist und ob der aktuell gesetzte Stop-Loss nicht gleich dem Positionseinstiegskurs ist. Wenn alle diese Bedingungen erfüllt sind, ändern wir den Stop-Loss der Position so, dass er dem Positionseinstiegskurs entspricht.

1
2
3
4
5
6
7
public static class MyExtensions {
    public static void BreakEven(this Position position) {
        if (position.StopLoss is not null && position.GrossProfit > 0 && position.StopLoss != position.EntryPrice) {
            position.ModifyStopLossPrice(position.EntryPrice);
        }
    }
}

Im cBot selbst müssen wir keine andere Methode als OnBar() verwenden. Bei jedem Balken bitten wir den cBot, eine einfache Operation durchzuführen, nämlich über die Positions-Sammlung zu iterieren und die neue BreakEven()-Methode für jedes Element darin aufzurufen.

1
2
3
4
5
6
protected override void OnBar() 
{
    foreach (var position in Positions) {
        position.BreakEven();
    }
}

Nachdem wir unseren cBot erstellt und gestartet haben, können wir ihn in Aktion sehen. Er kann ein nützlicher Handelsassistent sein, insbesondere bei der Verwaltung vieler offener Positionen.

Erweiterungsmethoden in Indikatoren verwenden

Wir werden auch einen nützlichen Indikator erstellen, der auf Erweiterungsmethoden basiert. Der Indikator misst die Volatilität, indem er den Prozentsatz darstellt, um den sich der Kurs eines Symbols auf jedem Balken im Vergleich zum Eröffnungskurs dieses Balkens verändert hat.

Dazu erstellen wir einen neuen Indikator und benennen ihn um. Im Code-Editor-Fenster erstellen wir die Klasse MyExtensions, um die Klasse Bar zu erweitern.

1
2
3
public static class MyExtensions {

}

Wir fügen auch die Methode PercentageChange() hinzu. In der Variablen priceChange subtrahieren wir den Schlusskurs eines Balkens von seinem Eröffnungskurs. Die Methode gibt unsere Kursänderung geteilt durch den Eröffnungskurs und multipliziert mit 100 zurück.

1
2
3
4
5
6
7
8
public static class MyExtensions 
{
    public static double PercentageChange(this Bar bar) 
    {
        var priceChange = bar.Open - bar.Close;
        return priceChange / bar.Open * 100;
    }
}

Im Indikatorcode selbst benötigen wir die Methode Initialize() und unnötige Parameter nicht. Im Hauptteil der Methode Calculate() rufen wir einfach unsere neue Methode PercentageChange() auf jedem Balken auf.

1
2
3
4
5
6
7
8
[Output("Main")]
public IndicatorDataSeries Result { get; set; }


public override void Calculate(int index)
{
    Result[index] = Bars[index].PercentageChange();
}

Anschließend speichern und erstellen wir unseren Indikator. Nach dem Erstellen einer Instanz sollten wir sehen, dass die korrekten prozentualen Änderungen dargestellt werden. Sie können verwendet werden, um die kurz- und langfristige Volatilität zu bestimmen, was allen Arten von Handelsstrategien zugutekommt.

Zusammenfassung

Zusammenfassend lässt sich sagen, dass Erweiterungsmethoden ein wertvolles Werkzeug sind, wenn Sie wiederverwendbaren Code erstellen möchten, der der cTrader API neue Funktionalitäten hinzufügt. Wir empfehlen dringend, mit Erweiterungsmethoden zu experimentieren, da sie Ihre Algos effizienter und einfacher zu warten machen können.