Samstag, 20. Februar 2010

NinjaTrader spezifische Order-Handling-Methoden

In diesem Artikel dieser Serie möchte ich gerne auf Methoden von NinjaTrader eingehen, die Event-Gesteuert von der NT-API beim Abarbeiten einer Order aufgerufen werden. Konkret handelt es sich dabei um die Methoden ...
  • OnExecution (IExecution execution)
  • OnPositionUpdate (IPosition position)
  • OnOrderUpdate (IOrder order)
Die Methoden Initialize() sowie OnBarUpdate() werde ich nicht näher erläutern. Diese sollten zur Standardausrüstung einer jeden Strategie gehören. Interessant an dieser Stelle ist vielleicht, dass ich meine Entries und Exits in eigenen Methoden ausgelagert habe, um den Code lesbarer und pflegbarer zu gestalten. Beiden Methoden werden entsprechend der Bedingungen, ob ein Signal vorliegt oder bereits ein Trade eingegangen wurde aus OnBarUpdate() heraus aufgerufen.

Aber zurück zu den Event-Methoden, die ich in jeder Strategie überschrieben habe, um die eigenen Bedürfnisse meiner Strategien besser umsetzen zu können. Ich werde wieder den entscheidenden Code posten und bei Bedarf noch weitere Erklärungen hinzufügen:















OnExecution
ist die zentrale Methode, wenn ich Stops oder Limits setzen möchte. Erst hier kann ich 100%ig sicher sein, dass die Order ausgeführt wurde. Wie groß die Position ist, kann ich über execution.Order.Filled herausfinden, denn auch ein Partial-Fill wird hier mit behandelt. Entsprechend muss ich das im Order-Objekt prüfen. Da ich mir zu jeder Order ein entsprechendes Order-Objekt im Code halte, sind diese Prüfungen recht trivial gehalten. Im NinjTrader Helpguide oder im Forum gibt es weitere Beispiele hierzu.












Nach jedem Positionswechsel können hier Variablen zurückgesetzt oder entsprechend initialisiert werden. So kann hier bspw. auch recht einfach ein Wechsel der Entries erfolgen. Möchte ich nach einem Long-Signal nur noch Short handeln, kann ich hier im Long-Fall eine bool'sche Variable mit true belegen und die entsprechende Short-Variable mit false. Der umgekehrte Fall gilt analog. Als kleines 'Schmankerl', lasse ich mir hier die aktuelle Position noch im Chart als Textstring mit ausgeben.



























Dieser, vielleicht interessantesten und wahrscheinlich auch wichtigsten Methode ist sehr viel Beachtung zu schenken. Ich muss gestehen, anfangs habe ich sie schlicht ignoriert, bis wiederholt Fehler bei meinen Stops und Limits aufgetreten sind und unerwünschte Orders abgesetzt wurden. Woran lag das? Nun, wenn ich mit eigenen Exit-Triggern per Market-Order aus dem Trade gehe, aber zusätzlich noch Stop-Orders aktiviert im Markt habe, muss ich diese erste Canceln. Das kann ich zwar über CancelOrder(IOrder) mit Hilfe der API hinbekommen, aber ob und wann mein Stop-Order wirklich gecancelt ist, weiß ich erst, wenn ich es in OnOrderUpdate prüfe. Erst wenn die Prüfung Erfolg hatte (siehe kommentierten Code), sollte ich wirklich per Market-Order rausgehen. Im Normalfall merke ich davon nichts und meine Strategie funktioniert auch ohne obige Implementierung. Allerdings hatte ich ab und zu den Fall das ich in schnellen Marktphasen einen TimedExit ausgeführt hatte und anschließend durch meine Stop-Order wieder in der Gegenrichtung im Markt war. Dies kommt selten vor, führt aber zu unerwünschten Ergebnissen.


Weiterhin kann ich in OnOrderUpdate noch ein Rejection-Handling für Orders einbauen, dazu aber in weiteren Artikeln mehr.

Beste Grüße
DarthTrader

hbreuer-trading.de - NinjaTrader Programmierung, Seminare und automatische Handelssysteme

Sonntag, 7. Februar 2010

UserDefinedMethods.cs - Methoden

Nachdem im letzten Teil die Variablen der Klasse UserDefinedMethods.cs besprochen wurden, folgend nun zentrale Methoden, die ich in meinen Strategien verwende.

Ich poste die Methoden inkl. meiner internen Beschreibung, so dass eine weitere Erklärung nicht notwendig erscheint. Dort wo es Sinn macht, werde ich weiterhin kommentieren:
























































Hier wird sich nach jedem Positionswechsel der Status gemerkt und in der nächsten Methode ausgewertet.Die im vorherigen Post angesprochenen Variablen orderFeed und dataFeed werden hiefür verwendet.





















Zusätzlich können weitere technische Methoden implementiert werden. In meinem Falls
sind das bisher nur die Methoden isUpGap() und isDownGap(). Auf deren Implementierung wird hier allerdings aus Trivialitätsgründen verzichtet.

Beste Grüße
DarthTrader

UserDefinedMethods.cs - Variablen

Da wir gerade beim Thema sind, möchte ich Euch gerne die Klasse UserDefinedMethods.cs etwas näher bringen.

Diese NT-Standardklasse ist Oberklasse von allen Strategien, die der User schreiben oder verwenden kann. Ausgdrückt wird die Vererbung im Code einer eigenen Klasse durch folgendes Konstrukt:






Der User kann in dieser Klasse globale Methode für alle Unterklassen und damit auch Strategien implementieren. Doch vorsicht, wie aus dem letzten Post ersichtlich besteht hier aufgrund von C# -spezifischen (bspw. Vererbungsregeln), aber auch von allgemeinen objekt-orientierten Prinzipien eine erhöhte Fehlergefahr bei der Programmierung. Im letzten Post hatte ich erwähnt, dass Trades nicht abgesetzt wurden. Dies war zum Glück ein Fehler, der keine großen Konsequenzen hatte, aber sicherlich sollte man hier aufpassen was man macht.


Welche Methoden oder Prüfungen gehören meiner Ansicht nach nun in diese Oberklasse und wo ist es sinnvoll Variablen oder Methoden vielleicht eher in Unterklassen zu verwalten? Da ich kein C# -Experte bin, mich allerdings mit objekt-orientierten-Methodiken auskenne, möchte ich vorab schonmal darauf hinweisen, dass ich mich nicht immer an das Prinzip der Datenkapselung gehalten habe. Wichtiger ist mir persönlich an dieser Stelle, dass der Code stabil läuft sowie einfach und schnell zu ändern ist. Programmiertechnisch gesehen oder gar aus Sicht architektureller Aspekte gibt es sicherlich elegantere Methoden, aber das soll hier nicht weiter relevant sein.

Ok, zurück zu den Prüfungen die ich in der Klasse UserDefinesMethod.cs hinterlegt habe. Gerne bin ich für weitere Anregungen oder Ideen offen.

Einschränken der Tradingzeiten:








Je nach Geschmack kann man die zusätzlich notwendigen Parameter-Deklaration in der Oberklasse einbauen oder in der Strategie selbst. Ich habe mich für letzteres entschieden, um nicht immer die Möglichkeit zu haben, die Tradingzeiten einzuschränken, da es manchmal einfach nur störend ist, den Parameter-Bereich zuzumüllen.


Globale Entry und Exit-Order-Objekte:





Beinahe jede Strategie besitzt bei mir Entry-, Stop- und Target-Orders. Deswegen habe ich mich dazu entschlossen, diese in eine Oberklasse mit aufzunehmen.

An den Sichtbarkeitseinschränkungen der Variablen (hier: protected) erkennt man, dass die Variablen mit vererbt werden, also pro Unterklasse vorhanden sind und dort auch überschrieben werden können.

Instanzvariablen, um den Connection-Status zum Orderserver und Preisserver zu speichern:




So, dass soll es erstmal gewesen sein. Die zentralen Methoden des Klasse UserDefinedMethods.cs werden im zweiten Teil besprochen.

Beste Grüße
DarthTrader

Mittwoch, 3. Februar 2010

Fehleranalyse - isNewDay()

Bevor es die nächstes Wochen mit konkreten Themen weiter geht kurz ein Fehlerquiz. Seit heute handel ich ein und dieselbe Strategie auf 3 Märkten, das hei0t ich habs versucht. Durch eine Codeumstellung wurde immer nur ein Markt gehandelt, obwohl Signale für alle drei vorhanden waren. 2 Märkte hatte ich schonmal parallel mit einer Strategie gehandelt, aber 3? Sollte es daran liegen, oder doch an folgendem Code:

Code aus der Strategie, um festzustellen, ob ein neuer Tag angefangen hat. Es wird eine Variable schonGetradet (zurück-)gesetzt, so dass ich damit sicherstellen kann, jeden Tag definitiv nur einen Trade auszuführen:












Code aus UserDefinedMethods.cs, um in einer Oberklasse zentrale Methoden zu verwalten, die alle Strategien verwenden können. Hier wird die von der Subklasse aufgerufene Methode isNewDay() implementiert:

















Wo ist der Fehler und warum wird nur ein Markt gehandelt und nicht alle 3 Signale, die es gestern und heute mit derselben Strategie gab?


Die Auflösung gibt es die nächsten Tage, wer möchte kann mit raten :-)

Beste Grüße
DarthTrader


UPDATE und AUFLÖSUNG:

Gerd hat recht newDay ist eine Klassenvariable und keine Instanzvariable. Deswegen existiert sie nur einmal. Zudem ist sie als private deklariert und wird demzufolge nicht mit vererbt. Ein Deklaration von

protected int newDay = -1

könnte das Problem lösen. Allerdings habe ich mich für die sicherere Variante entschieden und meinen Code wieder auf das hier geändert ...

if (ToDay(Time[0]) != ToDay(Time[1])) { ... }

... um weitere Fehler vorerst zu vermeiden.

Für Fortgeschrittene in Sachen Programmierung: Sicherlich gibt es auch Situationen, in denen die Fehler-Variante von oben von mehr als einer Strategie aufgerufen werden kann, aber sicher ist es nicht. Stichwort hierbei ist "Thread-Sicherheit", denn obiger Code ist nicht synchronisiert (vorr. in C# ist es ähnlich wie in Java :-)