Bibliothek für ein leichtes und schnelles Entwickeln vom Programmen für den MetaTrader (Teil XXII): Handelsklassen - Basisklasse des Handels, Verifikation der Einschränkungen
Inhalt
- Konzept
- Erweiterung der Funktionen der Basis des Handelsobjekts
- Handelsklasse
- Tests
- Was kommt als Nächstes?
In dem vorhergehenden Artikel haben wir einen umfangreichen Bibliotheksteil eröffnet, der den Handelsfunktionen gewidmet ist, und das Basisobjekt des Handels mit dem Symbol erstellt. Das Handelsobjekt erhält über seine Parameter alle Eigenschaften einer an den Server gesendeten Handelsanfrage, füllt die Struktur der Handelsanfrage nach dem Typ der aufgerufenen Klassenmethode (Eröffnung einer Position/ Platzierung einer schwebenden Order/ Modifizierung/ Schließung/Entfernung) aus und sendet einen Handelsauftrag an den Server. Die gültigen Werte der Eigenschaften des Handelsauftrags werden an das Basis-Handelsobjekt für das Senden der Handelsauftrag übergeben. Um das Handelsobjekt jedoch in vollem Umfang nutzen zu können, müssen wir zunächst die bestehenden Einschränkungen für die Durchführung von Handelsoperationen im Terminal, Programm, Konto und Symbol überprüfen. Nach dem Bestehen dieser ersten Prüfungen sind wir in der Lage, die Eigenschaften der Handelsanfrage zu überprüfen.
In diesem Artikel werden wir die Entwicklung einer vollwertigen Handelsklasse beginnen. Das erste, was wir implementieren werden, ist die Überprüfung der Einschränkungen der Handelsoperationen.
Konzept
Wir haben bereits das Basis-Handelsobjekt, das ein Teil des Symbolobjekts ist. Es füllt die Struktur der Handelsanfrage gemäß den an eine der Klassenmethoden übergebenen Parametern aus und sendet eine Handelsorder an den Server. Bevor wir eine vollwertige Handelsklasse implementieren, werden wir einige Funktionen des Basis-Handelsobjekts hinzufügen — nämlich die Möglichkeit, die Ergebnisse der gesendeten Handelsaufträge mitzuteilen. Dies wird uns erlauben, jeden beliebigen Ton für das Sprechen von Handelsereignissen einzustellen. Wir können benutzerdefinierte Sounds für jedes Handelsereignis in jedem Symbol einstellen. Natürlich können wir einen Satz von Sounds für jedes der Ereignisse, die allen Symbolen gemeinsam sind, festlegen. Das grundlegende Handelsobjekt ist es, reichlich Möglichkeiten zu bieten, um Sounds für Handelsereignisse einzustellen, unabhängig davon, ob die Töne für alle Symbole und Ereignisse gleich sein sollen oder ob sie für jedes einzelne Symbol und Ereignis unterschiedlich sein sollen.
Als Nächstes werden wir eine Handelsklasse erstellen, von der aus alle Handelsoperationen durchgeführt werden sollen. In diesem Artikel werden wir die minimale Funktionalität für die Klasse implementieren — die Überprüfung der Handelsoperationen und den Aufruf der notwendigen Methoden der Basis-Handelsobjekte der benötigten Symbole.
Erweiterung der Funktionen der Basis des Handelsobjekts
Um Töne oder Sounds Handelsereignissen zuzuordnen, benötigen wir Makro-Substitutionen und Enumerationen. Öffnen Sie die Datei Defines.mqh, fügen Sie Makro-Substitutionen hinzu und ersetzen Sie die Namen der Standard-Audiodateien:
//+------------------------------------------------------------------+ //| Macro-Substitution | //+------------------------------------------------------------------+ //--- Beschreibung der Funktion mit der Zeilennummer des Fehlers #define DFUN_ERR_LINE (__FUNCTION__+(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian" ? ", Page " : ", Line ")+(string)__LINE__+": ") #define DFUN (__FUNCTION__+": ") // "Function description" #define COUNTRY_LANG ("Russian") // Country language #define END_TIME (D'31.12.3000 23:59:59') // End date for account history data requests #define TIMER_FREQUENCY (16) // Minimal frequency of the library timer in milliseconds //--- Standard sounds #define SND_ALERT "alert.wav" #define SND_ALERT2 "alert2.wav" #define SND_CONNECT "connect.wav" #define SND_DISCONNECT "disconnect.wav" #define SND_EMAIL "email.wav" #define SND_EXPERT "expert.wav" #define SND_NEWS "news.wav" #define SND_OK "ok.wav" #define SND_REQUEST "request.wav" #define SND_STOPS "stops.wav" #define SND_TICK "tick.wav" #define SND_TIMEOUT "timeout.wav" #define SND_WAIT "wait.wav" //--- Parameters of the orders and deals collection timer
Dies macht es bequemer, Namen für die Festlegung von Standard-Audiodateien zu spezifizieren, wenn wir diese als Audiodateien für die Vertonung von Handelsereignissen verwenden wollen.
Nach der Auflistung innerhalb des Datenblocks für die Arbeit mit Handelsklassen, dem Hinzufügen der Enumeration der Handelsoperationsarten und der Enumeration der Audioeinstellungsmodi:
//+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Data for working with trading classes | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Logging level | //+------------------------------------------------------------------+ enum ENUM_LOG_LEVEL { LOG_LEVEL_NO_MSG, // Trading logging disabled LOG_LEVEL_ERROR_MSG, // Only trading errors LOG_LEVEL_ALL_MSG // Full logging }; //+------------------------------------------------------------------+ //| Types of performed operations | //+------------------------------------------------------------------+ enum ENUM_ACTION_TYPE { ACTION_TYPE_BUY = ORDER_TYPE_BUY, // Open Buy ACTION_TYPE_SELL = ORDER_TYPE_SELL, // Open Sell ACTION_TYPE_BUY_LIMIT = ORDER_TYPE_BUY_LIMIT, // Place BuyLimit ACTION_TYPE_SELL_LIMIT = ORDER_TYPE_SELL_LIMIT, // Place SellLimit ACTION_TYPE_BUY_STOP = ORDER_TYPE_BUY_STOP, // Place BuyStop ACTION_TYPE_SELL_STOP = ORDER_TYPE_SELL_STOP, // Place SellStop ACTION_TYPE_BUY_STOP_LIMIT = ORDER_TYPE_BUY_STOP_LIMIT, // Place BuyStopLimit ACTION_TYPE_SELL_STOP_LIMIT = ORDER_TYPE_SELL_STOP_LIMIT, // Place SellStopLimit ACTION_TYPE_CLOSE_BY = ORDER_TYPE_CLOSE_BY, // Close a position by an opposite one ACTION_TYPE_MODIFY = ACTION_TYPE_CLOSE_BY+1, // Modification }; //+------------------------------------------------------------------+ //| Sound setting mode | //+------------------------------------------------------------------+ enum ENUM_MODE_SET_SOUND { MODE_SET_SOUND_OPEN, // Opening/placing sound setting mode MODE_SET_SOUND_CLOSE, // Closing/removal sound setting mode MODE_SET_SOUND_MODIFY_SL, // StopLoss modification sound setting mode MODE_SET_SOUND_MODIFY_TP, // TakeProfit modification sound setting mode MODE_SET_SOUND_MODIFY_PRICE, // Placing price modification sound setting mode MODE_SET_SOUND_ERROR_OPEN, // Opening/placing error sound setting mode MODE_SET_SOUND_ERROR_CLOSE, // Closing/removal error sound setting mode MODE_SET_SOUND_ERROR_MODIFY_SL, // StopLoss modification error sound setting mode MODE_SET_SOUND_ERROR_MODIFY_TP, // TakeProfit modification error sound setting mode MODE_SET_SOUND_ERROR_MODIFY_PRICE, // Placing price modification error sound setting mode }; //+------------------------------------------------------------------+
Mit der Terminalversion 2155 wurden neue Symbol- und Kontoeigenschaften in MQL5 eingeführt:
- MQL5: Die Enumeration ENUM_SYMBOL_INFO_STRING wurde um folgende Werte erweitert:
- SYMBOL_CATEGORY — Symbolkategorie. Sie wird zur zusätzlichen Kennzeichnung von Finanzinstrumenten verwendet. Dies kann beispielsweise die Marktsparte sein, zu der das Symbol gehört: Landwirtschaft, Öl & Gas und andere.
- SYMBOL_EXCHANGE — der Name der Börse, an der das Symbol gehandelt wird.
- MQL5: Unterstützung für die Positionsschließung nach der FIFO-Regel hinzugefügt.
- Der Wert ACCOUNT_FIFO_CLOSE wurde zu ENUM_ACCOUNT_INFO_INTEGER hinzugefügt. Er führt dazu, dass Positionen nur nach der FIFO-Regel geschlossen werden können. Wenn der Wert der Eigenschaft wahr ist, können die Positionen für jedes Instrument nur in der gleichen Reihenfolge geschlossen werden, in der sie geöffnet wurden: das älteste sollte zuerst geschlossen werden, dann das nächste usw. Bei einem Versuch, Positionen in einer anderen Reihenfolge zu schließen, wird ein Fehler zurückgegeben. Bei Konten ohne Hedging-Positionsverwaltung (ACCOUNT_MARGIN_MODE!=ACCOUNT_MARGIN_MODE_RETAIL_HEDGING) ist der Wert dieser Eigenschaft immer "falsch".
- Neuer Rückgabewert: MT_RET_REQUEST_CLOSE_ONLY — der Auftrag wird abgelehnt, da für das Symbol die Regel "Nur das Schließen vorhandener Positionen nach FIFO-Regel erlaubt" gesetzt ist.
Es gibt im Wesentlichen drei Methoden, um eine Position zu schließen:
- Schließen vom Client-Terminal aus: Der Händler schließt die Position manuell, mit einem Handelsroboter, basierend auf dem Signals Service Abonnement, etc. Im Falle eines Versuchs, eine Position zu schließen, die nicht der FIFO-Regel entspricht, erhält der Händler einen entsprechenden Fehler.
- Schließen bei Stop-Loss oder Take-Profit-Aktivierung: Diese Orders werden serverseitig verarbeitet, so dass die Positionsschließung nicht auf der Händler-(Terminal-)Seite angefordert wird, sondern vom Server initiiert wird. Wenn Stop-Loss oder Take-Profit für eine Position auslöst und diese Position nicht der FIFO-Regel entspricht (es gibt eine ältere Position für das gleiche Symbol), wird die Position nicht geschlossen.
- Schließen beim Auslösen von Stop-Out: Solche Operationen werden auch serverseitig verarbeitet. In einem normalen Modus, in dem das FIFO-basierte Schließen deaktiviert ist, werden im Falle von Stop-Out Positionen geschlossen, beginnend mit derjenigen mit dem größten Verlust. Wenn diese Option aktiviert ist, wird zusätzlich die Eröffnungszeit der Verlustpositionen überprüft. Der Server ermittelt die Verlustpositionen für jedes Symbol, findet die älteste Position für jedes Symbol und schließt dann diejenige, die den größten Verlust unter den gefundenen Positionen aufweist.
In Anbetracht all dessen wurden die neuen Eigenschaften den Symbol- und Kontoobjekten hinzugefügt.
Die neue Eigenschaft wurde dem Block der ganzzahligen Eigenschaften des Kontos hinzugefügt, und die Anzahl der ganzzahligen Eigenschaften wurde auf 11 erhöht:
//+------------------------------------------------------------------+ //| Account integer properties | //+------------------------------------------------------------------+ enum ENUM_ACCOUNT_PROP_INTEGER { ACCOUNT_PROP_LOGIN, // Account number ACCOUNT_PROP_TRADE_MODE, // Trading account type ACCOUNT_PROP_LEVERAGE, // Leverage ACCOUNT_PROP_LIMIT_ORDERS, // Maximum allowed number of active pending orders ACCOUNT_PROP_MARGIN_SO_MODE, // Mode of setting the minimum available margin level ACCOUNT_PROP_TRADE_ALLOWED, // Permission to trade for the current account from the server side ACCOUNT_PROP_TRADE_EXPERT, // Permission to trade for an EA from the server side ACCOUNT_PROP_MARGIN_MODE, // Margin calculation mode ACCOUNT_PROP_CURRENCY_DIGITS, // Number of digits for an account currency necessary for accurate display of trading results ACCOUNT_PROP_SERVER_TYPE, // Trade server type (MetaTrader5, MetaTrader4) ACCOUNT_PROP_FIFO_CLOSE // Flag of a position closure by FIFO rule only }; #define ACCOUNT_PROP_INTEGER_TOTAL (11) // Total number of integer properties #define ACCOUNT_PROP_INTEGER_SKIP (0) // Number of integer account properties not used in sorting //+------------------------------------------------------------------+
Der Block der möglichen Sortierkriterien für Konten wurde um das neue Sortierkriterium nach ganzzahligen Eigenschaften erweitert:
//+------------------------------------------------------------------+ //| Possible account sorting criteria | //+------------------------------------------------------------------+ #define FIRST_ACC_DBL_PROP (ACCOUNT_PROP_INTEGER_TOTAL-ACCOUNT_PROP_INTEGER_SKIP) #define FIRST_ACC_STR_PROP (ACCOUNT_PROP_INTEGER_TOTAL-ACCOUNT_PROP_INTEGER_SKIP+ACCOUNT_PROP_DOUBLE_TOTAL-ACCOUNT_PROP_DOUBLE_SKIP) enum ENUM_SORT_ACCOUNT_MODE { //--- Sortieren nach den Integer-Eigenschaften SORT_BY_ACCOUNT_LOGIN = 0, // Sort by account number SORT_BY_ACCOUNT_TRADE_MODE, // Sort by trading account type SORT_BY_ACCOUNT_LEVERAGE, // Sort by leverage SORT_BY_ACCOUNT_LIMIT_ORDERS, // Sort by maximum acceptable number of existing pending orders SORT_BY_ACCOUNT_MARGIN_SO_MODE, // Sort by mode for setting the minimum acceptable margin level SORT_BY_ACCOUNT_TRADE_ALLOWED, // Sort by permission to trade for the current account SORT_BY_ACCOUNT_TRADE_EXPERT, // Sort by permission to trade for an EA SORT_BY_ACCOUNT_MARGIN_MODE, // Sort by margin calculation mode SORT_BY_ACCOUNT_CURRENCY_DIGITS, // Sort by number of digits for an account currency SORT_BY_ACCOUNT_SERVER_TYPE, // Sort by trade server type (MetaTrader5, MetaTrader4) SORT_BY_ACCOUNT_FIFO_CLOSE, // Sort by the flag of a position closure by FIFO rule only //--- Sortieren nach den Double-Eigenschaften
Die Eigenschaften der Symbolobjekte werden auf ähnliche Weise hinzugefügt.
Der Block der String-Eigenschaften verfügt über zwei neue Eigenschaften, und die Anzahl der String-Eigenschaften wurde auf 13 erhöht:
//+------------------------------------------------------------------+ //| Symbol string properties | //+------------------------------------------------------------------+ enum ENUM_SYMBOL_PROP_STRING { SYMBOL_PROP_NAME = (SYMBOL_PROP_INTEGER_TOTAL+SYMBOL_PROP_DOUBLE_TOTAL), // Symbol name SYMBOL_PROP_BASIS, // Name of the underlaying asset for a derivative symbol SYMBOL_PROP_CURRENCY_BASE, // Instrument base currency SYMBOL_PROP_CURRENCY_PROFIT, // Profit currency SYMBOL_PROP_CURRENCY_MARGIN, // Margin currency SYMBOL_PROP_BANK, // Source of the current quote SYMBOL_PROP_DESCRIPTION, // String description of a symbol SYMBOL_PROP_FORMULA, // The formula used for custom symbol pricing SYMBOL_PROP_ISIN, // The name of a trading symbol in the international system of securities identification numbers (ISIN) SYMBOL_PROP_PAGE, // The web page containing symbol information SYMBOL_PROP_PATH, // Location in the symbol tree SYMBOL_PROP_CATEGORY, // Symbol category SYMBOL_PROP_EXCHANGE // Name of an exchange a symbol is traded on }; #define SYMBOL_PROP_STRING_TOTAL (13) // Total number of string properties //+------------------------------------------------------------------+
Die Liste der möglichen Sortierkriterien für Symbole wurde um die beiden neuen Kriterien für die Sortierung nach den Eigenschaften von Symbolen erweitert:
//--- Sortieren nach den String-Eigenschaften SORT_BY_SYMBOL_NAME = FIRST_SYM_STR_PROP, // Sort by a symbol name SORT_BY_SYMBOL_BASIS, // Sort by an underlying asset of a derivative SORT_BY_SYMBOL_CURRENCY_BASE, // Sort by a base currency of a symbol SORT_BY_SYMBOL_CURRENCY_PROFIT, // Sort by a profit currency SORT_BY_SYMBOL_CURRENCY_MARGIN, // Sort by a margin currency SORT_BY_SYMBOL_BANK, // Sort by a feeder of the current quote SORT_BY_SYMBOL_DESCRIPTION, // Sort by a symbol string description SORT_BY_SYMBOL_FORMULA, // Sort by the formula used for custom symbol pricing SORT_BY_SYMBOL_ISIN, // Sort by the name of a symbol in the ISIN system SORT_BY_SYMBOL_PAGE, // Sort by an address of the web page containing symbol information SORT_BY_SYMBOL_PATH, // Sort by a path in the symbol tree SORT_BY_SYMBOL_CATEGORY, // Sort by symbol category SORT_BY_SYMBOL_EXCHANGE // Sort by a name of an exchange a symbol is traded on }; //+------------------------------------------------------------------+
Außerdem wurden einige neue Konstanten der Bibliotheksindizes für Textnachrichten hinzugefügt, um mit neuen Eigenschaften von Objekten, Klassen und Methoden arbeiten zu können.
Betrachten wir die neuen Konstanten in der Datei Datas.mqh:
//+------------------------------------------------------------------+ //| List of the library's text message indices | //+------------------------------------------------------------------+ enum ENUM_MESSAGES_LIB { MSG_LIB_PARAMS_LIST_BEG=ERR_USER_ERROR_FIRST, // Beginning of the parameter list MSG_LIB_PARAMS_LIST_END, // End of the parameter list MSG_LIB_PROP_NOT_SUPPORTED, // Property not supported MSG_LIB_PROP_NOT_SUPPORTED_MQL4, // Property not supported in MQL4 MSG_LIB_PROP_NOT_SUPPORTED_MT5_LESS_2155, // Property not supported in MetaTrader 5 versions lower than 2155 MSG_LIB_PROP_NOT_SUPPORTED_POSITION, // Property not supported for position MSG_LIB_PROP_NOT_SUPPORTED_PENDING, // Property not supported for pending order MSG_LIB_PROP_NOT_SUPPORTED_MARKET, // Property not supported for market order MSG_LIB_PROP_NOT_SUPPORTED_MARKET_HIST, // Property not supported for historical market order MSG_LIB_PROP_NOT_SET, // Value not set MSG_LIB_PROP_EMPTY, // Not set MSG_LIB_SYS_ERROR, // Error MSG_LIB_SYS_NOT_SYMBOL_ON_SERVER, // Error. No such symbol on server MSG_LIB_SYS_NOT_SYMBOL_ON_LIST, // Error. No such symbol in the list of used symbols: MSG_LIB_SYS_FAILED_PUT_SYMBOL, // Failed to place to market watch. Error: MSG_LIB_SYS_NOT_GET_PRICE, // Failed to get current prices. Error: MSG_LIB_SYS_NOT_GET_MARGIN_RATES, // Failed to get margin ratios. Error: MSG_LIB_SYS_NOT_GET_DATAS, // Failed to get data MSG_LIB_SYS_FAILED_CREATE_STORAGE_FOLDER, // Failed to create folder for storing files. Error: MSG_LIB_SYS_FAILED_ADD_ACC_OBJ_TO_LIST, // Error. Failed to add current account object to collection list MSG_LIB_SYS_FAILED_CREATE_CURR_ACC_OBJ, // Error. Failed to create account object with current account data MSG_LIB_SYS_FAILED_OPEN_FILE_FOR_WRITE, // Could not open file for writing MSG_LIB_SYS_INPUT_ERROR_NO_SYMBOL, // Input error: no symbol MSG_LIB_SYS_FAILED_CREATE_SYM_OBJ, // Failed to create symbol object MSG_LIB_SYS_FAILED_ADD_SYM_OBJ, // Failed to add symbol MSG_LIB_SYS_NOT_GET_CURR_PRICES, // Failed to get current prices by event symbol MSG_LIB_SYS_EVENT_ALREADY_IN_LIST, // This event is already in the list MSG_LIB_SYS_FILE_RES_ALREADY_IN_LIST, // This file already created and added to list: MSG_LIB_SYS_FAILED_CREATE_RES_LINK, // Error. Failed to create object pointing to resource file MSG_LIB_SYS_ERROR_ALREADY_CREATED_COUNTER, // Error. Counter with ID already created MSG_LIB_SYS_FAILED_CREATE_COUNTER, // Failed to create timer counter MSG_LIB_SYS_FAILED_CREATE_TEMP_LIST, // Error creating temporary list MSG_LIB_SYS_ERROR_NOT_MARKET_LIST, // Error. This is not a market collection list MSG_LIB_SYS_ERROR_NOT_HISTORY_LIST, // Error. This is not a history collection list MSG_LIB_SYS_FAILED_ADD_ORDER_TO_LIST, // Could not add order to the list MSG_LIB_SYS_FAILED_ADD_DEAL_TO_LIST, // Could not add deal to the list MSG_LIB_SYS_FAILED_ADD_CTRL_ORDER_TO_LIST, // Failed to add control order MSG_LIB_SYS_FAILED_ADD_CTRL_POSITION_TO_LIST, // Failed to add control position MSG_LIB_SYS_FAILED_ADD_MODIFIED_ORD_TO_LIST, // Could not add modified order to the list of modified orders MSG_LIB_SYS_FAILED_CREATE_TIMER, // Failed to create timer. Error: MSG_LIB_SYS_NO_TICKS_YET, // No ticks yet MSG_LIB_SYS_FAILED_CREATE_OBJ_STRUCT, // Could not create object structure MSG_LIB_SYS_FAILED_WRITE_UARRAY_TO_FILE, // Could not write uchar array to file MSG_LIB_SYS_FAILED_LOAD_UARRAY_FROM_FILE, // Could not load uchar array from file MSG_LIB_SYS_FAILED_CREATE_OBJ_STRUCT_FROM_UARRAY, // Could not create object structure from uchar array MSG_LIB_SYS_FAILED_SAVE_OBJ_STRUCT_TO_UARRAY, // Failed to save object structure to uchar array, error MSG_LIB_SYS_ERROR_INDEX, // Error. "index" value should be within 0 - 3 MSG_LIB_SYS_ERROR_FAILED_CONV_TO_LOWERCASE, // Failed to convert string to lowercase, error //--- COrder MSG_ORD_BUY, // Buy MSG_ORD_SELL, // Sell MSG_ORD_TO_BUY, // Buy order MSG_ORD_TO_SELL, // Sell order MSG_DEAL_TO_BUY, // Buy deal MSG_DEAL_TO_SELL, // Sell deal MSG_ORD_MARKET, // Market order MSG_ORD_HISTORY, // Historical order MSG_ORD_DEAL, // Deal MSG_ORD_POSITION, // Position MSG_ORD_PENDING_ACTIVE, // Active pending order MSG_ORD_PENDING, // Pending order MSG_ORD_UNKNOWN_TYPE, // Unknown order type MSG_POS_UNKNOWN_TYPE, // Unknown position type MSG_POS_UNKNOWN_DEAL, // Unknown deal type //--- //--- MSG_SYM_PROP_NAME, // Symbol name MSG_SYM_PROP_BASIS, // Underlying asset of derivative MSG_SYM_PROP_CURRENCY_BASE, // Basic currency of symbol MSG_SYM_PROP_CURRENCY_PROFIT, // Profit currency MSG_SYM_PROP_CURRENCY_MARGIN, // Margin currency MSG_SYM_PROP_BANK, // Feeder of the current quote MSG_SYM_PROP_DESCRIPTION, // Symbol description MSG_SYM_PROP_FORMULA, // Formula used for custom symbol pricing MSG_SYM_PROP_ISIN, // Symbol name in ISIN system MSG_SYM_PROP_PAGE, // Address of web page containing symbol information MSG_SYM_PROP_PATH, // Location in symbol tree MSG_SYM_PROP_CAYEGORY, // Symbol category MSG_SYM_PROP_EXCHANGE, // Name of an exchange a symbol is traded on //--- //--- MSG_SYM_TRADE_MODE_DISABLED, // Trade disabled for symbol MSG_SYM_TRADE_MODE_LONGONLY, // Only long positions allowed MSG_SYM_TRADE_MODE_SHORTONLY, // Only short positions allowed MSG_SYM_TRADE_MODE_CLOSEONLY, // Enable close only MSG_SYM_TRADE_MODE_FULL, // No trading limitations MSG_SYM_MARKET_ORDER_DISABLED, // Market orders disabled MSG_SYM_LIMIT_ORDER_DISABLED, // Limit orders disabled MSG_SYM_STOP_ORDER_DISABLED, // Stop orders disabled MSG_SYM_STOP_LIMIT_ORDER_DISABLED, // StopLimit orders disabled MSG_SYM_SL_ORDER_DISABLED, // StopLoss orders disabled MSG_SYM_TP_ORDER_DISABLED, // TakeProfit orders disabled MSG_SYM_CLOSE_BY_ORDER_DISABLED, // CloseBy orders disabled //--- //--- CAccount MSG_ACC_PROP_LOGIN, // Account number MSG_ACC_PROP_TRADE_MODE, // Trading account type MSG_ACC_PROP_LEVERAGE, // Leverage MSG_ACC_PROP_LIMIT_ORDERS, // Maximum allowed number of active pending orders MSG_ACC_PROP_MARGIN_SO_MODE, // Mode of setting the minimum available margin level MSG_ACC_PROP_TRADE_ALLOWED, // Trading permission of the current account MSG_ACC_PROP_TRADE_EXPERT, // Trading permission of an EA MSG_ACC_PROP_MARGIN_MODE, // Margin calculation mode MSG_ACC_PROP_CURRENCY_DIGITS, // Number of decimal places for the account currency MSG_ACC_PROP_SERVER_TYPE, // Trade server type MSG_ACC_PROP_FIFO_CLOSE, // Flag of a position closure by FIFO rule only //--- //--- CTrading MSG_LIB_TEXT_TERMINAL_NOT_TRADE_ENABLED, // Trade operations are not allowed in the terminal (the AutoTrading button is disabled) MSG_LIB_TEXT_EA_NOT_TRADE_ENABLED, // EA is not allowed to trade (F7 --> Common --> Allow Automated Trading) MSG_LIB_TEXT_ACCOUNT_NOT_TRADE_ENABLED, // Trading is disabled for the current account MSG_LIB_TEXT_ACCOUNT_EA_NOT_TRADE_ENABLED, // Trading on the trading server side is disabled for EAs on the current account MSG_LIB_TEXT_TERMINAL_NOT_CONNECTED, // No connection to the trade server MSG_LIB_TEXT_REQUEST_REJECTED_DUE, // Request was rejected before sending to the server due to: MSG_LIB_TEXT_NOT_ENOUTH_MONEY_FOR, // Insufficient funds for opening a position: MSG_LIB_TEXT_MAX_VOLUME_LIMIT_EXCEEDED, // Exceeded maximum allowed aggregate volume of orders and positions in one direction MSG_LIB_TEXT_REQ_VOL_LESS_MIN_VOLUME, // Request volume is less than the minimum acceptable one MSG_LIB_TEXT_REQ_VOL_MORE_MAX_VOLUME, // Request volume exceeds the maximum acceptable one MSG_LIB_TEXT_CLOSE_BY_ORDERS_DISABLED, // Close by is disabled MSG_LIB_TEXT_INVALID_VOLUME_STEP, // Request volume is not a multiple of the minimum lot change step gradation MSG_LIB_TEXT_CLOSE_BY_SYMBOLS_UNEQUAL, // Symbols of opposite positions are not equal };
Außerdem fügen wir die den deklarierten Konstanten entsprechenden Texte zu den Arrays der Textnachrichten hinzu:
//+------------------------------------------------------------------+ //| Array of predefined library messages | //| (1) in user's country language | //| (2) in the international language (English) | //| (3) any additional language. | //| The default languages are English and Russian. | //| To add the necessary number of other languages, simply | //| set the total number of used languages in TOTAL_LANG | //| and add the necessary translation after the English text | //+------------------------------------------------------------------+ string messages_library[][TOTAL_LANG]= { {"Начало списка параметров","Beginning of event parameter list"}, {"Конец списка параметров","End of parameter list"}, {"Свойство не поддерживается","Property not supported"}, {"Свойство не поддерживается в MQL4","Property not supported in MQL4"}, {"Свойство не поддерживается в MetaTrader5 версии ниже 2155","Property not supported in MetaTrader 5, build lower than 2155"}, {"Свойство не поддерживается у позиции","Property not supported for position"}, {"Свойство не поддерживается у отложенного ордера","Property not supported for pending order"}, {"Свойство не поддерживается у маркет-ордера","Property not supported for market order"}, {"Свойство не поддерживается у исторического маркет-ордера","Property not supported for historical market order"}, {"Значение не задано","Value not set"}, {"Отсутствует","Not set"}, {"Ошибка ","Error "}, {"Ошибка. Такого символа нет на сервере","Error. No such symbol on server"}, {"Ошибка. Такого символа нет в списке используемых символов: ","Error. This symbol is not in the list of symbols used: "}, {"Не удалось поместить в обзор рынка. Ошибка: ","Failed to put in market watch. Error: "}, {"Не удалось получить текущие цены. Ошибка: ","Could not get current prices. Error: "}, {"Не удалось получить коэффициенты взимания маржи. Ошибка: ","Failed to get margin rates. Error: "}, {"Не удалось получить данные ","Failed to get data of "}, {"Не удалось создать папку хранения файлов. Ошибка: ","Could not create file storage folder. Error: "}, {"Ошибка. Не удалось добавить текущий объект-аккаунт в список-коллекцию","Error. Failed to add current account object to collection list"}, {"Ошибка. Не удалось создать объект-аккаунт с данными текущего счёта","Error. Failed to create account object with current account data"}, {"Не удалось открыть для записи файл ","Could not open file for writing: "}, {"Ошибка входных данных: нет символа ","Input error: no "}, {"Не удалось создать объект-символ ","Failed to create symbol object "}, {"Не удалось добавить символ ","Failed to add "}, {"Не удалось получить текущие цены по символу события ","Failed to get current prices by event symbol "}, {"Такое событие уже есть в списке","This event already in the list"}, {"Такой файл уже создан и добавлен в список: ","This file has already been created and added to list: "}, {"Ошибка. Не удалось создать объект-указатель на файл ресурса","Error. Failed to create resource file link object"}, {"Ошибка. Уже создан счётчик с идентификатором ","Error. Already created counter with id "}, {"Не удалось создать счётчик таймера ","Failed to create timer counter "}, {"Ошибка создания временного списка","Error creating temporary list"}, {"Ошибка. Список не является списком рыночной коллекции","Error. The list is not a list of market collection"}, {"Ошибка. Список не является списком исторической коллекции","Error. The list is not a list of history collection"}, {"Не удалось добавить ордер в список","Could not add order to list"}, {"Не удалось добавить сделку в список","Could not add deal to list"}, {"Не удалось добавить контрольный ордер ","Failed to add control order "}, {"Не удалось добавить контрольую позицию ","Failed to add control position "}, {"Не удалось добавить модифицированный ордер в список изменённых ордеров","Could not add modified order to list of modified orders"}, {"Не удалось создать таймер. Ошибка: ","Could not create timer. Error: "}, //--- COrder {"Buy","Buy"}, {"Sell","Sell"}, {"Ордер на покупку","Buy order"}, {"Ордер на продажу","Sell order"}, {"Сделка на покупку","Buy deal"}, {"Сделка на продажу","Sell deal"}, {"Маркет-ордер","Market order"}, {"Исторический ордер","History order"}, {"Сделка","Deal"}, {"Позиция","Active position"}, {"Установленный отложенный ордер","Active pending order"}, {"Отложенный ордер","Pending order"}, {"Неизвестный тип ордера","Unknown order type"}, {"Неизвестный тип позиции","Unknown position type"}, {"Неизвестный тип сделки","Unknown deal type"}, //--- {"Путь в дереве символов","Path in symbol tree"}, {"Название категории или сектора, к которой принадлежит торговый символ","Name of sector or category trading symbol belongs to"}, {"Название биржи или площадки, на которой торгуется символ","Name of exchange financial symbol traded in"}, //--- {"Форекс символ","Forex symbol"}, {"Разрешены только операции закрытия позиций","Close only"}, {"Нет ограничений на торговые операции","No trade restrictions"}, {"Торговля рыночными ордерами запрещена","Trading through market orders prohibited"}, {"Установка Limit-ордеров запрещена","Limit orders prohibited"}, {"Установка Stop-ордеров запрещена","Stop orders prohibited"}, {"Установка StopLimit-ордеров запрещена","StopLimit orders prohibited"}, {"Установка StopLoss-ордеров запрещена","StopLoss orders prohibited"}, {"Установка TakeProfit-ордеров запрещена","TakeProfit orders prohibited"}, {"Установка CloseBy-ордеров запрещена","CloseBy orders prohibited"}, //--- {"Торговля по запросу","Execution by request"}, {"Торговля по потоковым ценам","Instant execution"}, {"Исполнение ордеров по рынку","Market execution"}, {"Биржевое исполнение","Exchange execution"}, //--- //--- CAccount {"Номер счёта","Account number"}, {"Тип торгового счета","Account trade mode"}, {"Размер предоставленного плеча","Account leverage"}, {"Максимально допустимое количество действующих отложенных ордеров","Maximum allowed number of active pending orders"}, {"Режим задания минимально допустимого уровня залоговых средств","Mode for setting minimal allowed margin"}, {"Разрешенность торговли для текущего счета","Allowed trade for the current account"}, {"Разрешенность торговли для эксперта","Allowed trade for Expert Advisor"}, {"Режим расчета маржи","Margin calculation mode"}, {"Количество знаков после запятой для валюты счета","Number of decimal places in account currency"}, {"Тип торгового сервера","Type of trading server"}, {"Признак закрытия позиций только по правилу FIFO","Sign of closing positions only according to FIFO rule"}, //--- {"Баланс счета","Account balance"}, //--- CEngine {"С момента последнего запуска ЕА торговых событий не было","No trade events since the last launch of EA"}, {"Не удалось получить описание последнего торгового события","Failed to get description of the last trading event"}, {"Не удалось получить список открытых позиций","Failed to get open positions list"}, {"Не удалось получить список установленных ордеров","Failed to get pending orders list"}, {"Нет открытых позиций","No open positions"}, {"Нет установленных ордеров","No placed orders"}, {"В терминале нет разрешения на проведение торговых операций (отключена кнопка \"Авто-торговля\")","No permission to conduct trading operations in terminal (\"AutoTrading\" button disabled)"}, {"Для советника нет разрешения на проведение торговых операций (F7 --> Общие --> \"Разрешить автоматическую торговлю\")","EA does not have permission to conduct trading operations (F7 --> Common --> \"Allow Automatic Trading\")"}, {"Для текущего счёта запрещена торговля","Trading prohibited for the current account"}, {"Для советников на текущем счёте запрещена торговля на стороне торгового сервера","From the side of trade server, trading for EA on the current account prohibited"}, {"Нет связи с торговым сервером","No connection to trade server"}, {"Запрос отклонён до отправки на сервер по причине:","Request rejected before being sent to server due to:"}, {"Не хватает средств на открытие позиции: ","Not enough money to open position: "}, {"Превышен максимальный совокупный объём ордеров и позиций в одном направлении","Exceeded maximum total volume of orders and positions in one direction"}, {"Объём в запросе меньше минимально-допустимого","Volume in request less than minimum allowable"}, {"Объём в запросе больше максимально-допустимого","Volume in request greater than maximum allowable"}, {"Закрытие встречным запрещено","CloseBy orders prohibited"}, {"Объём в запросе не кратен минимальной градации шага изменения лота","Volume in request not a multiple of minimum gradation of step for changing lot"}, {"Символы встречных позиций не равны","Symbols of two opposite positions not equal"}, }; //+---------------------------------------------------------------------+ //| Array of messages for trade server return codes (10004 - 10045) | //| (1) in user's country language | //| (2) in the international language | //+---------------------------------------------------------------------+ string messages_ts_ret_code[][TOTAL_LANG]= { {"Реквота","Requote"}, // 10004 {"Неизвестный код возврата торгового сервера","Unknown trading server return code"}, // 10005 {"Запрос отклонен","Request rejected"}, // 10006 {"Запрос отменен трейдером","Request canceled by trader"}, // 10007 {"Ордер размещен","Order placed"}, // 10008 {"Заявка выполнена","Request completed"}, // 10009 {"Заявка выполнена частично","Only part of request completed"}, // 10010 {"Ошибка обработки запроса","Request processing error"}, // 10011 {"Запрос отменен по истечению времени","Request canceled by timeout"}, // 10012 {"Неправильный запрос","Invalid request"}, // 10013 {"Неправильный объем в запросе","Invalid volume in request"}, // 10014 {"Неправильная цена в запросе","Invalid price in request"}, // 10015 {"Неправильные стопы в запросе","Invalid stops in request"}, // 10016 {"Торговля запрещена","Trading disabled"}, // 10017 {"Рынок закрыт","Market closed"}, // 10018 {"Нет достаточных денежных средств для выполнения запроса","Not enough money to complete request"}, // 10019 {"Цены изменились","Prices changed"}, // 10020 {"Отсутствуют котировки для обработки запроса","No quotes to process request"}, // 10021 {"Неверная дата истечения ордера в запросе","Invalid order expiration date in request"}, // 10022 {"Состояние ордера изменилось","Order state changed"}, // 10023 {"Слишком частые запросы","Too frequent requests"}, // 10024 {"В запросе нет изменений","No changes in request"}, // 10025 {"Автотрейдинг запрещен сервером","Autotrading disabled by server"}, // 10026 {"Автотрейдинг запрещен клиентским терминалом","Autotrading disabled by client terminal"}, // 10027 {"Запрос заблокирован для обработки","Request locked for processing"}, // 10028 {"Ордер или позиция заморожены","Order or position frozen"}, // 10029 {"Указан неподдерживаемый тип исполнения ордера по остатку","Invalid order filling type"}, // 10030 {"Нет соединения с торговым сервером","No connection with trade server"}, // 10031 {"Операция разрешена только для реальных счетов","Operation allowed only for live accounts"}, // 10032 {"Достигнут лимит на количество отложенных ордеров","Number of pending orders reached limit"}, // 10033 {"Достигнут лимит на объем ордеров и позиций для данного символа","Volume of orders and positions for symbol reached limit"}, // 10034 {"Неверный или запрещённый тип ордера","Incorrect or prohibited order type"}, // 10035 {"Позиция с указанным идентификатором уже закрыта","Position with specified identifier already closed"}, // 10036 {"Неизвестный код возврата торгового сервера","Unknown trading server return code"}, // 10037 {"Закрываемый объем превышает текущий объем позиции","Close volume exceeds the current position volume"}, // 10038 {"Для указанной позиции уже есть ордер на закрытие","Close order already exists for specified position"}, // 10039 {"Достигнут лимит на количество открытых позиций","Number of positions reached limit"}, // 10040 { "Запрос на активацию отложенного ордера отклонен, а сам ордер отменен", // 10041 "Pending order activation request rejected, order canceled" }, { "Запрос отклонен, так как на символе установлено правило \"Разрешены только длинные позиции\"", // 10042 "Request rejected, because \"Only long positions are allowed\" rule set for symbol" }, { "Запрос отклонен, так как на символе установлено правило \"Разрешены только короткие позиции\"", // 10043 "Request rejected, because \"Only short positions are allowed\" rule set for symbol" }, { "Запрос отклонен, так как на символе установлено правило \"Разрешено только закрывать существующие позиции\"", // 10044 "Request rejected because \"Only position closing is allowed\" rule set for symbol" }, { "Запрос отклонен, так как для торгового счета установлено правило \"Разрешено закрывать существующие позиции только по правилу FIFO\"", // 10045 "Request rejected, because \"Position closing is allowed only by FIFO rule\" flag set for trading account" }, }; //+------------------------------------------------------------------+
Wie wir bereits wissen, zielen alle durchgeführten Aktionen darauf ab, neue Nachrichten in die Bibliothek aufzunehmen und auf eine Nachricht über ihren in die Nachrichtenkonstante geschriebenen Index zuzugreifen.
Nun wollen wir die Nachrichtenklasse verbessern, die sich in \MQL5\Include\DoEasy\Services\Message.mqh befindet.
In dem 'public' Teil der Klasse deklarieren Sie die Methode, um das Abspielen einer beliebigen Audiodatei zu beenden:
public: //--- (1) Display a text message in the journal, send a push notification and e-mail, //--- (2) Display a message by ID, send a push notification and e-mail, //--- (3) play an audio file //--- (4) Stop playing any sound static bool Out(const string text,const bool push=false,const bool mail=false,const string subject=NULL); static bool OutByID(const int msg_id,const bool code=true); static bool PlaySound(const string file_name); static bool StopPlaySound(void); //--- Return (1) a message, (2) a code in the "(code)" format
Schreiben wir seine Implementierung außerhalb des Klassenkörpers:
//+------------------------------------------------------------------+ //| Stop playing any sound | //+------------------------------------------------------------------+ bool CMessage::StopPlaySound(void) { bool res=::PlaySound(NULL); CMessage::m_global_error=(res ? ERR_SUCCESS : ::GetLastError()); return res; } //+------------------------------------------------------------------+
Hier ist alles einfach: Wenn Sie die NULL Konstante als Dateinamen übergeben, stoppt die Standardfunktion PlaySound() die Wiedergabe der gerade aktiven Audiodatei.
Um die im Lieferumfang des Terminals enthaltenen Standard-Audiodateien abspielen zu können, müssen wir entweder einen Dateinamen angeben (um Audiodateien aus dem Standard-Speicherort der Dateien abzuspielen: terminal_ordner\Sounds), oder einen Dateinamen mit einem Präfix, das einen doppelten Schrägstrich enthält, und einem Unterordner, in dem nicht standardmäßige Audiodateien gespeichert sind.
Daher sollten wir die Methode PlaySound() verbessern:
//+------------------------------------------------------------------+ //| Play an audio file | //+------------------------------------------------------------------+ bool CMessage::PlaySound(const string file_name) { if(file_name==NULL) return true; string pref=(file_name==SND_ALERT || file_name==SND_ALERT2 || file_name==SND_CONNECT || file_name==SND_DISCONNECT || file_name==SND_EMAIL || file_name==SND_EXPERT || file_name==SND_NEWS || file_name==SND_OK || file_name==SND_REQUEST || file_name==SND_STOPS || file_name==SND_TICK || file_name==SND_TIMEOUT || file_name==SND_WAIT ? "" : "\\Files\\"); bool res=::PlaySound(pref+file_name); CMessage::m_global_error=(res ? ERR_SUCCESS : ::GetLastError()); return res; } //+------------------------------------------------------------------+
Was haben wir hier?
Wenn der Dateiname den Namen einer Standard-Audiodatei enthält, schreiben Sie eine leere Zeichenkette in den Dateinamenspräfix.
Andernfalls fügen Sie den doppelten Schrägstrich und den Namen eines Unterordners, der Bibliotheksklänge enthält, dem Präfix hinzu.
Der Dateiname setzt sich dann zusammen aus Präfix und einem Namen, der an die Methode übergeben wird.
Nun bei der Übergabe des Namens an die Funktion PlaySound() wird automatisch der Speicherort einer Sounddatei ausgewählt (entweder der Standard-Soundordner oder der Ordner für die Library-Audiodateien) und die entsprechende Datei abgespielt.
Jetzt haben wir den neuen Rückgabezahlen des Handelsservers. In der Methode zum Empfangen einer Nachricht aus dem Text-Array durch ID void CMessage::GetTextByID(), ändern Sie die Grenzen der Rückgabezahlen des Handelsservers durch eine Erhöhung um 1 (10045 statt 10044):
//--- Runtime errors (Economic calendar 5400 - 5402) msg_id>5399 && msg_id<5403 ? messages_runtime_calendar[msg_id-5400][m_lang_num] : //--- Trade server return codes (10004 - 10045) msg_id>10003 && msg_id<10046 ? messages_ts_ret_code[msg_id-10004][m_lang_num] : #else // MQL4 msg_id>0 && msg_id<10 ? messages_ts_ret_code_mql4[msg_id][m_lang_num] : msg_id>63 && msg_id<66 ? messages_ts_ret_code_mql4[msg_id-54][m_lang_num] : msg_id>127 && msg_id<151 ? messages_ts_ret_code_mql4[msg_id-116][m_lang_num] : msg_id<4000 ? messages_ts_ret_code_mql4[26][m_lang_num] : //--- MQL4 runtime errors (4000 - 4030) msg_id<4031 ? messages_runtime_4000_4030[msg_id-4000][m_lang_num] : //--- MQL4 runtime errors (4050 - 4075) msg_id>4049 && msg_id<4076 ? messages_runtime_4050_4075[msg_id-4050][m_lang_num] : //--- MQL4 runtime errors (4099 - 4112) msg_id>4098 && msg_id<4113 ? messages_runtime_4099_4112[msg_id-4099][m_lang_num] : //--- MQL4 runtime errors (4200 - 4220) msg_id>4199 && msg_id<4221 ? messages_runtime_4200_4220[msg_id-4200][m_lang_num] : //--- MQL4 runtime errors (4250 - 4266) msg_id>4249 && msg_id<4267 ? messages_runtime_4250_4266[msg_id-4250][m_lang_num] : //--- MQL4 runtime errors (5001 - 5029) msg_id>5000 && msg_id<5030 ? messages_runtime_5001_5029[msg_id-5001][m_lang_num] : //--- MQL4 runtime errors (5200 - 5203) msg_id>5199 && msg_id<5204 ? messages_runtime_5200_5203[msg_id-5200][m_lang_num] : #endif //--- Library messages (ERR_USER_ERROR_FIRST) msg_id>ERR_USER_ERROR_FIRST-1 ? messages_library[msg_id-ERR_USER_ERROR_FIRST][m_lang_num] : messages_library[MSG_LIB_SYS_ERROR_CODE_OUT_OF_RANGE-ERR_USER_ERROR_FIRST][m_lang_num] );
Damit sind die Änderungen in der Nachrichtenklasse der Bibliothek abgeschlossen.
Manchmal müssen wir einen Auftragstyp verwenden, um die Richtung einer Position herauszufinden, wenn der Auftrag aktiviert wird. Nehmen wir an, wir setzen eine ausstehende Bestellung vom Typ ORDER_TYPE_BUY_LIMIT. Sobald sie aktiviert ist, wird die Marktorder ORDER_TYPE_BUY platziert, die zum Deal DEAL_ENTRY_IN vom Typ DEAL_TYPE_BUY führt. Der Abschluss führt wiederum zu einer Position vom Typ POSITION_TYPE_BUY.
Um die Positionsrichtung durch eine Pending Order Type herauszufinden, müssen wir eine Market Order Type erhalten (im aktuellen Beispiel ist es ORDER_TYPE_BUY).
Zuvor haben wir sie für den Vergleich von mit dem Typ der Pending-Order mit dem ternären Operator definiert. Es kann jedoch einfacher gemacht werden: wir können einfach den Überschuss aus der Division des Typs einer geprüften Bestellung durch 2 nehmen. Der Typ 0 (ORDER_TYPE_BUY) wird immer für gerade Aufträge zurückgegeben, während der Typ 1 (ORDER_TYPE_SELL) für ungerade Aufträge zurückgegeben wird. Wir haben das in einigen Funktionen und Methoden implementiert.
In der abstrakten Auftragsklasse (\MQL5\Include\DoEasy\Objects\Orders\Order.mqh):
//+------------------------------------------------------------------+ //| Rückgabe des Typs auf Grund der Richtung | //+------------------------------------------------------------------+ long COrder::OrderTypeByDirection(void) const { ENUM_ORDER_STATUS status=(ENUM_ORDER_STATUS)this.GetProperty(ORDER_PROP_STATUS); if(status==ORDER_STATUS_MARKET_POSITION) { return (ENUM_ORDER_TYPE)this.OrderType(); } else if(status==ORDER_STATUS_MARKET_PENDING || status==ORDER_STATUS_HISTORY_PENDING) { return ENUM_ORDER_TYPE(this.OrderType()%2); } else if(status==ORDER_STATUS_MARKET_ORDER || status==ORDER_STATUS_HISTORY_ORDER) { return this.OrderType(); } else if(status==ORDER_STATUS_DEAL) { return ( (ENUM_DEAL_TYPE)this.TypeOrder()==DEAL_TYPE_BUY ? ORDER_TYPE_BUY : (ENUM_DEAL_TYPE)this.TypeOrder()==DEAL_TYPE_SELL ? ORDER_TYPE_SELL : WRONG_VALUE ); } return WRONG_VALUE; } //+------------------------------------------------------------------+
und in der Bibliothek der Dienstfunktionen (\MQL5\Include\DoEasy\Services\DELib.mqh):
//+------------------------------------------------------------------+ //| Return position type by order type | //+------------------------------------------------------------------+ ENUM_POSITION_TYPE PositionTypeByOrderType(ENUM_ORDER_TYPE type_order) { if(type_order==ORDER_TYPE_CLOSE_BY) return WRONG_VALUE; return ENUM_POSITION_TYPE(type_order%2); } //+------------------------------------------------------------------+
Die Funktion, die einen Auftragsnamen zurückgibt, wurde ebenfalls in der gleichen Datei der Servicefunktionen geändert.
Das Flag, das die Notwendigkeit der Anzeige der Auftragsbeschreibung anzeigt, wurde hinzugefügt. Abhängig vom Flag erhält der zurückgegebene Typ der Marktorder entweder die Beschreibung, dass es sich um eine Marktorder handelt oder nichts. Die Beschreibungen der Auftragstypen wurden den zurückgegebenen Typen von Pending-Orders hinzugefügt:
//+------------------------------------------------------------------+ //| Return the order name | //+------------------------------------------------------------------+ string OrderTypeDescription(const ENUM_ORDER_TYPE type,bool as_order=true,bool need_prefix=true) { string pref= ( !need_prefix ? "" : #ifdef __MQL5__ CMessage::Text(MSG_ORD_MARKET) #else/*__MQL4__*/(as_order ? CMessage::Text(MSG_ORD_MARKET) : CMessage::Text(MSG_ORD_POSITION)) #endif ); return ( type==ORDER_TYPE_BUY_LIMIT ? CMessage::Text(MSG_ORD_PENDING)+" Buy Limit" : type==ORDER_TYPE_BUY_STOP ? CMessage::Text(MSG_ORD_PENDING)+" Buy Stop" : type==ORDER_TYPE_SELL_LIMIT ? CMessage::Text(MSG_ORD_PENDING)+" Sell Limit" : type==ORDER_TYPE_SELL_STOP ? CMessage::Text(MSG_ORD_PENDING)+" Sell Stop" : #ifdef __MQL5__ type==ORDER_TYPE_BUY_STOP_LIMIT ? CMessage::Text(MSG_ORD_PENDING)+" Buy Stop Limit" : type==ORDER_TYPE_SELL_STOP_LIMIT ? CMessage::Text(MSG_ORD_PENDING)+" Sell Stop Limit" : type==ORDER_TYPE_CLOSE_BY ? CMessage::Text(MSG_ORD_CLOSE_BY) : #else type==ORDER_TYPE_BALANCE ? CMessage::Text(MSG_LIB_PROP_BALANCE) : type==ORDER_TYPE_CREDIT ? CMessage::Text(MSG_LIB_PROP_CREDIT) : #endif type==ORDER_TYPE_BUY ? pref+" Buy" : type==ORDER_TYPE_SELL ? pref+" Sell" : CMessage::Text(MSG_ORD_UNKNOWN_TYPE) ); } //+------------------------------------------------------------------+
Aufgrund der Einführung der neuen Symbol- und Kontoobjekteigenschaften müssen wir diese Eigenschaften den Objekten hinzufügen.
Öffnen Sie \MQL5\Include\DoEasy\Objects\Symbols\Symbol.mqh und nehmen Sie die notwendigen Änderungen vor.
Im Abschnitt der geschützten Klasse fügen Sie die Definition der Methoden für den Empfang der beiden neuen Eigenschaften hinzu:
protected: //--- 'Protected' Konstruktor CSymbol(ENUM_SYMBOL_STATUS symbol_status,const string name,const int index); //--- Get and return integer properties of a selected symbol from its parameters bool SymbolExists(const string name) const; long SymbolExists(void) const; long SymbolCustom(void) const; long SymbolChartMode(void) const; long SymbolMarginHedgedUseLEG(void) const; long SymbolOrderFillingMode(void) const; long SymbolOrderMode(void) const; long SymbolExpirationMode(void) const; long SymbolOrderGTCMode(void) const; long SymbolOptionMode(void) const; long SymbolOptionRight(void) const; long SymbolBackgroundColor(void) const; long SymbolCalcMode(void) const; long SymbolSwapMode(void) const; long SymbolDigitsLot(void); int SymbolDigitsBySwap(void); //--- Get and return real properties of a selected symbol from its parameters double SymbolBidHigh(void) const; double SymbolBidLow(void) const; double SymbolVolumeReal(void) const; double SymbolVolumeHighReal(void) const; double SymbolVolumeLowReal(void) const; double SymbolOptionStrike(void) const; double SymbolTradeAccruedInterest(void) const; double SymbolTradeFaceValue(void) const; double SymbolTradeLiquidityRate(void) const; double SymbolMarginHedged(void) const; bool SymbolMarginLong(void); bool SymbolMarginShort(void); bool SymbolMarginBuyStop(void); bool SymbolMarginBuyLimit(void); bool SymbolMarginBuyStopLimit(void); bool SymbolMarginSellStop(void); bool SymbolMarginSellLimit(void); bool SymbolMarginSellStopLimit(void); //--- Get and return string properties of a selected symbol from its parameters string SymbolBasis(void) const; string SymbolBank(void) const; string SymbolISIN(void) const; string SymbolFormula(void) const; string SymbolPage(void) const; string SymbolCategory(void) const; string SymbolExchange(void) const; //--- Search for a symbol and return the flag indicating its presence on the server bool Exist(void) const; public:
Fügen Sie im Block für den vereinfachten Empfang von Objekteigenschaften des öffentlichen Klassenteils die Definition der beiden neuen Methoden hinzu:
public: //+------------------------------------------------------------------+ //| Methods of a simplified access to the order object properties | //+------------------------------------------------------------------+ //--- Integer properties long Status(void) const { return this.GetProperty(SYMBOL_PROP_STATUS); } int IndexInMarketWatch(void) const { return (int)this.GetProperty(SYMBOL_PROP_INDEX_MW); } bool IsCustom(void) const { return (bool)this.GetProperty(SYMBOL_PROP_CUSTOM); } color ColorBackground(void) const { return (color)this.GetProperty(SYMBOL_PROP_BACKGROUND_COLOR); } ENUM_SYMBOL_CHART_MODE ChartMode(void) const { return (ENUM_SYMBOL_CHART_MODE)this.GetProperty(SYMBOL_PROP_CHART_MODE); } bool IsExist(void) const { return (bool)this.GetProperty(SYMBOL_PROP_EXIST); } bool IsExist(const string name) const { return this.SymbolExists(name); } bool IsSelect(void) const { return (bool)this.GetProperty(SYMBOL_PROP_SELECT); } bool IsVisible(void) const { return (bool)this.GetProperty(SYMBOL_PROP_VISIBLE); } long SessionDeals(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_DEALS); } long SessionBuyOrders(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_BUY_ORDERS); } long SessionSellOrders(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_SELL_ORDERS); } long Volume(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME); } long VolumeHigh(void) const { return this.GetProperty(SYMBOL_PROP_VOLUMEHIGH); } long VolumeLow(void) const { return this.GetProperty(SYMBOL_PROP_VOLUMELOW); } datetime Time(void) const { return (datetime)this.GetProperty(SYMBOL_PROP_TIME); } int Digits(void) const { return (int)this.GetProperty(SYMBOL_PROP_DIGITS); } int DigitsLot(void) const { return (int)this.GetProperty(SYMBOL_PROP_DIGITS_LOTS); } int Spread(void) const { return (int)this.GetProperty(SYMBOL_PROP_SPREAD); } bool IsSpreadFloat(void) const { return (bool)this.GetProperty(SYMBOL_PROP_SPREAD_FLOAT); } int TicksBookdepth(void) const { return (int)this.GetProperty(SYMBOL_PROP_TICKS_BOOKDEPTH); } ENUM_SYMBOL_CALC_MODE TradeCalcMode(void) const { return (ENUM_SYMBOL_CALC_MODE)this.GetProperty(SYMBOL_PROP_TRADE_CALC_MODE); } ENUM_SYMBOL_TRADE_MODE TradeMode(void) const { return (ENUM_SYMBOL_TRADE_MODE)this.GetProperty(SYMBOL_PROP_TRADE_MODE); } datetime StartTime(void) const { return (datetime)this.GetProperty(SYMBOL_PROP_START_TIME); } datetime ExpirationTime(void) const { return (datetime)this.GetProperty(SYMBOL_PROP_EXPIRATION_TIME); } int TradeStopLevel(void) const { return (int)this.GetProperty(SYMBOL_PROP_TRADE_STOPS_LEVEL); } int TradeFreezeLevel(void) const { return (int)this.GetProperty(SYMBOL_PROP_TRADE_FREEZE_LEVEL); } ENUM_SYMBOL_TRADE_EXECUTION TradeExecutionMode(void) const { return (ENUM_SYMBOL_TRADE_EXECUTION)this.GetProperty(SYMBOL_PROP_TRADE_EXEMODE); } ENUM_SYMBOL_SWAP_MODE SwapMode(void) const { return (ENUM_SYMBOL_SWAP_MODE)this.GetProperty(SYMBOL_PROP_SWAP_MODE); } ENUM_DAY_OF_WEEK SwapRollover3Days(void) const { return (ENUM_DAY_OF_WEEK)this.GetProperty(SYMBOL_PROP_SWAP_ROLLOVER3DAYS); } bool IsMarginHedgedUseLeg(void) const { return (bool)this.GetProperty(SYMBOL_PROP_MARGIN_HEDGED_USE_LEG); } int ExpirationModeFlags(void) const { return (int)this.GetProperty(SYMBOL_PROP_EXPIRATION_MODE); } int FillingModeFlags(void) const { return (int)this.GetProperty(SYMBOL_PROP_FILLING_MODE); } int OrderModeFlags(void) const { return (int)this.GetProperty(SYMBOL_PROP_ORDER_MODE); } ENUM_SYMBOL_ORDER_GTC_MODE OrderModeGTC(void) const { return (ENUM_SYMBOL_ORDER_GTC_MODE)this.GetProperty(SYMBOL_PROP_ORDER_GTC_MODE); } ENUM_SYMBOL_OPTION_MODE OptionMode(void) const { return (ENUM_SYMBOL_OPTION_MODE)this.GetProperty(SYMBOL_PROP_OPTION_MODE); } ENUM_SYMBOL_OPTION_RIGHT OptionRight(void) const { return (ENUM_SYMBOL_OPTION_RIGHT)this.GetProperty(SYMBOL_PROP_OPTION_RIGHT); } //--- Real properties double Bid(void) const { return this.GetProperty(SYMBOL_PROP_BID); } double BidHigh(void) const { return this.GetProperty(SYMBOL_PROP_BIDHIGH); } double BidLow(void) const { return this.GetProperty(SYMBOL_PROP_BIDLOW); } double Ask(void) const { return this.GetProperty(SYMBOL_PROP_ASK); } double AskHigh(void) const { return this.GetProperty(SYMBOL_PROP_ASKHIGH); } double AskLow(void) const { return this.GetProperty(SYMBOL_PROP_ASKLOW); } double Last(void) const { return this.GetProperty(SYMBOL_PROP_LAST); } double LastHigh(void) const { return this.GetProperty(SYMBOL_PROP_LASTHIGH); } double LastLow(void) const { return this.GetProperty(SYMBOL_PROP_LASTLOW); } double VolumeReal(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME_REAL); } double VolumeHighReal(void) const { return this.GetProperty(SYMBOL_PROP_VOLUMEHIGH_REAL); } double VolumeLowReal(void) const { return this.GetProperty(SYMBOL_PROP_VOLUMELOW_REAL); } double OptionStrike(void) const { return this.GetProperty(SYMBOL_PROP_OPTION_STRIKE); } double Point(void) const { return this.GetProperty(SYMBOL_PROP_POINT); } double TradeTickValue(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_TICK_VALUE); } double TradeTickValueProfit(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT); } double TradeTickValueLoss(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_TICK_VALUE_LOSS); } double TradeTickSize(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_TICK_SIZE); } double TradeContractSize(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_CONTRACT_SIZE); } double TradeAccuredInterest(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_ACCRUED_INTEREST); } double TradeFaceValue(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_FACE_VALUE); } double TradeLiquidityRate(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_LIQUIDITY_RATE); } double LotsMin(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME_MIN); } double LotsMax(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME_MAX); } double LotsStep(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME_STEP); } double VolumeLimit(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME_LIMIT); } double SwapLong(void) const { return this.GetProperty(SYMBOL_PROP_SWAP_LONG); } double SwapShort(void) const { return this.GetProperty(SYMBOL_PROP_SWAP_SHORT); } double MarginInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_INITIAL); } double MarginMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_MAINTENANCE); } double MarginLongInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_LONG_INITIAL); } double MarginBuyStopInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_BUY_STOP_INITIAL); } double MarginBuyLimitInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_BUY_LIMIT_INITIAL); } double MarginBuyStopLimitInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_INITIAL); } double MarginLongMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_LONG_MAINTENANCE); } double MarginBuyStopMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_BUY_STOP_MAINTENANCE); } double MarginBuyLimitMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_BUY_LIMIT_MAINTENANCE); } double MarginBuyStopLimitMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_MAINTENANCE); } double MarginShortInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SHORT_INITIAL); } double MarginSellStopInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SELL_STOP_INITIAL); } double MarginSellLimitInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SELL_LIMIT_INITIAL); } double MarginSellStopLimitInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_INITIAL); } double MarginShortMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SHORT_MAINTENANCE); } double MarginSellStopMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SELL_STOP_MAINTENANCE); } double MarginSellLimitMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SELL_LIMIT_MAINTENANCE); } double MarginSellStopLimitMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_MAINTENANCE); } double SessionVolume(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_VOLUME); } double SessionTurnover(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_TURNOVER); } double SessionInterest(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_INTEREST); } double SessionBuyOrdersVolume(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME); } double SessionSellOrdersVolume(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME); } double SessionOpen(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_OPEN); } double SessionClose(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_CLOSE); } double SessionAW(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_AW); } double SessionPriceSettlement(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_PRICE_SETTLEMENT); } double SessionPriceLimitMin(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_PRICE_LIMIT_MIN); } double SessionPriceLimitMax(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_PRICE_LIMIT_MAX); } double MarginHedged(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_HEDGED); } double NormalizedPrice(const double price) const; double NormalizedLot(const double volume) const; double BidLast(void) const; double BidLastHigh(void) const; double BidLastLow(void) const; //--- String properties string Name(void) const { return this.GetProperty(SYMBOL_PROP_NAME); } string Basis(void) const { return this.GetProperty(SYMBOL_PROP_BASIS); } string CurrencyBase(void) const { return this.GetProperty(SYMBOL_PROP_CURRENCY_BASE); } string CurrencyProfit(void) const { return this.GetProperty(SYMBOL_PROP_CURRENCY_PROFIT); } string CurrencyMargin(void) const { return this.GetProperty(SYMBOL_PROP_CURRENCY_MARGIN); } string Bank(void) const { return this.GetProperty(SYMBOL_PROP_BANK); } string Description(void) const { return this.GetProperty(SYMBOL_PROP_DESCRIPTION); } string Formula(void) const { return this.GetProperty(SYMBOL_PROP_FORMULA); } string ISIN(void) const { return this.GetProperty(SYMBOL_PROP_ISIN); } string Page(void) const { return this.GetProperty(SYMBOL_PROP_PAGE); } string Path(void) const { return this.GetProperty(SYMBOL_PROP_PATH); } string Category(void) const { return this.GetProperty(SYMBOL_PROP_CATEGORY); } string Exchange(void) const { return this.GetProperty(SYMBOL_PROP_EXCHANGE); } //+------------------------------------------------------------------+
Fügen Sie den Empfang dieser neuen Eigenschaften im geschlossenen parametrischen Klassenkonstruktor hinzu:
//--- Sichern der String-Eigenschaften this.m_string_prop[this.IndexProp(SYMBOL_PROP_NAME)] = this.m_name; this.m_string_prop[this.IndexProp(SYMBOL_PROP_CURRENCY_BASE)] = ::SymbolInfoString(this.m_name,SYMBOL_CURRENCY_BASE); this.m_string_prop[this.IndexProp(SYMBOL_PROP_CURRENCY_PROFIT)] = ::SymbolInfoString(this.m_name,SYMBOL_CURRENCY_PROFIT); this.m_string_prop[this.IndexProp(SYMBOL_PROP_CURRENCY_MARGIN)] = ::SymbolInfoString(this.m_name,SYMBOL_CURRENCY_MARGIN); this.m_string_prop[this.IndexProp(SYMBOL_PROP_DESCRIPTION)] = ::SymbolInfoString(this.m_name,SYMBOL_DESCRIPTION); this.m_string_prop[this.IndexProp(SYMBOL_PROP_PATH)] = ::SymbolInfoString(this.m_name,SYMBOL_PATH); this.m_string_prop[this.IndexProp(SYMBOL_PROP_BASIS)] = this.SymbolBasis(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_BANK)] = this.SymbolBank(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_ISIN)] = this.SymbolISIN(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_FORMULA)] = this.SymbolFormula(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_PAGE)] = this.SymbolPage(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_CATEGORY)] = this.SymbolCategory(); this.m_string_prop[this.IndexProp(SYMBOL_PROP_EXCHANGE)] = this.SymbolExchange(); //--- Sichern weiterer ganzzahliger Eigenschaften
Implementieren Sie die Methoden zum Empfang der beiden neuen Eigenschaften außerhalb des Klassenkörpers:
//+------------------------------------------------------------------+ //| Return a symbol category | //+------------------------------------------------------------------+ string CSymbol::SymbolCategory(void) const { return ( #ifdef __MQL5__ ( ::TerminalInfoInteger(TERMINAL_BUILD)<2155 ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED_MT5_LESS_2155) : ::SymbolInfoString(this.m_name,SYMBOL_CATEGORY) ) #else ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED_MQL4) #endif ); } //+------------------------------------------------------------------+ //| Return an exchange name | //| a symbol is traded on | //+------------------------------------------------------------------+ string CSymbol::SymbolExchange(void) const { return ( #ifdef __MQL5__ ( ::TerminalInfoInteger(TERMINAL_BUILD)<2155 ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED_MT5_LESS_2155) : ::SymbolInfoString(this.m_name,SYMBOL_EXCHANGE) ) #else ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED_MQL4) #endif ); } //+------------------------------------------------------------------+
Hier, prüfen Sie den Terminalversion für MQL5. Ist sie kleiner als 2155, informieren Sie, dass die aktuelle Eigenschaft in der Version unter 2155 nicht unterstützt wird, ansonsten geben Sie die neue SYMBOL_EXCHANGE Eigenschaft.
Im Falle von MQL4, informieren Sie, dass die Eigenschaft nicht unterstützt in MQL4 wird.
Hinzufügen der Rückgabe von Beschreibungen der beiden neuen Eigenschaften zur Implementierung der Methode, die die Beschreibung einer Symbolstring-Eigenschaft zurückgibt:
//+------------------------------------------------------------------+ //| Return the description of a symbol string property | //+------------------------------------------------------------------+ string CSymbol::GetPropertyDescription(ENUM_SYMBOL_PROP_STRING property) { return ( property==SYMBOL_PROP_NAME ? CMessage::Text(MSG_SYM_PROP_NAME)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : ": "+this.GetProperty(property) ) : property==SYMBOL_PROP_BASIS ? CMessage::Text(MSG_SYM_PROP_BASIS)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? ": ("+CMessage::Text(MSG_LIB_PROP_EMPTY)+")" : ": \""+this.GetProperty(property)+"\"") ) : property==SYMBOL_PROP_CURRENCY_BASE ? CMessage::Text(MSG_SYM_PROP_CURRENCY_BASE)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? ": ("+CMessage::Text(MSG_LIB_PROP_EMPTY)+")" : ": \""+this.GetProperty(property)+"\"") ) : property==SYMBOL_PROP_CURRENCY_PROFIT ? CMessage::Text(MSG_SYM_PROP_CURRENCY_PROFIT)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? ": ("+CMessage::Text(MSG_LIB_PROP_EMPTY)+")" : ": \""+this.GetProperty(property)+"\"") ) : property==SYMBOL_PROP_CURRENCY_MARGIN ? CMessage::Text(MSG_SYM_PROP_CURRENCY_MARGIN)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? ": ("+CMessage::Text(MSG_LIB_PROP_EMPTY)+")" : ": \""+this.GetProperty(property)+"\"") ) : property==SYMBOL_PROP_BANK ? CMessage::Text(MSG_SYM_PROP_BANK)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? ": ("+CMessage::Text(MSG_LIB_PROP_EMPTY)+")" : ": \""+this.GetProperty(property)+"\"") ) : property==SYMBOL_PROP_DESCRIPTION ? CMessage::Text(MSG_SYM_PROP_DESCRIPTION)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? ": ("+CMessage::Text(MSG_LIB_PROP_EMPTY)+")" : ": \""+this.GetProperty(property)+"\"") ) : property==SYMBOL_PROP_FORMULA ? CMessage::Text(MSG_SYM_PROP_FORMULA)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? ": ("+CMessage::Text(MSG_LIB_PROP_EMPTY)+")" : ": \""+this.GetProperty(property)+"\"") ) : property==SYMBOL_PROP_ISIN ? CMessage::Text(MSG_SYM_PROP_ISIN)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? ": ("+CMessage::Text(MSG_LIB_PROP_EMPTY)+")" : ": \""+this.GetProperty(property)+"\"") ) : property==SYMBOL_PROP_PAGE ? CMessage::Text(MSG_SYM_PROP_PAGE)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? ": ("+CMessage::Text(MSG_LIB_PROP_EMPTY)+")" : ": \""+this.GetProperty(property)+"\"") ) : property==SYMBOL_PROP_PATH ? CMessage::Text(MSG_SYM_PROP_PATH)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? ": ("+CMessage::Text(MSG_LIB_PROP_EMPTY)+")" : ": \""+this.GetProperty(property)+"\"") ) : property==SYMBOL_PROP_CATEGORY ? CMessage::Text(MSG_SYM_PROP_CAYEGORY)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? ": ("+CMessage::Text(MSG_LIB_PROP_EMPTY)+")" : ": \""+this.GetProperty(property)+"\"") ) : property==SYMBOL_PROP_EXCHANGE ? CMessage::Text(MSG_SYM_PROP_EXCHANGE)+ (!this.SupportProperty(property) ? ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? ": ("+CMessage::Text(MSG_LIB_PROP_EMPTY)+")" : ": \""+this.GetProperty(property)+"\"") ) : "" ); } //+------------------------------------------------------------------+
Nun fügen wir die neue Eigenschaft dem Kontoobjekt in \MQL5\Include\DoEasy\Objects\Accounts\Account.mqh hinzu.
Schreiben Sie das neue Feld in die Struktur der Kontoeigenschaften:
//+------------------------------------------------------------------+ //| Account class | //+------------------------------------------------------------------+ class CAccount : public CBaseObj { private: struct SData { //--- Account integer properties long login; // ACCOUNT_LOGIN (Account number) int trade_mode; // ACCOUNT_TRADE_MODE (Trading account type) long leverage; // ACCOUNT_LEVERAGE (Leverage) int limit_orders; // ACCOUNT_LIMIT_ORDERS (Maximum allowed number of active pending orders) int margin_so_mode; // ACCOUNT_MARGIN_SO_MODE (Mode of setting the minimum available margin level) bool trade_allowed; // ACCOUNT_TRADE_ALLOWED (Permission to trade for the current account from the server side) bool trade_expert; // ACCOUNT_TRADE_EXPERT (Permission to trade for an EA from the server side) int margin_mode; // ACCOUNT_MARGIN_MODE (Margin calculation mode) int currency_digits; // ACCOUNT_CURRENCY_DIGITS (Number of decimal places for the account currency) int server_type; // Trade server type (MetaTrader 5, MetaTrader 4) bool fifo_close; // The flag indicating that positions can be closed only by the FIFO rule //--- Account real properties double balance; // ACCOUNT_BALANCE (Account balance in a deposit currency) double credit; // ACCOUNT_CREDIT (Credit in a deposit currency) double profit; // ACCOUNT_PROFIT (Current profit on an account in the account currency) double equity; // ACCOUNT_EQUITY (Equity on an account in the deposit currency) double margin; // ACCOUNT_MARGIN (Reserved margin on an account in a deposit currency) double margin_free; // ACCOUNT_MARGIN_FREE (Free funds available for opening a position in a deposit currency) double margin_level; // ACCOUNT_MARGIN_LEVEL (Margin level on an account in %) double margin_so_call; // ACCOUNT_MARGIN_SO_CALL (MarginCall) double margin_so_so; // ACCOUNT_MARGIN_SO_SO (StopOut) double margin_initial; // ACCOUNT_MARGIN_INITIAL (Funds reserved on an account to ensure a guarantee amount for all pending orders) double margin_maintenance; // ACCOUNT_MARGIN_MAINTENANCE (Funds reserved on an account to ensure a minimum amount for all open positions) double assets; // ACCOUNT_ASSETS (Current assets on an account) double liabilities; // ACCOUNT_LIABILITIES (Current liabilities on an account) double comission_blocked; // ACCOUNT_COMMISSION_BLOCKED (Current sum of blocked commissions on an account) //--- Account string properties uchar name[128]; // ACCOUNT_NAME (Client name) uchar server[64]; // ACCOUNT_SERVER (Trade server name) uchar currency[32]; // ACCOUNT_CURRENCY (Deposit currency) uchar company[128]; // ACCOUNT_COMPANY (Name of a company serving an account) }; SData m_struct_obj; // Account object structure
Fügen Sie im Methodenblock für den vereinfachten Zugriff auf Objekteigenschaften der öffentlichen Klassensektion die Methode, die die neue Eigenschaft zurückgibt, hinzu:
//+------------------------------------------------------------------+ //| Methods of a simplified access to the account object properties | //+------------------------------------------------------------------+ //--- Return the account's integer properties ENUM_ACCOUNT_TRADE_MODE TradeMode(void) const { return (ENUM_ACCOUNT_TRADE_MODE)this.GetProperty(ACCOUNT_PROP_TRADE_MODE); } ENUM_ACCOUNT_STOPOUT_MODE MarginSOMode(void) const { return (ENUM_ACCOUNT_STOPOUT_MODE)this.GetProperty(ACCOUNT_PROP_MARGIN_SO_MODE); } ENUM_ACCOUNT_MARGIN_MODE MarginMode(void) const { return (ENUM_ACCOUNT_MARGIN_MODE)this.GetProperty(ACCOUNT_PROP_MARGIN_MODE); } long Login(void) const { return this.GetProperty(ACCOUNT_PROP_LOGIN); } long Leverage(void) const { return this.GetProperty(ACCOUNT_PROP_LEVERAGE); } long LimitOrders(void) const { return this.GetProperty(ACCOUNT_PROP_LIMIT_ORDERS); } long TradeAllowed(void) const { return this.GetProperty(ACCOUNT_PROP_TRADE_ALLOWED); } long TradeExpert(void) const { return this.GetProperty(ACCOUNT_PROP_TRADE_EXPERT); } long CurrencyDigits(void) const { return this.GetProperty(ACCOUNT_PROP_CURRENCY_DIGITS); } long ServerType(void) const { return this.GetProperty(ACCOUNT_PROP_SERVER_TYPE); } long FIFOClose(void) const { return this.GetProperty(ACCOUNT_PROP_FIFO_CLOSE); } //--- Return the account's real properties
Fügen Sie das Speichern der neuen Kontoobjekt-Eigenschaft im Klassenkonstruktor hinzu:
//+------------------------------------------------------------------+ //| Konstruktor | //+------------------------------------------------------------------+ CAccount::CAccount(void) { //--- Initialize control data this.SetControlDataArraySizeLong(ACCOUNT_PROP_INTEGER_TOTAL); this.SetControlDataArraySizeDouble(ACCOUNT_PROP_DOUBLE_TOTAL); this.ResetChangesParams(); this.ResetControlsParams(); //--- Sichern der ganzzahligen Eigenschaften this.m_long_prop[ACCOUNT_PROP_LOGIN] = ::AccountInfoInteger(ACCOUNT_LOGIN); this.m_long_prop[ACCOUNT_PROP_TRADE_MODE] = ::AccountInfoInteger(ACCOUNT_TRADE_MODE); this.m_long_prop[ACCOUNT_PROP_LEVERAGE] = ::AccountInfoInteger(ACCOUNT_LEVERAGE); this.m_long_prop[ACCOUNT_PROP_LIMIT_ORDERS] = ::AccountInfoInteger(ACCOUNT_LIMIT_ORDERS); this.m_long_prop[ACCOUNT_PROP_MARGIN_SO_MODE] = ::AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE); this.m_long_prop[ACCOUNT_PROP_TRADE_ALLOWED] = ::AccountInfoInteger(ACCOUNT_TRADE_ALLOWED); this.m_long_prop[ACCOUNT_PROP_TRADE_EXPERT] = ::AccountInfoInteger(ACCOUNT_TRADE_EXPERT); this.m_long_prop[ACCOUNT_PROP_MARGIN_MODE] = #ifdef __MQL5__::AccountInfoInteger(ACCOUNT_MARGIN_MODE) #else ACCOUNT_MARGIN_MODE_RETAIL_HEDGING #endif ; this.m_long_prop[ACCOUNT_PROP_CURRENCY_DIGITS] = #ifdef __MQL5__::AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS) #else 2 #endif ; this.m_long_prop[ACCOUNT_PROP_SERVER_TYPE] = (::TerminalInfoString(TERMINAL_NAME)=="MetaTrader 5" ? 5 : 4); this.m_long_prop[ACCOUNT_PROP_FIFO_CLOSE] = (#ifdef __MQL5__::TerminalInfoInteger(TERMINAL_BUILD)<2155 ? false : ::AccountInfoInteger(ACCOUNT_FIFO_CLOSE) #else false #endif ); //--- Sichern der Double-Eigenschaften
Wenn die Terminalversion kleiner als 2155 liegt, tragen Sie false ein, andernfalls den Kontoeigenschaftenwert ACCOUNT_FIFO_CLOSE.
Außerdem fügen Sie Speichern der Eigenschaft der Methode Refresh() das Aktualisieren der Kontoeigenschaften hinzu:
//+------------------------------------------------------------------+ //| Update all account data | //+------------------------------------------------------------------+ void CAccount::Refresh(void) { //--- Initialize event data this.m_is_event=false; this.m_hash_sum=0; //--- Update integer properties this.m_long_prop[ACCOUNT_PROP_LOGIN] = ::AccountInfoInteger(ACCOUNT_LOGIN); this.m_long_prop[ACCOUNT_PROP_TRADE_MODE] = ::AccountInfoInteger(ACCOUNT_TRADE_MODE); this.m_long_prop[ACCOUNT_PROP_LEVERAGE] = ::AccountInfoInteger(ACCOUNT_LEVERAGE); this.m_long_prop[ACCOUNT_PROP_LIMIT_ORDERS] = ::AccountInfoInteger(ACCOUNT_LIMIT_ORDERS); this.m_long_prop[ACCOUNT_PROP_MARGIN_SO_MODE] = ::AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE); this.m_long_prop[ACCOUNT_PROP_TRADE_ALLOWED] = ::AccountInfoInteger(ACCOUNT_TRADE_ALLOWED); this.m_long_prop[ACCOUNT_PROP_TRADE_EXPERT] = ::AccountInfoInteger(ACCOUNT_TRADE_EXPERT); this.m_long_prop[ACCOUNT_PROP_MARGIN_MODE] = #ifdef __MQL5__::AccountInfoInteger(ACCOUNT_MARGIN_MODE) #else ACCOUNT_MARGIN_MODE_RETAIL_HEDGING #endif ; this.m_long_prop[ACCOUNT_PROP_CURRENCY_DIGITS] = #ifdef __MQL5__::AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS) #else 2 #endif ; this.m_long_prop[ACCOUNT_PROP_SERVER_TYPE] = (::TerminalInfoString(TERMINAL_NAME)=="MetaTrader 5" ? 5 : 4); this.m_long_prop[ACCOUNT_PROP_FIFO_CLOSE] = (#ifdef __MQL5__::TerminalInfoInteger(TERMINAL_BUILD)<2155 ? false : ::AccountInfoInteger(ACCOUNT_FIFO_CLOSE) #else false #endif ); //--- Update real properties
Das Eintragen der neuen Eigenschaft in der Methode zum Anlegen des Kontoobjekts aus der Struktur hinzufügen:
//+------------------------------------------------------------------+ //| Create the account object from the structure | //+------------------------------------------------------------------+ void CAccount::StructToObject(void) { //--- Sichern der ganzzahligen Eigenschaften this.m_long_prop[ACCOUNT_PROP_LOGIN] = this.m_struct_obj.login; this.m_long_prop[ACCOUNT_PROP_TRADE_MODE] = this.m_struct_obj.trade_mode; this.m_long_prop[ACCOUNT_PROP_LEVERAGE] = this.m_struct_obj.leverage; this.m_long_prop[ACCOUNT_PROP_LIMIT_ORDERS] = this.m_struct_obj.limit_orders; this.m_long_prop[ACCOUNT_PROP_MARGIN_SO_MODE] = this.m_struct_obj.margin_so_mode; this.m_long_prop[ACCOUNT_PROP_TRADE_ALLOWED] = this.m_struct_obj.trade_allowed; this.m_long_prop[ACCOUNT_PROP_TRADE_EXPERT] = this.m_struct_obj.trade_expert; this.m_long_prop[ACCOUNT_PROP_MARGIN_MODE] = this.m_struct_obj.margin_mode; this.m_long_prop[ACCOUNT_PROP_CURRENCY_DIGITS] = this.m_struct_obj.currency_digits; this.m_long_prop[ACCOUNT_PROP_SERVER_TYPE] = this.m_struct_obj.server_type; this.m_long_prop[ACCOUNT_PROP_FIFO_CLOSE] = this.m_struct_obj.fifo_close; //--- Sichern der Double-Eigenschaften
Die Anzeige der neuen Eigenschaft in der Methode hinzufügen, die die Beschreibung der ganzzahligen Eigenschaften des Kontoobjekts zurückgibt:
//+------------------------------------------------------------------+ //| Return the description of the account integer property | //+------------------------------------------------------------------+ string CAccount::GetPropertyDescription(ENUM_ACCOUNT_PROP_INTEGER property) { return ( property==ACCOUNT_PROP_LOGIN ? CMessage::Text(MSG_ACC_PROP_LOGIN)+": "+(string)this.GetProperty(property) : property==ACCOUNT_PROP_TRADE_MODE ? CMessage::Text(MSG_ACC_PROP_TRADE_MODE)+": "+this.TradeModeDescription() : property==ACCOUNT_PROP_LEVERAGE ? CMessage::Text(MSG_ACC_PROP_LEVERAGE)+": "+(string)this.GetProperty(property) : property==ACCOUNT_PROP_LIMIT_ORDERS ? CMessage::Text(MSG_ACC_PROP_LIMIT_ORDERS)+": "+(string)this.GetProperty(property) : property==ACCOUNT_PROP_MARGIN_SO_MODE ? CMessage::Text(MSG_ACC_PROP_MARGIN_SO_MODE)+": "+this.MarginSOModeDescription() : property==ACCOUNT_PROP_TRADE_ALLOWED ? CMessage::Text(MSG_ACC_PROP_TRADE_ALLOWED)+": "+ (this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) : property==ACCOUNT_PROP_TRADE_EXPERT ? CMessage::Text(MSG_ACC_PROP_TRADE_EXPERT)+": "+ (this.GetProperty(property) ? CMessage::Text(MSG_LIB_TEXT_YES) : CMessage::Text(MSG_LIB_TEXT_NO)) : property==ACCOUNT_PROP_MARGIN_MODE ? CMessage::Text(MSG_ACC_PROP_MARGIN_MODE)+": "+this.MarginModeDescription() : property==ACCOUNT_PROP_CURRENCY_DIGITS ? CMessage::Text(MSG_ACC_PROP_CURRENCY_DIGITS)+": "+(string)this.GetProperty(property) : property==ACCOUNT_PROP_SERVER_TYPE ? CMessage::Text(MSG_ACC_PROP_SERVER_TYPE)+": "+(string)this.GetProperty(property) : property==ACCOUNT_PROP_FIFO_CLOSE ? CMessage::Text(MSG_ACC_PROP_FIFO_CLOSE)+": "+(string)this.GetProperty(property) : "" ); } //+------------------------------------------------------------------+
Beachten Sie, dass das Hinzufügen einer neuen Eigenschaft zum Kontoobjekt die zuvor im gemeinsamen Ordner aller Terminals gespeicherten Kontoobjekte ungültig macht. Um Lesefehler zu vermeiden, entfernen Sie unbedingt alle zuvor erstellten Kontodateien im gemeinsamen Ordner aller Terminals im Unterordner \DoEasy\Accounts\. Anschließend speichert die Bibliothek beim Ersetzen des Kontos durch ein neues Konto die Kontoobjekte im neuen Format selbstständig ab.
Um den gemeinsamen Ordner aller Terminals zu öffnen, verwenden Sie den Editorbefehl Datei —> Gemeinsamen Dateiordner öffnen. Gehen Sie im Explorer-Fenster in den Ordner "Files" und geben Sie dann \DoEasy\Accounts\ ein.
Im 'public' Teil der Klasse fügen Sie die Definition der Methode hinzu, die die für die Eröffnung einer bestimmten Position oder die Erteilung einer Pending Order erforderliche Marge zurückgibtIm nächsten Artikel werden wir die Überprüfung der Gültigkeit der Parameter von Handelsaufträgen implementieren:
public: //--- Konstructor CAccount(void); //--- Set account's (1) integer, (2) real and (3) string properties void SetProperty(ENUM_ACCOUNT_PROP_INTEGER property,long value) { this.m_long_prop[property]=value; } void SetProperty(ENUM_ACCOUNT_PROP_DOUBLE property,double value) { this.m_double_prop[this.IndexProp(property)]=value; } void SetProperty(ENUM_ACCOUNT_PROP_STRING property,string value) { this.m_string_prop[this.IndexProp(property)]=value; } //--- Return (1) integer, (2) real and (3) string order properties from the account string property long GetProperty(ENUM_ACCOUNT_PROP_INTEGER property) const { return this.m_long_prop[property]; } double GetProperty(ENUM_ACCOUNT_PROP_DOUBLE property) const { return this.m_double_prop[this.IndexProp(property)]; } string GetProperty(ENUM_ACCOUNT_PROP_STRING property) const { return this.m_string_prop[this.IndexProp(property)]; } //--- Return the flag of calculating MarginCall and StopOut levels in % bool IsPercentsForSOLevels(void) const { return this.MarginSOMode()==ACCOUNT_STOPOUT_MODE_PERCENT; } //--- Return the flag of supporting the property by the account object virtual bool SupportProperty(ENUM_ACCOUNT_PROP_INTEGER property) { return true; } virtual bool SupportProperty(ENUM_ACCOUNT_PROP_DOUBLE property) { return true; } virtual bool SupportProperty(ENUM_ACCOUNT_PROP_STRING property) { return true; } //--- Compare CAccount objects by all possible properties (for sorting the lists by a specified account object property) virtual int Compare(const CObject *node,const int mode=0) const; //--- Compare CAccount objects by account properties (to search for equal account objects) bool IsEqual(CAccount* compared_account) const; //--- Update all account data virtual void Refresh(void); //--- (1) Save the account object to the file, (2), download the account object from the file virtual bool Save(const int file_handle); virtual bool Load(const int file_handle); //--- Return the margin required for opening a position or placing a pending order double MarginForAction(const ENUM_ORDER_TYPE action,const string symbol,const double volume,const double price) const; //+------------------------------------------------------------------+
Schreiben wir seine Implementierung außerhalb des Klassenkörpers:
//+------------------------------------------------------------------+ //| Return the margin required for opening a position | //| or placing a pending order | //+------------------------------------------------------------------+ double CAccount::MarginForAction(const ENUM_ORDER_TYPE action,const string symbol,const double volume,const double price) const { double margin=EMPTY_VALUE; #ifdef __MQL5__ return(!::OrderCalcMargin(action,symbol,volume,price,margin) ? EMPTY_VALUE : margin); #else return this.MarginFree()-::AccountFreeMarginCheck(symbol,action,volume); #endif } //+------------------------------------------------------------------+
In MQL5 erhält man die für die Eröffnung einer neuen Position oder die Platzierung einer Pending-Order erforderliche Margin mit der Funktion OrderCalcMargin(). Wenn die Funktion aus irgendeinem Grund einen Fehler zurückgibt, geben Sie den maximalen Wert DBL_MAX zurück (dies ist der Wert der Konstante EMPTY_VALUE). Andernfalls geben Sie die berechnete benötigte Marge zurück.
In MQL4 geben Sie die vorhandene freie Marge abzüglich der nach Eröffnung einer bestimmten Position oder Ordererteilung verbliebenen Mittel zurück, die mit der Funktion AccountFreeMarginCheck() berechnet wurde.
Damit ist die Verbesserung der Objektklasse Konto abgeschlossen.
Nun wollen wir die Basisklasse des Handelsobjekts verbessern. Wir müssen die Möglichkeit hinzufügen, beliebige Audiodateien für die Signalisierung von Handelsereignissen abzuspielen.
Erstellen Sie die Struktur zum Speichern der Flags der Verwendung von Audiodateinamen für verschiedene Ereignisse in der 'private' Sektion der Klasse, um Daten zu speichern:
//+------------------------------------------------------------------+ //| Trading object class | //+------------------------------------------------------------------+ class CTradeObj { private: struct SActionsFlags { private: bool m_use_sound_open; // The flag of using the position opening/order placing sound bool m_use_sound_close; // The flag of using the position closing/order removal sound bool m_use_sound_modify_sl; // The flag of using the StopLoss position/order modification sound bool m_use_sound_modify_tp; // The flag of using the TakeProfit position/order modification sound bool m_use_sound_modify_price; // The flag of using the order placement price modification sound //--- string m_sound_open; // Position opening/order placing sound string m_sound_close; // Position closing/order removal sound string m_sound_modify_sl; // StopLoss position/order modification sound string m_sound_modify_tp; // TakeProfit position/order modification sound string m_sound_modify_price; // Order placement price modification sound //--- string m_sound_open_err; // Position opening/order placing error sound string m_sound_close_err; // Position closing/order removal error sound string m_sound_modify_sl_err; // StopLoss position/order modification error sound string m_sound_modify_tp_err; // TakeProfit position/order modification error sound string m_sound_modify_price_err; // Order placement price modification error sound public: //--- Method of placing/accessing flags and file names void UseSoundOpen(const bool flag) { this.m_use_sound_open=flag; } void UseSoundClose(const bool flag) { this.m_use_sound_close=flag; } void UseSoundModifySL(const bool flag) { this.m_use_sound_modify_sl=flag; } void UseSoundModifyTP(const bool flag) { this.m_use_sound_modify_tp=flag; } void UseSoundModifyPrice(const bool flag) { this.m_use_sound_modify_price=flag; } bool UseSoundOpen(void) const { return this.m_use_sound_open; } bool UseSoundClose(void) const { return this.m_use_sound_close; } bool UseSoundModifySL(void) const { return this.m_use_sound_modify_sl; } bool UseSoundModifyTP(void) const { return this.m_use_sound_modify_tp; } bool UseSoundModifyPrice(void) const { return this.m_use_sound_modify_price; } //--- void SoundOpen(const string sound) { this.m_sound_open=sound; } void SoundClose(const string sound) { this.m_sound_close=sound; } void SoundModifySL(const string sound) { this.m_sound_modify_sl=sound; } void SoundModifyTP(const string sound) { this.m_sound_modify_tp=sound; } void SoundModifyPrice(const string sound) { this.m_sound_modify_price=sound; } string SoundOpen(void) const { return this.m_sound_open; } string SoundClose(void) const { return this.m_sound_close; } string SoundModifySL(void) const { return this.m_sound_modify_sl; } string SoundModifyTP(void) const { return this.m_sound_modify_tp; } string SoundModifyPrice(void) const { return this.m_sound_modify_price; } //--- void SoundErrorOpen(const string sound) { this.m_sound_open_err=sound; } void SoundErrorClose(const string sound) { this.m_sound_close_err=sound; } void SoundErrorModifySL(const string sound) { this.m_sound_modify_sl_err=sound; } void SoundErrorModifyTP(const string sound) { this.m_sound_modify_tp_err=sound; } void SoundErrorModifyPrice(const string sound) { this.m_sound_modify_price_err=sound; } string SoundErrorOpen(void) const { return this.m_sound_open_err; } string SoundErrorClose(void) const { return this.m_sound_close_err; } string SoundErrorModifySL(void) const { return this.m_sound_modify_sl_err; } string SoundErrorModifyTP(void) const { return this.m_sound_modify_tp_err; } string SoundErrorModifyPrice(void) const { return this.m_sound_modify_price_err; } }; struct SActions { SActionsFlags Buy; SActionsFlags BuyStop; SActionsFlags BuyLimit; SActionsFlags BuyStopLimit; SActionsFlags Sell; SActionsFlags SellStop; SActionsFlags SellLimit; SActionsFlags SellStopLimit; }; SActions m_datas;
Die Struktur besteht aus zwei verschachtelten Strukturen: SActionsFlags mit Daten zu Flags und Flagnamen und SActions m_data mit Daten zum Strukturtyp SActionsFlags pro Position und Auftragsart. Dies ermöglicht uns den Zugriff auf das Strukturfeld mit Flags und Flagnamen jeder beliebigen Reihenfolge oder Position, was uns eine größere Flexibilität bei der Einstellung und Verwendung von Sounds für beliebige Ereignisse bietet.
Außerdem, deklarieren Sie in der 'private' Sektion der Klasse die Klassenvariable, die das Flag eines Handelsobjekts mit Hilfe von Sounds für Handelsereignisse speichert:
bool m_use_sound; // The flag of using sounds of the object trading events
Dieses Flag soll der gemeinsame Ein-/Ausschalter für die Verwendung von Tönen für alle Handelsereignisse eines Symbol-Handelsobjekts sein. Das Flag erlaubt die gleichzeitige Aktivierung/Deaktivierung von Tönen für die Trading-Events jedes Symbols.
In dem 'public' Teil der Klasse deklarieren Sie alle notwendigen Methoden für das Setzen und Empfangen der Flags für die Verwendung von Sounds und Audiodateinamen für alle Handelsereignisse eines Symbol-Basis-Handelsobjektes:
public: //--- Konstructor CTradeObj(); //--- Set default values void Init(const string symbol, const ulong magic, const double volume, const ulong deviation, const int stoplimit, const datetime expiration, const bool async_mode, const ENUM_ORDER_TYPE_FILLING type_filling, const ENUM_ORDER_TYPE_TIME type_expiration, ENUM_LOG_LEVEL log_level); //--- Set default sounds and flags of using sounds, void InitSounds(const bool use_sound=false, const string sound_open=NULL, const string sound_close=NULL, const string sound_sl=NULL, const string sound_tp=NULL, const string sound_price=NULL, const string sound_error=NULL); //--- Allow working with sounds and set standard sounds void SetSoundsStandart(void); //--- Set the flag of using the sound of (1) opening/placing a specified position/order type, //--- (2) closing/removal of a specified position/order type, (3) StopLoss modification for a specified position/order type, //--- (4) TakeProfit modification for a specified position/order type, (5) placement price modification for a specified order type void UseSoundOpen(const ENUM_ORDER_TYPE action,const bool flag); void UseSoundClose(const ENUM_ORDER_TYPE action,const bool flag); void UseSoundModifySL(const ENUM_ORDER_TYPE action,const bool flag); void UseSoundModifyTP(const ENUM_ORDER_TYPE action,const bool flag); void UseSoundModifyPrice(const ENUM_ORDER_TYPE action,const bool flag); //--- Return the flag of using the sound of (1) opening/placing a specified position/order type, //--- (2) closing/removal of a specified position/order type, (3) StopLoss modification for a specified position/order type, //--- (4) TakeProfit modification for a specified position/order type, (5) placement price modification for a specified order type bool UseSoundOpen(const ENUM_ORDER_TYPE action) const; bool UseSoundClose(const ENUM_ORDER_TYPE action) const; bool UseSoundModifySL(const ENUM_ORDER_TYPE action) const; bool UseSoundModifyTP(const ENUM_ORDER_TYPE action) const; bool UseSoundModifyPrice(const ENUM_ORDER_TYPE action) const; //--- Set the sound of (1) opening/placing a specified position/order type, //--- (2) closing/removal of a specified position/order type, (3) StopLoss modification for a specified position/order type, //--- (4) TakeProfit modification for a specified position/order type, (5) placement price modification for a specified order type void SetSoundOpen(const ENUM_ORDER_TYPE action,const string sound); void SetSoundClose(const ENUM_ORDER_TYPE action,const string sound); void SetSoundModifySL(const ENUM_ORDER_TYPE action,const string sound); void SetSoundModifyTP(const ENUM_ORDER_TYPE action,const string sound); void SetSoundModifyPrice(const ENUM_ORDER_TYPE action,const string sound); //--- Set the error sound of (1) opening/placing a specified position/order type, //--- (2) closing/removal of a specified position/order type, (3) StopLoss modification for a specified position/order type, //--- (4) TakeProfit modification for a specified position/order type, (5) placement price modification for a specified order type void SetSoundErrorOpen(const ENUM_ORDER_TYPE action,const string sound); void SetSoundErrorClose(const ENUM_ORDER_TYPE action,const string sound); void SetSoundErrorModifySL(const ENUM_ORDER_TYPE action,const string sound); void SetSoundErrorModifyTP(const ENUM_ORDER_TYPE action,const string sound); void SetSoundErrorModifyPrice(const ENUM_ORDER_TYPE action,const string sound); //--- Return the sound of (1) opening/placing a specified position/order type, //--- (2) closing/removal of a specified position/order type, (3) StopLoss modification for a specified position/order type, //--- (4) TakeProfit modification for a specified position/order type, (5) placement price modification for a specified order type string GetSoundOpen(const ENUM_ORDER_TYPE action) const; string GetSoundClose(const ENUM_ORDER_TYPE action) const; string GetSoundModifySL(const ENUM_ORDER_TYPE action) const; string GetSoundModifyTP(const ENUM_ORDER_TYPE action) const; string GetSoundModifyPrice(const ENUM_ORDER_TYPE action) const; //--- Return the error sound of (1) opening/placing a specified position/order type, //--- (2) closing/removal of a specified position/order type, (3) StopLoss modification for a specified position/order type, //--- (4) TakeProfit modification for a specified position/order type, (5) placement price modification for a specified order type string GetSoundErrorOpen(const ENUM_ORDER_TYPE action) const; string GetSoundErrorClose(const ENUM_ORDER_TYPE action) const; string GetSoundErrorModifySL(const ENUM_ORDER_TYPE action) const; string GetSoundErrorModifyTP(const ENUM_ORDER_TYPE action) const; string GetSoundErrorModifyPrice(const ENUM_ORDER_TYPE action) const; //--- Play the sound of (1) opening/placing a specified position/order type, //--- (2) closing/removal of a specified position/order type, (3) StopLoss modification for a specified position/order type, //--- (4) TakeProfit modification for a specified position/order type, (5) placement price modification for a specified order type void PlaySoundOpen(const ENUM_ORDER_TYPE action); void PlaySoundClose(const ENUM_ORDER_TYPE action); void PlaySoundModifySL(const ENUM_ORDER_TYPE action); void PlaySoundModifyTP(const ENUM_ORDER_TYPE action); void PlaySoundModifyPrice(const ENUM_ORDER_TYPE action); //--- Play the error sound of (1) opening/placing a specified position/order type, //--- (2) closing/removal of a specified position/order type, (3) StopLoss modification for a specified position/order type, //--- (4) TakeProfit modification for a specified position/order type, (5) placement price modification for a specified order type void PlaySoundErrorOpen(const ENUM_ORDER_TYPE action); void PlaySoundErrorClose(const ENUM_ORDER_TYPE action); void PlaySoundErrorModifySL(const ENUM_ORDER_TYPE action); void PlaySoundErrorModifyTP(const ENUM_ORDER_TYPE action); void PlaySoundErrorModifyPrice(const ENUM_ORDER_TYPE action); //--- Set/return the flag of using sounds void SetUseSound(const bool flag) { this.m_use_sound=flag; } bool IsUseSound(void) const { return this.m_use_sound; } //--- (1) Return the margin calculation mode, (2) hedge account flag
Rücksetzen des gemeinsamen Flags der Verwendung von Tönen im Klassenkonstruktor und Initialisieren der Flags der Verwendung von Tönen und Audiodateien auf Standardwerte mit deaktivierten Tönen und leere Dateinamen:
//+------------------------------------------------------------------+ //| Konstruktor | //+------------------------------------------------------------------+ CTradeObj::CTradeObj(void) : m_magic(0), m_deviation(5), m_stop_limit(0), m_expiration(0), m_async_mode(false), m_type_filling(ORDER_FILLING_FOK), m_type_expiration(ORDER_TIME_GTC), m_comment(::MQLInfoString(MQL_PROGRAM_NAME)+" by DoEasy"), m_log_level(LOG_LEVEL_ERROR_MSG) { //--- Margin calculation mode this.m_margin_mode= ( #ifdef __MQL5__ (ENUM_ACCOUNT_MARGIN_MODE)::AccountInfoInteger(ACCOUNT_MARGIN_MODE) #else /* MQL4 */ ACCOUNT_MARGIN_MODE_RETAIL_HEDGING #endif ); //--- Set default sounds and flags of using sounds this.m_use_sound=false; this.InitSounds(); } //+------------------------------------------------------------------+
Implementieren Sie die Methode zur Initialisierung von Flags zur Verwendung von Sounds und zum Setzen von Audiodateinamen außerhalb des Klassenkörpers:
//+------------------------------------------------------------------+ //| Set default sounds and flags of using sounds | //+------------------------------------------------------------------+ void CTradeObj::InitSounds(const bool use_sound=false, const string sound_open=NULL, const string sound_close=NULL, const string sound_sl=NULL, const string sound_tp=NULL, const string sound_price=NULL, const string sound_error=NULL) { this.m_datas.Buy.UseSoundOpen(use_sound); this.m_datas.Buy.UseSoundClose(use_sound); this.m_datas.Buy.UseSoundModifySL(use_sound); this.m_datas.Buy.UseSoundModifyTP(use_sound); this.m_datas.Buy.UseSoundModifyPrice(use_sound); this.m_datas.Buy.SoundOpen(sound_open); this.m_datas.Buy.SoundClose(sound_close); this.m_datas.Buy.SoundModifySL(sound_sl); this.m_datas.Buy.SoundModifyTP(sound_tp); this.m_datas.Buy.SoundModifyPrice(sound_price); this.m_datas.Buy.SoundErrorClose(sound_error); this.m_datas.Buy.SoundErrorOpen(sound_error); this.m_datas.Buy.SoundErrorModifySL(sound_error); this.m_datas.Buy.SoundErrorModifyTP(sound_error); this.m_datas.Buy.SoundErrorModifyPrice(sound_error); this.m_datas.BuyStop.UseSoundOpen(use_sound); this.m_datas.BuyStop.UseSoundClose(use_sound); this.m_datas.BuyStop.UseSoundModifySL(use_sound); this.m_datas.BuyStop.UseSoundModifyTP(use_sound); this.m_datas.BuyStop.UseSoundModifyPrice(use_sound); this.m_datas.BuyStop.SoundOpen(sound_open); this.m_datas.BuyStop.SoundClose(sound_close); this.m_datas.BuyStop.SoundModifySL(sound_sl); this.m_datas.BuyStop.SoundModifyTP(sound_tp); this.m_datas.BuyStop.SoundModifyPrice(sound_price); this.m_datas.BuyStop.SoundErrorClose(sound_error); this.m_datas.BuyStop.SoundErrorOpen(sound_error); this.m_datas.BuyStop.SoundErrorModifySL(sound_error); this.m_datas.BuyStop.SoundErrorModifyTP(sound_error); this.m_datas.BuyStop.SoundErrorModifyPrice(sound_error); this.m_datas.BuyLimit.UseSoundOpen(use_sound); this.m_datas.BuyLimit.UseSoundClose(use_sound); this.m_datas.BuyLimit.UseSoundModifySL(use_sound); this.m_datas.BuyLimit.UseSoundModifyTP(use_sound); this.m_datas.BuyLimit.UseSoundModifyPrice(use_sound); this.m_datas.BuyLimit.SoundOpen(sound_open); this.m_datas.BuyLimit.SoundClose(sound_close); this.m_datas.BuyLimit.SoundModifySL(sound_sl); this.m_datas.BuyLimit.SoundModifyTP(sound_tp); this.m_datas.BuyLimit.SoundModifyPrice(sound_price); this.m_datas.BuyLimit.SoundErrorClose(sound_error); this.m_datas.BuyLimit.SoundErrorOpen(sound_error); this.m_datas.BuyLimit.SoundErrorModifySL(sound_error); this.m_datas.BuyLimit.SoundErrorModifyTP(sound_error); this.m_datas.BuyLimit.SoundErrorModifyPrice(sound_error); this.m_datas.BuyStopLimit.UseSoundOpen(use_sound); this.m_datas.BuyStopLimit.UseSoundClose(use_sound); this.m_datas.BuyStopLimit.UseSoundModifySL(use_sound); this.m_datas.BuyStopLimit.UseSoundModifyTP(use_sound); this.m_datas.BuyStopLimit.UseSoundModifyPrice(use_sound); this.m_datas.BuyStopLimit.SoundOpen(sound_open); this.m_datas.BuyStopLimit.SoundClose(sound_close); this.m_datas.BuyStopLimit.SoundModifySL(sound_sl); this.m_datas.BuyStopLimit.SoundModifyTP(sound_tp); this.m_datas.BuyStopLimit.SoundModifyPrice(sound_price); this.m_datas.BuyStopLimit.SoundErrorClose(sound_error); this.m_datas.BuyStopLimit.SoundErrorOpen(sound_error); this.m_datas.BuyStopLimit.SoundErrorModifySL(sound_error); this.m_datas.BuyStopLimit.SoundErrorModifyTP(sound_error); this.m_datas.BuyStopLimit.SoundErrorModifyPrice(sound_error); this.m_datas.Sell.UseSoundOpen(use_sound); this.m_datas.Sell.UseSoundClose(use_sound); this.m_datas.Sell.UseSoundModifySL(use_sound); this.m_datas.Sell.UseSoundModifyTP(use_sound); this.m_datas.Sell.UseSoundModifyPrice(use_sound); this.m_datas.Sell.SoundOpen(sound_open); this.m_datas.Sell.SoundClose(sound_close); this.m_datas.Sell.SoundModifySL(sound_sl); this.m_datas.Sell.SoundModifyTP(sound_tp); this.m_datas.Sell.SoundModifyPrice(sound_price); this.m_datas.Sell.SoundErrorClose(sound_error); this.m_datas.Sell.SoundErrorOpen(sound_error); this.m_datas.Sell.SoundErrorModifySL(sound_error); this.m_datas.Sell.SoundErrorModifyTP(sound_error); this.m_datas.Sell.SoundErrorModifyPrice(sound_error); this.m_datas.SellStop.UseSoundOpen(use_sound); this.m_datas.SellStop.UseSoundClose(use_sound); this.m_datas.SellStop.UseSoundModifySL(use_sound); this.m_datas.SellStop.UseSoundModifyTP(use_sound); this.m_datas.SellStop.UseSoundModifyPrice(use_sound); this.m_datas.SellStop.SoundOpen(sound_open); this.m_datas.SellStop.SoundClose(sound_close); this.m_datas.SellStop.SoundModifySL(sound_sl); this.m_datas.SellStop.SoundModifyTP(sound_tp); this.m_datas.SellStop.SoundModifyPrice(sound_price); this.m_datas.SellStop.SoundErrorClose(sound_error); this.m_datas.SellStop.SoundErrorOpen(sound_error); this.m_datas.SellStop.SoundErrorModifySL(sound_error); this.m_datas.SellStop.SoundErrorModifyTP(sound_error); this.m_datas.SellStop.SoundErrorModifyPrice(sound_error); this.m_datas.SellLimit.UseSoundOpen(use_sound); this.m_datas.SellLimit.UseSoundClose(use_sound); this.m_datas.SellLimit.UseSoundModifySL(use_sound); this.m_datas.SellLimit.UseSoundModifyTP(use_sound); this.m_datas.SellLimit.UseSoundModifyPrice(use_sound); this.m_datas.SellLimit.SoundOpen(sound_open); this.m_datas.SellLimit.SoundClose(sound_close); this.m_datas.SellLimit.SoundModifySL(sound_sl); this.m_datas.SellLimit.SoundModifyTP(sound_tp); this.m_datas.SellLimit.SoundModifyPrice(sound_price); this.m_datas.SellLimit.SoundErrorClose(sound_error); this.m_datas.SellLimit.SoundErrorOpen(sound_error); this.m_datas.SellLimit.SoundErrorModifySL(sound_error); this.m_datas.SellLimit.SoundErrorModifyTP(sound_error); this.m_datas.SellLimit.SoundErrorModifyPrice(sound_error); this.m_datas.SellStopLimit.UseSoundOpen(use_sound); this.m_datas.SellStopLimit.UseSoundClose(use_sound); this.m_datas.SellStopLimit.UseSoundModifySL(use_sound); this.m_datas.SellStopLimit.UseSoundModifyTP(use_sound); this.m_datas.SellStopLimit.UseSoundModifyPrice(use_sound); this.m_datas.SellStopLimit.SoundOpen(sound_open); this.m_datas.SellStopLimit.SoundClose(sound_close); this.m_datas.SellStopLimit.SoundModifySL(sound_sl); this.m_datas.SellStopLimit.SoundModifyTP(sound_tp); this.m_datas.SellStopLimit.SoundModifyPrice(sound_price); this.m_datas.SellStopLimit.SoundErrorClose(sound_error); this.m_datas.SellStopLimit.SoundErrorOpen(sound_error); this.m_datas.SellStopLimit.SoundErrorModifySL(sound_error); this.m_datas.SellStopLimit.SoundErrorModifyTP(sound_error); this.m_datas.SellStopLimit.SoundErrorModifyPrice(sound_error); } //+------------------------------------------------------------------+
Die Methode erhält das Flag zum Verwenden von Sounds bei Handelsobjekt-Ereignissen, Dateinamen jeweils für das Öffnen, Schließen, den StopLoss/TakeProfitModifikation, Orderplatzierungspreis und für Fehlersounds. Als Nächstes werden die Strukturfelder für jedes Handelsereignis für jede an den Server gesendete Orderart durch übergebene Werte ausgefüllt.
Das Flag für die Verwendung von Sounds und der Name der Fehlersound-Datei werden für alle aufgezählten Handelsereignisse auf Eins gesetzt, während für jedes Handelsereignis die einzelnen Sounds individuell gesetzt werden. Sie können jedoch auch einen benutzerdefinierten Sound für die Fehlertöne bestimmter Ereignisse mit den oben angekündigten Methoden setzen, sowie das Flag für die Verwendung eines Sounds für jedes Handelsereignis eines Objekts einzeln setzen. Standardmäßig sind die Sounds deaktiviert und Dateinamen leer.
Außerdem verfügt die Klasse über die Methode, die Standard-Sounds für alle Objekt-Handelsereignisse setzt und ihre Verwendung für jedes Handelsereignis erlaubt:
//+------------------------------------------------------------------+ //| Allow working with sounds and set standard sounds | //+------------------------------------------------------------------+ void CTradeObj::SetSoundsStandart(void) { this.m_datas.Buy.UseSoundClose(true); this.m_datas.Buy.UseSoundOpen(true); this.m_datas.Buy.UseSoundModifySL(true); this.m_datas.Buy.UseSoundModifyTP(true); this.m_datas.Buy.UseSoundModifyPrice(true); this.m_datas.Buy.SoundOpen(SND_OK); this.m_datas.Buy.SoundClose(SND_OK); this.m_datas.Buy.SoundModifySL(SND_OK); this.m_datas.Buy.SoundModifyTP(SND_OK); this.m_datas.Buy.SoundModifyPrice(SND_OK); this.m_datas.Buy.SoundErrorClose(SND_TIMEOUT); this.m_datas.Buy.SoundErrorOpen(SND_TIMEOUT); this.m_datas.Buy.SoundErrorModifySL(SND_TIMEOUT); this.m_datas.Buy.SoundErrorModifyTP(SND_TIMEOUT); this.m_datas.Buy.SoundErrorModifyPrice(SND_TIMEOUT); this.m_datas.BuyStop.UseSoundClose(true); this.m_datas.BuyStop.UseSoundOpen(true); this.m_datas.BuyStop.UseSoundModifySL(true); this.m_datas.BuyStop.UseSoundModifyTP(true); this.m_datas.BuyStop.UseSoundModifyPrice(true); this.m_datas.BuyStop.SoundOpen(SND_OK); this.m_datas.BuyStop.SoundClose(SND_OK); this.m_datas.BuyStop.SoundModifySL(SND_OK); this.m_datas.BuyStop.SoundModifyTP(SND_OK); this.m_datas.BuyStop.SoundModifyPrice(SND_OK); this.m_datas.BuyStop.SoundErrorClose(SND_TIMEOUT); this.m_datas.BuyStop.SoundErrorOpen(SND_TIMEOUT); this.m_datas.BuyStop.SoundErrorModifySL(SND_TIMEOUT); this.m_datas.BuyStop.SoundErrorModifyTP(SND_TIMEOUT); this.m_datas.BuyStop.SoundErrorModifyPrice(SND_TIMEOUT); this.m_datas.BuyLimit.UseSoundClose(true); this.m_datas.BuyLimit.UseSoundOpen(true); this.m_datas.BuyLimit.UseSoundModifySL(true); this.m_datas.BuyLimit.UseSoundModifyTP(true); this.m_datas.BuyLimit.UseSoundModifyPrice(true); this.m_datas.BuyLimit.SoundOpen(SND_OK); this.m_datas.BuyLimit.SoundClose(SND_OK); this.m_datas.BuyLimit.SoundModifySL(SND_OK); this.m_datas.BuyLimit.SoundModifyTP(SND_OK); this.m_datas.BuyLimit.SoundModifyPrice(SND_OK); this.m_datas.BuyLimit.SoundErrorClose(SND_TIMEOUT); this.m_datas.BuyLimit.SoundErrorOpen(SND_TIMEOUT); this.m_datas.BuyLimit.SoundErrorModifySL(SND_TIMEOUT); this.m_datas.BuyLimit.SoundErrorModifyTP(SND_TIMEOUT); this.m_datas.BuyLimit.SoundErrorModifyPrice(SND_TIMEOUT); this.m_datas.BuyStopLimit.UseSoundClose(true); this.m_datas.BuyStopLimit.UseSoundOpen(true); this.m_datas.BuyStopLimit.UseSoundModifySL(true); this.m_datas.BuyStopLimit.UseSoundModifyTP(true); this.m_datas.BuyStopLimit.UseSoundModifyPrice(true); this.m_datas.BuyStopLimit.SoundOpen(SND_OK); this.m_datas.BuyStopLimit.SoundClose(SND_OK); this.m_datas.BuyStopLimit.SoundModifySL(SND_OK); this.m_datas.BuyStopLimit.SoundModifyTP(SND_OK); this.m_datas.BuyStopLimit.SoundModifyPrice(SND_OK); this.m_datas.BuyStopLimit.SoundErrorClose(SND_TIMEOUT); this.m_datas.BuyStopLimit.SoundErrorOpen(SND_TIMEOUT); this.m_datas.BuyStopLimit.SoundErrorModifySL(SND_TIMEOUT); this.m_datas.BuyStopLimit.SoundErrorModifyTP(SND_TIMEOUT); this.m_datas.BuyStopLimit.SoundErrorModifyPrice(SND_TIMEOUT); this.m_datas.Sell.UseSoundClose(true); this.m_datas.Sell.UseSoundOpen(true); this.m_datas.Sell.UseSoundModifySL(true); this.m_datas.Sell.UseSoundModifyTP(true); this.m_datas.Sell.UseSoundModifyPrice(true); this.m_datas.Sell.SoundOpen(SND_OK); this.m_datas.Sell.SoundClose(SND_OK); this.m_datas.Sell.SoundModifySL(SND_OK); this.m_datas.Sell.SoundModifyTP(SND_OK); this.m_datas.Sell.SoundModifyPrice(SND_OK); this.m_datas.Sell.SoundErrorClose(SND_TIMEOUT); this.m_datas.Sell.SoundErrorOpen(SND_TIMEOUT); this.m_datas.Sell.SoundErrorModifySL(SND_TIMEOUT); this.m_datas.Sell.SoundErrorModifyTP(SND_TIMEOUT); this.m_datas.Sell.SoundErrorModifyPrice(SND_TIMEOUT); this.m_datas.SellStop.UseSoundClose(true); this.m_datas.SellStop.UseSoundOpen(true); this.m_datas.SellStop.UseSoundModifySL(true); this.m_datas.SellStop.UseSoundModifyTP(true); this.m_datas.SellStop.UseSoundModifyPrice(true); this.m_datas.SellStop.SoundOpen(SND_OK); this.m_datas.SellStop.SoundClose(SND_OK); this.m_datas.SellStop.SoundModifySL(SND_OK); this.m_datas.SellStop.SoundModifyTP(SND_OK); this.m_datas.SellStop.SoundModifyPrice(SND_OK); this.m_datas.SellStop.SoundErrorClose(SND_TIMEOUT); this.m_datas.SellStop.SoundErrorOpen(SND_TIMEOUT); this.m_datas.SellStop.SoundErrorModifySL(SND_TIMEOUT); this.m_datas.SellStop.SoundErrorModifyTP(SND_TIMEOUT); this.m_datas.SellStop.SoundErrorModifyPrice(SND_TIMEOUT); this.m_datas.SellLimit.UseSoundClose(true); this.m_datas.SellLimit.UseSoundOpen(true); this.m_datas.SellLimit.UseSoundModifySL(true); this.m_datas.SellLimit.UseSoundModifyTP(true); this.m_datas.SellLimit.UseSoundModifyPrice(true); this.m_datas.SellLimit.SoundOpen(SND_OK); this.m_datas.SellLimit.SoundClose(SND_OK); this.m_datas.SellLimit.SoundModifySL(SND_OK); this.m_datas.SellLimit.SoundModifyTP(SND_OK); this.m_datas.SellLimit.SoundModifyPrice(SND_OK); this.m_datas.SellLimit.SoundErrorClose(SND_TIMEOUT); this.m_datas.SellLimit.SoundErrorOpen(SND_TIMEOUT); this.m_datas.SellLimit.SoundErrorModifySL(SND_TIMEOUT); this.m_datas.SellLimit.SoundErrorModifyTP(SND_TIMEOUT); this.m_datas.SellLimit.SoundErrorModifyPrice(SND_TIMEOUT); this.m_datas.SellStopLimit.UseSoundClose(true); this.m_datas.SellStopLimit.UseSoundOpen(true); this.m_datas.SellStopLimit.UseSoundModifySL(true); this.m_datas.SellStopLimit.UseSoundModifyTP(true); this.m_datas.SellStopLimit.UseSoundModifyPrice(true); this.m_datas.SellStopLimit.SoundOpen(SND_OK); this.m_datas.SellStopLimit.SoundClose(SND_OK); this.m_datas.SellStopLimit.SoundModifySL(SND_OK); this.m_datas.SellStopLimit.SoundModifyTP(SND_OK); this.m_datas.SellStopLimit.SoundModifyPrice(SND_OK); this.m_datas.SellStopLimit.SoundErrorClose(SND_TIMEOUT); this.m_datas.SellStopLimit.SoundErrorOpen(SND_TIMEOUT); this.m_datas.SellStopLimit.SoundErrorModifySL(SND_TIMEOUT); this.m_datas.SellStopLimit.SoundErrorModifyTP(SND_TIMEOUT); this.m_datas.SellStopLimit.SoundErrorModifyPrice(SND_TIMEOUT); } //+------------------------------------------------------------------+
Implementieren Sie über den Klassenkörper hinaus die Methoden zum Abspielen von Audiodateien und zum Setzen von Flags und die Sounds für einen bestimmten Handelsereignistyp:
//+------------------------------------------------------------------+ //| Set the flag of using sounds | //| of opening/placing a specified position/order type | //+------------------------------------------------------------------+ void CTradeObj::UseSoundOpen(const ENUM_ORDER_TYPE action,const bool flag) { int index=action; switch(index) { case ORDER_TYPE_BUY : this.m_datas.Buy.UseSoundOpen(flag); break; case ORDER_TYPE_BUY_STOP : this.m_datas.BuyStop.UseSoundOpen(flag); break; case ORDER_TYPE_BUY_LIMIT : this.m_datas.BuyLimit.UseSoundOpen(flag); break; case ORDER_TYPE_SELL : this.m_datas.Sell.UseSoundOpen(flag); break; case ORDER_TYPE_SELL_STOP : this.m_datas.SellStop.UseSoundOpen(flag); break; case ORDER_TYPE_SELL_LIMIT : this.m_datas.SellLimit.UseSoundOpen(flag); break; case ORDER_TYPE_BUY_STOP_LIMIT : this.m_datas.BuyStopLimit.UseSoundOpen(flag); break; case ORDER_TYPE_SELL_STOP_LIMIT : this.m_datas.SellStopLimit.UseSoundOpen(flag); break; default: break; } } //+------------------------------------------------------------------+ //| Set the flag of using a sound | //| of closing/removal of a specified position/order type | //+------------------------------------------------------------------+ void CTradeObj::UseSoundClose(const ENUM_ORDER_TYPE action,const bool flag) { int index=action; switch(index) { case ORDER_TYPE_BUY : this.m_datas.Buy.UseSoundClose(flag); break; case ORDER_TYPE_BUY_STOP : this.m_datas.BuyStop.UseSoundClose(flag); break; case ORDER_TYPE_BUY_LIMIT : this.m_datas.BuyLimit.UseSoundClose(flag); break; case ORDER_TYPE_BUY_STOP_LIMIT : this.m_datas.BuyStopLimit.UseSoundClose(flag); break; case ORDER_TYPE_SELL : this.m_datas.Sell.UseSoundClose(flag); break; case ORDER_TYPE_SELL_STOP : this.m_datas.SellStop.UseSoundClose(flag); break; case ORDER_TYPE_SELL_LIMIT : this.m_datas.SellLimit.UseSoundClose(flag); break; case ORDER_TYPE_SELL_STOP_LIMIT : this.m_datas.SellStopLimit.UseSoundClose(flag); break; default: break; } } //+------------------------------------------------------------------+ //| Set the flag of using a sound | //| of StopLoss modification for a specified position/order type | //+------------------------------------------------------------------+ void CTradeObj::UseSoundModifySL(const ENUM_ORDER_TYPE action,const bool flag) { int index=action; switch(index) { case ORDER_TYPE_BUY : this.m_datas.Buy.UseSoundModifySL(flag); break; case ORDER_TYPE_BUY_STOP : this.m_datas.BuyStop.UseSoundModifySL(flag); break; case ORDER_TYPE_BUY_LIMIT : this.m_datas.BuyLimit.UseSoundModifySL(flag); break; case ORDER_TYPE_BUY_STOP_LIMIT : this.m_datas.BuyStopLimit.UseSoundModifySL(flag); break; case ORDER_TYPE_SELL : this.m_datas.Sell.UseSoundModifySL(flag); break; case ORDER_TYPE_SELL_STOP : this.m_datas.SellStop.UseSoundModifySL(flag); break; case ORDER_TYPE_SELL_LIMIT : this.m_datas.SellLimit.UseSoundModifySL(flag); break; case ORDER_TYPE_SELL_STOP_LIMIT : this.m_datas.SellStopLimit.UseSoundModifySL(flag); break; default: break; } } //+------------------------------------------------------------------+ //| Set the flag of using a sound | //| of TakeProfit modification for a specified position/order type | //+------------------------------------------------------------------+ void CTradeObj::UseSoundModifyTP(const ENUM_ORDER_TYPE action,const bool flag) { int index=action; switch(index) { case ORDER_TYPE_BUY : this.m_datas.Buy.UseSoundModifyTP(flag); break; case ORDER_TYPE_BUY_STOP : this.m_datas.BuyStop.UseSoundModifyTP(flag); break; case ORDER_TYPE_BUY_LIMIT : this.m_datas.BuyLimit.UseSoundModifyTP(flag); break; case ORDER_TYPE_BUY_STOP_LIMIT : this.m_datas.BuyStopLimit.UseSoundModifyTP(flag); break; case ORDER_TYPE_SELL : this.m_datas.Sell.UseSoundModifyTP(flag); break; case ORDER_TYPE_SELL_STOP : this.m_datas.SellStop.UseSoundModifyTP(flag); break; case ORDER_TYPE_SELL_LIMIT : this.m_datas.SellLimit.UseSoundModifyTP(flag); break; case ORDER_TYPE_SELL_STOP_LIMIT : this.m_datas.SellStopLimit.UseSoundModifyTP(flag); break; default: break; } } //+------------------------------------------------------------------+ //| Set the flag of using a modification sound | //| of the placement price for a specified order type | //+------------------------------------------------------------------+ void CTradeObj::UseSoundModifyPrice(const ENUM_ORDER_TYPE action,const bool flag) { int index=action; switch(index) { case ORDER_TYPE_BUY_STOP : this.m_datas.BuyStop.UseSoundModifyPrice(flag); break; case ORDER_TYPE_BUY_LIMIT : this.m_datas.BuyLimit.UseSoundModifyPrice(flag); break; case ORDER_TYPE_BUY_STOP_LIMIT : this.m_datas.BuyStopLimit.UseSoundModifyPrice(flag); break; case ORDER_TYPE_SELL_STOP : this.m_datas.SellStop.UseSoundModifyPrice(flag); break; case ORDER_TYPE_SELL_LIMIT : this.m_datas.SellLimit.UseSoundModifyPrice(flag); break; case ORDER_TYPE_SELL_STOP_LIMIT : this.m_datas.SellStopLimit.UseSoundModifyPrice(flag); break; default: break; } } //+------------------------------------------------------------------+ //| Return the flag of using the sound of opening/placing | //| a specified position/order type | //+------------------------------------------------------------------+ bool CTradeObj::UseSoundOpen(const ENUM_ORDER_TYPE action) const { int index=action; switch(index) { case ORDER_TYPE_BUY : return this.m_datas.Buy.UseSoundOpen(); case ORDER_TYPE_BUY_STOP : return this.m_datas.BuyStop.UseSoundOpen(); case ORDER_TYPE_BUY_LIMIT : return this.m_datas.BuyLimit.UseSoundOpen(); case ORDER_TYPE_BUY_STOP_LIMIT : return this.m_datas.BuyStopLimit.UseSoundOpen(); case ORDER_TYPE_SELL : return this.m_datas.Sell.UseSoundOpen(); case ORDER_TYPE_SELL_STOP : return this.m_datas.SellStop.UseSoundOpen(); case ORDER_TYPE_SELL_LIMIT : return this.m_datas.SellLimit.UseSoundOpen(); case ORDER_TYPE_SELL_STOP_LIMIT : return this.m_datas.SellStopLimit.UseSoundOpen(); default: return false; } } //+------------------------------------------------------------------+ //| Return the flag of using the sound of closing/removal of | //| a specified position/order type | //+------------------------------------------------------------------+ bool CTradeObj::UseSoundClose(const ENUM_ORDER_TYPE action) const { int index=action; switch(index) { case ORDER_TYPE_BUY : return this.m_datas.Buy.UseSoundClose(); case ORDER_TYPE_BUY_STOP : return this.m_datas.BuyStop.UseSoundClose(); case ORDER_TYPE_BUY_LIMIT : return this.m_datas.BuyLimit.UseSoundClose(); case ORDER_TYPE_BUY_STOP_LIMIT : return this.m_datas.BuyStopLimit.UseSoundClose(); case ORDER_TYPE_SELL : return this.m_datas.Sell.UseSoundClose(); case ORDER_TYPE_SELL_STOP : return this.m_datas.SellStop.UseSoundClose(); case ORDER_TYPE_SELL_LIMIT : return this.m_datas.SellLimit.UseSoundClose(); case ORDER_TYPE_SELL_STOP_LIMIT : return this.m_datas.SellStopLimit.UseSoundClose(); default: return false; } } //+------------------------------------------------------------------+ //| Return the flag of using a sound | //| of StopLoss modification for a specified position/order type | //+------------------------------------------------------------------+ bool CTradeObj::UseSoundModifySL(const ENUM_ORDER_TYPE action) const { int index=action; switch(index) { case ORDER_TYPE_BUY : return this.m_datas.Buy.UseSoundModifySL(); case ORDER_TYPE_BUY_STOP : return this.m_datas.BuyStop.UseSoundModifySL(); case ORDER_TYPE_BUY_LIMIT : return this.m_datas.BuyLimit.UseSoundModifySL(); case ORDER_TYPE_BUY_STOP_LIMIT : return this.m_datas.BuyStopLimit.UseSoundModifySL(); case ORDER_TYPE_SELL : return this.m_datas.Sell.UseSoundModifySL(); case ORDER_TYPE_SELL_STOP : return this.m_datas.SellStop.UseSoundModifySL(); case ORDER_TYPE_SELL_LIMIT : return this.m_datas.SellLimit.UseSoundModifySL(); case ORDER_TYPE_SELL_STOP_LIMIT : return this.m_datas.SellStopLimit.UseSoundModifySL(); default: return false; } } //+------------------------------------------------------------------+ //| Return the flag of using a sound | //| of TakeProfit modification for a specified position/order type | //+------------------------------------------------------------------+ bool CTradeObj::UseSoundModifyTP(const ENUM_ORDER_TYPE action) const { int index=action; switch(index) { case ORDER_TYPE_BUY : return this.m_datas.Buy.UseSoundModifyTP(); case ORDER_TYPE_BUY_STOP : return this.m_datas.BuyStop.UseSoundModifyTP(); case ORDER_TYPE_BUY_LIMIT : return this.m_datas.BuyLimit.UseSoundModifyTP(); case ORDER_TYPE_BUY_STOP_LIMIT : return this.m_datas.BuyStopLimit.UseSoundModifyTP(); case ORDER_TYPE_SELL : return this.m_datas.Sell.UseSoundModifyTP(); case ORDER_TYPE_SELL_STOP : return this.m_datas.SellStop.UseSoundModifyTP(); case ORDER_TYPE_SELL_LIMIT : return this.m_datas.SellLimit.UseSoundModifyTP(); case ORDER_TYPE_SELL_STOP_LIMIT : return this.m_datas.SellStopLimit.UseSoundModifyTP(); default: return false; } } //+------------------------------------------------------------------+ //| Return the flag of using a modification sound | //| of the placement price for a specified order type | //+------------------------------------------------------------------+ bool CTradeObj::UseSoundModifyPrice(const ENUM_ORDER_TYPE action) const { int index=action; switch(index) { case ORDER_TYPE_BUY_STOP : return this.m_datas.BuyStop.UseSoundModifyPrice(); case ORDER_TYPE_BUY_LIMIT : return this.m_datas.BuyLimit.UseSoundModifyPrice(); case ORDER_TYPE_BUY_STOP_LIMIT : return this.m_datas.BuyStopLimit.UseSoundModifyPrice(); case ORDER_TYPE_SELL_STOP : return this.m_datas.SellStop.UseSoundModifyPrice(); case ORDER_TYPE_SELL_LIMIT : return this.m_datas.SellLimit.UseSoundModifyPrice(); case ORDER_TYPE_SELL_STOP_LIMIT : return this.m_datas.SellStopLimit.UseSoundModifyPrice(); default: return false; } } //+------------------------------------------------------------------+ //| Set the sound of opening/placing | //| a specified position/order type | //+------------------------------------------------------------------+ void CTradeObj::SetSoundOpen(const ENUM_ORDER_TYPE action,const string sound) { int index=action; switch(index) { case ORDER_TYPE_BUY : this.m_datas.Buy.SoundOpen(sound); break; case ORDER_TYPE_BUY_STOP : this.m_datas.BuyStop.SoundOpen(sound); break; case ORDER_TYPE_BUY_LIMIT : this.m_datas.BuyLimit.SoundOpen(sound); break; case ORDER_TYPE_BUY_STOP_LIMIT : this.m_datas.BuyStopLimit.SoundOpen(sound); break; case ORDER_TYPE_SELL : this.m_datas.Sell.SoundOpen(sound); break; case ORDER_TYPE_SELL_STOP : this.m_datas.SellStop.SoundOpen(sound); break; case ORDER_TYPE_SELL_LIMIT : this.m_datas.SellLimit.SoundOpen(sound); break; case ORDER_TYPE_SELL_STOP_LIMIT : this.m_datas.SellStopLimit.SoundOpen(sound); break; default: break; } } //+------------------------------------------------------------------+ //| Set the sound of closing/removal of | //| a specified position/order type | //+------------------------------------------------------------------+ void CTradeObj::SetSoundClose(const ENUM_ORDER_TYPE action,const string sound) { int index=action; switch(index) { case ORDER_TYPE_BUY : this.m_datas.Buy.SoundClose(sound); break; case ORDER_TYPE_BUY_STOP : this.m_datas.BuyStop.SoundClose(sound); break; case ORDER_TYPE_BUY_LIMIT : this.m_datas.BuyLimit.SoundClose(sound); break; case ORDER_TYPE_BUY_STOP_LIMIT : this.m_datas.BuyStopLimit.SoundClose(sound); break; case ORDER_TYPE_SELL : this.m_datas.Sell.SoundClose(sound); break; case ORDER_TYPE_SELL_STOP : this.m_datas.SellStop.SoundClose(sound); break; case ORDER_TYPE_SELL_LIMIT : this.m_datas.SellLimit.SoundClose(sound); break; case ORDER_TYPE_SELL_STOP_LIMIT : this.m_datas.SellStopLimit.SoundClose(sound); break; default: break; } } //+------------------------------------------------------------------+ //| Set StopLoss modification sound of | //| a specified position/order type | //+------------------------------------------------------------------+ void CTradeObj::SetSoundModifySL(const ENUM_ORDER_TYPE action,const string sound) { int index=action; switch(index) { case ORDER_TYPE_BUY : this.m_datas.Buy.SoundModifySL(sound); break; case ORDER_TYPE_BUY_STOP : this.m_datas.BuyStop.SoundModifySL(sound); break; case ORDER_TYPE_BUY_LIMIT : this.m_datas.BuyLimit.SoundModifySL(sound); break; case ORDER_TYPE_BUY_STOP_LIMIT : this.m_datas.BuyStopLimit.SoundModifySL(sound); break; case ORDER_TYPE_SELL : this.m_datas.Sell.SoundModifySL(sound); break; case ORDER_TYPE_SELL_STOP : this.m_datas.SellStop.SoundModifySL(sound); break; case ORDER_TYPE_SELL_LIMIT : this.m_datas.SellLimit.SoundModifySL(sound); break; case ORDER_TYPE_SELL_STOP_LIMIT : this.m_datas.SellStopLimit.SoundModifySL(sound); break; default: break; } } //+------------------------------------------------------------------+ //| Set TakeProfit modification sound of | //| a specified position/order type | //+------------------------------------------------------------------+ void CTradeObj::SetSoundModifyTP(const ENUM_ORDER_TYPE action,const string sound) { int index=action; switch(index) { case ORDER_TYPE_BUY : this.m_datas.Buy.SoundModifyTP(sound); break; case ORDER_TYPE_BUY_STOP : this.m_datas.BuyStop.SoundModifyTP(sound); break; case ORDER_TYPE_BUY_LIMIT : this.m_datas.BuyLimit.SoundModifyTP(sound); break; case ORDER_TYPE_BUY_STOP_LIMIT : this.m_datas.BuyStopLimit.SoundModifyTP(sound); break; case ORDER_TYPE_SELL : this.m_datas.Sell.SoundModifyTP(sound); break; case ORDER_TYPE_SELL_STOP : this.m_datas.SellStop.SoundModifyTP(sound); break; case ORDER_TYPE_SELL_LIMIT : this.m_datas.SellLimit.SoundModifyTP(sound); break; case ORDER_TYPE_SELL_STOP_LIMIT : this.m_datas.SellStopLimit.SoundModifyTP(sound); break; default: break; } } //+------------------------------------------------------------------+ //| Set price modification sound | //| for a specified order type | //+------------------------------------------------------------------+ void CTradeObj::SetSoundModifyPrice(const ENUM_ORDER_TYPE action,const string sound) { int index=action; switch(index) { case ORDER_TYPE_BUY_STOP : this.m_datas.BuyStop.SoundModifyPrice(sound); break; case ORDER_TYPE_BUY_LIMIT : this.m_datas.BuyLimit.SoundModifyPrice(sound); break; case ORDER_TYPE_BUY_STOP_LIMIT : this.m_datas.BuyStopLimit.SoundModifyPrice(sound); break; case ORDER_TYPE_SELL_STOP : this.m_datas.SellStop.SoundModifyPrice(sound); break; case ORDER_TYPE_SELL_LIMIT : this.m_datas.SellLimit.SoundModifyPrice(sound); break; case ORDER_TYPE_SELL_STOP_LIMIT : this.m_datas.SellStopLimit.SoundModifyPrice(sound); break; default: break; } } //+------------------------------------------------------------------+ //| Set the error sound of opening/placing | //| a specified position/order type | //+------------------------------------------------------------------+ void CTradeObj::SetSoundErrorOpen(const ENUM_ORDER_TYPE action,const string sound) { int index=action; switch(index) { case ORDER_TYPE_BUY : this.m_datas.Buy.SoundErrorOpen(sound); break; case ORDER_TYPE_BUY_STOP : this.m_datas.BuyStop.SoundErrorOpen(sound); break; case ORDER_TYPE_BUY_LIMIT : this.m_datas.BuyLimit.SoundErrorOpen(sound); break; case ORDER_TYPE_BUY_STOP_LIMIT : this.m_datas.BuyStopLimit.SoundErrorOpen(sound); break; case ORDER_TYPE_SELL : this.m_datas.Sell.SoundErrorOpen(sound); break; case ORDER_TYPE_SELL_STOP : this.m_datas.SellStop.SoundErrorOpen(sound); break; case ORDER_TYPE_SELL_LIMIT : this.m_datas.SellLimit.SoundErrorOpen(sound); break; case ORDER_TYPE_SELL_STOP_LIMIT : this.m_datas.SellStopLimit.SoundErrorOpen(sound); break; default: break; } } //+------------------------------------------------------------------+ //| Set the error sound of closing/removal of | //| a specified position/order type | //+------------------------------------------------------------------+ void CTradeObj::SetSoundErrorClose(const ENUM_ORDER_TYPE action,const string sound) { int index=action; switch(index) { case ORDER_TYPE_BUY : this.m_datas.Buy.SoundErrorClose(sound); break; case ORDER_TYPE_BUY_STOP : this.m_datas.BuyStop.SoundErrorClose(sound); break; case ORDER_TYPE_BUY_LIMIT : this.m_datas.BuyLimit.SoundErrorClose(sound); break; case ORDER_TYPE_BUY_STOP_LIMIT : this.m_datas.BuyStopLimit.SoundErrorClose(sound); break; case ORDER_TYPE_SELL : this.m_datas.Sell.SoundErrorClose(sound); break; case ORDER_TYPE_SELL_STOP : this.m_datas.SellStop.SoundErrorClose(sound); break; case ORDER_TYPE_SELL_LIMIT : this.m_datas.SellLimit.SoundErrorClose(sound); break; case ORDER_TYPE_SELL_STOP_LIMIT : this.m_datas.SellStopLimit.SoundErrorClose(sound); break; default: break; } } //+------------------------------------------------------------------+ //| Set StopLoss modification error sound of | //| a specified position/order type | //+------------------------------------------------------------------+ void CTradeObj::SetSoundErrorModifySL(const ENUM_ORDER_TYPE action,const string sound) { int index=action; switch(index) { case ORDER_TYPE_BUY : this.m_datas.Buy.SoundErrorModifySL(sound); break; case ORDER_TYPE_BUY_STOP : this.m_datas.BuyStop.SoundErrorModifySL(sound); break; case ORDER_TYPE_BUY_LIMIT : this.m_datas.BuyLimit.SoundErrorModifySL(sound); break; case ORDER_TYPE_BUY_STOP_LIMIT : this.m_datas.BuyStopLimit.SoundErrorModifySL(sound); break; case ORDER_TYPE_SELL : this.m_datas.Sell.SoundErrorModifySL(sound); break; case ORDER_TYPE_SELL_STOP : this.m_datas.SellStop.SoundErrorModifySL(sound); break; case ORDER_TYPE_SELL_LIMIT : this.m_datas.SellLimit.SoundErrorModifySL(sound); break; case ORDER_TYPE_SELL_STOP_LIMIT : this.m_datas.SellStopLimit.SoundErrorModifySL(sound); break; default: break; } } //+------------------------------------------------------------------+ //| Set TakeProfit modification error sound of | //| a specified position/order type | //+------------------------------------------------------------------+ void CTradeObj::SetSoundErrorModifyTP(const ENUM_ORDER_TYPE action,const string sound) { int index=action; switch(index) { case ORDER_TYPE_BUY : this.m_datas.Buy.SoundErrorModifyTP(sound); break; case ORDER_TYPE_BUY_STOP : this.m_datas.BuyStop.SoundErrorModifyTP(sound); break; case ORDER_TYPE_BUY_LIMIT : this.m_datas.BuyLimit.SoundErrorModifyTP(sound); break; case ORDER_TYPE_BUY_STOP_LIMIT : this.m_datas.BuyStopLimit.SoundErrorModifyTP(sound); break; case ORDER_TYPE_SELL : this.m_datas.Sell.SoundErrorModifyTP(sound); break; case ORDER_TYPE_SELL_STOP : this.m_datas.SellStop.SoundErrorModifyTP(sound); break; case ORDER_TYPE_SELL_LIMIT : this.m_datas.SellLimit.SoundErrorModifyTP(sound); break; case ORDER_TYPE_SELL_STOP_LIMIT : this.m_datas.SellStopLimit.SoundErrorModifyTP(sound); break; default: break; } } //+------------------------------------------------------------------+ //| Set price modification error sound | //| for a specified order type | //+------------------------------------------------------------------+ void CTradeObj::SetSoundErrorModifyPrice(const ENUM_ORDER_TYPE action,const string sound) { int index=action; switch(index) { case ORDER_TYPE_BUY_STOP : this.m_datas.BuyStop.SoundErrorModifyPrice(sound); break; case ORDER_TYPE_BUY_LIMIT : this.m_datas.BuyLimit.SoundErrorModifyPrice(sound); break; case ORDER_TYPE_BUY_STOP_LIMIT : this.m_datas.BuyStopLimit.SoundErrorModifyPrice(sound); break; case ORDER_TYPE_SELL_STOP : this.m_datas.SellStop.SoundErrorModifyPrice(sound); break; case ORDER_TYPE_SELL_LIMIT : this.m_datas.SellLimit.SoundErrorModifyPrice(sound); break; case ORDER_TYPE_SELL_STOP_LIMIT : this.m_datas.SellStopLimit.SoundErrorModifyPrice(sound); break; default: break; } } //+------------------------------------------------------------------+ //| Return the sound of opening/placing | //| a specified position/order type | //+------------------------------------------------------------------+ string CTradeObj::GetSoundOpen(const ENUM_ORDER_TYPE action) const { int index=action; switch(index) { case ORDER_TYPE_BUY : return this.m_datas.Buy.SoundOpen(); case ORDER_TYPE_BUY_STOP : return this.m_datas.BuyStop.SoundOpen(); case ORDER_TYPE_BUY_LIMIT : return this.m_datas.BuyLimit.SoundOpen(); case ORDER_TYPE_BUY_STOP_LIMIT : return this.m_datas.BuyStopLimit.SoundOpen(); case ORDER_TYPE_SELL : return this.m_datas.Sell.SoundOpen(); case ORDER_TYPE_SELL_STOP : return this.m_datas.SellStop.SoundOpen(); case ORDER_TYPE_SELL_LIMIT : return this.m_datas.SellLimit.SoundOpen(); case ORDER_TYPE_SELL_STOP_LIMIT : return this.m_datas.SellStopLimit.SoundOpen(); default: return NULL; } } //+------------------------------------------------------------------+ //| Return the sound of closing/removal of | //| a specified position/order type | //+------------------------------------------------------------------+ string CTradeObj::GetSoundClose(const ENUM_ORDER_TYPE action) const { int index=action; switch(index) { case ORDER_TYPE_BUY : return this.m_datas.Buy.SoundClose(); case ORDER_TYPE_BUY_STOP : return this.m_datas.BuyStop.SoundClose(); case ORDER_TYPE_BUY_LIMIT : return this.m_datas.BuyLimit.SoundClose(); case ORDER_TYPE_BUY_STOP_LIMIT : return this.m_datas.BuyStopLimit.SoundClose(); case ORDER_TYPE_SELL : return this.m_datas.Sell.SoundClose(); case ORDER_TYPE_SELL_STOP : return this.m_datas.SellStop.SoundClose(); case ORDER_TYPE_SELL_LIMIT : return this.m_datas.SellLimit.SoundClose(); case ORDER_TYPE_SELL_STOP_LIMIT : return this.m_datas.SellStopLimit.SoundClose(); default: return NULL; } } //+------------------------------------------------------------------+ //| Return StopLoss modification sound of | //| a specified position/order type | //+------------------------------------------------------------------+ string CTradeObj::GetSoundModifySL(const ENUM_ORDER_TYPE action) const { int index=action; switch(index) { case ORDER_TYPE_BUY : return this.m_datas.Buy.SoundModifySL(); case ORDER_TYPE_BUY_STOP : return this.m_datas.BuyStop.SoundModifySL(); case ORDER_TYPE_BUY_LIMIT : return this.m_datas.BuyLimit.SoundModifySL(); case ORDER_TYPE_BUY_STOP_LIMIT : return this.m_datas.BuyStopLimit.SoundModifySL(); case ORDER_TYPE_SELL : return this.m_datas.Sell.SoundModifySL(); case ORDER_TYPE_SELL_STOP : return this.m_datas.SellStop.SoundModifySL(); case ORDER_TYPE_SELL_LIMIT : return this.m_datas.SellLimit.SoundModifySL(); case ORDER_TYPE_SELL_STOP_LIMIT : return this.m_datas.SellStopLimit.SoundModifySL(); default: return NULL; } } //+------------------------------------------------------------------+ //| Return TakeProfit modification sound of | //| a specified position/order type | //+------------------------------------------------------------------+ string CTradeObj::GetSoundModifyTP(const ENUM_ORDER_TYPE action) const { int index=action; switch(index) { case ORDER_TYPE_BUY : return this.m_datas.Buy.SoundModifyTP(); case ORDER_TYPE_BUY_STOP : return this.m_datas.BuyStop.SoundModifyTP(); case ORDER_TYPE_BUY_LIMIT : return this.m_datas.BuyLimit.SoundModifyTP(); case ORDER_TYPE_BUY_STOP_LIMIT : return this.m_datas.BuyStopLimit.SoundModifyTP(); case ORDER_TYPE_SELL : return this.m_datas.Sell.SoundModifyTP(); case ORDER_TYPE_SELL_STOP : return this.m_datas.SellStop.SoundModifyTP(); case ORDER_TYPE_SELL_LIMIT : return this.m_datas.SellLimit.SoundModifyTP(); case ORDER_TYPE_SELL_STOP_LIMIT : return this.m_datas.SellStopLimit.SoundModifyTP(); default: return NULL; } } //+------------------------------------------------------------------+ //| Return price modification sound | //| for a specified order type | //+------------------------------------------------------------------+ string CTradeObj::GetSoundModifyPrice(const ENUM_ORDER_TYPE action) const { int index=action; switch(index) { case ORDER_TYPE_BUY_STOP : return this.m_datas.BuyStop.SoundModifyPrice(); case ORDER_TYPE_BUY_LIMIT : return this.m_datas.BuyLimit.SoundModifyPrice(); case ORDER_TYPE_BUY_STOP_LIMIT : return this.m_datas.BuyStopLimit.SoundModifyPrice(); case ORDER_TYPE_SELL_STOP : return this.m_datas.SellStop.SoundModifyPrice(); case ORDER_TYPE_SELL_LIMIT : return this.m_datas.SellLimit.SoundModifyPrice(); case ORDER_TYPE_SELL_STOP_LIMIT : return this.m_datas.SellStopLimit.SoundModifyPrice(); default: return NULL; } } //+------------------------------------------------------------------+ //| Return the error sound of opening/placing | //| a specified position/order type | //+------------------------------------------------------------------+ string CTradeObj::GetSoundErrorOpen(const ENUM_ORDER_TYPE action) const { int index=action; switch(index) { case ORDER_TYPE_BUY : return this.m_datas.Buy.SoundErrorOpen(); case ORDER_TYPE_BUY_STOP : return this.m_datas.BuyStop.SoundErrorOpen(); case ORDER_TYPE_BUY_LIMIT : return this.m_datas.BuyLimit.SoundErrorOpen(); case ORDER_TYPE_BUY_STOP_LIMIT : return this.m_datas.BuyStopLimit.SoundErrorOpen(); case ORDER_TYPE_SELL : return this.m_datas.Sell.SoundErrorOpen(); case ORDER_TYPE_SELL_STOP : return this.m_datas.SellStop.SoundErrorOpen(); case ORDER_TYPE_SELL_LIMIT : return this.m_datas.SellLimit.SoundErrorOpen(); case ORDER_TYPE_SELL_STOP_LIMIT : return this.m_datas.SellStopLimit.SoundErrorOpen(); default: return NULL; } } //+------------------------------------------------------------------+ //| Return the error sound of closing/removal of | //| a specified position/order type | //+------------------------------------------------------------------+ string CTradeObj::GetSoundErrorClose(const ENUM_ORDER_TYPE action) const { int index=action; switch(index) { case ORDER_TYPE_BUY : return this.m_datas.Buy.SoundErrorClose(); case ORDER_TYPE_BUY_STOP : return this.m_datas.BuyStop.SoundErrorClose(); case ORDER_TYPE_BUY_LIMIT : return this.m_datas.BuyLimit.SoundErrorClose(); case ORDER_TYPE_BUY_STOP_LIMIT : return this.m_datas.BuyStopLimit.SoundErrorClose(); case ORDER_TYPE_SELL : return this.m_datas.Sell.SoundErrorClose(); case ORDER_TYPE_SELL_STOP : return this.m_datas.SellStop.SoundErrorClose(); case ORDER_TYPE_SELL_LIMIT : return this.m_datas.SellLimit.SoundErrorClose(); case ORDER_TYPE_SELL_STOP_LIMIT : return this.m_datas.SellStopLimit.SoundErrorClose(); default: return NULL; } } //+------------------------------------------------------------------+ //| Return StopLoss modification error sound of | //| a specified position/order type | //+------------------------------------------------------------------+ string CTradeObj::GetSoundErrorModifySL(const ENUM_ORDER_TYPE action) const { int index=action; switch(index) { case ORDER_TYPE_BUY : return this.m_datas.Buy.SoundErrorModifySL(); case ORDER_TYPE_BUY_STOP : return this.m_datas.BuyStop.SoundErrorModifySL(); case ORDER_TYPE_BUY_LIMIT : return this.m_datas.BuyLimit.SoundErrorModifySL(); case ORDER_TYPE_BUY_STOP_LIMIT : return this.m_datas.BuyStopLimit.SoundErrorModifySL(); case ORDER_TYPE_SELL : return this.m_datas.Sell.SoundErrorModifySL(); case ORDER_TYPE_SELL_STOP : return this.m_datas.SellStop.SoundErrorModifySL(); case ORDER_TYPE_SELL_LIMIT : return this.m_datas.SellLimit.SoundErrorModifySL(); case ORDER_TYPE_SELL_STOP_LIMIT : return this.m_datas.SellStopLimit.SoundErrorModifySL(); default: return NULL; } } //+------------------------------------------------------------------+ //| Return TakeProfit modification error sound of | //| a specified position/order type | //+------------------------------------------------------------------+ string CTradeObj::GetSoundErrorModifyTP(const ENUM_ORDER_TYPE action) const { int index=action; switch(index) { case ORDER_TYPE_BUY : return this.m_datas.Buy.SoundErrorModifyTP(); case ORDER_TYPE_BUY_STOP : return this.m_datas.BuyStop.SoundErrorModifyTP(); case ORDER_TYPE_BUY_LIMIT : return this.m_datas.BuyLimit.SoundErrorModifyTP(); case ORDER_TYPE_BUY_STOP_LIMIT : return this.m_datas.BuyStopLimit.SoundErrorModifyTP(); case ORDER_TYPE_SELL : return this.m_datas.Sell.SoundErrorModifyTP(); case ORDER_TYPE_SELL_STOP : return this.m_datas.SellStop.SoundErrorModifyTP(); case ORDER_TYPE_SELL_LIMIT : return this.m_datas.SellLimit.SoundErrorModifyTP(); case ORDER_TYPE_SELL_STOP_LIMIT : return this.m_datas.SellStopLimit.SoundErrorModifyTP(); default: return NULL; } } //+------------------------------------------------------------------+ //| Return price modification error sound | //| for a specified order type | //+------------------------------------------------------------------+ string CTradeObj::GetSoundErrorModifyPrice(const ENUM_ORDER_TYPE action) const { int index=action; switch(index) { case ORDER_TYPE_BUY_STOP : return this.m_datas.BuyStop.SoundErrorModifyPrice(); case ORDER_TYPE_BUY_LIMIT : return this.m_datas.BuyLimit.SoundErrorModifyPrice(); case ORDER_TYPE_BUY_STOP_LIMIT : return this.m_datas.BuyStopLimit.SoundErrorModifyPrice(); case ORDER_TYPE_SELL_STOP : return this.m_datas.SellStop.SoundErrorModifyPrice(); case ORDER_TYPE_SELL_LIMIT : return this.m_datas.SellLimit.SoundErrorModifyPrice(); case ORDER_TYPE_SELL_STOP_LIMIT : return this.m_datas.SellStopLimit.SoundErrorModifyPrice(); default: return NULL; } } //+------------------------------------------------------------------+ //| Play the sound of opening/placing | //| a specified position/order type | //+------------------------------------------------------------------+ void CTradeObj::PlaySoundOpen(const ENUM_ORDER_TYPE action) { if(!this.m_use_sound) return; int index=action; switch(index) { case ORDER_TYPE_BUY : CMessage::PlaySound(this.m_datas.Buy.SoundOpen()); break; case ORDER_TYPE_BUY_STOP : CMessage::PlaySound(this.m_datas.BuyStop.SoundOpen()); break; case ORDER_TYPE_BUY_LIMIT : CMessage::PlaySound(this.m_datas.BuyLimit.SoundOpen()); break; case ORDER_TYPE_BUY_STOP_LIMIT : CMessage::PlaySound(this.m_datas.BuyStopLimit.SoundOpen()); break; case ORDER_TYPE_SELL : CMessage::PlaySound(this.m_datas.Sell.SoundOpen()); break; case ORDER_TYPE_SELL_STOP : CMessage::PlaySound(this.m_datas.SellStop.SoundOpen()); break; case ORDER_TYPE_SELL_LIMIT : CMessage::PlaySound(this.m_datas.SellLimit.SoundOpen()); break; case ORDER_TYPE_SELL_STOP_LIMIT : CMessage::PlaySound(this.m_datas.SellStopLimit.SoundOpen()); break; default: break; } } //+------------------------------------------------------------------+ //| Play the sound of closing/removal of | //| a specified position/order type | //+------------------------------------------------------------------+ void CTradeObj::PlaySoundClose(const ENUM_ORDER_TYPE action) { if(!this.m_use_sound) return; int index=action; switch(index) { case ORDER_TYPE_BUY : CMessage::PlaySound(this.m_datas.Buy.SoundClose()); break; case ORDER_TYPE_BUY_STOP : CMessage::PlaySound(this.m_datas.BuyStop.SoundClose()); break; case ORDER_TYPE_BUY_LIMIT : CMessage::PlaySound(this.m_datas.BuyLimit.SoundClose()); break; case ORDER_TYPE_BUY_STOP_LIMIT : CMessage::PlaySound(this.m_datas.BuyStopLimit.SoundClose()); break; case ORDER_TYPE_SELL : CMessage::PlaySound(this.m_datas.Sell.SoundClose()); break; case ORDER_TYPE_SELL_STOP : CMessage::PlaySound(this.m_datas.SellStop.SoundClose()); break; case ORDER_TYPE_SELL_LIMIT : CMessage::PlaySound(this.m_datas.SellLimit.SoundClose()); break; case ORDER_TYPE_SELL_STOP_LIMIT : CMessage::PlaySound(this.m_datas.SellStopLimit.SoundClose()); break; default: break; } } //+------------------------------------------------------------------+ //| Play StopLoss modification sound of | //| a specified position/order type | //+------------------------------------------------------------------+ void CTradeObj::PlaySoundModifySL(const ENUM_ORDER_TYPE action) { if(!this.m_use_sound) return; int index=action; switch(index) { case ORDER_TYPE_BUY : CMessage::PlaySound(this.m_datas.Buy.SoundModifySL()); break; case ORDER_TYPE_BUY_STOP : CMessage::PlaySound(this.m_datas.BuyStop.SoundModifySL()); break; case ORDER_TYPE_BUY_LIMIT : CMessage::PlaySound(this.m_datas.BuyLimit.SoundModifySL()); break; case ORDER_TYPE_BUY_STOP_LIMIT : CMessage::PlaySound(this.m_datas.BuyStopLimit.SoundModifySL()); break; case ORDER_TYPE_SELL : CMessage::PlaySound(this.m_datas.Sell.SoundModifySL()); break; case ORDER_TYPE_SELL_STOP : CMessage::PlaySound(this.m_datas.SellStop.SoundModifySL()); break; case ORDER_TYPE_SELL_LIMIT : CMessage::PlaySound(this.m_datas.SellLimit.SoundModifySL()); break; case ORDER_TYPE_SELL_STOP_LIMIT : CMessage::PlaySound(this.m_datas.SellStopLimit.SoundModifySL()); break; default: break; } } //+------------------------------------------------------------------+ //| Play TakeProfit modification sound of | //| a specified position/order type | //+------------------------------------------------------------------+ void CTradeObj::PlaySoundModifyTP(const ENUM_ORDER_TYPE action) { if(!this.m_use_sound) return; int index=action; switch(index) { case ORDER_TYPE_BUY : CMessage::PlaySound(this.m_datas.Buy.SoundModifyTP()); break; case ORDER_TYPE_BUY_STOP : CMessage::PlaySound(this.m_datas.BuyStop.SoundModifyTP()); break; case ORDER_TYPE_BUY_LIMIT : CMessage::PlaySound(this.m_datas.BuyLimit.SoundModifyTP()); break; case ORDER_TYPE_BUY_STOP_LIMIT : CMessage::PlaySound(this.m_datas.BuyStopLimit.SoundModifyTP()); break; case ORDER_TYPE_SELL : CMessage::PlaySound(this.m_datas.Sell.SoundModifyTP()); break; case ORDER_TYPE_SELL_STOP : CMessage::PlaySound(this.m_datas.SellStop.SoundModifyTP()); break; case ORDER_TYPE_SELL_LIMIT : CMessage::PlaySound(this.m_datas.SellLimit.SoundModifyTP()); break; case ORDER_TYPE_SELL_STOP_LIMIT : CMessage::PlaySound(this.m_datas.SellStopLimit.SoundModifyTP()); break; default: break; } } //+------------------------------------------------------------------+ //| Play price modification sound | //| for a specified order type | //+------------------------------------------------------------------+ void CTradeObj::PlaySoundModifyPrice(const ENUM_ORDER_TYPE action) { if(!this.m_use_sound) return; int index=action; switch(index) { case ORDER_TYPE_BUY_STOP : CMessage::PlaySound(this.m_datas.BuyStop.SoundModifyPrice()); break; case ORDER_TYPE_BUY_LIMIT : CMessage::PlaySound(this.m_datas.BuyLimit.SoundModifyPrice()); break; case ORDER_TYPE_BUY_STOP_LIMIT : CMessage::PlaySound(this.m_datas.BuyStopLimit.SoundModifyPrice()); break; case ORDER_TYPE_SELL_STOP : CMessage::PlaySound(this.m_datas.SellStop.SoundModifyPrice()); break; case ORDER_TYPE_SELL_LIMIT : CMessage::PlaySound(this.m_datas.SellLimit.SoundModifyPrice()); break; case ORDER_TYPE_SELL_STOP_LIMIT : CMessage::PlaySound(this.m_datas.SellStopLimit.SoundModifyPrice()); break; default: break; } } //+------------------------------------------------------------------+ //| Play the error sound of opening/placing | //| a specified position/order type | //+------------------------------------------------------------------+ void CTradeObj::PlaySoundErrorOpen(const ENUM_ORDER_TYPE action) { if(!this.m_use_sound) return; int index=action; switch(index) { case ORDER_TYPE_BUY : CMessage::PlaySound(this.m_datas.Buy.SoundErrorOpen()); break; case ORDER_TYPE_BUY_STOP : CMessage::PlaySound(this.m_datas.BuyStop.SoundErrorOpen()); break; case ORDER_TYPE_BUY_LIMIT : CMessage::PlaySound(this.m_datas.BuyLimit.SoundErrorOpen()); break; case ORDER_TYPE_BUY_STOP_LIMIT : CMessage::PlaySound(this.m_datas.BuyStopLimit.SoundErrorOpen()); break; case ORDER_TYPE_SELL : CMessage::PlaySound(this.m_datas.Sell.SoundErrorOpen()); break; case ORDER_TYPE_SELL_STOP : CMessage::PlaySound(this.m_datas.SellStop.SoundErrorOpen()); break; case ORDER_TYPE_SELL_LIMIT : CMessage::PlaySound(this.m_datas.SellLimit.SoundErrorOpen()); break; case ORDER_TYPE_SELL_STOP_LIMIT : CMessage::PlaySound(this.m_datas.SellStopLimit.SoundErrorOpen()); break; default: break; } } //+------------------------------------------------------------------+ //| Play the error sound of closing/removal of | //| a specified position/order type | //+------------------------------------------------------------------+ void CTradeObj::PlaySoundErrorClose(const ENUM_ORDER_TYPE action) { if(!this.m_use_sound) return; int index=action; switch(index) { case ORDER_TYPE_BUY : CMessage::PlaySound(this.m_datas.Buy.SoundErrorClose()); break; case ORDER_TYPE_BUY_STOP : CMessage::PlaySound(this.m_datas.BuyStop.SoundErrorClose()); break; case ORDER_TYPE_BUY_LIMIT : CMessage::PlaySound(this.m_datas.BuyLimit.SoundErrorClose()); break; case ORDER_TYPE_BUY_STOP_LIMIT : CMessage::PlaySound(this.m_datas.BuyStopLimit.SoundErrorClose()); break; case ORDER_TYPE_SELL : CMessage::PlaySound(this.m_datas.Sell.SoundErrorClose()); break; case ORDER_TYPE_SELL_STOP : CMessage::PlaySound(this.m_datas.SellStop.SoundErrorClose()); break; case ORDER_TYPE_SELL_LIMIT : CMessage::PlaySound(this.m_datas.SellLimit.SoundErrorClose()); break; case ORDER_TYPE_SELL_STOP_LIMIT : CMessage::PlaySound(this.m_datas.SellStopLimit.SoundErrorClose()); break; default: break; } } //+------------------------------------------------------------------+ //| Play StopLoss modification error sound of | //| a specified position/order type | //+------------------------------------------------------------------+ void CTradeObj::PlaySoundErrorModifySL(const ENUM_ORDER_TYPE action) { if(!this.m_use_sound) return; int index=action; switch(index) { case ORDER_TYPE_BUY : CMessage::PlaySound(this.m_datas.Buy.SoundErrorModifySL()); break; case ORDER_TYPE_BUY_STOP : CMessage::PlaySound(this.m_datas.BuyStop.SoundErrorModifySL()); break; case ORDER_TYPE_BUY_LIMIT : CMessage::PlaySound(this.m_datas.BuyLimit.SoundErrorModifySL()); break; case ORDER_TYPE_BUY_STOP_LIMIT : CMessage::PlaySound(this.m_datas.BuyStopLimit.SoundErrorModifySL()); break; case ORDER_TYPE_SELL : CMessage::PlaySound(this.m_datas.Sell.SoundErrorModifySL()); break; case ORDER_TYPE_SELL_STOP : CMessage::PlaySound(this.m_datas.SellStop.SoundErrorModifySL()); break; case ORDER_TYPE_SELL_LIMIT : CMessage::PlaySound(this.m_datas.SellLimit.SoundErrorModifySL()); break; case ORDER_TYPE_SELL_STOP_LIMIT : CMessage::PlaySound(this.m_datas.SellStopLimit.SoundErrorModifySL()); break; default: break; } } //+------------------------------------------------------------------+ //| Play TakeProfit modification error sound of | //| a specified position/order type | //+------------------------------------------------------------------+ void CTradeObj::PlaySoundErrorModifyTP(const ENUM_ORDER_TYPE action) { if(!this.m_use_sound) return; int index=action; switch(index) { case ORDER_TYPE_BUY : CMessage::PlaySound(this.m_datas.Buy.SoundErrorModifyTP()); break; case ORDER_TYPE_BUY_STOP : CMessage::PlaySound(this.m_datas.BuyStop.SoundErrorModifyTP()); break; case ORDER_TYPE_BUY_LIMIT : CMessage::PlaySound(this.m_datas.BuyLimit.SoundErrorModifyTP()); break; case ORDER_TYPE_BUY_STOP_LIMIT : CMessage::PlaySound(this.m_datas.BuyStopLimit.SoundErrorModifyTP()); break; case ORDER_TYPE_SELL : CMessage::PlaySound(this.m_datas.Sell.SoundErrorModifyTP()); break; case ORDER_TYPE_SELL_STOP : CMessage::PlaySound(this.m_datas.SellStop.SoundErrorModifyTP()); break; case ORDER_TYPE_SELL_LIMIT : CMessage::PlaySound(this.m_datas.SellLimit.SoundErrorModifyTP()); break; case ORDER_TYPE_SELL_STOP_LIMIT : CMessage::PlaySound(this.m_datas.SellStopLimit.SoundErrorModifyTP()); break; default: break; } } //+------------------------------------------------------------------+ //| Play price modification error sound | //| for a specified order type | //+------------------------------------------------------------------+ void CTradeObj::PlaySoundErrorModifyPrice(const ENUM_ORDER_TYPE action) { if(!this.m_use_sound) return; int index=action; switch(index) { case ORDER_TYPE_BUY_STOP : CMessage::PlaySound(this.m_datas.BuyStop.SoundErrorModifyPrice()); break; case ORDER_TYPE_BUY_LIMIT : CMessage::PlaySound(this.m_datas.BuyLimit.SoundErrorModifyPrice()); break; case ORDER_TYPE_BUY_STOP_LIMIT : CMessage::PlaySound(this.m_datas.BuyStopLimit.SoundErrorModifyPrice()); break; case ORDER_TYPE_SELL_STOP : CMessage::PlaySound(this.m_datas.SellStop.SoundErrorModifyPrice()); break; case ORDER_TYPE_SELL_LIMIT : CMessage::PlaySound(this.m_datas.SellLimit.SoundErrorModifyPrice()); break; case ORDER_TYPE_SELL_STOP_LIMIT : CMessage::PlaySound(this.m_datas.SellStopLimit.SoundErrorModifyPrice()); break; default: break; } } //+------------------------------------------------------------------+
Hier ist alles ähnlich wie bei allen Methoden, und alles ist auf den ersten Blick klar: Die Methode, deren Name den Typ eines Handelsereignisses enthält, erhält einen Typ einer Order (Marktordertyp für eine Position), deren Ereignis gesetzt, zurückgegeben oder abgespielt werden soll. Anschließend wird je nach Position/Ordertyp ein Sound eines bestimmten Handelsereignisses gesetzt/zurückgegeben/abgespielt.
Damit ist die Verbesserung des Basisobjekts des Handels mit einem Symbol abgeschlossen. Es ist an der Zeit, die Basis-Handelsklasse zu entwickeln.
Für ihre korrekte Funktionsweise soll die Handelsklasse die Zeiger auf die zuvor erstellten Collections erhalten. Dazu fügen wir jeder Klasse von Kollektionen die Methode hinzu, die den Zeiger auf das Kollektionsobjekt zurückgibt:
Für das historische Kollektionsobjekt:
public: //--- Return itself CHistoryCollection *GetObject(void) { return &this; }
Für das Markt-Kollektionsobjekt:
public: //--- Return itself CMarketCollection *GetObject(void) { return &this; }
For die Symbolkollektion:
public: //--- Return itself CSymbolsCollection *GetObject(void) { return &this; }
Die derzeit entwickelte Handelsklasse soll einen zentralen Zugang zu den Handelstätigkeiten ermöglichen. Sie soll alle Überprüfungen sammeln, bevor sie eine Handelsorder sendet, die Antworten des Handelsservers bearbeiten und Entscheidungen über weitere Aktionen in Abhängigkeit von der Antwort des Handelsservers und den Einstellungen des Verhaltens der Handelsmethode der Klasse treffen.
In diesem Artikel werden wir die Grundlage der weiterzuentwickelnden Klasse schaffen. Aber zuerst überprüfen wir die Handelsbeschränkungen des Programms, Terminals, Kontos und der Symbole.
Handelsklasse
In \MQL5\Include\DoEasy\, erstellen Sie die neue Klasse CTrading in der Datei Trading.mqh.
Damit die Klasse funktioniert, benötigen wir die Listen von einigen vorläufig erstellten Kollektionen, während wir , um Fehler bei der Überprüfung von Berechtigungen zu speichern, das Objekt des dynamischen Arrays benötigen, das int oder uint Variablen der Standardbibliothek enthält.
Also nehmen wir gleich in die Klassendatei aufnehmen:
//+------------------------------------------------------------------+ //| Trading.mqh | //| Copyright 2019, MetaQuotes Software Corp. | //| https://mql5.com/de/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2019, MetaQuotes Software Corp." #property link "https://mql5.com/de/users/artmedia70" #property version "1.00" //+------------------------------------------------------------------+ //| Include-Dateien | //+------------------------------------------------------------------+ #include <Arrays\ArrayInt.mqh> #include "Objects\Trade\TradeObj.mqh" #include "Collections\AccountsCollection.mqh" #include "Collections\SymbolsCollection.mqh" #include "Collections\MarketCollection.mqh" #include "Collections\HistoryCollection.mqh" //+------------------------------------------------------------------+ //| Trading class | //+------------------------------------------------------------------+
Werfen wir einen Blick auf die vollständige Auflistung des Klassenkörpers und analysieren wir seine Struktur:
//+------------------------------------------------------------------+ //| Trading.mqh | //| Copyright 2019, MetaQuotes Software Corp. | //| https://mql5.com/de/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2019, MetaQuotes Software Corp." #property link "https://mql5.com/de/users/artmedia70" #property version "1.00" //+------------------------------------------------------------------+ //| Include-Dateien | //+------------------------------------------------------------------+ #include <Arrays\ArrayInt.mqh> #include "Objects\Trade\TradeObj.mqh" #include "Collections\AccountsCollection.mqh" #include "Collections\SymbolsCollection.mqh" #include "Collections\MarketCollection.mqh" #include "Collections\HistoryCollection.mqh" //+------------------------------------------------------------------+ //| Trading class | //+------------------------------------------------------------------+ class CTrading { private: CAccount *m_account; // Pointer to the current account object CSymbolsCollection *m_symbols; // Pointer to the symbol collection list CMarketCollection *m_market; // Pointer to the list of the collection of market orders and positions CHistoryCollection *m_history; // Pointer to the list of the collection of historical orders and deals CArrayInt m_list_errors; // Error list bool m_is_trade_enable; // Flag enabling trading ENUM_LOG_LEVEL m_log_level; // Logging level //--- Add the error code to the list bool AddErrorCodeToList(const int error_code); //--- Return the symbol object by (1) position, (2) order ticket CSymbol *GetSymbolObjByPosition(const ulong ticket,const string source_method); CSymbol *GetSymbolObjByOrder(const ulong ticket,const string source_method); //--- Return a symbol trading object by (1) position, (2) order ticket, (3) symbol name CTradeObj *GetTradeObjByPosition(const ulong ticket,const string source_method); CTradeObj *GetTradeObjByOrder(const ulong ticket,const string source_method); CTradeObj *GetTradeObjBySymbol(const string symbol,const string source_method); //--- Return the number of (1) all positions, (2) buy, (3) sell positions int PositionsTotalAll(void) const; int PositionsTotalLong(void) const; int PositionsTotalShort(void) const; //--- Return the number of (1) all pending orders, (2) buy, (3) sell pending orders int OrdersTotalAll(void) const; int OrdersTotalLong(void) const; int OrdersTotalShort(void) const; //--- Return the total volume of (1) buy, (2) sell positions double PositionsTotalVolumeLong(void) const; double PositionsTotalVolumeShort(void) const; //--- Return the total volume of (1) buy, (2) sell orders double OrdersTotalVolumeLong(void) const; double OrdersTotalVolumeShort(void) const; //--- Return the order direction by an operation type ENUM_ORDER_TYPE DirectionByActionType(ENUM_ACTION_TYPE action) const; //--- Check the presence of a (1) position, (2) order by ticket bool CheckPositionAvailablity(const ulong ticket,const string source_method); bool CheckOrderAvailablity(const ulong ticket,const string source_method); //--- Set the desired sound for a trading object void SetSoundByMode(const ENUM_MODE_SET_SOUND mode,const ENUM_ORDER_TYPE action,const string sound,CTradeObj *trade_obj); public: //--- Konstructor CTrading(); //--- Get the pointers to the lists (make sure to call the method in program's OnInit() since the symbol collection list is created there) void OnInit(CAccount *account,CSymbolsCollection *symbols,CMarketCollection *market,CHistoryCollection *history) { this.m_account=account; this.m_symbols=symbols; this.m_market=market; this.m_history=history; } //--- Return the error list CArrayInt *GetListErrors(void) { return &this.m_list_errors; } //--- Check trading limitations bool CheckTradeConstraints(const double volume, const ENUM_ACTION_TYPE action_type, const CSymbol *symbol_obj, const string source_method, double sl=0, double tp=0); //--- Check if the funds are sufficient bool CheckMoneyFree(const ENUM_ORDER_TYPE order_type,const double volume,const double price,const CSymbol *symbol_obj,const string source_method) const; //--- Set the following for symbol trading objects: //--- (1) correct filling policy, (2) filling policy, //--- (3) correct order expiration type, (4) order expiration type, //--- (5) magic number, (6) comment, (7) slippage, (8) volume, (9) order expiration date, //--- (10) the flag of asynchronous sending of a trading request, (11) logging level void SetCorrectTypeFilling(const ENUM_ORDER_TYPE_FILLING type=ORDER_FILLING_FOK,const string symbol=NULL); void SetTypeFilling(const ENUM_ORDER_TYPE_FILLING type=ORDER_FILLING_FOK,const string symbol=NULL); void SetCorrectTypeExpiration(const ENUM_ORDER_TYPE_TIME type=ORDER_TIME_GTC,const string symbol=NULL); void SetTypeExpiration(const ENUM_ORDER_TYPE_TIME type=ORDER_TIME_GTC,const string symbol=NULL); void SetMagic(const ulong magic,const string symbol=NULL); void SetComment(const string comment,const string symbol=NULL); void SetDeviation(const ulong deviation,const string symbol=NULL); void SetVolume(const double volume=0,const string symbol=NULL); void SetExpiration(const datetime expiration=0,const string symbol=NULL); void SetAsyncMode(const bool mode=false,const string symbol=NULL); void SetLogLevel(const ENUM_LOG_LEVEL log_level=LOG_LEVEL_ERROR_MSG,const string symbol=NULL); //--- Set standard sounds (1 symbol=NULL) for trading objects of all symbols, (2 symbol!=NULL) for a symbol trading object void SetSoundsStandart(const string symbol=NULL); //--- Set a sound for a specified order/position type and symbol //--- 'mode' specifies an event a sound is set for //--- (symbol=NULL) for trading objects of all symbols, //--- (symbol!=NULL) for a trading object of a specified symbol void SetSound(const ENUM_MODE_SET_SOUND mode,const ENUM_ORDER_TYPE action,const string sound,const string symbol=NULL); //--- Open (1) Buy, (2) Sell position bool OpenBuy(const double volume,const string symbol,const ulong magic=ULONG_MAX,double sl=0,double tp=0,const string comment=NULL); bool OpenSell(const double volume,const string symbol,const ulong magic=ULONG_MAX,double sl=0,double tp=0,const string comment=NULL); //--- Modify a position bool ModifyPosition(const ulong ticket,const double sl=WRONG_VALUE,const double tp=WRONG_VALUE); //--- Close a position (1) fully, (2) partially, (3) by an opposite one bool ClosePosition(const ulong ticket); bool ClosePositionPartially(const ulong ticket,const double volume); bool ClosePositionBy(const ulong ticket,const ulong ticket_by); //--- Set (1) BuyStop, (2) BuyLimit, (3) BuyStopLimit pending order bool PlaceBuyStop(const double volume, const string symbol, const double price, const double sl=0, const double tp=0, const ulong magic=ULONG_MAX, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC); bool PlaceBuyLimit(const double volume, const string symbol, const double price, const double sl=0, const double tp=0, const ulong magic=ULONG_MAX, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC); bool PlaceBuyStopLimit(const double volume, const string symbol, const double price_stop, const double price_limit, const double sl=0, const double tp=0, const ulong magic=ULONG_MAX, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC); //--- Set (1) SellStop, (2) SellLimit, (3) SellStopLimit pending order bool PlaceSellStop(const double volume, const string symbol, const double price, const double sl=0, const double tp=0, const ulong magic=ULONG_MAX, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC); bool PlaceSellLimit(const double volume, const string symbol, const double price, const double sl=0, const double tp=0, const ulong magic=ULONG_MAX, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC); bool PlaceSellStopLimit(const double volume, const string symbol, const double price_stop, const double price_limit, const double sl=0, const double tp=0, const ulong magic=ULONG_MAX, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC); //--- Modify a pending order bool ModifyOrder(const ulong ticket, const double price=WRONG_VALUE, const double sl=WRONG_VALUE, const double tp=WRONG_VALUE, const double stoplimit=WRONG_VALUE, datetime expiration=WRONG_VALUE, ENUM_ORDER_TYPE_TIME type_time=WRONG_VALUE); //--- Remove a pending order bool DeleteOrder(const ulong ticket); }; //+------------------------------------------------------------------+
Jede der Klassenmethoden enthält einen erläuternden Kommentar, so dass ich glaube, dass die Struktur der Klassenmethoden keine zusätzlichen Erläuterungen benötigt.
Die Klassenmethoden haben fast die gleiche Signatur wie die Methoden des Symbol-Basis-Handelsobjekts. Die einzigen Unterschiede sind das Vorhandensein des Namens eines Symbols, auf dem eine Handelsoperation durchgeführt werden soll, in den Methoden zur Positionseröffnung und bei der Platzierung einer Pending-Order.
Betrachten wir die Implementierung der Klassenmethoden.
Da es mehrere Beschränkungen auf einmal geben kann, sollte der Code jedes Fehlers in die Liste aufgenommen werden und die Liste der festgestellten Beschränkungen sollte nach der Überprüfung aller notwendigen Bedingungen angezeigt werden. Um die Werte der Einschränkungen (der in den verschiedenen Fragmenten des Verifizierungscodes entdeckt wurde) nicht zweimal in die Liste einzutragen, überprüfen Sie das Vorhandensein der entsprechenden Einschränkung in der Liste und setzen Sie sie nur, wenn es sie noch nicht gibt. In diesem Fall wird jede Art der Einschränkung nur einmal in die Liste eingetragen.
Mit der folgenden Methode können Sie das Vorhandensein der Art der Einschränkung in der Liste überprüfen und sie der Liste hinzufügen:
//+------------------------------------------------------------------+ //| Add the error code to the list | //+------------------------------------------------------------------+ bool CTrading::AddErrorCodeToList(const int error_code) { this.m_list_errors.Sort(); if(this.m_list_errors.Search(error_code)==WRONG_VALUE) return this.m_list_errors.Add(error_code); return false; } //+------------------------------------------------------------------+
Die Methode erhält den Fehlercode, der den Grund für die Handelseinschränkung angibt. Das Flag für die sortierte Liste wird für das Flag gesetzt, das Fehlen eines solchen Codes in der Liste wird geprüft. Wenn die Prüfung erfolgreich ist, wird das Ergebnis des Hinzufügens des Codes zur Liste mit der Methode Add() zurückgegeben.
Wenn der Code bereits in der Liste vorhanden ist, geben Sie false zurück.
Da die Handelsobjekte zu einem Symbol gehören (jedes Symbol hat sein Handelsobjekt), während viele Handelsmethoden mit einem Order/Positions-Ticket arbeiten, müssen wir ein Symbol, wo eine solche Position oder eine Order vorhanden ist, durch ein Ticket definieren.
Die Methoden, die ein Symbolobjekt durch ein Positionsticket zurückgeben, lösen diese Aufgabe:
//+------------------------------------------------------------------+ //| Return a symbol object by a position ticket | //+------------------------------------------------------------------+ CSymbol *CTrading::GetSymbolObjByPosition(const ulong ticket,const string source_method) { //--- Get the list of open positions CArrayObj *list=this.m_market.GetList(); list=CSelect::ByOrderProperty(list,ORDER_PROP_STATUS,ORDER_STATUS_MARKET_POSITION,EQUAL); //--- If failed to get the list of open positions, display the message and return NULL if(list==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_ENG_FAILED_GET_MARKET_POS_LIST)); return NULL; } //--- If the list is empty (no open positions), display the message and return NULL if(list.Total()==0) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(source_method,CMessage::Text(MSG_ENG_NO_OPEN_POSITIONS)); return NULL; } //--- Sort the list by a ticket list=CSelect::ByOrderProperty(list,ORDER_PROP_TICKET,ticket,EQUAL); //--- If failed to get the list of open positions, display the message and return NULL if(list==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_ENG_FAILED_GET_MARKET_POS_LIST)); return NULL; } //--- If the list is empty (no required ticket), display the message and return NULL if(list.Total()==0) { //--- Error. No open position with #ticket if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(source_method,CMessage::Text(MSG_LIB_SYS_ERROR_NO_OPEN_POSITION_WITH_TICKET),(string)ticket); return NULL; } //--- Get a position with #ticket from the obtained list COrder *pos=list.At(0); //--- If failed to get the position object, display the message and return NULL if(pos==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_POS_OBJ)); return NULL; } //--- Get a symbol object by name CSymbol * symbol_obj=this.m_symbols.GetSymbolObjByName(pos.Symbol()); //--- If failed to get the symbol object, display the message and return NULL if(symbol_obj==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_SYM_OBJ)); return NULL; } //--- Return a symbol object return symbol_obj; } //+------------------------------------------------------------------+
durch das Ticket des Auftrags:
//+------------------------------------------------------------------+ //| Return a symbol object by an order ticket | //+------------------------------------------------------------------+ CSymbol *CTrading::GetSymbolObjByOrder(const ulong ticket,const string source_method) { //--- Get the list of placed orders CArrayObj *list=this.m_market.GetList(); list=CSelect::ByOrderProperty(list,ORDER_PROP_STATUS,ORDER_STATUS_MARKET_PENDING,EQUAL); //--- If failed to get the list of placed orders, display the message and return NULL if(list==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_ENG_FAILED_GET_PENDING_ORD_LIST)); return NULL; } //--- If the list is empty (no placed orders), display the message and return NULL if(list.Total()==0) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(source_method,CMessage::Text(MSG_ENG_NO_PLACED_ORDERS)); return NULL; } //--- Sort the list by a ticket list=CSelect::ByOrderProperty(list,ORDER_PROP_TICKET,ticket,EQUAL); //--- If failed to get the list of placed orders, display the message and return NULL if(list==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_ENG_FAILED_GET_PENDING_ORD_LIST)); return NULL; } //--- If the list is empty (no required ticket), display the message and return NULL if(list.Total()==0) { //--- Error. No placed order with #ticket if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(source_method,CMessage::Text(MSG_LIB_SYS_ERROR_NO_PLACED_ORDER_WITH_TICKET),(string)ticket); return NULL; } //--- Get an order with #ticket from the obtained list COrder *ord=list.At(0); //--- If failed to get an object order, display the message and return NULL if(ord==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_ORD_OBJ)); return NULL; } //--- Get a symbol object by name CSymbol *symbol_obj=this.m_symbols.GetSymbolObjByName(ord.Symbol()); //--- If failed to get the symbol object, display the message and return NULL if(symbol_obj==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_SYM_OBJ)); return NULL; } //--- Return a symbol object return symbol_obj; } //+------------------------------------------------------------------+
Diese beiden Methoden sind fast identisch. Der einzige Unterschied besteht darin, dass wir in der Ersten eine Position über ein Ticket suchen und in der Zweiten eine Order über ein Ticket. Die Methode erhält ein Ticket einer gewünschten Position oder Reihenfolge und den Namen einer Methode, von der diese Methode aufgerufen wurde. Dadurch können wir im Falle eines Fehlers den Methodennamen im Journal sehen. Der Name der Hilfsmethode liefert keine Daten für die Suche nach der Stelle, an der der Fehler aufgetreten ist (wir müssen die Methode angeben, von der aus die Suche nach einem Symbolobjekt aufgerufen wurde).
Für die Operation der Klassenmethoden müssen wir manchmal ein Symbolhandelsobjekt durch ein Positionsticket, ein Order-Ticket oder einen Symbolnamen übergeben:
//+------------------------------------------------------------------+ //| Return a symbol trading object by a position ticket | //+------------------------------------------------------------------+ CTradeObj *CTrading::GetTradeObjByPosition(const ulong ticket,const string source_method) { //--- Get a symbol object by a position ticket CSymbol * symbol_obj=this.GetSymbolObjByPosition(ticket,DFUN); //--- If failed to get the symbol object, display the message and return NULL if(symbol_obj==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_SYM_OBJ)); return NULL; } //--- Get and return the trading object from the symbol object CTradeObj *trade_obj=symbol_obj.GetTradeObj(); return trade_obj; } //+------------------------------------------------------------------+ //| Return a symbol trading object by an order ticket | //+------------------------------------------------------------------+ CTradeObj *CTrading::GetTradeObjByOrder(const ulong ticket,const string source_method) { //--- Get a symbol object by an order ticket CSymbol * symbol_obj=this.GetSymbolObjByOrder(ticket,source_method); //--- If failed to get the symbol object, display the message and return NULL if(symbol_obj==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_SYM_OBJ)); return NULL; } //--- Get and return the trading object from the symbol object CTradeObj *trade_obj=symbol_obj.GetTradeObj(); return trade_obj; } //+------------------------------------------------------------------+ //| Return a symbol trading object by a symbol name | //+------------------------------------------------------------------+ CTradeObj *CTrading::GetTradeObjBySymbol(const string symbol,const string source_method) { //--- Get a symbol object by its name CSymbol *symbol_obj=this.m_symbols.GetSymbolObjByName(symbol); //--- If failed to get the symbol object, display the message and return NULL if(symbol_obj==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_NOT_SYMBOL_ON_LIST)); return NULL; } //--- Get and return the trading object from the symbol object CTradeObj *trade_obj=symbol_obj.GetTradeObj(); return trade_obj; } //+------------------------------------------------------------------+
Alle drei Hilfsmethoden liefern ein Handelsobjekt zur weiteren Bearbeitung zurück. Alle Aktionen sind in den Methodenlisten kommentiert.
Wir müssen die Anzahl der offenen Positionen und der in beide Richtungen platzierten Orders kennen, um einige Einschränkungen zu überprüfen und Handelsentscheidungen zu treffen.
Die Methode, die die Anzahl der offenen Positionen auf dem Konto zurückgibt:
//+------------------------------------------------------------------+ //| Return the number of positions | //+------------------------------------------------------------------+ int CTrading::PositionsTotalAll(void) const { CArrayObj *list=this.m_market.GetList(); list=CSelect::ByOrderProperty(list,ORDER_PROP_STATUS,ORDER_STATUS_MARKET_POSITION,EQUAL); return(list==NULL ? 0 : list.Total()); } //+------------------------------------------------------------------+
Hier erhalten wir die Liste aller offenen Positionen und erteilten Orders und die Liste nach dem Orderstatus "Marktposition" sortiert.
Die Anzahl der Objekte in der erhaltenen Liste wird zurückgeben. Wenn die Liste nicht erhalten werden konnte, wird Null zurückgegeben.
Die Methode, die die Anzahl der offenen Kaufpositionen des Kontos zurückgibt:
//+------------------------------------------------------------------+ //| Return the number of buy positions | //+------------------------------------------------------------------+ int CTrading::PositionsTotalLong(void) const { CArrayObj *list=this.m_market.GetList(); list=CSelect::ByOrderProperty(list,ORDER_PROP_STATUS,ORDER_STATUS_MARKET_POSITION,EQUAL); list=CSelect::ByOrderProperty(list,ORDER_PROP_TYPE,POSITION_TYPE_BUY,EQUAL); return(list==NULL ? 0 : list.Total()); } //+------------------------------------------------------------------+
Hier erhalten wir die Liste aller offenen Positionen und erteilten Orders und die Liste nach dem Orderstatus "Marktposition" sortiert.
Die so erhaltene Liste ist nach der Art der Kaufsposition sortiert.
Die Anzahl der Objekte in der erhaltenen Liste wird zurückgeben. Wenn die Liste nicht erhalten werden konnte, wird Null zurückgegeben.
Die Methode, die die Anzahl der offenen Verkaufspositionen des Kontos zurückgibt: Return the number of sell positio
//+------------------------------------------------------------------+ //| Return the number of sell positions | //+------------------------------------------------------------------+ int CTrading::PositionsTotalShort(void) const { CArrayObj *list=this.m_market.GetList(); list=CSelect::ByOrderProperty(list,ORDER_PROP_STATUS,ORDER_STATUS_MARKET_POSITION,EQUAL); list=CSelect::ByOrderProperty(list,ORDER_PROP_TYPE,POSITION_TYPE_SELL,EQUAL); return(list==NULL ? 0 : list.Total()); } //+------------------------------------------------------------------+
Hier erhalten wir die Liste aller offenen Positionen und erteilten Orders und die Liste nach dem Orderstatus "Marktposition" sortiert.
Die so erhaltene Liste ist nach der Art der Verkaufsposition sortiert.
Die Anzahl der Objekte in der erhaltenen Liste wird zurückgeben. Wenn die Liste nicht erhalten werden konnte, wird Null zurückgegeben.
Die Methode für den Erhalt der Anzahl aller Pending-Orders auf einem Konto, Kauf- und Verkaufsaufträge:
//+------------------------------------------------------------------+ //| Returns the number of pending orders | //+------------------------------------------------------------------+ int CTrading::OrdersTotalAll(void) const { CArrayObj *list=this.m_market.GetList(); list=CSelect::ByOrderProperty(list,ORDER_PROP_STATUS,ORDER_STATUS_MARKET_PENDING,EQUAL); return(list==NULL ? 0 : list.Total()); } //+------------------------------------------------------------------+ //| Return the number of buy pending orders | //+------------------------------------------------------------------+ int CTrading::OrdersTotalLong(void) const { CArrayObj *list=this.m_market.GetList(); list=CSelect::ByOrderProperty(list,ORDER_PROP_STATUS,ORDER_STATUS_MARKET_PENDING,EQUAL); list=CSelect::ByOrderProperty(list,ORDER_PROP_DIRECTION,ORDER_TYPE_BUY,EQUAL); return(list==NULL ? 0 : list.Total()); } //+------------------------------------------------------------------+ //| Return the number of sell pending orders | //+------------------------------------------------------------------+ int CTrading::OrdersTotalShort(void) const { CArrayObj *list=this.m_market.GetList(); list=CSelect::ByOrderProperty(list,ORDER_PROP_STATUS,ORDER_STATUS_MARKET_PENDING,EQUAL); list=CSelect::ByOrderProperty(list,ORDER_PROP_DIRECTION,ORDER_TYPE_SELL,EQUAL); return(list==NULL ? 0 : list.Total()); } //+------------------------------------------------------------------+
Diese drei Hilfsmethoden sind identisch mit den drei oben diskutierten Methoden. Der einzige Unterschied besteht darin, dass wir hier die Liste nach dem Status "aktive Pending-Order" und nach Richtung der Ordertypen Kauf und Verkauf sortieren.
Um einige Einschränkungen zu definieren, müssen wir auch das Gesamtvolumen der offenen Positionen und der platzierten Pending Orders kennen.
Die Methode, die das Gesamtvolumen der Kaufpositionen zurückgibt:
//+------------------------------------------------------------------+ //| Return the total volume of buy positions | //+------------------------------------------------------------------+ double CTrading::PositionsTotalVolumeLong(void) const { double vol=0; CArrayObj *list=this.m_market.GetList(); list=CSelect::ByOrderProperty(list,ORDER_PROP_STATUS,ORDER_STATUS_MARKET_POSITION,EQUAL); list=CSelect::ByOrderProperty(list,ORDER_PROP_TYPE,POSITION_TYPE_BUY,EQUAL); if(list==NULL || list.Total()==0) return 0; for(int i=0;i<list.Total();i++) { COrder *obj=list.At(i); if(obj==NULL) continue; vol+=obj.Volume(); } return vol; } //+------------------------------------------------------------------+
Hier erhalten wir die Liste aller offenen Positionen und platzierten Orders, sowie eine Sortierung der Liste nach dem Orderstatus "Marktposition".
Die erhaltene Liste ist nach der Art der Kaufposition sortiert.
Wenn die Liste leer ist, wird Null zurückgegeben.
In einer Schleife durch die erhaltene Liste, erhält man das nächste Orderobjekt und addiert dessen Volumen zu der Variablen vol.
Nach dem Ende der Schleife, wird der erhaltene Wert der Variablen vol zurückgegeben.
Die Methode, die das Gesamtvolumen der Verkaufspositionen zurückgibt:
//+------------------------------------------------------------------+ //| Return the total volume of sell positions | //+------------------------------------------------------------------+ double CTrading::PositionsTotalVolumeShort(void) const { double vol=0; CArrayObj *list=this.m_market.GetList(); list=CSelect::ByOrderProperty(list,ORDER_PROP_STATUS,ORDER_STATUS_MARKET_POSITION,EQUAL); list=CSelect::ByOrderProperty(list,ORDER_PROP_TYPE,POSITION_TYPE_SELL,EQUAL); if(list==NULL || list.Total()==0) return 0; for(int i=0;i<list.Total();i++) { COrder *obj=list.At(i); if(obj==NULL) continue; vol+=obj.Volume(); } return vol; } //+------------------------------------------------------------------+
Die Methode ist ähnlich wie die vorherige, mit Ausnahme der Sortierung nach Verkaufspositionen.
Die Methoden, die das Gesamtvolumen der platzierten Pending-Buy und -Sell-Orders zurückgegeben:
//+------------------------------------------------------------------+ //| Return the total volume of buy orders | //+------------------------------------------------------------------+ double CTrading::OrdersTotalVolumeLong(void) const { double vol=0; CArrayObj *list=this.m_market.GetList(); list=CSelect::ByOrderProperty(list,ORDER_PROP_STATUS,ORDER_STATUS_MARKET_PENDING,EQUAL); list=CSelect::ByOrderProperty(list,ORDER_PROP_DIRECTION,ORDER_TYPE_BUY,EQUAL); if(list==NULL || list.Total()==0) return 0; for(int i=0;i<list.Total();i++) { COrder *obj=list.At(i); if(obj==NULL) continue; vol+=obj.Volume(); } return vol; } //+------------------------------------------------------------------+ //| Return the total volume of sell orders | //+------------------------------------------------------------------+ double CTrading::OrdersTotalVolumeShort(void) const { double vol=0; CArrayObj *list=this.m_market.GetList(); list=CSelect::ByOrderProperty(list,ORDER_PROP_STATUS,ORDER_STATUS_MARKET_PENDING,EQUAL); list=CSelect::ByOrderProperty(list,ORDER_PROP_DIRECTION,ORDER_TYPE_SELL,EQUAL); if(list==NULL || list.Total()==0) return 0; for(int i=0;i<list.Total();i++) { COrder *obj=list.At(i); if(obj==NULL) continue; vol+=obj.Volume(); } return vol; } //+------------------------------------------------------------------+
Die Methoden sind identisch mit den Methoden für das Gesamtvolumen der Positionen. Allerdings sind die Listen nach dem Typ "Market Pending Order" und nach einer Orderrichtung (Kauf oder Verkauf) sortiert.
Die Methode, die die Orderrichtung durch einen Handelsoperationstyp zurückgibt:
//+------------------------------------------------------------------+ //| Return the order direction by an operation type | //+------------------------------------------------------------------+ ENUM_ORDER_TYPE CTrading::DirectionByActionType(ENUM_ACTION_TYPE action) const { if(action>ACTION_TYPE_SELL_STOP_LIMIT) return WRONG_VALUE; return ENUM_ORDER_TYPE(action%2); } //+------------------------------------------------------------------+
Wenn die Methode den Typ "close by" oder "modification" erhält, wird -1 zurückgegeben. Andernfalls wird der Rest der Division eines Handels-Operationstyps durch 2 zurück, was entweder 0 (ORDER_TYPE_BUY) oder 1 (ORDER_TYPE_SELL) ergibt.
Die Methode zur Prüfung der Existenz einer Position nach dem Ticket:
//+------------------------------------------------------------------+ //| Check if a position is present by ticket | //+------------------------------------------------------------------+ bool CTrading::CheckPositionAvailablity(const ulong ticket,const string source_method) { CArrayObj* list=this.m_market.GetList(); list=CSelect::ByOrderProperty(list,ORDER_PROP_STATUS,ORDER_STATUS_MARKET_POSITION,EQUAL); list.Sort(SORT_BY_ORDER_TICKET); list=CSelect::ByOrderProperty(list,ORDER_PROP_TICKET,ticket,EQUAL); if(list.Total()==1) return true; if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(source_method,CMessage::Text(MSG_LIB_SYS_ERROR_NO_OPEN_POSITION_WITH_TICKET),(string)ticket); return false; } //+------------------------------------------------------------------+
Hier erhält die Methode ein Ticket einer geprüften Position und eines Quellennamens.
Liste aller offenen Positionen und erteilten Orders abrufen, sowie die Liste nach Orderstatus "Marktposition" sortieren.
Setzen des Flags für die Sortierung der Liste nach den Tickets.
Die erhaltene Liste wird nach einem durch die Eingabe übergebenen Ticket sortiert.
Wenn die Liste ein einzelnes Objekt (eine Position mit einem gewünschten Ticket) enthält, wird true zurückgegeben.
Andernfalls wird über die Abwesenheit von Positionen durch die Rückgabe von false informiert.
Die Methode der Überprüfung der Existenz einer Pending-Order nach dem Ticket:
//+------------------------------------------------------------------+ //| Check the presence of an order by ticket | //+------------------------------------------------------------------+ bool CTrading::CheckOrderAvailablity(const ulong ticket,const string source_method) { CArrayObj* list=this.m_market.GetList(); list=CSelect::ByOrderProperty(list,ORDER_PROP_STATUS,ORDER_STATUS_MARKET_PENDING,EQUAL); list.Sort(SORT_BY_ORDER_TICKET); list=CSelect::ByOrderProperty(list,ORDER_PROP_TICKET,ticket,EQUAL); if(list.Total()==1) return true; if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(source_method,CMessage::Text(MSG_LIB_SYS_ERROR_NO_PLACED_ORDER_WITH_TICKET),(string)ticket); return false; } //+------------------------------------------------------------------+
Die Methode ist identisch mit der vorhergehenden, mit der Ausnahme, dass die Liste nach dem Status "Market Pending Order" sortiert ist.
Die Methode, die einem Handelsobjekt einem bestimmten Sound zuordnet:
//+------------------------------------------------------------------+ //| Set a necessary sound to a trading object | //+------------------------------------------------------------------+ void CTrading::SetSoundByMode(const ENUM_MODE_SET_SOUND mode,const ENUM_ORDER_TYPE action,const string sound,CTradeObj *trade_obj) { switch(mode) { case MODE_SET_SOUND_OPEN : trade_obj.SetSoundOpen(action,sound); break; case MODE_SET_SOUND_CLOSE : trade_obj.SetSoundClose(action,sound); break; case MODE_SET_SOUND_MODIFY_SL : trade_obj.SetSoundModifySL(action,sound); break; case MODE_SET_SOUND_MODIFY_TP : trade_obj.SetSoundModifyTP(action,sound); break; case MODE_SET_SOUND_MODIFY_PRICE : trade_obj.SetSoundModifyPrice(action,sound); break; case MODE_SET_SOUND_ERROR_OPEN : trade_obj.SetSoundErrorOpen(action,sound); break; case MODE_SET_SOUND_ERROR_CLOSE : trade_obj.SetSoundErrorClose(action,sound); break; case MODE_SET_SOUND_ERROR_MODIFY_SL : trade_obj.SetSoundErrorModifySL(action,sound); break; case MODE_SET_SOUND_ERROR_MODIFY_TP : trade_obj.SetSoundErrorModifyTP(action,sound); break; case MODE_SET_SOUND_ERROR_MODIFY_PRICE : trade_obj.SetSoundErrorModifyPrice(action,sound); break; default: break; } } //+------------------------------------------------------------------+
Die Methode empfängt den Soundeinstellungsmodus (jedes Handelsereignis soll seinen eigenen Sound haben), den Ordertyp eines Handelsereignisses, für den ein Sound eingestellt wird, den Audiodateinamen (Sound, der einem Order- oder Positionshandelsereignis zugeordnet werden soll) und den Zeiger auf ein Handelsobjekt, für den der Sound gespielt werden soll (ein Zielsymbol, für das eigene Handelsereignis-Sounds eingestellt werden).
Abhängig von dem an die Methode übergebenen Modus werden die entsprechenden Methoden zur Platzierung eines Handelsobjektes Sound eingestellt.
Die Methoden zur Platzierung von Symbol-Handelsobjekt, die wir im vorigen Artikel besprochen und sie vorläufig in der Basisobjektklasse der Bibliothek CEngine implementierten Methoden platziert:
void TradingSetCorrectTypeFilling(const ENUM_ORDER_TYPE_FILLING type=ORDER_FILLING_FOK,const string symbol_name=NULL); void TradingSetTypeFilling(const ENUM_ORDER_TYPE_FILLING type=ORDER_FILLING_FOK,const string symbol_name=NULL); void TradingSetCorrectTypeExpiration(const ENUM_ORDER_TYPE_TIME type=ORDER_TIME_GTC,const string symbol_name=NULL); void TradingSetTypeExpiration(const ENUM_ORDER_TYPE_TIME type=ORDER_TIME_GTC,const string symbol_name=NULL); void TradingSetMagic(const ulong magic,const string symbol_name=NULL); void TradingSetComment(const string comment,const string symbol_name=NULL); void TradingSetDeviation(const ulong deviation,const string symbol_name=NULL); void TradingSetVolume(const double volume=0,const string symbol_name=NULL); void TradingSetExpiration(const datetime expiration=0,const string symbol_name=NULL); void TradingSetAsyncMode(const bool mode=false,const string symbol_name=NULL); void TradingSetLogLevel(const ENUM_LOG_LEVEL log_level=LOG_LEVEL_ERROR_MSG,const string symbol_name=NULL);
wurden in die Handelsklasse verschoben und in der Klasse CEngine überarbeitet (sie rufen einfach die hier befindlichen Methoden auf). Wir haben diese Methoden schon einmal besprochen, und es hat keinen Sinn, hier darauf zu verweilen. Ihre Implementierung finden Sie in den unten angehängten Dateien.
Die Methode, die die Sounds der Standard-Handelsobjekte setzt:
//+------------------------------------------------------------------+ //| Set standard sounds for a symbol trading object | //+------------------------------------------------------------------+ void CTrading::SetSoundsStandart(const string symbol=NULL) { //--- Declare an empty symbol object CSymbol *symbol_obj=NULL; //--- If NULL is passed as a symbol name, set sounds for trading objects of all symbols if(symbol==NULL) { //--- Get the symbol list CArrayObj *list=this.m_symbols.GetList(); if(list==NULL || list.Total()==0) return; //--- In a loop by the list of symbols int total=list.Total(); for(int i=0;i<total;i++) { //--- get the next symbol object symbol_obj=list.At(i); if(symbol_obj==NULL) continue; //--- get a symbol trading object CTradeObj *trade_obj=symbol_obj.GetTradeObj(); if(trade_obj==NULL) continue; //--- set standard sounds for a trading object trade_obj.SetSoundsStandart(); } } //--- If a symbol name is passed else { //--- get a symbol trading object CTradeObj *trade_obj=this.GetTradeObjBySymbol(symbol,DFUN); if(trade_obj==NULL) return; //--- set standard sounds for a trading object trade_obj.SetSoundsStandart(); } } //+------------------------------------------------------------------+
Die Methode, die den Sound eines bestimmten Handelsereignisses für eine bestimmte Order festlegt:
//+------------------------------------------------------------------+ //| Set a sound for a specified order/position type and symbol | //| 'mode' specifies an event a sound is set for | //| (symbol=NULL) for trading objects of all symbols, | //| (symbol!=NULL) for a trading object of a specified symbol | //+------------------------------------------------------------------+ void CTrading::SetSound(const ENUM_MODE_SET_SOUND mode,const ENUM_ORDER_TYPE action,const string sound,const string symbol=NULL) { //--- Declare an empty symbol object CSymbol *symbol_obj=NULL; //--- If NULL is passed as a symbol name, set sounds for trading objects of all symbols if(symbol==NULL) { //--- Get the symbol list CArrayObj *list=this.m_symbols.GetList(); if(list==NULL || list.Total()==0) return; //--- In a loop by the list of symbols int total=list.Total(); for(int i=0;i<total;i++) { //--- get the next symbol object symbol_obj=list.At(i); if(symbol_obj==NULL) continue; //--- get a symbol trading object CTradeObj *trade_obj=symbol_obj.GetTradeObj(); if(trade_obj==NULL) continue; //--- set a sound of a necessary event for a trading object this.SetSoundByMode(mode,action,sound,trade_obj); } } //--- If a symbol name is passed else { //--- get a symbol trading object CTradeObj *trade_obj=this.GetTradeObjBySymbol(symbol,DFUN); if(trade_obj==NULL) return; //--- set a sound of a necessary event for a trading object this.SetSoundByMode(mode,action,sound,trade_obj); } } //+------------------------------------------------------------------+
Alle Aktionen in beiden Methoden werden in den Codekommentaren beschrieben.
In diesem Artikel werden wir die Methoden der Anfangsüberprüfung der Handelseinschränkungen erstellen. Was können wir dieser Kategorie zuordnen? Es handelt sich um die Prüfung der Geldmittel, die für die Durchführung der Handelsoperation ausreichend sind. Wenn die Geldmittel nicht ausreichen, hat es keinen Sinn, eine Anfrage zu senden. Diese Art der Begrenzung erfordert Zeit für die Beseitigung. Wir müssen die Erhöhung der freien Geldmittel auf natürliche Weise abwarten — eine geplante Positionsschließung gemäß der Handelsstrategie und das Erzielen eines Gewinns (Verlustes) mit der Freigabe der Marge, die zur Unterstützung einer offenen Position oder zur erzwungenen Schließung einer verlustreichen Position erforderlich ist, um nur die Marge zurückzugeben, oder die Einzahlung auf ein Konto. Vorerst ist es viel einfacher, die Unmöglichkeit der Erfüllung einer Handelsanforderung hier wieder zu kennzeichnen.
Außerdem gibt es einige andere Handelseinschränkungen — Deaktivierung des Autohandels im Terminal, Deaktivierung des Autohandels für einen EA in seinen Einstellungen, Deaktivierung des Autohandels von der Serverseite oder für ein bestimmtes Symbol, sowie einige andere zusätzliche Faktoren.
Das ist alles, was wir in diesem Artikel für die Trading-Klasse implementieren werden.
Die Methode zur Überprüfung der Angemessenheit der Mittel zur Durchführung einer Handelsoperation:
//+------------------------------------------------------------------+ //| Check if the funds are sufficient | //+------------------------------------------------------------------+ bool CTrading::CheckMoneyFree(const ENUM_ORDER_TYPE order_type,const double volume,const double price,const CSymbol *symbol_obj,const string source_method) const { ::ResetLastError(); //--- Get the type of a market order by a trading operation type ENUM_ORDER_TYPE action=this.DirectionByActionType((ENUM_ACTION_TYPE)order_type); //--- Get the value of free funds to be left after conducting a trading operation double money_free= ( //--- For MQL5, calculate the difference between free funds and the funds required to conduct a trading operation #ifdef __MQL5__ this.m_account.MarginFree()-this.m_account.MarginForAction(action,symbol_obj.Name(),volume,price) //--- For MQL4, use the operation result of the standard function returning the amount of funds left #else/*__MQL4__*/::AccountFreeMarginCheck(symbol_obj.Name(),order_type,volume) #endif ); //--- If no free funds are left, inform of that and return 'false' if(money_free<=0 #ifdef __MQL4__ || ::GetLastError()==134 #endif ) { if(this.m_log_level>LOG_LEVEL_NO_MSG) { //--- create a message text string message= ( symbol_obj.Name()+" "+::DoubleToString(volume,symbol_obj.DigitsLot())+" "+ ( order_type>ORDER_TYPE_SELL ? OrderTypeDescription(order_type,false,false) : PositionTypeDescription(PositionTypeByOrderType(order_type)) )+" ("+::DoubleToString(money_free,(int)this.m_account.CurrencyDigits())+")" ); //--- display a journal message if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(source_method,CMessage::Text(MSG_LIB_TEXT_NOT_ENOUTH_MONEY_FOR),message); } return false; } //--- Verification successful return true; } //+------------------------------------------------------------------+
Die Methode zur Überprüfung der Einschränkungen für die Durchführung von Handelsgeschäften:
//+------------------------------------------------------------------+ //| Check trading limitations | //+------------------------------------------------------------------+ bool CTrading::CheckTradeConstraints(const double volume, const ENUM_ACTION_TYPE action_type, const CSymbol *symbol_obj, const string source_method, double sl=0, double tp=0) { //--- the result of conducting all checks bool res=true; //--- Clear the error list (codes of found limitations) this.m_list_errors.Clear(); this.m_list_errors.Sort(); //--- Check connection with the trade server (not in the test mode) if(!::TerminalInfoInteger(TERMINAL_CONNECTED)) { if(!::MQLInfoInteger(MQL_TESTER)) { //--- add the error code to the list and write 'false' to the result this.AddErrorCodeToList(MSG_LIB_TEXT_TERMINAL_NOT_CONNECTED); res &=false; } } //--- Check if trading is enabled for an account (if there is a connection with the trade server) else if(!this.m_account.TradeAllowed()) { //--- add the error code to the list and write 'false' to the result this.AddErrorCodeToList(MSG_LIB_TEXT_ACCOUNT_NOT_TRADE_ENABLED); res &=false; } //--- Check if trading is allowed for any EAs/scripts for the current account if(!this.m_account.TradeExpert()) { //--- add the error code to the list and write 'false' to the result this.AddErrorCodeToList(MSG_LIB_TEXT_ACCOUNT_EA_NOT_TRADE_ENABLED); res &=false; } //--- Check if auto trading is allowed in the terminal. //--- AutoTrading button (Options --> Expert Advisors --> "Allowed automated trading") if(!::TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) { //--- add the error code to the list and write 'false' to the result this.AddErrorCodeToList(MSG_LIB_TEXT_TERMINAL_NOT_TRADE_ENABLED); res &=false; } //--- Check if auto trading is allowed for the current EA. //--- (F7 --> Common --> Allow Automated Trading) if(!::MQLInfoInteger(MQL_TRADE_ALLOWED)) { //--- add the error code to the list and write 'false' to the result this.AddErrorCodeToList(MSG_LIB_TEXT_EA_NOT_TRADE_ENABLED); res &=false; } //--- Check if trading is enabled on a symbol. //--- If trading is disabled, add the error code to the list and write 'false' to the result if(symbol_obj.TradeMode()==SYMBOL_TRADE_MODE_DISABLED) { this.AddErrorCodeToList(MSG_SYM_TRADE_MODE_DISABLED); res &=false; } //--- If not closing/removal/modification if(action_type>WRONG_VALUE && action_type<ACTION_TYPE_CLOSE_BY) { //--- In case of close-only, add the error code to the list and write 'false' to the result if(symbol_obj.TradeMode()==SYMBOL_TRADE_MODE_CLOSEONLY) { this.AddErrorCodeToList(MSG_SYM_TRADE_MODE_CLOSEONLY); res &=false; } //--- Check the minimum volume if(volume<symbol_obj.LotsMin()) { //--- The volume in a request is less than the minimum allowed one //--- add the error code to the list and write 'false' to the result this.AddErrorCodeToList(MSG_LIB_TEXT_REQ_VOL_LESS_MIN_VOLUME); res &=false; } //--- Check the maximum volume else if(volume>symbol_obj.LotsMax()) { //--- The volume in the request exceeds the maximum acceptable one //--- add the error code to the list and write 'false' to the result this.AddErrorCodeToList(MSG_LIB_TEXT_REQ_VOL_MORE_MAX_VOLUME); res &=false; } //--- Check the minimum volume gradation double step=symbol_obj.LotsStep(); if(fabs((int)round(volume/step)*step-volume)>0.0000001) { //--- The volume in the request is not a multiple of the minimum gradation of the lot change step //--- add the error code to the list and write 'false' to the result this.AddErrorCodeToList(MSG_LIB_TEXT_INVALID_VOLUME_STEP); res &=false; } } //--- When opening a position if(action_type>WRONG_VALUE && action_type<ACTION_TYPE_BUY_LIMIT) { //--- Check if sending market orders is allowed on a symbol. //--- If trading market orders is disabled, add the error code to the list and write 'false' to the result if(!symbol_obj.IsMarketOrdersAllowed()) { this.AddErrorCodeToList(MSG_SYM_MARKET_ORDER_DISABLED); res &=false; } } //--- When placing a pending order else if(action_type>ACTION_TYPE_SELL && action_type<ACTION_TYPE_CLOSE_BY) { //--- If there is a limitation on the number of pending orders on the account //--- and placing a new order exceeds the acceptable number if(this.m_account.LimitOrders()>0 && this.OrdersTotalAll()+1 > this.m_account.LimitOrders()) { //--- The maximum number of pending orders is reached //--- add the error code to the list and write 'false' to the result this.AddErrorCodeToList(10033); res &=false; } //--- Check if placing limit orders is allowed on a symbol. if(action_type==ACTION_TYPE_BUY_LIMIT || action_type==ACTION_TYPE_SELL_LIMIT) { //--- If it is not, add the error code to the list and write 'false' to the result if(!symbol_obj.IsLimitOrdersAllowed()) { this.AddErrorCodeToList(MSG_SYM_LIMIT_ORDER_DISABLED); res &=false; } } //--- Check if placing stop orders is allowed on a symbol. else if(action_type==ACTION_TYPE_BUY_STOP || action_type==ACTION_TYPE_SELL_STOP) { //--- If placing stop orders is disabled, add the error code to the list and write 'false' to the result if(!symbol_obj.IsStopOrdersAllowed()) { this.AddErrorCodeToList(MSG_SYM_STOP_ORDER_DISABLED); res &=false; } } //--- For MQL5, check if placing stop limit orders is allowed on a symbol. #ifdef __MQL5__ else if(action_type==ACTION_TYPE_BUY_STOP_LIMIT || action_type==ACTION_TYPE_SELL_STOP_LIMIT) { //--- If it is not, add the error code to the list and write 'false' to the result if(!symbol_obj.IsStopLimitOrdersAllowed()) { this.AddErrorCodeToList(MSG_SYM_STOP_LIMIT_ORDER_DISABLED); res &=false; } } #endif } //--- In case of opening/placing/modification if(action_type>WRONG_VALUE && action_type!=ACTION_TYPE_CLOSE_BY) { //--- If not modification if(action_type!=ACTION_TYPE_MODIFY) { //--- When buying, check if long trading is enabled on a symbol if(this.DirectionByActionType(action_type)==ORDER_TYPE_BUY) { //--- If only selling is allowed, add the error code to the list and write 'false' to the result if(symbol_obj.TradeMode()==SYMBOL_TRADE_MODE_SHORTONLY) { this.AddErrorCodeToList(MSG_SYM_TRADE_MODE_SHORTONLY); res &=false; } //--- If a symbol has the limitation on the total volume of an open position and pending orders in the same direction if(symbol_obj.VolumeLimit()>0) { //--- (If the total volume of placed long orders and open long positions)+open volume exceed the maximum one if(this.OrdersTotalVolumeLong()+this.PositionsTotalVolumeLong()+volume > symbol_obj.VolumeLimit()) { //--- Exceeded maximum allowed aggregate volume of orders and positions in one direction //--- add the error code to the list and write 'false' to the result this.AddErrorCodeToList(MSG_LIB_TEXT_MAX_VOLUME_LIMIT_EXCEEDED); res &=false; } } } //--- When selling, check if short trading is enabled on a symbol else if(this.DirectionByActionType(action_type)==ORDER_TYPE_SELL) { //--- If only buying is allowed, add the error code to the list and write 'false' to the result if(symbol_obj.TradeMode()==SYMBOL_TRADE_MODE_LONGONLY) { this.AddErrorCodeToList(MSG_SYM_TRADE_MODE_LONGONLY); res &=false; } //--- If a symbol has the limitation on the total volume of an open position and pending orders in the same direction if(symbol_obj.VolumeLimit()>0) { //--- (If the total volume of placed short orders and open short positions)+open volume exceed the maximum one if(this.OrdersTotalVolumeShort()+this.PositionsTotalVolumeShort()+volume > symbol_obj.VolumeLimit()) { //--- Exceeded maximum allowed aggregate volume of orders and positions in one direction //--- add the error code to the list and write 'false' to the result this.AddErrorCodeToList(MSG_LIB_TEXT_MAX_VOLUME_LIMIT_EXCEEDED); res &=false; } } } } //--- If the request features StopLoss and its placing is not allowed if(sl>0 && !symbol_obj.IsStopLossOrdersAllowed()) { //--- add the error code to the list and write 'false' to the result this.AddErrorCodeToList(MSG_SYM_SL_ORDER_DISABLED); res &=false; } //--- If the request features TakeProfit and its placing is not allowed if(tp>0 && !symbol_obj.IsTakeProfitOrdersAllowed()) { //--- add the error code to the list and write 'false' to the result this.AddErrorCodeToList(MSG_SYM_TP_ORDER_DISABLED); res &=false; } } //--- Beim Schließen durch einen Gegenposition else if(action_type==ACTION_TYPE_CLOSE_BY) { //--- When closing by an opposite position is disabled if(!symbol_obj.IsCloseByOrdersAllowed()) { //--- add the error code to the list and write 'false' to the result this.AddErrorCodeToList(MSG_LIB_TEXT_CLOSE_BY_ORDERS_DISABLED); res &=false; } } //--- If there are limitations, display the header and the error list if(!res) { //--- Request was rejected before sending to the server due to: int total=this.m_list_errors.Total(); if(this.m_log_level>LOG_LEVEL_NO_MSG) { //--- For MQL5, first display the list header followed by the error list #ifdef __MQL5__ ::Print(source_method,CMessage::Text(MSG_LIB_TEXT_REQUEST_REJECTED_DUE)); for(int i=0;i<total;i++) ::Print((total>1 ? string(i+1)+". " : ""),CMessage::Text(m_list_errors.At(i))); //--- For MQL4, the journal messages are displayed in the reverse order: the error list is followed by the list header #else for(int i=total-1;i>WRONG_VALUE;i--) ::Print((total>1 ? string(i+1)+". " : ""),CMessage::Text(m_list_errors.At(i))); ::Print(source_method,CMessage::Text(MSG_LIB_TEXT_REQUEST_REJECTED_DUE)); #endif } } return res; } //+------------------------------------------------------------------+
Die Methode ist recht umfangreich, aber hier ist bereits alles bekannt — Überprüfung der Eigenschaften des Programms, des Terminals, des Kontos oder des Symbols, bei dem die Einschränkungen möglich sind. Wenn eine Einschränkung existiert, fügen Sie den Code der erkannten Einschränkung in die Liste ein und fügen Sie false zum Ergebnisflag hinzu. Wenn die Variable nach allen Prüfungen auf false steht, zeigen Sie die Kopfzeile der Liste der erkannten Begrenzungen an und zeigen Sie alle erkannten Handelsbegrenzungen unter der Kopfzeile in einer Schleife durch die Liste der Begrenzungscodes an. Wenn die Variable, die die Prüfergebnisse speichert, true hat (durch die diese Variable ursprünglich initialisiert wurde), dann sind alle Prüfungen bestanden und true wird zurückgegeben.
In der aktuellen Version der Handelsklasse werden wir an dieser Stelle aufhören. Im weiteren Verlauf sollen bei der Erstellung der Fehlerbehandlungsmethoden alle Aktionen als Reaktion auf Einschränkungen und Fehler in dieser Klasse behandelt werden.
Handelsmethoden der Klasse:
//+------------------------------------------------------------------+ //| Open Buy position | //+------------------------------------------------------------------+ bool CTrading::OpenBuy(const double volume,const string symbol,const ulong magic=ULONG_MAX,double sl=0,double tp=0,const string comment=NULL) { //--- Get a symbol object by a symbol name CSymbol *symbol_obj=this.m_symbols.GetSymbolObjByName(symbol); //--- If failed to get the symbol object, display the message and return 'false' if(symbol_obj==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_SYM_OBJ)); return false; } //--- Update symbol quotes symbol_obj.RefreshRates(); //--- If there are trading limitations, inform of that and exit if(!this.CheckTradeConstraints(volume,ACTION_TYPE_BUY,symbol_obj,DFUN,sl,tp)) { return false; } //--- If the funds are insufficient, inform of that and exit if(!this.CheckMoneyFree(ORDER_TYPE_BUY,volume,symbol_obj.Ask(),symbol_obj,DFUN)) { return false; } //--- get a trading object from a symbol object CTradeObj *trade_obj=symbol_obj.GetTradeObj(); if(trade_obj==NULL) { //--- Error. Failed to get trading object if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_TRADE_OBJ)); return false; } //--- Return the result of sending a trading request in a symbol trading object return trade_obj.OpenPosition(POSITION_TYPE_BUY,volume,sl,tp,magic,trade_obj.GetDeviation(),comment); } //+------------------------------------------------------------------+ //| Open a Sell position | //+------------------------------------------------------------------+ bool CTrading::OpenSell(const double volume,const string symbol,const ulong magic=ULONG_MAX,double sl=0,double tp=0,const string comment=NULL) { //--- Get a symbol object by a symbol name CSymbol *symbol_obj=this.m_symbols.GetSymbolObjByName(symbol); //--- If failed to get the symbol object, display the message and return 'false' if(symbol_obj==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_SYM_OBJ)); return false; } //--- Update symbol quotes symbol_obj.RefreshRates(); //--- If there are trading limitations, inform of that and exit if(!this.CheckTradeConstraints(volume,ACTION_TYPE_SELL,symbol_obj,DFUN,sl,tp)) { return false; } //--- If the funds are insufficient, inform of that and exit if(!this.CheckMoneyFree(ORDER_TYPE_SELL,volume,symbol_obj.Bid(),symbol_obj,DFUN)) { return false; } //--- get a trading object from a symbol object CTradeObj *trade_obj=symbol_obj.GetTradeObj(); if(trade_obj==NULL) { //--- Error. Failed to get trading object if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_TRADE_OBJ)); return false; } //--- Return the result of sending a trading request in a symbol trading object return trade_obj.OpenPosition(POSITION_TYPE_SELL,volume,sl,tp,magic,trade_obj.GetDeviation(),comment); } //+------------------------------------------------------------------+ //| Modify a position | //+------------------------------------------------------------------+ bool CTrading::ModifyPosition(const ulong ticket,const double sl=WRONG_VALUE,const double tp=WRONG_VALUE) { //--- Get a symbol object by a position ticket CSymbol *symbol_obj=this.GetSymbolObjByPosition(ticket,DFUN); //--- If failed to get the symbol object, display the message and return 'false' if(symbol_obj==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_SYM_OBJ)); return false; } //--- Update symbol quotes symbol_obj.RefreshRates(); //--- If there are trading limitations, inform of that and exit if(!this.CheckTradeConstraints(0,ACTION_TYPE_MODIFY,symbol_obj,DFUN,sl,tp)) { return false; } //--- get a trading object from a symbol object CTradeObj *trade_obj=symbol_obj.GetTradeObj(); if(trade_obj==NULL) { //--- Error. Failed to get trading object if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_TRADE_OBJ)); return false; } //--- Return the result of sending a trading request in a symbol trading object return trade_obj.ModifyPosition(ticket,sl,tp); } //+------------------------------------------------------------------+ //| Close a position in full | //+------------------------------------------------------------------+ bool CTrading::ClosePosition(const ulong ticket) { //--- Get a symbol object by a position ticket CSymbol *symbol_obj=this.GetSymbolObjByPosition(ticket,DFUN); //--- If failed to get the symbol object, display the message and return 'false' if(symbol_obj==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_SYM_OBJ)); return false; } //--- Update symbol quotes symbol_obj.RefreshRates(); //--- If there are trading limitations, inform of that and exit if(!this.CheckTradeConstraints(0,WRONG_VALUE,symbol_obj,DFUN)) { return false; } //--- get a trading object from a symbol object CTradeObj *trade_obj=symbol_obj.GetTradeObj(); if(trade_obj==NULL) { //--- Error. Failed to get trading object if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_TRADE_OBJ)); return false; } //--- Return the result of sending a trading request in a symbol trading object return trade_obj.ClosePosition(ticket); } //+------------------------------------------------------------------+ //| Close a position partially | //+------------------------------------------------------------------+ bool CTrading::ClosePositionPartially(const ulong ticket,const double volume) { //--- Get a symbol object by a position ticket CSymbol *symbol_obj=this.GetSymbolObjByPosition(ticket,DFUN); //--- If failed to get the symbol object, display the message and return 'false' if(symbol_obj==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_SYM_OBJ)); return false; } //--- Update symbol quotes symbol_obj.RefreshRates(); //--- If there are trading limitations, inform of that and exit if(!this.CheckTradeConstraints(0,WRONG_VALUE,symbol_obj,DFUN)) { return false; } //--- get a trading object from a symbol object CTradeObj *trade_obj=symbol_obj.GetTradeObj(); if(trade_obj==NULL) { //--- Error. Failed to get trading object if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_TRADE_OBJ)); return false; } //--- Return the result of sending a trading request in a symbol trading object return trade_obj.ClosePositionPartially(ticket,symbol_obj.NormalizedLot(volume)); } //+------------------------------------------------------------------+ //| Close a position by an opposite one | //+------------------------------------------------------------------+ bool CTrading::ClosePositionBy(const ulong ticket,const ulong ticket_by) { //--- Get a symbol object by a position ticket CSymbol *symbol_obj=this.GetSymbolObjByPosition(ticket,DFUN); //--- If failed to get the symbol object, display the message and return 'false' if(symbol_obj==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_SYM_OBJ)); return false; } //--- Update symbol quotes symbol_obj.RefreshRates(); //--- If there are trading limitations, inform of that and exit if(!this.CheckTradeConstraints(0,ACTION_TYPE_CLOSE_BY,symbol_obj,DFUN)) { return false; } //--- trading object of a closed position CTradeObj *trade_obj_pos=this.GetTradeObjByPosition(ticket,DFUN); if(trade_obj_pos==NULL) { //--- Error. Failed to get trading object if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_TRADE_OBJ)); return false; } //--- check the presence of an opposite position if(!this.CheckPositionAvailablity(ticket_by,DFUN)) return false; //--- trading object of an opposite position CTradeObj *trade_obj_pos_by=this.GetTradeObjByPosition(ticket_by,DFUN); if(trade_obj_pos_by==NULL) { //--- Error. Failed to get trading object if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_TRADE_OBJ)); return false; } //--- If a symbol of a closed position is not equal to an opposite position's one, inform of that and exit if(symbol_obj.Name()!=trade_obj_pos_by.GetSymbol()) { //--- Symbols of opposite positions are not equal if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_TEXT_CLOSE_BY_SYMBOLS_UNEQUAL)); return false; } //--- Return the result of sending a trading request in a symbol trading object return trade_obj_pos.ClosePositionBy(ticket,ticket_by); } //+------------------------------------------------------------------+ //| Place BuyStop pending order | //+------------------------------------------------------------------+ bool CTrading::PlaceBuyStop(const double volume, const string symbol, const double price, const double sl=0, const double tp=0, const ulong magic=WRONG_VALUE, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC) { //--- Get a symbol object by a symbol name CSymbol *symbol_obj=this.m_symbols.GetSymbolObjByName(symbol); //--- If failed to get the symbol object, display the message and return 'false' if(symbol_obj==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_SYM_OBJ)); return false; } //--- Update symbol quotes symbol_obj.RefreshRates(); //--- If there are trading limitations, inform of that and exit if(!this.CheckTradeConstraints(volume,ACTION_TYPE_BUY_STOP,symbol_obj,DFUN,sl,tp)) { return false; } //--- get a trading object from a symbol object CTradeObj *trade_obj=symbol_obj.GetTradeObj(); if(trade_obj==NULL) { //--- Error. Failed to get trading object if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_TRADE_OBJ)); return false; } //--- Return the result of sending a trading request in a symbol trading object return trade_obj.SetOrder(ORDER_TYPE_BUY_STOP,volume,price,sl,tp,0,magic,expiration,type_time,comment); } //+------------------------------------------------------------------+ //| Place BuyLimit pending order | //+------------------------------------------------------------------+ bool CTrading::PlaceBuyLimit(const double volume, const string symbol, const double price, const double sl=0, const double tp=0, const ulong magic=WRONG_VALUE, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC) { //--- Get a symbol object by a symbol name CSymbol *symbol_obj=this.m_symbols.GetSymbolObjByName(symbol); //--- If failed to get the symbol object, display the message and return 'false' if(symbol_obj==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_SYM_OBJ)); return false; } //--- Update symbol quotes symbol_obj.RefreshRates(); //--- If there are trading limitations, inform of that and exit if(!this.CheckTradeConstraints(volume,ACTION_TYPE_BUY_LIMIT,symbol_obj,DFUN,sl,tp)) { return false; } //--- get a trading object from a symbol object CTradeObj *trade_obj=symbol_obj.GetTradeObj(); if(trade_obj==NULL) { //--- Error. Failed to get trading object if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_TRADE_OBJ)); return false; } //--- Return the result of sending a trading request in a symbol trading object return trade_obj.SetOrder(ORDER_TYPE_BUY_LIMIT,volume,price,sl,tp,0,magic,expiration,type_time,comment); } //+------------------------------------------------------------------+ //| Place BuyStopLimit pending order | //+------------------------------------------------------------------+ bool CTrading::PlaceBuyStopLimit(const double volume, const string symbol, const double price_stop, const double price_limit, const double sl=0, const double tp=0, const ulong magic=WRONG_VALUE, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC) { //--- Get a symbol object by a symbol name CSymbol *symbol_obj=this.m_symbols.GetSymbolObjByName(symbol); //--- If failed to get the symbol object, display the message and return 'false' if(symbol_obj==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_SYM_OBJ)); return false; } //--- Update symbol quotes symbol_obj.RefreshRates(); //--- If there are trading limitations, inform of that and exit if(!this.CheckTradeConstraints(volume,ACTION_TYPE_BUY_STOP_LIMIT,symbol_obj,DFUN,sl,tp)) { return false; } #ifdef __MQL5__ //--- get a trading object from a symbol object CTradeObj *trade_obj=symbol_obj.GetTradeObj(); if(trade_obj==NULL) { //--- Error. Failed to get trading object if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_TRADE_OBJ)); return false; } //--- Return the result of sending a trading request in a symbol trading object return trade_obj.SetOrder(ORDER_TYPE_BUY_STOP_LIMIT,volume,price_stop,sl,tp,price_limit,magic,expiration,type_time,comment); //--- MQL4 #else return true; #endif } //+------------------------------------------------------------------+ //| Place SellStop pending order | //+------------------------------------------------------------------+ bool CTrading::PlaceSellStop(const double volume, const string symbol, const double price, const double sl=0, const double tp=0, const ulong magic=WRONG_VALUE, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC) { //--- Get a symbol object by a symbol name CSymbol *symbol_obj=this.m_symbols.GetSymbolObjByName(symbol); //--- If failed to get the symbol object, display the message and return 'false' if(symbol_obj==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_SYM_OBJ)); return false; } //--- Update symbol quotes symbol_obj.RefreshRates(); //--- If there are trading limitations, inform of that and exit if(!this.CheckTradeConstraints(volume,ACTION_TYPE_SELL_STOP,symbol_obj,DFUN,sl,tp)) { return false; } //--- get a trading object from a symbol object CTradeObj *trade_obj=symbol_obj.GetTradeObj(); if(trade_obj==NULL) { //--- Error. Failed to get trading object if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_TRADE_OBJ)); return false; } //--- Return the result of sending a trading request in a symbol trading object return trade_obj.SetOrder(ORDER_TYPE_SELL_STOP,volume,price,sl,tp,0,magic,expiration,type_time,comment); } //+------------------------------------------------------------------+ //| Place SellLimit pending order | //+------------------------------------------------------------------+ bool CTrading::PlaceSellLimit(const double volume, const string symbol, const double price, const double sl=0, const double tp=0, const ulong magic=WRONG_VALUE, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC) { //--- Get a symbol object by a symbol name CSymbol *symbol_obj=this.m_symbols.GetSymbolObjByName(symbol); //--- If failed to get the symbol object, display the message and return 'false' if(symbol_obj==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_SYM_OBJ)); return false; } //--- Update symbol quotes symbol_obj.RefreshRates(); //--- If there are trading limitations, inform of that and exit if(!this.CheckTradeConstraints(volume,ACTION_TYPE_SELL_LIMIT,symbol_obj,DFUN,sl,tp)) { return false; } //--- get a trading object from a symbol object CTradeObj *trade_obj=symbol_obj.GetTradeObj(); if(trade_obj==NULL) { //--- Error. Failed to get trading object if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_TRADE_OBJ)); return false; } //--- Return the result of sending a trading request in a symbol trading object return trade_obj.SetOrder(ORDER_TYPE_SELL_LIMIT,volume,price,sl,tp,0,magic,expiration,type_time,comment); } //+------------------------------------------------------------------+ //| Place SellStopLimit pending order | //+------------------------------------------------------------------+ bool CTrading::PlaceSellStopLimit(const double volume, const string symbol, const double price_stop, const double price_limit, const double sl=0, const double tp=0, const ulong magic=WRONG_VALUE, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC) { //--- Get a symbol object by a symbol name CSymbol *symbol_obj=this.m_symbols.GetSymbolObjByName(symbol); //--- If failed to get the symbol object, display the message and return 'false' if(symbol_obj==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_SYM_OBJ)); return false; } //--- Update symbol quotes symbol_obj.RefreshRates(); //--- If there are trading limitations, inform of that and exit if(!this.CheckTradeConstraints(volume,ACTION_TYPE_SELL_STOP_LIMIT,symbol_obj,DFUN,sl,tp)) { return false; } #ifdef __MQL5__ //--- get a trading object from a symbol object CTradeObj *trade_obj=symbol_obj.GetTradeObj(); if(trade_obj==NULL) { //--- Error. Failed to get trading object if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_TRADE_OBJ)); return false; } //--- Return the result of sending a trading request in a symbol trading object return trade_obj.SetOrder(ORDER_TYPE_SELL_STOP_LIMIT,volume,price_stop,sl,tp,price_limit,magic,expiration,type_time,comment); //--- MQL4 #else return true; #endif } //+------------------------------------------------------------------+ //| Modify a pending order | //+------------------------------------------------------------------+ bool CTrading::ModifyOrder(const ulong ticket, const double price=WRONG_VALUE, const double sl=WRONG_VALUE, const double tp=WRONG_VALUE, const double stoplimit=WRONG_VALUE, datetime expiration=WRONG_VALUE, ENUM_ORDER_TYPE_TIME type_time=WRONG_VALUE) { //--- Get a symbol object by an order ticket CSymbol *symbol_obj=this.GetSymbolObjByOrder(ticket,DFUN); //--- If failed to get the symbol object, display the message and return 'false' if(symbol_obj==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_SYM_OBJ)); return false; } //--- Update symbol quotes symbol_obj.RefreshRates(); //--- If there are trading limitations, inform of that and exit if(!this.CheckTradeConstraints(0,ACTION_TYPE_MODIFY,symbol_obj,DFUN,sl,tp)) { return false; } //--- get a trading object from a symbol object CTradeObj *trade_obj=symbol_obj.GetTradeObj(); if(trade_obj==NULL) { //--- Error. Failed to get trading object if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_TRADE_OBJ)); return false; } //--- Return the result of sending a trading request in a symbol trading object return trade_obj.ModifyOrder(ticket,price,sl,tp,stoplimit,expiration,type_time); } //+------------------------------------------------------------------+ //| Remove a pending order | //+------------------------------------------------------------------+ bool CTrading::DeleteOrder(const ulong ticket) { //--- Get a symbol object by an order ticket CSymbol *symbol_obj=this.GetSymbolObjByOrder(ticket,DFUN); //--- If failed to get the symbol object, display the message and return 'false' if(symbol_obj==NULL) { if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_SYM_OBJ)); return false; } //--- Update symbol quotes symbol_obj.RefreshRates(); //--- If there are trading limitations, inform of that and exit if(!this.CheckTradeConstraints(0,WRONG_VALUE,symbol_obj,DFUN)) { return false; } //--- get a trading object from a symbol object CTradeObj *trade_obj=symbol_obj.GetTradeObj(); if(trade_obj==NULL) { //--- Error. Failed to get trading object if(this.m_log_level>LOG_LEVEL_NO_MSG) ::Print(DFUN_ERR_LINE,CMessage::Text(MSG_LIB_SYS_ERROR_FAILED_GET_TRADE_OBJ)); return false; } //--- Return the result of sending a trading request in a symbol trading object return trade_obj.DeleteOrder(ticket); } //+------------------------------------------------------------------+
Wir haben die Handelsmethoden (Senden von Handelsanfragen an den Server) im vorigen Artikel bei der Erstellung des Basishandelsobjekts berücksichtigt. Hier erhalten die Methoden mit ähnlicher Signatur die notwendigen Parameter einer Handelsanfrage, die oben untersuchten Handelseinschränkungen werden geprüft und die entsprechende Methode eines Symbol-Basishandelsobjekts wird aufgerufen. Das Ergebnis der aktiven Methode wird an das Programm zurückgegeben.
In diesem Stadium sind dies alle Prüfungen, die vor dem Senden einer Handelsanforderung durchgeführt werden. Wir werden sie weiter ausbauen, da wir die Gültigkeit der Parameter der Handelsanfrage prüfen und behandeln müssen. Nun wird davon ausgegangen, dass alle Parameter bereits gültig sind.
Die Handelsklasse in ihrer aktuellen Implementierung mit der geplanten Funktionalität ist bereit.
Jetzt müssen wir auf das Basisobjekt aus der Bibliothek CEngine zugreifen und mit den Klassenhandelsmethoden durch sie arbeiten.
Öffnen Sie \MQL5\Include\DoEasy\Engine.mqh und nehmen Sie alle notwendigen Änderungen daran vor.
Zuerst binden Sie die Handelsklassendatei ein:
//+------------------------------------------------------------------+ //| Engine.mqh | //| Copyright 2019, MetaQuotes Software Corp. | //| https://mql5.com/de/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2019, MetaQuotes Software Corp." #property link "https://mql5.com/de/users/artmedia70" #property version "1.00" //+------------------------------------------------------------------+ //| Include-Dateien | //+------------------------------------------------------------------+ #include "Services\TimerCounter.mqh" #include "Collections\HistoryCollection.mqh" #include "Collections\MarketCollection.mqh" #include "Collections\EventsCollection.mqh" #include "Collections\AccountsCollection.mqh" #include "Collections\SymbolsCollection.mqh" #include "Collections\ResourceCollection.mqh" #include "Trading.mqh" //+------------------------------------------------------------------+
In der 'private' Teil der Klasse deklarieren Sie das Handelsklassenobjekt:
//+------------------------------------------------------------------+ //| Bibliothek der Basisklasse | //+------------------------------------------------------------------+ class CEngine { private: CHistoryCollection m_history; // Kollektion der historischen Aufträge und Deals CMarketCollection m_market; // Kollektion der Marktorder und Deals CEventsCollection m_events; // Event collection CAccountsCollection m_accounts; // Account collection CSymbolsCollection m_symbols; // Symbol collection CResourceCollection m_resource; // Resource list CTrading m_trading; // Trading class object CArrayObj m_list_counters; // Liste der Timerzähler int m_global_error; // Global error code bool m_first_start; // Flag des Erststarts bool m_is_hedge; // Flag des Hedging-Kontos bool m_is_tester; // Flag of working in the tester bool m_is_market_trade_event; // Flag eines Handelsereignisses des Kontos bool m_is_history_trade_event; // Flag eines historischen Handelsereignisses auf dem Konto bool m_is_account_event; // Account change event flag bool m_is_symbol_event; // Symbol change event flag ENUM_TRADE_EVENT m_last_trade_event; // Last account trading event int m_last_account_event; // Last event in the account properties int m_last_symbol_event; // Last event in the symbol properties //--- Rückgabe des Zählerindex über die ID
Die Methoden
//--- Set the following for the trading classes: //--- (1) correct filling policy, (2) filling policy, //--- (3) correct order expiration type, (4) order expiration type, //--- (5) magic number, (6) comment, (7) slippage, (8) volume, (9) order expiration date, //--- (10) the flag of asynchronous sending of a trading request, (11) logging level void SetTradeCorrectTypeFilling(const ENUM_ORDER_TYPE_FILLING type=ORDER_FILLING_FOK,const string symbol_name=NULL); void SetTradeTypeFilling(const ENUM_ORDER_TYPE_FILLING type=ORDER_FILLING_FOK,const string symbol_name=NULL); void SetTradeCorrectTypeExpiration(const ENUM_ORDER_TYPE_TIME type=ORDER_TIME_GTC,const string symbol_name=NULL); void SetTradeTypeExpiration(const ENUM_ORDER_TYPE_TIME type=ORDER_TIME_GTC,const string symbol_name=NULL); void SetTradeMagic(const ulong magic,const string symbol_name=NULL); void SetTradeComment(const string comment,const string symbol_name=NULL); void SetTradeDeviation(const ulong deviation,const string symbol_name=NULL); void SetTradeVolume(const double volume=0,const string symbol_name=NULL); void SetTradeExpiration(const datetime expiration=0,const string symbol_name=NULL); void SetTradeAsyncMode(const bool mode=false,const string symbol_name=NULL); void SetTradeLogLevel(const ENUM_LOG_LEVEL log_level=LOG_LEVEL_ERROR_MSG,const string symbol_name=NULL);
werden umbenannt auf
//--- Set the following for the trading classes: //--- (1) correct filling policy, (2) filling policy, //--- (3) correct order expiration type, (4) order expiration type, //--- (5) magic number, (6) comment, (7) slippage, (8) volume, (9) order expiration date, //--- (10) the flag of asynchronous sending of a trading request, (11) logging level void TradingSetCorrectTypeFilling(const ENUM_ORDER_TYPE_FILLING type=ORDER_FILLING_FOK,const string symbol_name=NULL); void TradingSetTypeFilling(const ENUM_ORDER_TYPE_FILLING type=ORDER_FILLING_FOK,const string symbol_name=NULL); void TradingSetCorrectTypeExpiration(const ENUM_ORDER_TYPE_TIME type=ORDER_TIME_GTC,const string symbol_name=NULL); void TradingSetTypeExpiration(const ENUM_ORDER_TYPE_TIME type=ORDER_TIME_GTC,const string symbol_name=NULL); void TradingSetMagic(const ulong magic,const string symbol_name=NULL); void TradingSetComment(const string comment,const string symbol_name=NULL); void TradingSetDeviation(const ulong deviation,const string symbol_name=NULL); void TradingSetVolume(const double volume=0,const string symbol_name=NULL); void TradingSetExpiration(const datetime expiration=0,const string symbol_name=NULL); void TradingSetAsyncMode(const bool mode=false,const string symbol_name=NULL); void TradingSetLogLevel(const ENUM_LOG_LEVEL log_level=LOG_LEVEL_ERROR_MSG,const string symbol_name=NULL);
so dass ihr Name die Zugehörigkeit zur Handelsklasse anzeigt.
Im 'public' Teil der Klasse fügen Sie die Methoden zum Setzen von Standardsounds hinzu, die Sounds für eine bestimmte Position/Orderart und ein Handelsereignis und die Methode, die Zeiger auf alle notwendigen Kollektionslisten zur Handelsklasse sendet. Außerdem deklarieren Sie die Methode zum Abspielen eines Sounds durch seine Beschreibung:
//--- Set standard sounds (symbol==NULL) for a symbol trading object, (symbol!=NULL) for trading objects of all symbols void SetSoundsStandart(const string symbol=NULL) { this.m_trading.SetSoundsStandart(symbol); } //--- Set a sound for a specified order/position type and symbol. 'mode' specifies an event a sound is set for //--- (symbol=NULL) for trading objects of all symbols, (symbol!=NULL) for a trading object of a specified symbol void SetSound(const ENUM_MODE_SET_SOUND mode,const ENUM_ORDER_TYPE action,const string sound,const string symbol=NULL) { this.m_trading.SetSound(mode,action,sound,symbol); } //--- Play a sound by its description bool PlaySoundByDescription(const string sound_description); //--- Pass the pointers to all the necessary collections to the trading class void TradingOnInit(void) { this.m_trading.OnInit(this.GetAccountCurrent(),m_symbols.GetObject(),m_market.GetObject(),m_history.GetObject()); }
Drei Methoden rufen einfach die gleichnamigen Methoden der Handelsklasse auf. Betrachten wir die Methode zum Abspielen eines Tons anhand der folgenden Beschreibung:
//+------------------------------------------------------------------+ //| Play a sound by its description | //+------------------------------------------------------------------+ bool CEngine::PlaySoundByDescription(const string sound_description) { string file_name=NULL; //--- Get the list of resources CArrayObj* list=this.GetListResource(); if(list==NULL) return false; //--- Get an index of a resource object by its description int index=this.m_resource.GetIndexResObjByDescription(sound_description); //--- If a resource object with a specified description is found in the list if(index>WRONG_VALUE) { //--- Get a resource object by its index in the list CResObj *res_obj=list.At(index); if(res_obj==NULL) return false; //--- Get a resource object file name file_name=res_obj.FileName(); } //--- If there is no resource object with a specified description in the list, attempt to play the file by the name written in its description //--- To do this, make sure that either a standard audio file (macro substitution of its name), //--- or a name of a new *.wav audio file is passed as a description else if(::StringFind(sound_description,"SND_")==0 || StringSubstr(sound_description,StringLen(sound_description)-4)==".wav") file_name=sound_description; //--- Return the file playing result return(file_name!=NULL ? CMessage::PlaySound(file_name) : false); } //+------------------------------------------------------------------+
Zuvor haben wir Ressourcenobjekte erstellt, in denen wir Audio- und Bilddateien speichern konnten. Wir haben die Möglichkeit hinzugefügt, eine Beschreibung zu jeder Ressource dieser Art hinzuzufügen. So ist es für uns einfach geworden, zu spezifizieren, welche Audiodatei wir abspielen müssen. Zum Beispiel ist es viel einfacher, sich eine benutzerdefinierte Dateibeschreibung zu merken als ihren Namen. Wenn der Dateiname "featureless" ist (wie sound_01.wav), können wir eine beliebige Beschreibung dafür festlegen, zum Beispiel "Sound beim Kauf von EURUSD".
Die Methode erlaubt es, die notwendige Dateibeschreibung in ihren Parametern zu spezifizieren. Sie erkennt ein Ressourcenobjekt mit der passenden Beschreibung und spielt die Audiodatei ab. Optional ist die Methode in der Lage, sowohl Standard-Sounds durch die Makro-Substitutionen ihrer Namen, die wir in Defines.mqh erstellt haben, als auch jede unbekannte Sounddatei abzuspielen. Wir müssen lediglich ihren Namen als Beschreibung übergeben. Eine solche Datei sollte sich in der Sandbox des Terminals befinden, die Erweiterung wav und den richtigen Pfad im Namen haben.
Die Handelsmethoden, die wir vorübergehend in der Klasse CEngine platziert haben, sowie die Methoden, die die Parameter der Handelsobjekte setzen und die, die sich vorübergehend in der CEngine befinden, wurden geändert — alle diese Methoden sowie ihre Implementierung wurden in eine Handelsklasse verschoben, während die entsprechenden Methoden der Handelsklasse einfach von den Klassenmethoden der CEngine aufgerufen werden:
//+------------------------------------------------------------------+ //| Open Buy position | //+------------------------------------------------------------------+ bool CEngine::OpenBuy(const double volume,const string symbol,const ulong magic=ULONG_MAX,double sl=0,double tp=0,const string comment=NULL) { return this.m_trading.OpenBuy(volume,symbol,magic,sl,tp,comment); } //+------------------------------------------------------------------+ //| Open a Sell position | //+------------------------------------------------------------------+ bool CEngine::OpenSell(const double volume,const string symbol,const ulong magic=ULONG_MAX,double sl=0,double tp=0,const string comment=NULL) { return this.m_trading.OpenSell(volume,symbol,magic,sl,tp,comment); } //+------------------------------------------------------------------+ //| Modify a position | //+------------------------------------------------------------------+ bool CEngine::ModifyPosition(const ulong ticket,const double sl=WRONG_VALUE,const double tp=WRONG_VALUE) { return this.m_trading.ModifyPosition(ticket,sl,tp); } //+------------------------------------------------------------------+ //| Close a position in full | //+------------------------------------------------------------------+ bool CEngine::ClosePosition(const ulong ticket) { return this.m_trading.ClosePosition(ticket); } //+------------------------------------------------------------------+ //| Close a position partially | //+------------------------------------------------------------------+ bool CEngine::ClosePositionPartially(const ulong ticket,const double volume) { return this.m_trading.ClosePositionPartially(ticket,volume); } //+------------------------------------------------------------------+ //| Close a position by an opposite one | //+------------------------------------------------------------------+ bool CEngine::ClosePositionBy(const ulong ticket,const ulong ticket_by) { return this.m_trading.ClosePositionBy(ticket,ticket_by); } //+------------------------------------------------------------------+ //| Place BuyStop pending order | //+------------------------------------------------------------------+ bool CEngine::PlaceBuyStop(const double volume, const string symbol, const double price, const double sl=0, const double tp=0, const ulong magic=WRONG_VALUE, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC) { return this.m_trading.PlaceBuyStop(volume,symbol,price,sl,tp,magic,comment,expiration,type_time); } //+------------------------------------------------------------------+ //| Place BuyLimit pending order | //+------------------------------------------------------------------+ bool CEngine::PlaceBuyLimit(const double volume, const string symbol, const double price, const double sl=0, const double tp=0, const ulong magic=WRONG_VALUE, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC) { return this.m_trading.PlaceBuyLimit(volume,symbol,price,sl,tp,magic,comment,expiration,type_time); } //+------------------------------------------------------------------+ //| Place BuyStopLimit pending order | //+------------------------------------------------------------------+ bool CEngine::PlaceBuyStopLimit(const double volume, const string symbol, const double price_stop, const double price_limit, const double sl=0, const double tp=0, const ulong magic=WRONG_VALUE, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC) { return this.m_trading.PlaceBuyStopLimit(volume,symbol,price_stop,price_limit,sl,tp,magic,comment,expiration,type_time); } //+------------------------------------------------------------------+ //| Place SellStop pending order | //+------------------------------------------------------------------+ bool CEngine::PlaceSellStop(const double volume, const string symbol, const double price, const double sl=0, const double tp=0, const ulong magic=WRONG_VALUE, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC) { return this.m_trading.PlaceSellStop(volume,symbol,price,sl,tp,magic,comment,expiration,type_time); } //+------------------------------------------------------------------+ //| Place SellLimit pending order | //+------------------------------------------------------------------+ bool CEngine::PlaceSellLimit(const double volume, const string symbol, const double price, const double sl=0, const double tp=0, const ulong magic=WRONG_VALUE, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC) { return this.m_trading.PlaceSellLimit(volume,symbol,price,sl,tp,magic,comment,expiration,type_time); } //+------------------------------------------------------------------+ //| Place SellStopLimit pending order | //+------------------------------------------------------------------+ bool CEngine::PlaceSellStopLimit(const double volume, const string symbol, const double price_stop, const double price_limit, const double sl=0, const double tp=0, const ulong magic=WRONG_VALUE, const string comment=NULL, const datetime expiration=0, const ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC) { return this.m_trading.PlaceSellStopLimit(volume,symbol,price_stop,price_limit,sl,tp,magic,comment,expiration,type_time); } //+------------------------------------------------------------------+ //| Modify a pending order | //+------------------------------------------------------------------+ bool CEngine::ModifyOrder(const ulong ticket, const double price=WRONG_VALUE, const double sl=WRONG_VALUE, const double tp=WRONG_VALUE, const double stoplimit=WRONG_VALUE, datetime expiration=WRONG_VALUE, ENUM_ORDER_TYPE_TIME type_time=WRONG_VALUE) { return this.m_trading.ModifyOrder(ticket,price,sl,tp,stoplimit,expiration,type_time); } //+------------------------------------------------------------------+ //| Remove a pending order | //+------------------------------------------------------------------+ bool CEngine::DeleteOrder(const ulong ticket) { return this.m_trading.DeleteOrder(ticket); } //+------------------------------------------------------------------+ //| Set the valid filling policy | //| for trading objects of all symbols | //+------------------------------------------------------------------+ void CEngine::TradingSetCorrectTypeFilling(const ENUM_ORDER_TYPE_FILLING type=ORDER_FILLING_FOK,const string symbol_name=NULL) { this.m_trading.SetCorrectTypeFilling(type,symbol_name); } //+------------------------------------------------------------------+ //| Set the filling policy | //| for trading objects of all symbols | //+------------------------------------------------------------------+ void CEngine::TradingSetTypeFilling(const ENUM_ORDER_TYPE_FILLING type=ORDER_FILLING_FOK,const string symbol_name=NULL) { this.m_trading.SetTypeFilling(type,symbol_name); } //+------------------------------------------------------------------+ //| Set a correct order expiration type | //| for trading objects of all symbols | //+------------------------------------------------------------------+ void CEngine::TradingSetCorrectTypeExpiration(const ENUM_ORDER_TYPE_TIME type=ORDER_TIME_GTC,const string symbol_name=NULL) { this.m_trading.SetCorrectTypeExpiration(type,symbol_name); } //+------------------------------------------------------------------+ //| Set an order expiration type | //| for trading objects of all symbols | //+------------------------------------------------------------------+ void CEngine::TradingSetTypeExpiration(const ENUM_ORDER_TYPE_TIME type=ORDER_TIME_GTC,const string symbol_name=NULL) { this.m_trading.SetTypeExpiration(type,symbol_name); } //+------------------------------------------------------------------+ //| Set a magic number for trading objects of all symbols | //+------------------------------------------------------------------+ void CEngine::TradingSetMagic(const ulong magic,const string symbol_name=NULL) { this.m_trading.SetMagic(magic,symbol_name); } //+------------------------------------------------------------------+ //| Set a comment for trading objects of all symbols | //+------------------------------------------------------------------+ void CEngine::TradingSetComment(const string comment,const string symbol_name=NULL) { this.m_trading.SetComment(comment,symbol_name); } //+------------------------------------------------------------------+ //| Set a slippage | //| for trading objects of all symbols | //+------------------------------------------------------------------+ void CEngine::TradingSetDeviation(const ulong deviation,const string symbol_name=NULL) { this.m_trading.SetDeviation(deviation,symbol_name); } //+------------------------------------------------------------------+ //| Set a volume for trading objects of all symbols | //+------------------------------------------------------------------+ void CEngine::TradingSetVolume(const double volume=0,const string symbol_name=NULL) { this.m_trading.SetVolume(volume,symbol_name); } //+------------------------------------------------------------------+ //| Set an order expiration date | //| for trading objects of all symbols | //+------------------------------------------------------------------+ void CEngine::TradingSetExpiration(const datetime expiration=0,const string symbol_name=NULL) { this.m_trading.SetExpiration(expiration,symbol_name); } //+------------------------------------------------------------------+ //| Set the flag of asynchronous sending of trading requests | //| for trading objects of all symbols | //+------------------------------------------------------------------+ void CEngine::TradingSetAsyncMode(const bool mode=false,const string symbol_name=NULL) { this.m_trading.SetAsyncMode(mode,symbol_name); } //+------------------------------------------------------------------+ //| Set a logging level of trading requests | //| for trading objects of all symbols | //+------------------------------------------------------------------+ void CEngine::TradingSetLogLevel(const ENUM_LOG_LEVEL log_level=LOG_LEVEL_ERROR_MSG,const string symbol_name=NULL) { this.m_trading.SetLogLevel(log_level,symbol_name); } //+------------------------------------------------------------------+
Damit ist die Verbesserung der Klasse von CEngine abgeschlossen. Nun müssen wir prüfen, wie das alles funktioniert.
Tests
Um den Test durchzuführen, verwenden wir den EA aus dem vorherigen Artikel und speichern ihn in \MQL5\Experts\TestDoEasy\Part22\ unter dem Namen TestDoEasyPart22.mq5.
Im vorherigen EA zeigte das Journal im OnInit()-Handler eine Menge textueller Verifikationsdaten an. Momentan brauchen wir sie nicht, also entfernen wir alle überflüssigen Aufrufe von Print() und fügen der Handelsklassen-Initialisierung und Prüfung einer Standard-Soundwiedergabe durch Makro-Substitution und eines benutzerdefinierten Sounds durch seine Beschreibung hinzu:
//+------------------------------------------------------------------+ //| Initialisierungsfunktion des Experten | //+------------------------------------------------------------------+ int OnInit() { //--- Calling the function displays the list of enumeration constants in the journal //--- (the list is set in the strings 22 and 25 of the DELib.mqh file) for checking the constants validity //EnumNumbersTest(); //--- Set EA global variables prefix=MQLInfoString(MQL_PROGRAM_NAME)+"_"; for(int i=0;i<TOTAL_BUTT;i++) { butt_data[i].name=prefix+EnumToString((ENUM_BUTTONS)i); butt_data[i].text=EnumToButtText((ENUM_BUTTONS)i); } lot=NormalizeLot(Symbol(),fmax(InpLots,MinimumLots(Symbol())*2.0)); magic_number=InpMagic; stoploss=InpStopLoss; takeprofit=InpTakeProfit; distance_pending=InpDistance; distance_stoplimit=InpDistanceSL; slippage=InpSlippage; trailing_stop=InpTrailingStop*Point(); trailing_step=InpTrailingStep*Point(); trailing_start=InpTrailingStart; stoploss_to_modify=InpStopLossModify; takeprofit_to_modify=InpTakeProfitModify; //--- Check if working with the full list is selected used_symbols_mode=InpModeUsedSymbols; if((ENUM_SYMBOLS_MODE)used_symbols_mode==SYMBOLS_MODE_ALL) { int total=SymbolsTotal(false); string ru_n="\nКоличество символов на сервере "+(string)total+".\nМаксимальное количество: "+(string)SYMBOLS_COMMON_TOTAL+" символов."; string en_n="\nNumber of symbols on server "+(string)total+".\nMaximum number: "+(string)SYMBOLS_COMMON_TOTAL+" symbols."; string caption=TextByLanguage("Внимание!","Attention!"); string ru="Выбран режим работы с полным списком.\nВ этом режиме первичная подготовка списка коллекции символов может занять длительное время."+ru_n+"\nПродолжить?\n\"Нет\" - работа с текущим символом \""+Symbol()+"\""; string en="Full list mode selected.\nIn this mode, the initial preparation of the collection symbols list may take a long time."+en_n+"\nContinue?\n\"No\" - working with the current symbol \""+Symbol()+"\""; string message=TextByLanguage(ru,en); int flags=(MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2); int mb_res=MessageBox(message,caption,flags); switch(mb_res) { case IDNO : used_symbols_mode=SYMBOLS_MODE_CURRENT; break; default: break; } } //--- Fill in the array of used symbols used_symbols=InpUsedSymbols; CreateUsedSymbolsArray((ENUM_SYMBOLS_MODE)used_symbols_mode,used_symbols,array_used_symbols); //--- Set the type of the used symbol list in the symbol collection engine.SetUsedSymbols(array_used_symbols); //--- Displaying the selected mode of working with the symbol object collection Print(engine.ModeSymbolsListDescription(),TextByLanguage(". Number of used symbols: ",". Number of symbols used: "),engine.GetSymbolsCollectionTotal()); //--- Create resource text files engine.CreateFile(FILE_TYPE_WAV,"sound_array_coin_01",TextByLanguage("Звук упавшей монетки 1","Sound of falling coin 1"),sound_array_coin_01); engine.CreateFile(FILE_TYPE_WAV,"sound_array_coin_02",TextByLanguage("Звук упавших монеток","Falling coins"),sound_array_coin_02); engine.CreateFile(FILE_TYPE_WAV,"sound_array_coin_03",TextByLanguage("Звук монеток","Coins"),sound_array_coin_03); engine.CreateFile(FILE_TYPE_WAV,"sound_array_coin_04",TextByLanguage("Звук упавшей монетки 2","Sound of falling coin 2"),sound_array_coin_04); engine.CreateFile(FILE_TYPE_WAV,"sound_array_click_01",TextByLanguage("Звук щелчка по кнопке 1","Click on button sound 1"),sound_array_click_01); engine.CreateFile(FILE_TYPE_WAV,"sound_array_click_02",TextByLanguage("Звук щелчка по кнопке 2","Click on button sound 1"),sound_array_click_02); engine.CreateFile(FILE_TYPE_WAV,"sound_array_click_03",TextByLanguage("Звук щелчка по кнопке 3","Click on button sound 1"),sound_array_click_03); engine.CreateFile(FILE_TYPE_WAV,"sound_array_cash_machine_01",TextByLanguage("Звук кассового аппарата","Sound of cash machine"),sound_array_cash_machine_01); engine.CreateFile(FILE_TYPE_BMP,"img_array_spot_green",TextByLanguage("Изображение \"Зелёный светодиод\"","Image \"Green Spot lamp\""),img_array_spot_green); engine.CreateFile(FILE_TYPE_BMP,"img_array_spot_red",TextByLanguage("Изображение \"Красный светодиод\"","Image \"Red Spot lamp\""),img_array_spot_red); //--- Pass all existing collections to the trading class engine.TradingOnInit(); //--- Set synchronous passing of orders for all used symbols engine.TradingSetAsyncMode(); //--- Set standard sounds for trading objects of all used symbols engine.SetSoundsStandart(); //--- Check playing a standard sound by macro substitution and a custom sound by description engine.PlaySoundByDescription(SND_OK); Sleep(600); engine.PlaySoundByDescription(TextByLanguage("Звук упавшей монетки 2","Falling coin 2")); //--- Set controlled values for symbols //--- Get the list of all collection symbols CArrayObj *list=engine.GetListAllUsedSymbols(); if(list!=NULL && list.Total()!=0) { //--- In a loop by the list, set the necessary values for tracked symbol properties //--- By default, the LONG_MAX value is set to all properties, which means "Do not track this property" //--- It can be enabled or disabled (by setting the value less than LONG_MAX or vice versa - set the LONG_MAX value) at any time and anywhere in the program for(int i=0;i<list.Total();i++) { CSymbol* symbol=list.At(i); if(symbol==NULL) continue; //--- Set control of the symbol price increase by 100 points symbol.SetControlBidInc(100*symbol.Point()); //--- Set control of the symbol price decrease by 100 points symbol.SetControlBidDec(100*symbol.Point()); //--- Set control of the symbol spread increase by 40 points symbol.SetControlSpreadInc(40); //--- Set control of the symbol spread decrease by 40 points symbol.SetControlSpreadDec(40); //--- Set control of the current spread by the value of 40 points symbol.SetControlSpreadLevel(40); } } //--- Set controlled values for the current account CAccount* account=engine.GetAccountCurrent(); if(account!=NULL) { //--- Set control of the profit increase to 10 account.SetControlledValueINC(ACCOUNT_PROP_PROFIT,10.0); //--- Set control of the funds increase to 15 account.SetControlledValueINC(ACCOUNT_PROP_EQUITY,15.0); //--- Set profit control level to 20 account.SetControlledValueLEVEL(ACCOUNT_PROP_PROFIT,20.0); } //--- Check and remove remaining EA graphical objects if(IsPresentObects(prefix)) ObjectsDeleteAll(0,prefix); //--- Create the button panel if(!CreateButtons(InpButtShiftX,InpButtShiftY)) return INIT_FAILED; //--- Set trailing activation button status ButtonState(butt_data[TOTAL_BUTT-1].name,trailing_on); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+
Nach dem Kompilieren und Starten des EAs wird der Standard-Audiodatei "ok.wav" abgespielt. In 1/6 Sekunde folgt der benutzerdefinierte Audiodatei mit der Beschreibung "Falling Coin 2".
Um die Arbeit der Methoden zur Überprüfung der Handelsgrenzen zu überprüfen, müssen wir diese künstlich erzeugen.
Zum Beispiel:
- Internet-Zugang unterbrechen (um den Verlust der Verbindung zum Handelsserver zu simulieren)
- Deaktivieren Sie die Handelsoption in den EA-Einstellungen (drücken Sie F7 und deaktivieren Sie "Automatischen Handel erlauben" im Tab "Allgemein" des EA-Einstellungsfensters)
- Deaktivieren Sie den Autohandel im Terminal (die Schaltfläche AutoTrading)
Klicken Sie auf den Positionseröffnungs-Button im EA-Handelspanel. Der folgende Eintrag erscheint im Journal:
2019.09.26 15:07:55.582 CTrading::OpenBuy: Request rejected before being sent to server due to: 2019.09.26 15:07:55.582 1. No permission to conduct trading operations in terminal ("AutoTrading" button disabled) 2019.09.26 15:07:55.582 2. No connection to trade server 2019.09.26 15:07:55.582 3. EA does not have permission to conduct trading operations (F7 --> Common --> "Allow Automatic Trading")
Lassen Sie uns die Einschränkungen nach und nach beseitigen.
Nachdem wir die Internetverbindung aktiviert haben, erhalten wir beim Versuch, eine Position zu eröffnen, folgende Meldung:
2019.09.26 15:10:36.766 CTrading::OpenBuy: Request rejected before being sent to server due to: 2019.09.26 15:10:36.766 1. No permission to conduct trading operations in terminal ("AutoTrading" button disabled) 2019.09.26 15:10:36.766 2. EA does not have permission to conduct trading operations (F7 --> Common --> "Allow Automatic Trading")
Aktivieren Sie den Autohandel im Terminal, indem Sie auf die Schaltfläche AutoTrading klicken. Wenn wir versuchen, eine Position zu eröffnen, erhalten wir Folgendes:
2019.09.26 15:13:03.424 CTrading::OpenBuy: Request rejected before being sent to server due to: 2019.09.26 15:13:03.424 EA does not have permission to conduct trading operations (F7 --> Common --> "Allow Automatic Trading")
Drücken Sie F7 und erlauben Sie dem EA den Handel mit seinen Einstellungen. Beim Versuch, eine Position zu eröffnen, sind wir jetzt erfolgreich:
2019.09.26 15:14:32.619 - Position is open: 2019.09.26 11:14:32.711 - 2019.09.26 15:14:32.619 EURUSD Opened 0.10 Buy #455179802 [0.10 Market-order Buy #455179802] at price 1.09441, Magic number 123
Andere Einschränkungen können im Tester oder einem Demokonto überprüft werden, indem eine Situation geschaffen wird, in der eine der Einschränkungen aktiviert wird, z.B. eine Begrenzung durch die maximale Anzahl der ausstehenden Aufträge auf dem Konto.
Was kommt als Nächstes?
Im nächsten Artikel werden wir die Überprüfung der Gültigkeit der Parameter von Handelsaufträgen implementieren.
Alle Dateien der aktuellen Version der Bibliothek sind unten zusammen mit den Dateien der Test-EAs angehängt, die Sie testen und herunterladen können.
Stellen Sie Ihre Fragen, Kommentare und Vorschläge in den Kommentaren.
Frühere Artikel dieser Serie:
Teil 1. Konzept, Datenverwaltung.
Teil 2. Erhebung (Collection) historischer Aufträge und Deals.
Teil 3. Erhebung (Collection) von Marktorders und Positionen, Organisieren der Suche
Teil 4. Handelsereignisse. Konzept
Teil 5. Klassen und Kollektionen von Handelsereignissen. Senden von Ereignissen an das Programm
Teil 6. Ereignisse auf Netting-Konten
Teil 7. Ereignis der Aktivierung einer StopLimit-Order, Vorbereiten der Funktionsweise bei Änderungen von Orders und Positionen
Teil 8. Ereignisse von Änderungen von Orders und Positionen
Teil 9. Kompatibilität mit MQL4 - Datenvorbereitung
Teil 10. Kompatibilität mit MQL4 - Ereignisse der Positionseröffnung und Aktivierung von Pending-Orders
Teil 11. Kompatibilität mit MQL4 - Ereignisse des Schließens von Positionen
Teil 12. Objektklasse "Account" und die Kollektion von Konto-Objekten
Teil 13. Das Objekt der Kontoereignisse
Teil 14. Das Symbolobjekt
Teil 15. Die Kollektion der Symbolobjekte
Teil 16. Ereignisse der Kollektionssymbole
Teil 17. Interaktivität von Bibliotheksobjekten
Teil 18. Interaktivität des Kontos und aller anderen Bibliotheksobjekt
Teil 19. Klassenbibliothek für Nachrichten
Teil 20. Erstellen und Speichern von Programmressourcen
Teil 21. Handelsklassen - Plattformübergreifendes Basis-Handelsobjekt
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/7258
- 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.