Risikomanagement (Teil 3): Aufbau der Hauptklasse für das Risikomanagement
- Einführung
- Konzeption und Planung des Risikomanagements
- Definition von Konstanten, Enumerationen und Strukturen
- Erklärung der Schlüsselvariablen für das Risikomanagement
- Erstellung von Konstruktor-, Destruktor- und Initialisierungsmethoden
- Methoden für die Zuordnung von Werten zu Verlusten und Gewinnen
- Berechnung von Losgröße und Stop-Loss auf der Grundlage des Risikos pro Handel
- Funktionen zum Abrufen von Verlust-, Gewinn- und Risikowerten
- Geplante Ereignisse für den neuen Tag und die neue Woche
- Schlussfolgerung
Einführung
Wir setzen unsere Artikelserie fort, in der wir ein Risikomanagementsystem entwickeln. Im vorigen Artikel haben wir die Schnittstelle unter Anwendung der im ersten Teil gelernten Konzepte erstellt. Im dritten Teil der Serie werden wir uns nun auf die Vervollständigung der Kernstruktur des Risikomanagementkurses konzentrieren.
In diesem Artikel werden wir eine Klasse erstellen, die es uns ermöglicht, Verlusten und Gewinnen Werte zuzuweisen und damit die Grundlage für die Gewinnberechnung und -verfolgung zu legen. Dies ist ein wichtiger Schritt auf dem Weg zum Aufbau eines robusten und funktionierenden Risikomanagementsystems.

Der folgende Rahmen skizziert einen strukturierten Plan für die Gestaltung und Planung des Risikomanagements in unserem System:
-
Definitionen, Strukturen und Enumerationen
Der erste Schritt besteht darin, die erforderlichen Strukturen und Enumerationen zu definieren. Diese sind für die Speicherung von Schlüsselinformationen wie kumulierten Verlusten und Gewinnen sowie für die Erleichterung der Datenverarbeitung innerhalb des Systems unerlässlich. -
Erstellen der Klasse CRiskManagement
Als Nächstes entwickeln wir die Hauptklasse, die für das Risikomanagement zuständig ist: CRiskManagement. Diese zentrale Klasse wird alle Berechnungen und Prozesse im Zusammenhang mit der Risikokontrolle konsolidieren und eine organisierte und effiziente Umsetzung gewährleisten. -
Grundlegende Funktionen: Zuweisung und Abruf von Werten
Anschließend werden wir Funktionen zum Zuweisen und Abrufen von Werten implementieren, mit denen wir Verluste und Gewinne aktualisieren und abfragen können. In diesem Stadium werden wir auch den Konstruktor und den Destruktor der Klasse definieren, um den Speicher und die Dateninitialisierung richtig zu verwalten. -
Ereignisgesteuerte Funktionen
Schließlich werden wir Funktionen entwickeln, die zu wichtigen Zeitpunkten ausgelöst werden, z. B. zu Beginn eines neuen Tages oder einer neuen Woche. Diese Funktionen sind nützlich für die Neuberechnung von Gewinnen, die Anpassung des Risikos und die Neuinitialisierung akkumulierter Variablen über bestimmte Zeiträume hinweg, um eine korrekte Leistungsverfolgung im Laufe der Zeit zu gewährleisten.
Wenn dieser Plan steht, werden wir mit dem Aufbau von Grund auf beginnen.
Definition von Konstanten, Enumerationen und Strukturen
Bevor wir den Code implementieren, werden wir die gesamte Risikomanagementlogik in einer separaten Datei mit dem Namen Risk_Management.mqh (die von uns erstellte Basisdatei) organisieren. Dadurch bleibt der Code besser strukturiert und modular.
Gemäß unserem Rahmen für das Risikomanagement besteht der erste Schritt darin, die erforderlichen Strukturen, Enumerationen und Konstanten zu definieren. Diese Elemente sind für mehrere Funktionen unerlässlich, vor allem für die Berechnung und Kontrolle von Werten wie dem täglichen, wöchentlichen oder maximalen Verlust pro Handel.
Definition von Konstanten (#define)
Um das Risikomanagement zu erleichtern und die Lesbarkeit des Codes zu verbessern, werden wir mehrere Schlüsselkonstanten definieren:
1. NOT_MAGIC_NUMBER
Diese Konstante wird als Initialisierungswert im Klassenkonstruktor verwendet. Sie soll darauf hinweisen, dass keine bestimmte magische Zahl verwendet wird, sondern dass das Risikomanagement für alle Handelsgeschäfte ohne Beschränkung auf eine bestimmte Kennziffer gilt. Dies ist nützlich bei der Implementierung des Risikomanagements für das gesamte Konto in einer Live-Handelsumgebung.
#define NOT_MAGIC_NUMBER 0 //Not Magic Number
2. dieFlags für den Abschluss von Geschäften
Um die Positionsschließungsfunktion dynamischer zu gestalten, werden wir Flags verwenden, anstatt mehrere separate Funktionen zum Schließen von Handelsgeschäften mit Gewinn, Verlust oder beidem zu erstellen. Diese Flags vereinfachen den Code und verbessern die Wiederverwendbarkeit.
#define FLAG_CLOSE_ALL_PROFIT 2 //Flag indicating to close only operations with profit #define FLAG_CLOSE_ALL_LOSS 4 //Flag indicating to close only operations without profit
Enumerationen
1. Berechnungsmethode: Fester Betrag oder ProzentsatzWir brauchen eine Enumeration, um festzulegen, wie die maximalen Verluste und Gewinne innerhalb der Strategie berechnet werden. Es gibt zwei Hauptansätze:
-
Konstant (Geld): Der Nutzer legt einen bestimmten Geldbetrag fest, um den maximalen Verlust oder Gewinn zu definieren. Dieser Wert bleibt unabhängig vom Kontostand konstant.
- Beispiel: Ein täglicher Höchstverlust von 1.000 $ bleibt unverändert, solange das System läuft.
-
Dynamisch (in Prozent): Anstelle eines festen Wertes wählt der Nutzer einen Prozentsatz, der auf eine Bezugsgröße innerhalb des Kontos angewendet wird, z. B. den Saldo oder das Eigenkapital.
- Beispiel: Wenn die Grenze bei 2 % des Guthabens liegt, hängt der maximale Verlust vom Kontostand ab. Wächst der Saldo, erhöht sich die Verlustgrenze proportional, sinkt der Saldo, sinkt die Grenze.
Dies wird im Code mit der folgenden Enumeration dargestellt.
enum ENUM_RISK_CALCULATION_MODE //enumeration to define the types of calculation of the value of maximum profits and losses { money, //Money percentage //Percentage % };
2. Prozentuale Anwendung: Referenzparameter für die Risikoberechnung
Wenn die Berechnungsmethode prozentual ist, müssen wir den Kontowert definieren, auf den dieser Prozentsatz angewendet wird. Wir erwägen vier Schlüsseloptionen:
- Balance – wird auf den Gesamtsaldo des Kontos angewendet.
- ganancianeta – basierend auf dem kumulierten Gewinn seit Kontoeröffnung.
- free_margin – berechnet auf das für die Eröffnung neuer Handelsgeschäfte verfügbare Kapital.
- equity – stellt den um Gewinne oder Verluste aus offenen Positionen bereinigten Saldo dar.
enum ENUM_APPLIED_PERCENTAGES //enumeration to define the value to which the percentages will be applied { Balance, //Balance ganancianeta,//Net profit free_margin, //Free margin equity //Equity };
3. Risikomanagement Typ: Persönliches Konto oder Prop-Firma (FTMO)
Wie in den vorangegangenen Kapiteln erwähnt, kann dieses System sowohl auf persönliche Konten als auch auf Prop-Firmen, insbesondere FTMO, angewendet werden. FTMO hat einen dynamischeren Ansatz für die Berechnung des maximalen Tagesverlustes.
Wie FTMO diese Berechnung durchführt, werden wir später bei der Analyse von Strukturen im Detail erläutern. Zunächst werden wir eine Enumeration erstellen, die es dem Nutzer ermöglicht, den Kontotyp für das Risikomanagement auszuwählen.
enum ENUM_MODE_RISK_MANAGEMENT //enumeration to define the type of risk management { propfirm_ftmo, //Prop Firm FTMO personal_account // Personal Account };
4. Auswahl des Typs für die Losgröße
Nicht alle Händler bevorzugen den Handel mit einer dynamischen Losgröße. Wir werden dem Nutzer die Möglichkeit geben, den Lostyp zu wählen. Diese Wahl hat keinen Einfluss auf die Kernlogik der Risikomanagementklasse, ist aber für die Entwicklung eines EA wichtig, da der Nutzer in der Lage sein sollte, entweder mit einem festen oder einem dynamischen Lot zu handeln.
Wir werden die folgende Enumeration erstellen:
enum ENUM_LOTE_TYPE //lot type { Dinamico,//Dynamic Fijo//Fixed };
Bei der Eröffnung eines Handelsgeschäfts kann die Bestimmung der Losgröße wie folgt beeinflusst werden:
trade.Sell( (Lote_Type == Dinamico ? risk.GetLote(ORDER_TYPE_SELL,GET_LOT_BY_ONLY_RISK_PER_OPERATION) : lote), _Symbol,tick.bid,sl,tp,"EA Sell");
Wenn der Nutzer in diesem Code ein dynamisches Losgröße (Dinamico) auswählt, berechnet die Funktion GetLote die Losgröße auf der Grundlage des Risikos pro Handel. Wenn der Nutzer eine feste Losgröße (Fijo) auswählt, verwendet der EA den Standardwert, der der Variablen der Losgröße (lote) zugewiesen ist.
Später werden wir die Funktion GetLot erstellen, um die dynamische Losgröße ordnungsgemäß abzurufen.
5. Dynamische Berechnungsmethode der Losgröße
Wenn der Nutzer eine dynamisches Losgröße wählt, muss festgelegt werden, wie dessen Größe berechnet wird. Wir werden eine Enumeration erstellen, um festzulegen, ob die Berechnung ausschließlich auf dem Risiko pro Handelsgeschäft basiert oder nach dem Stop Loss angepasst wird.
-
Die Berechnung basiert nur auf dem Risiko pro Handel:
Die Losgröße wird ausschließlich auf der Grundlage des prozentualen Risikos pro Handel festgelegt. In diesem Fall ist es nicht erforderlich, einen bestimmten Wert für den Stop-Loss anzugeben. -
Berechnung auf der Grundlage von Risiko und Stop-Loss
Die Losgröße wird auf der Grundlage des Risikos pro Handel berechnet und entsprechend dem Stop-Loss angepasst. Dies ist wichtig, denn wenn Sie einen festen Prozentsatz des Risikos ohne Bezug auf den Stop-Loss festlegen, erhalten Sie möglicherweise eine unangemessene Losgröße.Beispiel:
Nehmen wir an, wir wollen 1 % eines $1000-Kontos riskieren, was einem maximalen Risiko von $10 entspricht. Unsere Strategie verwendet ein Chance-Risiko-Verhältnis von 1:2 und einen 100-Punkte-Stop-Loss auf EUR/USD (5-stelliger Broker), eine naive Berechnung könnte ein Losgröße von 0,02 ergeben.- Wenn der Handel den Stop-Loss erreicht, würde der tatsächliche Verlust 2 $ statt 10 $ betragen.
- Wenn der Handel die Gewinnmitnahme erreicht, würde der tatsächliche Gewinn 4 $ statt 20 $ betragen.
Um dieses Problem zu lösen, passen wir die Losgröße so an, dass bei einem bestimmten Stop-Loss der maximale Verlust genau 1 % des Kontos beträgt. Damit ist sichergestellt, dass der Gewinn 2 % beträgt, wenn das Handelsgeschäft bei einem Verhältnis von 1:2 den Take Profit erreicht.
Die Funktion GetIdealLot (die in einem früheren Artikel vorgestellt wurde) passt die Losgröße automatisch an.
void GetIdealLot(double& nlot, double glot, double max_risk_per_operation, double& new_risk_per_operation, long StopLoss)
Sie passt die Losgröße so an, dass das Risiko pro Handelsgeschäft innerhalb des festgelegten Limits bleibt.
Um diese beiden Berechnungsmethoden darzustellen, definieren wir die folgende Enumeration:enum ENUM_GET_LOT { GET_LOT_BY_ONLY_RISK_PER_OPERATION, //Obtain the lot for the risk per operation GET_LOT_BY_STOPLOSS_AND_RISK_PER_OPERATION //Obtain and adjust the lot through the risk per operation and stop loss respectively. };
Strukturen:
Strukturen spielen in unserem Risikomanagementsystem eine zentrale Rolle. Wie bereits erwähnt, werden Verluste und Gewinne entweder direkt (konstanter Wert) oder dynamisch (Prozentsatz) berechnet. Bei der prozentualen Methode gilt sie für einen Referenzwert auf dem Konto.
Wir erstellen eine Struktur mit allen notwendigen Informationen, um einen Verlust oder Gewinn zu definieren.
- value – stellt den Verlust- oder Gewinnbetrag dar.
- assigned_percentage – gibt den zugewiesenen Prozentsatz an, wenn die Berechnung dynamisch ist.
- mode_calculation_risk – definiert die Methode zur Berechnung des Risikos pro Handelsgeschäft (direkt oder dynamisch).
- percentage_applied_to – Enumeration, die angibt, für welche Kontenmetrik der Prozentsatz gilt, wenn die dynamische Methode verwendet wird.
Dies wird im Code wie folgt dargestellt:
struct Loss_Profit { double value; //value double assigned_percentage; //percentage to apply ENUM_RISK_CALCULATION_MODE mode_calculation_risk; //risk calculation method ENUM_APPLIED_PERCENTAGES percentage_applied_to; //percentage applied to };
Anhand dieser Struktur können wir die folgenden Gewinn- und Verlustoptionen ermitteln:
| Name | Beschreibung | Zurücksetzung |
|---|---|---|
| Maximum Daily Loss (MDL) | Der maximal zulässige Verlust an einem einzigen Tag. | Wird täglich auf 0 zurückgesetzt. |
| Maximum Loss (ML) | Der maximale Gesamtverlust, den ein Konto während seiner Laufzeit erreichen kann. | Wird nicht zurückgesetzt. |
| Maximum Loss Per Trade (GMLPO) | Ähnlich wie das vom Nutzer definierte Risiko pro Handelsgeschäft; wird verwendet, um die angemessene Losgröße zu schätzen. | Wird jedes Mal neu berechnet, wenn ein Handelsgeschäft geschlossen wird oder wenn ein neuer Tag beginnt. |
| Maximum Weekly Loss (MWL) | Der maximal zulässige Verlust innerhalb einer Woche. Fakultativ, da sie für Prop-Firmen nicht erforderlich ist. | Wird wöchentlich zurückgesetzt. |
| Net Maximum Loss Per Trade (NMLPO) | Wird nur erzeugt, wenn die Funktion aufgerufen wird, die das Lot auf der Grundlage des Risikos pro Handel und des Stop Loss berechnet. | Wird jedes Mal neu berechnet, wenn die auf Risiko und Stop-Loss basierende Losabfragefunktion aufgerufen wird. |
| Maximum Daily Profit | Der maximale Gewinn, den der Bot oder das Konto an einem einzigen Tag erzielen kann. | Wird täglich zurückgesetzt. |
Besonderheiten des maximalen Tagesverlustes im FTMO
Bei der Anpassung dieses Risikomanagementsystems für reguläre Konten und Prop-Firmen wie FTMO ergeben sich einige wesentliche Unterschiede. Bei FTMO ist der maximale Tagesverlust sehr dynamisch, da er sich erhöhen kann, wenn während des Tages Gewinne erzielt werden.
Im Falle einer FTMO-Herausforderung mit einem anfänglichen Kontostand von 200.000 $ beträgt das Limit für den maximalen täglichen Verlust beispielsweise 10.000 $. Wenn Sie bei Ihren geschlossenen Handelsgeschäften $8.000 verlieren, darf Ihr Konto an diesem Tag nicht mehr als $2.000 verlieren. Außerdem dürfen Ihre offenen schwebenden Verluste nicht über -$2.000 liegen. Die Obergrenze gilt einschließlich Provisionen und Swaps.
Umgekehrt gilt: Wenn Sie an einem Tag 5.000 Dollar gewinnen, können Sie es sich leisten, 15.000 Dollar zu verlieren, aber nicht mehr als das. Denken Sie daran, dass Ihr maximaler Tagesverlust auch Ihre offenen Handelsgeschäfte berücksichtigt. Wenn Sie z.B. an einem Tag Handelsgeschäfte mit einem Verlust von 6.000 $ abgeschlossen haben und dann ein neues Handelsgeschäft eröffnen, das mit einem schwebenden Verlust von etwa -5.700 $ endet, aber am Ende positiv ist, ist es leider schon zu spät. In einem Moment betrug Ihr täglicher Verlust -11.700 $ vom Kapital (equitty), was mehr als der zulässige Verlust von 10.000 $ ist.
FTMO Maximaler täglicher Verlust
Wie direkt aus den FTMO-Richtlinien hervorgeht, kann der maximale Tagesverlust in Abhängigkeit von den im Laufe des Tages erzielten Gewinnen variieren.
Wenn Ihr zulässiger Maximalverlust zu Beginn des Tages beispielsweise 10.000 $ beträgt und Sie am selben Tag einen Gewinn erzielen, wird dieser Gewinn zu den ursprünglichen 10.000 $ hinzugerechnet, wodurch sich Ihre zulässige Verlustspanne erhöht. Wenn sich also die Gewinne häufen, passt sich auch der Betrag, den Sie riskieren können, entsprechend an.
Erklärung der Schlüsselvariablen für das Risikomanagement
In diesem Abschnitt wird die Klasse CRiskManagement definiert, die für die Verwaltung des Risikos von Handelsgeschäften zuständig ist.
//+------------------------------------------------------------------+ //| Class CRisk Management | //+------------------------------------------------------------------+ class CRiskManagemet final
Einbinden der Bibliotheken
Bevor wir die Klasse definieren, werden wir die Bibliothek CTrade.mqh einbinden, um Trades, wie z.B. das Schließen von Positionen, verwalten zu können:
#include <Trade/Trade.mqh> 1. Zeiger auf CTrade
Als erste Variable erstellen wir einen Zeiger auf die Klasse CTrade, die es uns ermöglicht, mit offenen Positionen zu interagieren:
private: //--- CTrade class pointer to be able to work with open positions CTrade *trade;
2. Wichtige Variablen
Wir definieren drei Hauptvariablen:
- account_profit (double) – speichert den Nettogewinn des Kontos seit dem 1972.01.01 (frühstes Datum im Datums-/Uhrzeitformat);
- StopLoss (long) – hält die Höhe des Stop-Loss in Punkten fest, der zur Berechnung der Losgröße verwendet wird;
- batch (double) – eine interne Variable, die das zuletzt berechnete Los speichert.
Code:
//-- Main variables double account_profit; long StopLoss; double lote;
3. Gemeinsame Variablen
- magic_number (ulong) – speichert die magische Zahl, die verwendet wird, um das mit einer bestimmten Gruppe von Handelsgeschäften verbundene Risiko zu verwalten. Er kann auch gleich 0 sein, sodass er auch für persönliche Konten verwendet werden kann.
- mode_risk_management (ENUM_MODE_RISK_MANAGEMENT) – definiert die Art des Risikomanagements, das angewandt wird: für reguläre Konten oder für Prop Companies (z.B. FTMO).
Code:
//--- General variables ENUM_MODE_RISK_MANAGEMENT mode_risk_managemet; ulong magic_number;
4. Spezifische Variablen für Prop-Firmenkonten (FTMO)
Bei Konten von Prop-Firmen gelten die Risikomanagementregeln für den Eröffnungssaldo, nicht für den laufenden Saldo. So werden beispielsweise der maximale Tagesverlust und der maximale Gesamtverlust in der Regel als Prozentsatz des Eröffnungssaldos (in der Regel 10 %) berechnet.
Um diese Funktion zu berücksichtigen, fügen wir eine Variable hinzu, um den Anfangssaldo zu speichern, den der Nutzer manuell einstellen muss:
//--- Variables to work with anchoring tests double account_balance_propfirm;
5. Variable für den erwarteten maximalen Verlust beim nächsten Abschluss (NMLPO)
Diese Variable speichert den geschätzten maximalen Verlust für den nächsten Handel. Sie ist nicht zwingend erforderlich, kann aber nützlich sein, um vorherzusagen, wie viel der Roboter verlieren wird, wenn die Position das Stop-Loss-Niveau erreicht.
Sie wird nur mit dem Aufruf von GetLote() berechnet.
//--- Variables to store the values of the maximum losses double nmlpo;
6. Variablen für das Gewinn- und Verlustmanagement
Die zuvor definierte Struktur Loss_Profit wird verwendet, um die Höhe des Verlustes, die Methode zu seiner Berechnung und die Art der Anwendung des Prozentsatzes zu speichern.
Lassen Sie uns fünf Schlüsselvariablen definieren:
//--- variables that store percentages and enumeration, which will be used for the subsequent calculation of losses
Loss_Profit mdl, mwl, ml, gmlpo, mdp; wobei:
- mdl – maximaler Tagesverlust;
- mwl – maximaler wöchentlicher Verlust;
- ml – maximaler Gesamtschaden;
- gmlpo – maximaler Verlust pro Handel;
- mdp – maximaler Tagesgewinn.
7. Variablen für den Gewinn (täglich, wöchentlich und insgesamt)
Um die Leistung des Roboters/Expert Advisors zu überwachen, werden wir Variablen hinzufügen, die Gewinndaten speichern und es ermöglichen, Warnungen auszugeben, wenn Verlustgrenzen erreicht oder Sicherheitsmaßnahmen ergriffen werden.
Wir brauchen:
- Referenzzeitpunkt, ab dem der Gewinn berechnet wird,
- Variablen, um den Gewinn zu speichern.
Code:
//--- Variables to store the profit and the time from which they will be obtained double daily_profit, weekly_profit, gross_profit; datetime last_weekly_time, last_day_time, init_time;
wobei:
- daily_profit – während des Tages erzielter Gewinn,
- weekly_profit – während der Woche erzielter Gewinn,
- gross_profit – Gesamtgewinn seit Beginn des Risikomanagements,
- last_weekly_time – das letzte aufgezeichnete Datum für die Berechnung des wöchentlichen Gewinns,
- last_day_time – das letzte aufgezeichnete Datum für die Berechnung des Tagesgewinns,
- init_time – das Datum des Beginns des Risikomanagements.
Erstellung von Konstruktor-, Destruktor- und Initialisierungsmethoden
Nachdem wir nun die Schlüsselvariablen definiert haben, werden wir die Hauptfunktionen der Klasse CRiskManagement implementieren.
Konstrukteur
Der Konstruktor ist für die Initialisierung von Schlüsselvariablen wie die magische Zahl, den Risikomanagementmodus und den Kontostand des Unternehmens (falls zutreffend) verantwortlich.
Die Konstruktordeklaration lautet wie folgt:
CRiskManagemet(ulong magic_number_ = NOT_MAGIC_NUMBER,ENUM_MODE_RISK_MANAGEMENT mode_risk_management_ = personal_account, double account_propfirm_balance=0);
In der Konstruktorimplementierung weisen wir Variablen Werte zu, initialisieren das CTrade-Objekt und berechnen den Nettogewinn des Kontos ab dem 1. Januar 1972. Wir setzen auch entsprechende Zeitstempel, um Gewinne zu verfolgen.
CRiskManagemet::CRiskManagemet(ulong magic_number_ = NOT_MAGIC_NUMBER,ENUM_MODE_RISK_MANAGEMENT mode_risk_management_ = personal_account, double account_propfirm_balance =0) { if(magic_number_ == NOT_MAGIC_NUMBER) { Print("| Warning | No magic number has been chosen, taking into account all the magic numbers and the user's trades"); } //--- this.account_balance_propfirm = account_propfirm_balance ; trade = new CTrade(); this.account_profit = GetNetProfitSince(true,this.magic_number,D'1972.01.01 00:00'); this.magic_number = magic_number_; this.mode_risk_managemet = mode_risk_management_; //--- this.last_day_time = iTime(_Symbol,PERIOD_D1,0); this.last_weekly_time = iTime(_Symbol,PERIOD_W1,0); this.init_time =magic_number_ != NOT_MAGIC_NUMBER ? TimeCurrent() : D'1972.01.01 00:00'; }
Anmerkung: Wenn der Nutzer keine magische Zahl angibt, wird eine Warnung angezeigt, dass das System alle vom Nutzer eröffneten Handelsgeschäfte berücksichtigt.
Zerstörer
Der Destruktor der Klasse ist für die Freigabe des dem CTrade-Objekt zugewiesenen Speichers verantwortlich, wenn die CRiskManagement-Instanz gelöscht wird.
CRiskManagemet::~CRiskManagemet()
{
delete trade;
}
Initialisierungsmethoden
Um die Einrichtung und Aktualisierung des Risikomanagements zu vereinfachen, werden wir spezielle Funktionen entwickeln, die es Ihnen ermöglichen:
- Stop-Loss setzen,
- Gewinn- und Verlustparameter einrichten.
1. Funktionen zum Setzen von Verluststrukturwerten
Wir definieren Methoden, mit denen wir den Schlüsselvariablen für die Gewinn- und Verlustberechnung Werte zuweisen können.
//--- Functions to assign values to variables for subsequent calculation of losses void SetPorcentages(double percentage_or_money_mdl, double percentage_or_money_mwl,double percentage_or_money_gmlpo, double percentage_or_money_ml, double percentage_or_money_mdp_); void SetEnums(ENUM_RISK_CALCULATION_MODE mode_mdl_, ENUM_RISK_CALCULATION_MODE mode_mwl_, ENUM_RISK_CALCULATION_MODE mode_gmlpo_, ENUM_RISK_CALCULATION_MODE mode_ml_, ENUM_RISK_CALCULATION_MODE mode_mdp_); void SetApplieds(ENUM_APPLIED_PERCENTAGES applied_mdl_, ENUM_APPLIED_PERCENTAGES applied_mwl_, ENUM_APPLIED_PERCENTAGES applied_gmlpo_, ENUM_APPLIED_PERCENTAGES applied_ml_, ENUM_APPLIED_PERCENTAGES applied_mdp_);
2. Zuweisung von Prozenten zu Verluststrukturen
Die folgende Methode ordnet den entsprechenden Strukturen prozentuale oder monetäre Werte zu.
void CRiskManagemet::SetPorcentages(double percentage_or_money_mdl,double percentage_or_money_mwl,double percentage_or_money_gmlpo,double percentage_or_money_ml,double percentage_or_money_mdp_) { this.gmlpo.assigned_percentage = percentage_or_money_gmlpo; this.mdl.assigned_percentage = percentage_or_money_mdl; this.ml.assigned_percentage = percentage_or_money_ml; this.mdp.assigned_percentage = percentage_or_money_mdp_; this.mwl.assigned_percentage = percentage_or_money_mwl; }
3. Initialisierung der Risikoberechnungsmodi
Mit dieser Methode wird der Berechnungsmodus für jede Struktur festgelegt. Wählt der Nutzer den geldbasierten Berechnungsmodus, wird der entsprechende Wert direkt zugewiesen.
void CRiskManagemet::SetEnums(ENUM_RISK_CALCULATION_MODE mode_mdl_,ENUM_RISK_CALCULATION_MODE mode_mwl_,ENUM_RISK_CALCULATION_MODE mode_gmlpo_,ENUM_RISK_CALCULATION_MODE mode_ml_,ENUM_RISK_CALCULATION_MODE mode_mdp_) { this.gmlpo.mode_calculation_risk = mode_gmlpo_; this.mdl.mode_calculation_risk = mode_mdl_; this.mdp.mode_calculation_risk = mode_mdp_; this.ml.mode_calculation_risk = mode_ml_; this.mwl.mode_calculation_risk = mode_mwl_; //-- If the money mode has been chosen, assign the variable that stores the money or percentage to the corresponding variables. this.gmlpo.value = this.gmlpo.mode_calculation_risk == money ? this.gmlpo.value : 0; this.mdp.value = this.mdp.mode_calculation_risk == money ? this.mdp.value : 0; this.mdl.value = this.mdl.mode_calculation_risk == money ? this.mdl.value : 0; this.ml.value = this.ml.mode_calculation_risk == money ? this.ml.value : 0; this.mwl.value = this.mwl.mode_calculation_risk == money ? this.mwl.value : 0; }
4. Zuweisung von Parametern, die auf das Konto angewendet werden
Diese Methode legt fest, wie die konfigurierten Prozentsätze auf das Konto angewendet werden sollen.
void CRiskManagemet::SetApplieds(ENUM_APPLIED_PERCENTAGES applied_mdl_,ENUM_APPLIED_PERCENTAGES applied_mwl_,ENUM_APPLIED_PERCENTAGES applied_gmlpo_,ENUM_APPLIED_PERCENTAGES applied_ml_,ENUM_APPLIED_PERCENTAGES applied_mdp_) { this.gmlpo.percentage_applied_to = applied_gmlpo_; this.mdl.percentage_applied_to = applied_mdl_; this.mdp.percentage_applied_to = applied_mdp_; this.mwl.percentage_applied_to = applied_mwl_; this.ml.percentage_applied_to = applied_ml_; }
5. Stop-Loss-Einstellungsfunktionen
Um den Stop-Loss zu setzen, werden wir 2 einfache Methoden verwenden, um der StopLoss-Variable einen Wert zuzuweisen:
- Methode 1: Der Nutzer legt die Anzahl der Stop-Loss-Punkte direkt fest.
- Methode 2: Der Nutzer definiert den Abstand zwischen dem Stop-Loss und dem Einstiegspunkt, der dann in Punkte umgerechnet wird (mit der Funktion, die wir im ersten Teil des Artikels programmiert haben).
//--- Function to set the "StopLoss" variable, in points or distance inline void SetStopLoss(double dist_open_sl) { this.StopLoss = DistanceToPoint(dist_open_sl); } inline void SetStopLoss(long _sl_point_) { this.StopLoss = _sl_point_; }
Methoden für die Zuordnung von Werten zu Verlusten und Gewinnen
In diesem Abschnitt werden wir die Methoden entwickeln, die erforderlich sind, um den Gewinnen und Verlusten in unserem Risikomanagementsystem Werte zuzuweisen.
1. Allgemeine Funktion für die Wertzuweisung
Um ein flexibles und anpassungsfähiges Risikomanagement zu gewährleisten, werden wir eine allgemeine Funktion schaffen, die den entsprechenden Wert auf der Grundlage des Prozentsatzes berechnet, der auf die verschiedenen Kontokennzahlen angewendet wird.
Definition der Funktion:
Die wichtigste Funktion, die wir verwenden werden, ist die folgende:
//--- General function to assign values to loss variables double GetValorWithApplied(const ENUM_APPLIED_PERCENTAGES applied,const double percentage_);
Diese Funktion benötigt zwei Schlüsselparameter:
- applied – legt fest, auf welche Kontometrik der Prozentsatz angewandt wird (Saldo, freie Marge, Kapital usw.).
- percentage_ – der Prozentsatz, der auf die ausgewählte Metrik anzuwenden ist.
double CRiskManagemet::GetValorWithApplied(const ENUM_APPLIED_PERCENTAGES applied,const double percentage_) { if(this.mode_risk_managemet == propfirm_ftmo && percentage_ != this.mdp.assigned_percentage && percentage_ != this.gmlpo.assigned_percentage) return this.account_balance_propfirm * (percentage_/100.0); switch(applied) { case Balance: return NormalizeDouble((percentage_/100.0) * AccountInfoDouble(ACCOUNT_BALANCE),2); case ganancianeta: { if(this.account_profit <= 0) { PrintFormat("The total profit of the account which is %+.2f is invalid or negative",this.account_profit); return 0; } else return NormalizeDouble((percentage_/100.0) * this.account_profit,2); } case free_margin: { if(AccountInfoDouble(ACCOUNT_MARGIN_FREE) <= 0) { PrintFormat("free margin of %+.2f is invalid",AccountInfoDouble(ACCOUNT_MARGIN_FREE)); return 0; } else return NormalizeDouble((percentage_/100.0) * AccountInfoDouble(ACCOUNT_MARGIN_FREE),2); } case equity: return NormalizeDouble((percentage_/100.0) * AccountInfoDouble(ACCOUNT_EQUITY),2); default: Print("Critical Error | It was not found that: ", EnumToString(applied), " be part of the allowed enumeration"); } return 0; }Code-Erklärung
- Verwaltung von Prop-Firmenkonten:
- Wenn das Konto zu einer Prop-Firma gehört (z.B. FTMO) und der angewandte Prozentsatz sich nicht auf den maximalen Tagesverlust (mdp.assigned_percentage) oder den maximalen Verlust pro Handel (gmlpo.assigned_percentage) bezieht, basiert die Berechnung auf dem Kontostand der Prop-Firma.
- Berechnung auf der Grundlage verschiedener Kontometrien:
- Balance – Prozentsatz, der auf den Gesamtsaldo des Kontos angewendet wird.
- ganancianeta – Prozentsatz, der auf den Nettogewinn des Kontos angewendet wird. Wenn der Gewinn negativ oder Null ist, wird eine Fehlermeldung angezeigt.
- free_margin – Prozentsatz, der auf die frei Marge angewandt wird. Wenn die freie Marge negativ ist, gibt die Funktion 0 zurück.
- equity – Prozentsatz, der auf das aktuelle Kapital des Kontos angewendet wird.
- Fehlerbehandlung:
- Wenn eine ungültige Metrik an die angewandte Funktion übergeben wird, gibt die Funktion eine Fehlermeldung aus und gibt 0 zurück.
2. Erstellen von Funktionen zur Konfiguration von Verlust- und Gewinnvariablen
Um Verluste und Gewinne effizient zu verwalten, werden wir eine Reihe von Funktionen erstellen, die es uns ermöglichen, Werte auf strukturierte Weise zuzuweisen. Insgesamt werden wir sechs Funktionen definieren: fünf für die Konfiguration der wichtigsten Verlustparameter und eine für die Berechnung der idealen Losgröße auf der Grundlage des Stop Loss.
1. Funktionen zur Wertzuweisung
Die Methode zur Zuweisung von Verlust- und Gewinnwerten basiert auf der folgenden Logik:
- Wenn der Berechnungsmodus Geld ist, wird der zuvor zugewiesene Wert beibehalten.
- Wenn die Berechnung nicht im Geldmodus erfolgt, wird die Funktion GetValorWithApplied verwendet, um den Wert auf der Grundlage des zugewiesenen Prozentsatzes und des entsprechenden Anwendungsparameters zu ermitteln.
- Ist der zugewiesene Prozentsatz 0, so gilt der Verlust als ungenutzt und wird daher mit dem Wert 0 angesetzt.
2. Zuweisungsfunktionen
Die folgenden Funktionen implementieren die oben beschriebene Logik für jede Art von Verlust:
//--- Functions to assign values to internal variables void SetMDL() {this.mdl.value = this.mdl.mode_calculation_risk == money ? this.mdl.value : (this.mdl.assigned_percentage > 0 ? GetValorWithApplied(this.mdl.percentage_applied_to,mdl.assigned_percentage) : 0); } void SetMWL() {this.mwl.value = this.mwl.mode_calculation_risk == money ? this.mwl.value : (this.mwl.assigned_percentage > 0 ? GetValorWithApplied(this.mwl.percentage_applied_to,mwl.assigned_percentage) : 0); } void SetML() {this.ml.value = this.ml.mode_calculation_risk == money ? this.ml.value : (this.ml.assigned_percentage > 0 ? GetValorWithApplied(this.ml.percentage_applied_to,ml.assigned_percentage): 0); } void SetGMLPO() {this.gmlpo.value = this.gmlpo.mode_calculation_risk == money ? this.gmlpo.value : (this.gmlpo.assigned_percentage > 0 ? GetValorWithApplied(this.gmlpo.percentage_applied_to,gmlpo.assigned_percentage) : 0); } void SetMDP() {this.mdp.value = this.mdp.mode_calculation_risk == money ? this.mdp.value : (this.mdp.assigned_percentage > 0 ? GetValorWithApplied(this.mdp.percentage_applied_to,mdp.assigned_percentage) : 0); } void SetNMPLO(double& TLB_new, double tlb) { GetIdealLot(TLB_new,tlb,this.gmlpo.value,this.nmlpo,this.StopLoss); }
Berechnung von Losgröße und Stop-Loss auf der Grundlage des Risikos pro Handel
In diesem Abschnitt werden wir zwei wesentliche Funktionen implementieren, um die Losgröße und den Stop-Loss genau zu berechnen und so sicherzustellen, dass jeder Handel mit dem Risikoniveau übereinstimmt, das wir bereit sind, einzugehen.
1. Funktion zur Berechnung der Losgröße
Zur Berechnung der Losgröße verwenden wir die im ersten Artikel entwickelten Funktionen, wobei wir sicherstellen, dass das Los unseren vordefinierten Risikoregeln entspricht.
Die Funktion, mit der wir die geeignete Losgröße ermitteln können, lautet:
//--- Get the lot double GetLote(const ENUM_ORDER_TYPE order_type, const ENUM_GET_LOT mode_get_lot);Die Parameter:
- order_type – gibt den Auftragstyp an (Kauf, Verkauf, Stop, Limit, Stop-Limit usw.).
- mode_get_lot – gibt die Methode zur Berechnung der Losgröße an (wurde bereits im Abschnitt Enumerationen erläutert).
Zweck der Funktion
Diese Funktion hilft bei der Berechnung der idealen Losgröße mit zwei verschiedenen Ansätzen:
- basierend auf dem Stop-Loss und dem maximalen Risiko pro Handel,
- direkt auf dem maximalen Risiko pro Handelsgeschäft basiert.
Schauen wir uns nun an, wie die Berechnung im Code umgesetzt wird.
//+-----------------------------------------------------------------------------------------------+ //| Function to obtain the ideal lot based on the maximum loss per operation and the stop loss | //+-----------------------------------------------------------------------------------------------+ double CRiskManagemet::GetLote(const ENUM_ORDER_TYPE order_type, const ENUM_GET_LOT mode_get_lot) { if(mode_get_lot == GET_LOT_BY_STOPLOSS_AND_RISK_PER_OPERATION) { double MaxLote = GetMaxLote(order_type); SetNMPLO(this.lote,MaxLote); PrintFormat("Maximum loss in case the next operation fails %.2f ", this.nmlpo); } else { this.lote = GetLotByRiskPerOperation(this.gmlpo.value,order_type); } return this.lote; }
Modus 1. Berechnung der Losgröße auf Basis von Stop Loss und maximalem Risiko pro Handelsgeschäft
Wenn der Nutzer GET_LOT_BY_STOPLOSS_AND_RISK_PER_OPERATION auswählt, berechnet das System die Losgröße auf der Grundlage des Risikos pro Handel und passt sie dann entsprechend dem Stop-Loss an, um sicherzustellen, dass im Falle eines Verlustes der tatsächliche Verlust dem definierten Risiko entspricht.
- Die maximal zulässige Losgröße wird mit der Funktion GetMaxLote(order_type) ermittelt.
- Die Losgröße wird mit SetNMPLO(this.lot, MaxLot) angepasst, um zu verhindern, dass Kontolimits überschritten werden.
- Es wird eine Informationsmeldung gedruckt, die den erwarteten maximalen Verlust angibt, wenn das Handelsgeschäft den Stop-Loss erreicht.
Modus 2. Berechnung der Losgröße auf Basis des maximalen Risikos pro Handelsgeschäft
Wenn der Nutzer einen anderen Berechnungsmodus wählt (z.B. GET_LOT_BY_RISK_PER_OPERATION), passt das System die Losgröße auf direktere Weise an:
- Die Funktion GetLotByRiskPerOperation(this.gmlpo.value, order_type) bestimmt die Losgröße auf der Grundlage des maximalen Risikos, das wir für den Handel zu übernehmen bereit sind.
- Diese Methode ist einfacher und kann für Händler nützlich sein, die sich nicht auf einen festen Stop-Loss verlassen, sondern ihr Risiko eher dynamisch anpassen.
2. Funktion zum Berechnen des Stop Loss
Da wir in den vorangegangenen Abschnitten bereits Hilfsfunktionen entwickelt haben, wird diese Funktion relativ einfach sein, da wir diese Funktionen zur effizienten Berechnung des Stop-Loss wiederverwenden werden.
Die Funktion, die uns hilft, den idealen Stop-Loss zu finden, lautet:
long GetSL(const ENUM_ORDER_TYPE type, double DEVIATION = 100, double STOP_LIMIT = 50);Die Parameter:
- type – gibt die Art des Auftrags an: Kauf, Verkauf, Stop, Limit, Stop-Limit, etc.
- DEVIATION (optional) – stellt die zulässige Ausführungsabweichung dar, mit einem Standardwert von 100 Punkten.
- STOP_LIMIT (optional) – stellt den Abstand in Punkten für Aufträge vom Typ STOP_LIMIT dar.
Diese Parameter stellen sicher, dass die Berechnung von Stop-Loss dynamisch ist und an unterschiedliche Marktbedingungen angepasst werden kann.
Implementierung der Funktion:
//+----------------------------------------------------------------------------------+ //| Get the ideal stop loss based on a specified lot and the maximum loss per trade | //+----------------------------------------------------------------------------------+ long CRiskManagemet::GetSL(const ENUM_ORDER_TYPE type, double DEVIATION = 100, double STOP_LIMIT = 50) { double lot; return CalculateSL(type,this.gmlpo.value,lot,DEVIATION,STOP_LIMIT); }
- Wie diese Funktion funktioniert
- Sie definiert die Variable Lot, in der die aus der Stop-Loss-Berechnung resultierende Losgröße gespeichert wird.
- Sie ruft die Funktion CalculateSL() auf und übergibt die folgenden Parameter:
- Auftragsart (Typ), damit der Stop Loss für Käufe oder Verkäufe korrekt berechnet wird;
- maximales Risiko pro Handelsgeschäft (this.gmlpo.value), sodass der Stop-Loss mit den Regeln des Risikomanagements vereinbar ist;
- lot – es wird auf der Grundlage der verwendeten Losgröße aktualisiert;
- DEVIATION – die zulässige Abweichung, die eine gewisse Flexibilität bei der Auftragsausführung ermöglicht;
- STOP_LIMIT – stellt die Entfernung in Punkten für STOP_LIMIT-Aufträge dar.
- Schließlich gibt die Funktion den Stop-Loss-Wert in Punkten zurück.
Funktionen zum Abrufen von Verlust- und Gewinnwerten
In diesem Abschnitt werden die Funktionen beschrieben, die für die Abfrage der wichtigsten Verlust- und Gewinnkennzahlen innerhalb des Handelssystems verantwortlich sind. Diese Funktionen werden als inline und const deklariert, um Effizienz zu gewährleisten und unbeabsichtigte Änderungen an Klassenvariablen zu verhindern.
1. Funktionen zum Abrufen von maximalen Verlusten und Gewinnen
Die folgenden Funktionen geben die Werte zurück, die in den Variablen gespeichert sind, die den maximalen Gewinn und Verlust über verschiedene Zeiträume hinweg verfolgen:
inline double GetML() const { return this.ml.value; } inline double GetMWL() const { return this.mwl.value; } inline double GetMDL() const { return this.mdl.value; } inline double GetGMLPO() const { return this.gmlpo.value; } inline double GetNMLPO() const { return this.nmlpo; } inline double GetMDP() const { return this.mdp.value; }
Jede Funktion liefert relevante Daten zur Handelsleistung auf verschiedenen Analyseebenen.
2. Funktionen zur Ermittlung des täglichen, wöchentlichen und gesamten Gewinns
Diese Funktionen liefern Gewinne über verschiedene Zeiträume und ermöglichen so eine Leistungsbewertung des Systems.
//--- Obtain only profits: inline double GetGrossProfit() const { return this.gross_profit; } inline double GetWeeklyProfit() const { return this.weekly_profit; } inline double GetDailyProfit() const { return this.daily_profit; }
3. Funktion zum Schließen offener Positionen basierend auf der magischer Zahl und den Flags
Diese Funktion dient dazu, alle offenen Positionen zu schließen, die bestimmte Kriterien erfüllen. Es basiert auf einem Flag-System, mit dem festgelegt werden kann, welche Handelsgeschäfte zu schließen sind:
- nur mit Gewinn,
- nur mit Verlust,
- beide Arten (alle Handelsgeschäfte).
void CloseAllPositions(int flags = FLAG_CLOSE_ALL_LOSS | FLAG_CLOSE_ALL_PROFIT);
- Flags – eine ganze Zahl, die die Bedingungen angibt, unter denen Positionen geschlossen werden sollen. Mehrere Merker können mit bitweisen OR-Operatoren (|) kombiniert werden.
#define FLAG_CLOSE_ALL_PROFIT 2 //Flag indicating to close only operations with profit #define FLAG_CLOSE_ALL_LOSS 4 //Flag indicating to close only operations without profit
Die Flags sind als Zweierpotenzen definiert.
Jedes Flag steht für einen Wert, der unabhängig oder in Kombination aktiviert werden kann:
| Flag | Wert (dezimal) | Wert (binär) | Zweck |
|---|---|---|---|
| FLAG_CLOSE_ALL_PROFIT | 2 | 00000010 | Schließt nur profitable Handelsgeschäfte ab. |
| FLAG_CLOSE_ALL_LOSS | 4 | 00000100 | Schließt nur Verlustgeschäfte ab. |
2. Funktion zum Schließen von Positionen
Diese Funktion durchläuft alle offenen Positionen und schließt sie entsprechend den aktiven Flags.
3. Iteration durch alle offenen Positionen
for(int i = PositionsTotal() - 1; i >= 0; i--)
- PositionsTotal() gibt die Gesamtzahl der offenen Positionen zurück.
- Die Schleife durchläuft die Positionen in umgekehrter Reihenfolge (von der letzten zur ersten), um Fehler beim Schließen von Positionen in Echtzeit zu vermeiden.
4. Abrufen der Positionskennung (Ticket)
ulong position_ticket = PositionGetTicket(i);
- Jede Position hat ein eindeutiges Ticket, das sie identifiziert.
5. Auswahl der Position
if (!PositionSelectByTicket(position_ticket)) continue;
- PositionSelectByTicket(position_ticket) versucht, anhand des übergebenen Tickets eine Position auszuwählen.
- Wenn die Auswahl fehlschlägt, wird mit „continue“ zur nächsten Position übergegangen.
6. Überprüfung der magischen Zahl
ulong magic = PositionGetInteger(POSITION_MAGIC); if (magic != this.magic_number && this.magic_number != NOT_MAGIC_NUMBER) continue;
- Die magische Zahl der Position wird abgerufen.
- Wenn die Position eine andere magische Zahl als die erwartete hat und die Bearbeitung einer beliebigen Reihenfolge nicht zulässig ist (NOT_MAGIC_NUMBER), wird die Position ignoriert.
7. Abrufen des Positionsgewinns
double profit = PositionGetDouble(POSITION_PROFIT);
- POSITION_PROFIT gibt den aktuellen Gewinn des Handelsgeschäfts zurück. Dieser Wert kann positiv (Gewinn) oder negativ (Verlust) sein.
8. Prüfen von Flags und das Schließen von Handelsgeschäften
if ((flags & FLAG_CLOSE_ALL_PROFIT) != 0 && profit > 0) { trade.PositionClose(position_ticket); } else if ((flags & FLAG_CLOSE_ALL_LOSS) != 0 && profit < 0) { trade.PositionClose(position_ticket); }
- Der &-Operator wird verwendet, um zu prüfen, ob ein Flag aktiviert ist.
- Wenn FLAG_CLOSE_ALL_PROFIT aktiv ist und die Position profitabel ist, wird sie geschlossen.
- Wenn FLAG_CLOSE_ALL_LOSS aktiv ist und die Position zeigt einen Verlust, wird sie geschlossen.
void CRiskManagemet::CloseAllPositions(int flags = FLAG_CLOSE_ALL_LOSS | FLAG_CLOSE_ALL_PROFIT) { for(int i = PositionsTotal() - 1; i >= 0; i--) { ulong position_ticket = PositionGetTicket(i); if(!PositionSelectByTicket(position_ticket)) continue; // If you don't select the position, continue double profit = PositionGetDouble(POSITION_PROFIT); // Check flags before closing the position if((flags & FLAG_CLOSE_ALL_PROFIT) != 0 && profit > 0) // Close only profit positions { trade.PositionClose(position_ticket); } else if((flags & FLAG_CLOSE_ALL_LOSS) != 0 && profit < 0) // Close only losing positions { trade.PositionClose(position_ticket); } } }
Geplante Ereignisse für den neuen Tag und die neue Woche
Zum Abschluss dieses Artikels werden wir die letzten Funktionen implementieren, die bei bestimmten Ereignissen ausgeführt werden. Insbesondere werden wir zwei Schlüsselfunktionen schaffen:
- Tägliches Ereignis – wird zu Beginn eines jeden neuen Tages ausgeführt.
- Wöchentliches Ereignis – wird zu Beginn einer jeden neuen Woche ausgeführt.
Diese Ereignisse tragen dazu bei, Verluste und Gewinne strukturiert zu verwalten und die korrekte Aktualisierung der Werte zu gewährleisten.
Tägliches Ereignis
Jeden Tag müssen die Werte für alle maximalen Verluste und Gewinne neu berechnet und eingestellt sowie der kumulierte Tagesgewinn auf Null gesetzt werden. Wir drucken auch Verlust- und Gewinnwerte zu Kontrollzwecken in das Protokoll.//+------------------------------------------------------------------+ //| Function that runs every new day | //+------------------------------------------------------------------+ void CRiskManagemet::OnNewDay(void) { SetMWL(); SetMDL(); SetML(); SetMDP(); SetGMLPO(); this.daily_profit = 0; this.last_day_time = iTime(_Symbol,PERIOD_D1,0); Print(" New day "); Print(StringFormat("%-6s| %s", "Losses", "Loss")); Print(StringFormat("%-6s| %.2f", "MDP", this.mdp.value)); Print(StringFormat("%-6s| %.2f", "MWL", this.mwl.value)); Print(StringFormat("%-6s| %.2f", "ML", this.ml.value)); Print(StringFormat("%-6s| %.2f", "MDl", this.mdl.value)); Print(StringFormat("%-6s| %.2f", "GMLPO", this.gmlpo.value)); }
- Alle erforderlichen Funktionen zum Setzen von Verlust- und Gewinnwerten werden aufgerufen.
- Die Variable daily_profit wird auf Null zurückgesetzt, um einen neuen Tag zu beginnen, ohne frühere Gewinne oder Verluste zu übertragen.
- Der Zeitstempel des letzten aufgezeichneten Tages wird mit iTime(_Symbol, PERIOD_D1, 0) gespeichert.
- Verlust- und Gewinnwerte werden zur Überwachung des Systemverhaltens im Protokoll ausgedruckt.
Wöchentliche Ereignisse
Das wöchentliche Ereignis ist dafür verantwortlich, den Beginn einer neuen Woche zu registrieren und den kumulierten Gewinn der Vorwoche auf Null zurückzusetzen.//+------------------------------------------------------------------+ //| Function that runs every new week | //+------------------------------------------------------------------+ void CRiskManagemet::OnNewWeek(void) { this.last_weekly_time = iTime(_Symbol,PERIOD_W1,0); this.weekly_profit = 0; }
- Die Variable last_weekly_time wird mit der Öffnungszeit der neuen Woche aktualisiert.
- Die Variable weekly_profit wird auf Null zurückgesetzt, um eine Kumulierung von Gewinnen oder Verlusten aus der Vorwoche zu verhindern.
Erkennung neuer Ereignisse (Tag/Woche/Nutzerdefinierter Zeitraum)
Um diese Funktionen in einem Expert Advisor (EA) automatisch auszuführen, können wir mit Hilfe einer Datetime-Variablen prüfen, ob sich der Zeitraum geändert hat. So können wir einen neuen Tag, eine neue Woche oder einen anderen Zeitrahmen (H1, H12 usw.) erkennen.
Beispiel für die Erkennung eines neuen Tages:
datetime prev_time = 0; void OnTick() { if(prev_time != iTime(_Symbol, PERIOD_D1, 0)) { Print("New day detected"); prev_time = iTime(_Symbol, PERIOD_D1, 0); OnNewDay(); // Call the corresponding function } }
Beispiel für die Erkennung einer neuen Woche:
datetime prev_week_time = 0; void OnTick() { if(prev_week_time != iTime(_Symbol, PERIOD_W1, 0)) { Print("New week detected") //Call the corresponding function prev_week_time = iTime(_Symbol, PERIOD_W1, 0); } }
Erläuterung:
- Eine Datetime-Variable wird definiert, um die zuvor aufgezeichnete Zeit zu speichern.
- Bei jedem Tick (OnTick) wird die aktuelle Zeit mit dem in prev_time oder prev_week_time gespeicherten Wert verglichen.
- Wenn sich der Wert geändert hat, bedeutet dies, dass ein neuer Tag oder eine neue Woche begonnen hat, und die Funktion OnNewDay() oder OnNewWeek() wird aufgerufen.
- Die Variable prev_time oder prev_week_time wird mit dem neuen Wert aktualisiert.
Schlussfolgerung
In diesem Artikel haben wir den ersten Teil der Risikomanagementklasse CRiskManagement entwickelt. In dieser ersten Phase haben wir uns vor allem darauf konzentriert, den maximalen Verlusten und Gewinnen Werte zuzuweisen und damit die Grundlage für eine strukturierte Risikokontrolle zu schaffen.
Obwohl die Klasse noch nicht für den Einsatz in einer realen Handelsumgebung bereit ist, können wir bereits sehen, wie diese Werte im System zugewiesen und verwaltet werden.
Im nächsten Artikel werden wir die Implementierung dieser Klasse vervollständigen, indem wir Schlüsselfunktionen hinzufügen, mit denen wir:
- prüfen, ob die Verlustobergrenzen überschritten wurden, und die entsprechenden Maßnahmen durchführen;
- neue Ereignisse hinzufügen, um das Risikomanagement weiter zu verbessern;
- spezifische Funktionen erstellen, wie z.B. die automatische Aktualisierung des maximalen Tagesverlustes für Konten vom Typ Prop Firm, wie z.B. FTMO.
Mit diesen Verbesserungen wird die Klasse CRiskManagement in der Lage sein, Risikolimits effizient zu verwalten und sich an unterschiedliche Marktbedingungen anzupassen.
In diesem Artikel verwendete/verbesserte Dateien:
| Dateiname | Typ | Beschreibung |
|---|---|---|
| Risk_Management.mqh | .mqh (Include-Datei) | Die Hauptdatei mit gemeinsamen Funktionen und der Implementierung der Klasse CRiskManagement, die für das Risikomanagement im System zuständig ist. Diese Datei definiert, entwickelt und erweitert alle Funktionen im Zusammenhang mit der Gewinn- und Verlustverwaltung. |
Übersetzt aus dem Spanischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/es/articles/17249
Warnung: Alle Rechte sind von MetaQuotes Ltd. vorbehalten. Kopieren oder Vervielfältigen untersagt.
Dieser Artikel wurde von einem Nutzer der Website verfasst und gibt dessen persönliche Meinung wieder. MetaQuotes Ltd übernimmt keine Verantwortung für die Richtigkeit der dargestellten Informationen oder für Folgen, die sich aus der Anwendung der beschriebenen Lösungen, Strategien oder Empfehlungen ergeben.
Swap-Arbitrage am Devisenmarkt: Aufbau eines synthetischen Portfolios und Generierung eines konsistenten Swapflusses
Neuronale Netze im Handel: Hybride Graphsequenzmodelle (GSM++)
Eine alternative Log-datei mit der Verwendung der HTML und CSS
Verwendung von Deep Reinforcement Learning zur Verbesserung des Ilan Expert Advisor
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.