Bibliothek für ein leichtes und schnelles Entwickeln vom Programmen für den MetaTrader (Teil XV): Kollektion von Symbolobjekten
Inhalt
- Konzept der Symbolkollektion
- Abgeleitete Objekte des abstrakten Basisobjekts "Symbol".
- Die Klasse der Symbolkollektion
- Test der Symbolkollektion
- Was kommt als Nächstes?
Konzept der Symbolkollektion
Ich habe das Konzept der Konstruktion von Klassenobjekten von Kollektionen bereits im dritten Teil der Bibliotheksbeschreibung definiert. Hier werde ich mich an die angenommene Datenspeicherstruktur halten. Das bedeutet, dass wir eine Liste für die Symbolkollektion erstellen müssen. Die Liste dient zum Speichern der abgeleiteten Objekten der Klasse "symbol", die in der Klasse vorheriger Artikel angelegt wurde. Die abstrakten, abgeleiteten Symbole sollen Symboldaten verdeutlichen und die Verfügbarkeit der grundlegenden Eigenschaften der Symbolobjekte in einem Programm definieren. Solche Symbolobjekte sind durch ihre Zugehörigkeit zu Gruppen zu unterscheiden (Symbolstatus).
- Forex Symbol — alle Forex Symbole, die nicht in die folgenden Forex Symbolkategorien fallen:
- Major Forex-Symbol — die nutzerdefinierte Kategorie der am häufigsten verwendeten Forex-Symbole.
- Minor Forex-Symbol — die nutzerdefinierte Kategorie der weniger oft verwendeten Forex-Symbole.
- Exotic Forex-Symbol — die nutzerdefinierte Kategorie der selten verwendeten Forex-Symbole.
- Forex-Symbol/RUB — die nutzerdefinierte Kategorie von Forex-Symbolen mit RUB
- Metal — die nutzerdefinierte Kategorie der Metallsymbole
- Index — die nutzerdefinierte Kategorie der Indexsymbole
- Indikative — die nutzerdefinierte Kategorie der indikativen Symbole
- KryptowährungsSymbol — die nutzerdefinierte Kategorie der Kryptowährungssymbolen
- Rohstoffsymbol — die nutzerdefinierte Kategorie von Rohstoffsymbolen
- Börsensymbol — alle Symbole eines Börsenplatzes, die nicht in die folgenden Kategorien von Börsensymbolen fallen:
- Futures
- CFD
- Security (Wertpapiere)
- Bond (Anleihen)
- Option
- Nicht handelbare Finanzinstrumente
- Nutzerdefiniertes Symbol
- Allgemeine Kategorie — Symbole, die nicht in der obigen Kategorien fallen
Um eine Gruppe zu definieren, zu der ein Symbol gehört (Symbolstatus), erstellen wir nutzerdefinierte Datensätze — Arrays mit den
Namen der Symbole, in denen wir zunächst nach einer notwendigen Kategorie suchen sollen. Wenn ein Symbol nicht in einer
nutzerdefinierten Kategorie gefunden wird (sein Name ist in keinem der nutzerdefinierten Arrays mit Symbolnamen enthalten), dann
wird die Kategorie durch die Symboleigenschaft "margin calculation method" (
ENUM_SYMBOL_CALC_MODE)
definiert, mit der wir bestimmen können, ob das Symbol zu einer der oben genannten Kategorien gehört. Mit anderen Worten, wir führen
eine Suche mit zwei Prüfungen durch: Die erste wird in nutzerdefinierten Kategorien durchgeführt. Wenn eine Kategorie nicht
definiert werden konnte, wird sie mit der Margenkalkulationsmethode für ein Symbol gesucht. Zuvor hatte ich geplant, eine weitere
Methode zu verwenden — die Definition durch den Namen eines Ordners, in dem sich das Symbol im Symbolverzeichnisbaum des Servers
befindet. Diese Methode ist jedoch zu unzuverlässig, da Ordner beliebige Namen haben können und sich auf verschiedenen Servern für
das gleiche Symbol befinden können. Also entschied ich mich, es nicht zu nutzen.
Eine nutzerdefinierte Kategorie soll eine höhere Priorität haben — wenn ein Nutzer möchte, dass ein Symbol (z.B. USDUSC) in der
"großen" Kategorie platziert wird, dann kann ihn nichts daran hindern, obwohl es sich um einen Hinweis handelt.
Nun, da wir uns für die Kategorien entschieden haben, lassen Sie uns die notwendigen abgeleiteten Klassen der abstrakten Symbole für sie
erstellen. Das abstrakte Symbol selbst wurde im
vorherigen Artikel angelegt.
Um alle Symbolobjekte zu speichern,
müssen wir die CListObj-Klasse verwenden, die von der Standard-Bibliotheksklasse
CArrayObj geerbt wurde, die wir im fünften
Artikel berücksichtigt haben, wenn wir die Neuanordnung der Bibliotheksklassen diskutieren. In den bibliotheksbasierten
Programmen gibt es die Möglichkeit, eine Symbolliste auszuwählen, mit der gearbeitet werden soll:
- Nur eine — das aktuelle Symbol, an das das Programm angehängt ist.
- Ein vordefinierter Symbolsatz, der im Programm angegeben ist.
- Arbeiten mit einer Liste von Symbolen im Fenster Marktübersicht.
- Arbeiten mit einer vollständigen Liste der auf dem Server verfügbaren Symbole.
Damit decken wir die meisten der notwendigen Programmieraufgaben für den Zugriff auf Arbeitssymbole ab.
Hier sollte ich zwei Dinge erwähnen:
- Arbeiten mit einer Symbolliste aus der Marktübersicht — in diesem Modus müssen wir die Suche nach den Ereignissen des Fensters der Marktübersicht nutzen, um rechtzeitig auf deren Änderungen zu reagieren (Hinzufügen/Entfernen eines Symbols aus der Liste und Sortieren mit der Maus),
- Bei der Arbeit mit der vollständigen Liste der auf dem Server verfügbaren Symbole müssen wir eine normale Handhabung einer möglichen großen Anzahl verfügbarer Symbole vereinbaren, da die vollständige Liste der Symbole auf dem Server beim ersten Start angezeigt werden kann. Außerdem werden Symbolobjekte erzeugt, für die alle Eigenschaften empfangen werden sollen. Der Prozess dauert einige Zeit. In meinem Fall dauerte es etwa zwei Minuten, bis die Kollektion aller Symbole auf dem Server auf meinem mittelmäßigen Laptop erstellt war.
Bei der Wahl dieser Arbeitsmethode ist es zunächst notwendig, die Nutzer zumindest vor der Zeit zu warnen, die sie mit der Erfassung
der ersten Informationen verbringen.
Wir werden das und das Verfolgen der Symbolereignisse und der Ereignisse im Fenster der Marktübersicht in nachfolgenden
Artikeln implementieren. Lassen Sie uns zunächst eine Kollektionsliste erstellen.
Für den Anfang erstellen wir eine weitere Include-Datei, in der wir alle für die Bibliothek benötigten Daten speichern — Arrays von
nutzerdefinierten Symbolgruppen, Dateien, Bildern und anderen später benötigten Datensätzen für die Bibliothek.
Im Bibliotheksordner \MQL5\Include\DoEasy\ erstellen wir die neue Include-Datei Datas.mqh und
fügen einige Arrays hinzu, die ich bereits im Voraus vorbereitet habe, während ich mehrere Konten durchsuche und Daten über
Symbolgruppen sammle, die auf verschiedenen Servern für die Fensterbaumstruktur der Marktübersicht gesetzt sind:
//+------------------------------------------------------------------+ //| Datas.mqh | //| Copyright 2018, MetaQuotes Software Corp. | //| https://mql5.com/de/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://mql5.com/de/users/artmedia70" //+------------------------------------------------------------------+ //| Data sets | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Major Forex symbols | //+------------------------------------------------------------------+ string DataSymbolsFXMajors[]= { "AUDCAD","AUDCHF","AUDJPY","AUDNZD","AUDUSD","CADCHF","CADJPY","CHFJPY","EURAUD","EURCAD","EURCHF","EURGBP","EURJPY","EURNZD", "EURUSD","GBPAUD","GBPCAD","GBPCHF","GBPJPY","GBPNZD","GBPUSD","NZDCAD","NZDCHF","NZDJPY","NZDUSD","USDCAD","USDCHF","USDJPY" }; //+------------------------------------------------------------------+ //| Minor Forex symbols | //+------------------------------------------------------------------+ string DataSymbolsFXMinors[]= { "EURCZK","EURDKK","EURHKD","EURNOK","EURPLN","EURSEK","EURSGD","EURTRY","EURZAR","GBPSEK","GBPSGD" ,"NZDSGD","USDCZK","USDDKK","USDHKD","USDNOK","USDPLN","USDSEK","USDSGD","USDTRY","USDZAR" }; //+------------------------------------------------------------------+ //| Exotic Forex symbols | //+------------------------------------------------------------------+ string DataSymbolsFXExotics[]= { "EURMXN","USDCNH","USDMXN","EURTRY","USDTRY" }; //+------------------------------------------------------------------+ //| Forex RUB symbols | //+------------------------------------------------------------------+ string DataSymbolsFXRub[]= { "EURRUB","USDRUB" }; //+------------------------------------------------------------------+ //| Indicative Forex symbols | //+------------------------------------------------------------------+ string DataSymbolsFXIndicatives[]= { "EUREUC","USDEUC","USDUSC" }; //+------------------------------------------------------------------+ //| Metal symbols | //+------------------------------------------------------------------+ string DataSymbolsMetalls[]= { "XAGUSD","XAUUSD" }; //+------------------------------------------------------------------+ //| Commodity symbols | //+------------------------------------------------------------------+ string DataSymbolsCommodities[]= { "BRN","WTI","NG" }; //+------------------------------------------------------------------+ //| Indices | //+------------------------------------------------------------------+ string DataSymbolsIndexes[]= { "CAC40","HSI50","ASX200","STOXX50","NQ100","FTSE100","DAX30","IBEX35","SPX500","NIKK225" "Volatility 10 Index","Volatility 25 Index","Volatility 50 Index","Volatility 75 Index","Volatility 100 Index", "HF Volatility 10 Index","HF Volatility 50 Index","Crash 1000 Index","Boom 1000 Index","Step Index" }; //+------------------------------------------------------------------+ //| Cryptocurrency Symbols | //+------------------------------------------------------------------+ string DataSymbolsCrypto[]= { "BCHUSD","BTCEUR","BTCUSD","DSHUSD","EOSUSD","ETHEUR","ETHUSD","LTCUSD","XRPUSD" }; //+------------------------------------------------------------------+ //| Options | //+------------------------------------------------------------------+ string DataSymbolsOptions[]= { "BO Volatility 10 Index","BO Volatility 25 Index","BO Volatility 50 Index","BO Volatility 75 Index","BO Volatility 100 Index" }; //+------------------------------------------------------------------+
Wie wir aus der Auflistung ersehen können, handelt es sich hierbei nur um eine Liste mit Symbolnamen, die zu den erforderlichen Arrays hinzugefügt wurden und eine Gruppe von Symbolen definieren, die sich in jedem der Arrays befinden. Wenn gewünscht und notwendig, können Sie den Inhalt dieser Arrays mit Symbolnamen verwenden, indem Sie einige Namen an ein anderes Array senden, einige Namen hinzufügen/entfernen, etc.
Eine "genauere" Prüfung des Verhaltens des abstrakten Symbolobjekts liefert das Verständnis, dass die Verwendung der Konstanten
SYMBOL_MARGIN_LONG, SYMBOL_MARGIN_SHORT, SYMBOL_MARGIN_STOP, SYMBOL_MARGIN_LIMIT und SYMBOL_MARGIN_STOPLIMIT die
Symboleigenschaften nicht ergeben hat. Daher musste ich den Empfang der Eigenschaften mit der Funktion
SymbolInfoMarginRate() implementieren.
Da ein Auftragstyp an die Funktion gesendet wird, musste ich eine
nutzerdefinierte Konstante in den realen Eigenschaften des Symbolobjekts in der Datei
Defines.mqh für jeden der Auftragstypen
erzeugen:
//+------------------------------------------------------------------+ //| Symbol real properties | //+------------------------------------------------------------------+ enum ENUM_SYMBOL_PROP_DOUBLE { SYMBOL_PROP_BID = SYMBOL_PROP_INTEGER_TOTAL, // Bid - the best price at which a symbol can be sold SYMBOL_PROP_BIDHIGH, // The highest Bid price of the day SYMBOL_PROP_BIDLOW, // The lowest Bid price of the day SYMBOL_PROP_ASK, // Ask - best price, at which an instrument can be bought SYMBOL_PROP_ASKHIGH, // The highest Ask price of the day SYMBOL_PROP_ASKLOW, // The lowest Ask price of the day SYMBOL_PROP_LAST, // The price at which the last deal was executed SYMBOL_PROP_LASTHIGH, // The highest Last price of the day SYMBOL_PROP_LASTLOW, // The lowest Last price of the day SYMBOL_PROP_VOLUME_REAL, // Volume of the day SYMBOL_PROP_VOLUMEHIGH_REAL, // Maximum Volume within a day SYMBOL_PROP_VOLUMELOW_REAL, // Minimum Volume within a day SYMBOL_PROP_OPTION_STRIKE, // Option execution price SYMBOL_PROP_POINT, // One point value SYMBOL_PROP_TRADE_TICK_VALUE, // SYMBOL_TRADE_TICK_VALUE_PROFIT value SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT, // Calculated tick value for a winning position SYMBOL_PROP_TRADE_TICK_VALUE_LOSS, // Calculated tick value for a losing position SYMBOL_PROP_TRADE_TICK_SIZE, // Minimum price change SYMBOL_PROP_TRADE_CONTRACT_SIZE, // Trade contract size SYMBOL_PROP_TRADE_ACCRUED_INTEREST, // Accrued interest SYMBOL_PROP_TRADE_FACE_VALUE, // Face value – initial bond value set by an issuer SYMBOL_PROP_TRADE_LIQUIDITY_RATE, // Liquidity rate – the share of an asset that can be used for a margin SYMBOL_PROP_VOLUME_MIN, // Minimum volume for a deal SYMBOL_PROP_VOLUME_MAX, // Maximum volume for a deal SYMBOL_PROP_VOLUME_STEP, // Minimum volume change step for deal execution SYMBOL_PROP_VOLUME_LIMIT, // The maximum allowed total volume of an open position and pending orders in one direction (either buy or sell) SYMBOL_PROP_SWAP_LONG, // Long swap value SYMBOL_PROP_SWAP_SHORT, // Short swap value SYMBOL_PROP_MARGIN_INITIAL, // Initial margin SYMBOL_PROP_MARGIN_MAINTENANCE, // Maintenance margin for an instrument SYMBOL_PROP_MARGIN_LONG_INITIAL, // Initial margin requirement applicable to long positions SYMBOL_PROP_MARGIN_BUY_STOP_INITIAL, // Initial margin requirement applicable to BuyStop orders SYMBOL_PROP_MARGIN_BUY_LIMIT_INITIAL, // Initial margin requirement applicable to BuyLimit orders SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_INITIAL, // Initial margin requirement applicable to BuyStopLimit orders SYMBOL_PROP_MARGIN_LONG_MAINTENANCE, // Maintenance margin requirement applicable to long positions SYMBOL_PROP_MARGIN_BUY_STOP_MAINTENANCE, // Maintenance margin requirement applicable to BuyStop orders SYMBOL_PROP_MARGIN_BUY_LIMIT_MAINTENANCE, // Maintenance margin requirement applicable to BuyLimit orders SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_MAINTENANCE, // Maintenance margin requirement applicable to BuyStopLimit orders SYMBOL_PROP_MARGIN_SHORT_INITIAL, // Initial margin requirement applicable to short positions SYMBOL_PROP_MARGIN_SELL_STOP_INITIAL, // Initial margin requirement applicable to SellStop orders SYMBOL_PROP_MARGIN_SELL_LIMIT_INITIAL, // Initial margin requirement applicable to SellLimit orders SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_INITIAL, // Initial margin requirement applicable to SellStopLimit orders SYMBOL_PROP_MARGIN_SHORT_MAINTENANCE, // Maintenance margin requirement applicable to short positions SYMBOL_PROP_MARGIN_SELL_STOP_MAINTENANCE, // Maintenance margin requirement applicable to SellStop orders SYMBOL_PROP_MARGIN_SELL_LIMIT_MAINTENANCE, // Maintenance margin requirement applicable to SellLimit orders SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_MAINTENANCE, // Maintenance margin requirement applicable to SellStopLimit orders SYMBOL_PROP_SESSION_VOLUME, // The total volume of deals in the current session SYMBOL_PROP_SESSION_TURNOVER, // The total turnover in the current session SYMBOL_PROP_SESSION_INTEREST, // The total volume of open positions SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME, // The total volume of Buy orders at the moment SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME, // The total volume of Sell orders at the moment SYMBOL_PROP_SESSION_OPEN, // Open price of the session SYMBOL_PROP_SESSION_CLOSE, // Close price of the session SYMBOL_PROP_SESSION_AW, // The average weighted price of the session SYMBOL_PROP_SESSION_PRICE_SETTLEMENT, // The settlement price of the current session SYMBOL_PROP_SESSION_PRICE_LIMIT_MIN, // Minimum allowable price value for the session SYMBOL_PROP_SESSION_PRICE_LIMIT_MAX, // Maximum allowable price value for the session SYMBOL_PROP_MARGIN_HEDGED // Size of a contract or margin for one lot of hedged positions (oppositely directed positions at one symbol). }; #define SYMBOL_PROP_DOUBLE_TOTAL (58) // Total number of real properties #define SYMBOL_PROP_DOUBLE_SKIP (0) // Number of real symbol properties not used in sorting //+------------------------------------------------------------------+
Dementsprechend ist die Gesamtzahl der Eigenschaften auf 58 (statt der bisherigen 47) gestiegen.
Ich musste auch die entsprechenden Konstanten zur Aufzählung der möglichen Sortierkriterien für Symbole hinzufügen:
//+------------------------------------------------------------------+ //| Possible symbol sorting criteria | //+------------------------------------------------------------------+ #define FIRST_SYM_DBL_PROP (SYMBOL_PROP_INTEGER_TOTAL-SYMBOL_PROP_INTEGER_SKIP) #define FIRST_SYM_STR_PROP (SYMBOL_PROP_INTEGER_TOTAL-SYMBOL_PROP_INTEGER_SKIP+SYMBOL_PROP_DOUBLE_TOTAL-SYMBOL_PROP_DOUBLE_SKIP) enum ENUM_SORT_SYMBOLS_MODE { //--- Sortieren nach den Integer-Eigenschaften SORT_BY_SYMBOL_STATUS = 0, // Sort by symbol status SORT_BY_SYMBOL_CUSTOM, // Sort by custom symbol property SORT_BY_SYMBOL_CHART_MODE, // Sort by price type for constructing bars – Bid or Last (from the ENUM_SYMBOL_CHART_MODE enumeration) SORT_BY_SYMBOL_EXIST, // Sort by the flag that a symbol with such a name exists SORT_BY_SYMBOL_SELECT, // Sort by the flag indicating that a symbol is selected in Market Watch SORT_BY_SYMBOL_VISIBLE, // Sort by the flag indicating that a selected symbol is displayed in Market Watch SORT_BY_SYMBOL_SESSION_DEALS, // Sort by the number of deals in the current session SORT_BY_SYMBOL_SESSION_BUY_ORDERS, // Sort by the total number of current buy orders SORT_BY_SYMBOL_SESSION_SELL_ORDERS, // Sort by the total number of current sell orders SORT_BY_SYMBOL_VOLUME, // Sort by last deal volume SORT_BY_SYMBOL_VOLUMEHIGH, // Sort by maximum volume for a day SORT_BY_SYMBOL_VOLUMELOW, // Sort by minimum volume for a day SORT_BY_SYMBOL_TIME, // Sort by the last quote time SORT_BY_SYMBOL_DIGITS, // Sort by a number of decimal places SORT_BY_SYMBOL_DIGITS_LOT, // Sort by a number of decimal places in a lot SORT_BY_SYMBOL_SPREAD, // Sort by spread in points SORT_BY_SYMBOL_SPREAD_FLOAT, // Sort by floating spread SORT_BY_SYMBOL_TICKS_BOOKDEPTH, // Sort by a maximum number of requests displayed in the market depth SORT_BY_SYMBOL_TRADE_CALC_MODE, // Sort by contract price calculation method (from the ENUM_SYMBOL_CALC_MODE enumeration) SORT_BY_SYMBOL_TRADE_MODE, // Sort by order execution type (from the ENUM_SYMBOL_TRADE_MODE enumeration) SORT_BY_SYMBOL_START_TIME, // Sort by an instrument trading start date (usually used for futures) SORT_BY_SYMBOL_EXPIRATION_TIME, // Sort by an instrument trading end date (usually used for futures) SORT_BY_SYMBOL_TRADE_STOPS_LEVEL, // Sort by the minimum indent from the current close price (in points) for setting Stop orders SORT_BY_SYMBOL_TRADE_FREEZE_LEVEL, // Sort by trade operation freeze distance (in points) SORT_BY_SYMBOL_TRADE_EXEMODE, // Sort by trade execution mode (from the ENUM_SYMBOL_TRADE_EXECUTION enumeration) SORT_BY_SYMBOL_SWAP_MODE, // Sort by swap calculation model (from the ENUM_SYMBOL_SWAP_MODE enumeration) SORT_BY_SYMBOL_SWAP_ROLLOVER3DAYS, // Sort by week day for accruing a triple swap (from the ENUM_DAY_OF_WEEK enumeration) SORT_BY_SYMBOL_MARGIN_HEDGED_USE_LEG, // Sort by the calculation mode of a hedged margin using the larger leg (Buy or Sell) SORT_BY_SYMBOL_EXPIRATION_MODE, // Sort by flags of allowed order expiration modes SORT_BY_SYMBOL_FILLING_MODE, // Sort by flags of allowed order filling modes SORT_BY_SYMBOL_ORDER_MODE, // Sort by flags of allowed order types SORT_BY_SYMBOL_ORDER_GTC_MODE, // Sort by StopLoss and TakeProfit orders lifetime SORT_BY_SYMBOL_OPTION_MODE, // Sort by option type (from the ENUM_SYMBOL_OPTION_MODE enumeration) SORT_BY_SYMBOL_OPTION_RIGHT, // Sort by option right (Call/Put) (from the ENUM_SYMBOL_OPTION_RIGHT enumeration) //--- Sortieren nach den Double-Eigenschaften SORT_BY_SYMBOL_BID = FIRST_SYM_DBL_PROP, // Sort by Bid SORT_BY_SYMBOL_BIDHIGH, // Sort by maximum Bid for a day SORT_BY_SYMBOL_BIDLOW, // Sort by minimum Bid for a day SORT_BY_SYMBOL_ASK, // Sort by Ask SORT_BY_SYMBOL_ASKHIGH, // Sort by maximum Ask for a day SORT_BY_SYMBOL_ASKLOW, // Sort by minimum Ask for a day SORT_BY_SYMBOL_LAST, // Sort by the last deal price SORT_BY_SYMBOL_LASTHIGH, // Sort by maximum Last for a day SORT_BY_SYMBOL_LASTLOW, // Sort by minimum Last for a day SORT_BY_SYMBOL_VOLUME_REAL, // Sort by Volume for a day SORT_BY_SYMBOL_VOLUMEHIGH_REAL, // Sort by maximum Volume for a day SORT_BY_SYMBOL_VOLUMELOW_REAL, // Sort by minimum Volume for a day SORT_BY_SYMBOL_OPTION_STRIKE, // Sort by an option execution price SORT_BY_SYMBOL_POINT, // Sort by a single point value SORT_BY_SYMBOL_TRADE_TICK_VALUE, // Sort by SYMBOL_TRADE_TICK_VALUE_PROFIT value SORT_BY_SYMBOL_TRADE_TICK_VALUE_PROFIT, // Sort by a calculated tick price for a profitable position SORT_BY_SYMBOL_TRADE_TICK_VALUE_LOSS, // Sort by a calculated tick price for a loss-making position SORT_BY_SYMBOL_TRADE_TICK_SIZE, // Sort by a minimum price change SORT_BY_SYMBOL_TRADE_CONTRACT_SIZE, // Sort by a trading contract size SORT_BY_SYMBOL_TRADE_ACCRUED_INTEREST, // Sort by accrued interest SORT_BY_SYMBOL_TRADE_FACE_VALUE, // Sort by face value SORT_BY_SYMBOL_TRADE_LIQUIDITY_RATE, // Sort by liquidity rate SORT_BY_SYMBOL_VOLUME_MIN, // Sort by a minimum volume for performing a deal SORT_BY_SYMBOL_VOLUME_MAX, // Sort by a maximum volume for performing a deal SORT_BY_SYMBOL_VOLUME_STEP, // Sort by a minimum volume change step for deal execution SORT_BY_SYMBOL_VOLUME_LIMIT, // Sort by a maximum allowed aggregate volume of an open position and pending orders in one direction SORT_BY_SYMBOL_SWAP_LONG, // Sort by a long swap value SORT_BY_SYMBOL_SWAP_SHORT, // Sort by a short swap value SORT_BY_SYMBOL_MARGIN_INITIAL, // Sort by an initial margin SORT_BY_SYMBOL_MARGIN_MAINTENANCE, // Sort by a maintenance margin for an instrument SORT_BY_SYMBOL_MARGIN_LONG_INITIAL, // Sort by initial margin requirement applicable to Long orders SORT_BY_SYMBOL_MARGIN_BUY_STOP_INITIAL, // Sort by initial margin requirement applicable to BuyStop orders SORT_BY_SYMBOL_MARGIN_BUY_LIMIT_INITIAL, // Sort by initial margin requirement applicable to BuyLimit orders SORT_BY_SYMBOL_MARGIN_BUY_STOPLIMIT_INITIAL, // Sort by initial margin requirement applicable to BuyStopLimit orders SORT_BY_SYMBOL_MARGIN_LONG_MAINTENANCE, // Sort by maintenance margin requirement applicable to Long orders SORT_BY_SYMBOL_MARGIN_BUY_STOP_MAINTENANCE, // Sort by maintenance margin requirement applicable to BuyStop orders SORT_BY_SYMBOL_MARGIN_BUY_LIMIT_MAINTENANCE, // Sort by maintenance margin requirement applicable to BuyLimit orders SORT_BY_SYMBOL_MARGIN_BUY_STOPLIMIT_MAINTENANCE, // Sort by maintenance margin requirement applicable to BuyStopLimit orders SORT_BY_SYMBOL_MARGIN_SHORT_INITIAL, // Sort by initial margin requirement applicable to Short orders SORT_BY_SYMBOL_MARGIN_SELL_STOP_INITIAL, // Sort by initial margin requirement applicable to SellStop orders SORT_BY_SYMBOL_MARGIN_SELL_LIMIT_INITIAL, // Sort by initial margin requirement applicable to SellLimit orders SORT_BY_SYMBOL_MARGIN_SELL_STOPLIMIT_INITIAL, // Sort by initial margin requirement applicable to SellStopLimit orders SORT_BY_SYMBOL_MARGIN_SHORT_MAINTENANCE, // Sort by maintenance margin requirement applicable to Short orders SORT_BY_SYMBOL_MARGIN_SELL_STOP_MAINTENANCE, // Sort by maintenance margin requirement applicable to SellStop orders SORT_BY_SYMBOL_MARGIN_SELL_LIMIT_MAINTENANCE, // Sort by maintenance margin requirement applicable to SellLimit orders SORT_BY_SYMBOL_MARGIN_SELL_STOPLIMIT_MAINTENANCE, // Sort by maintenance margin requirement applicable to SellStopLimit orders SORT_BY_SYMBOL_SESSION_VOLUME, // Sort by summary volume of the current session deals SORT_BY_SYMBOL_SESSION_TURNOVER, // Sort by the summary turnover of the current session SORT_BY_SYMBOL_SESSION_INTEREST, // Sort by the summary open interest SORT_BY_SYMBOL_SESSION_BUY_ORDERS_VOLUME, // Sort by the current volume of Buy orders SORT_BY_SYMBOL_SESSION_SELL_ORDERS_VOLUME, // Sort by the current volume of Sell orders SORT_BY_SYMBOL_SESSION_OPEN, // Sort by a session Open price SORT_BY_SYMBOL_SESSION_CLOSE, // Sort by a session Close price SORT_BY_SYMBOL_SESSION_AW, // Sort by an average weighted price of the current session SORT_BY_SYMBOL_SESSION_PRICE_SETTLEMENT, // Sort by a settlement price of the current session SORT_BY_SYMBOL_SESSION_PRICE_LIMIT_MIN, // Sort by a minimum price of the current session SORT_BY_SYMBOL_SESSION_PRICE_LIMIT_MAX, // Sort by a maximum price of the current session SORT_BY_SYMBOL_MARGIN_HEDGED, // Sort by a contract size or a margin value per one lot of hedged positions //--- 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 }; //+------------------------------------------------------------------+
Da wir die Datei Defines.mqh bearbeiten, fügen wir alles hinzu, was wir dazu benötigen, und erklären, warum wir das auf dem Weg dorthin tun.
Wir benötigen einen Timer, um die Daten für alle Symbole innerhalb der Kollektion zu aktualisieren. Beachten Sie, dass wir die Kursdaten
aller Symbole zusammen mit Daten, die sich ändern können, aktualisieren müssen, um sie in der Klasse der Symbolereignisse zu verfolgen
(mehr dazu im nächsten Artikel). Im Timer müssen wir auch die Symbolliste im Fenster Marktübersicht überprüfen, um auf die Änderungen zu
reagieren und die Kollektionsliste rechtzeitig zu aktualisieren.
Wir müssen die Kursdaten häufiger aktualisieren als die restlichen Symboldaten und deren Liste im Fenster Marktübersicht. Das
bedeutet, dass wir für die Symbolerfassung zwei Timer benötigen — den Timer für die Kursdaten und den für andere Aktionen mit Symbollisten.
Fügen wir die notwendigen Makro-Substitutionen für zwei Timer der Symbolsammlung hinzu:
//--- Symbol collection timer 1 parameters #define COLLECTION_SYM_PAUSE1 (100) // Pause of the symbol collection timer 1 in milliseconds (for scanning market watch symbols) #define COLLECTION_SYM_COUNTER_STEP1 (16) // Increment of the symbol timer 1 counter #define COLLECTION_SYM_COUNTER_ID1 (3) // Symbol timer 1 counter ID //--- Symbol collection timer 2 parameters #define COLLECTION_SYM_PAUSE2 (300) // Pause of the symbol collection timer 2 in milliseconds (for events of the market watch symbol list) #define COLLECTION_SYM_COUNTER_STEP2 (16) // Increment of the symbol timer 2 counter #define COLLECTION_SYM_COUNTER_ID2 (4) // Symbol timer 2 counter ID
Der Unterschied zwischen diesen Daten besteht nur in der Pause für jeden Timer und deren IDs — für den ersten Timer beträgt die Pause 100 Millisekunden, während sie für den zweiten 300 Millisekunden beträgt.
Wir haben für jede Kollektion eine eigene ID. Die Symbolkollektion bildet dabei keine Ausnahme.
Lassen Sie uns eine
nutzerdefinierte
ID für ihre Liste festlegen:
//--- Collection list IDs #define COLLECTION_HISTORY_ID (0x7778+1) // Historical collection list ID #define COLLECTION_MARKET_ID (0x7778+2) // Market collection list ID #define COLLECTION_EVENTS_ID (0x7778+3) // Event collection list ID #define COLLECTION_ACCOUNT_ID (0x7778+4) // Account collection list ID #define COLLECTION_SYMBOLS_ID (0x7778+5) // Symbol collection list ID
Im vorherigen Artikel haben wir, um eine Hintergrundfarbe zu definieren, die verwendet wird, um ein Symbol im Fenster Marktübersicht hervorzuheben und seine Zeichenkettenbeschreibung anzuzeigen, die Farbe mit clrWhite verglichen — wenn der Eigenschaftswert einen 'long' Wert der Farbe überschreitet, wird die Hintergrundfarbe nicht als eingestellt betrachtet:
property==SYMBOL_PROP_BACKGROUND_COLOR ? TextByLanguage("Цвет фона символа в Market Watch","Background color of symbol in Market Watch")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : #ifdef __MQL5__ (this.GetProperty(property)>clrWhite ? TextByLanguage(": (Отсутствует)",": (Not set)") : ": "+::ColorToString((color)this.GetProperty(property),true)) #else TextByLanguage(": Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) :
Nach Ansicht der Entwickler ist dies jedoch falsch — ein 'long' Wert eines Symbolhintergrunds im Fenster Marktübersicht kann einen 'long'
Wert der Farbe Weiß überschreiten. Das bedeutet, dass eine solche Prüfung in einigen Fällen falsche Ergebnisse liefert.
Um das Fehlen der Hintergrundfarbe richtig zu erkennen, müssen wir den Eigenschaftswert mit den Werten CLR_DEFAULT und CLR_NONE
vergleichen.
Lassen Sie uns die Makroersetzung verwenden, um die "Standard"-Farbe einzustellen (die "Keine-Farbe" CLR_NONE
ist bereits in MQL5 und MQL4 vorhanden):
//--- Symbol parameters #define CLR_DEFAULT (0xFF000000) // Default color //+------------------------------------------------------------------+
As a result, the section of the Defines file macro substitutions now looks as follows:
//+------------------------------------------------------------------+ //| Macro substitutions | //+------------------------------------------------------------------+ //--- 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 //--- Parameters of the orders and deals collection timer #define COLLECTION_ORD_PAUSE (250) // Orders and deals collection timer pause in milliseconds #define COLLECTION_ORD_COUNTER_STEP (16) // Increment of the orders and deals collection timer counter #define COLLECTION_ORD_COUNTER_ID (1) // Orders and deals collection timer counter ID //--- Parameters of the account collection timer #define COLLECTION_ACC_PAUSE (1000) // Account collection timer pause in milliseconds #define COLLECTION_ACC_COUNTER_STEP (16) // Account timer counter increment #define COLLECTION_ACC_COUNTER_ID (2) // Account timer counter ID //--- Symbol collection timer 1 parameters #define COLLECTION_SYM_PAUSE1 (100) // Pause of the symbol collection timer 1 in milliseconds (for scanning market watch symbols) #define COLLECTION_SYM_COUNTER_STEP1 (16) // Increment of the symbol timer 1 counter #define COLLECTION_SYM_COUNTER_ID1 (3) // Symbol timer 1 counter ID //--- Symbol collection timer 2 parameters #define COLLECTION_SYM_PAUSE2 (300) // Pause of the symbol collection timer 2 in milliseconds (for events of the market watch symbol list) #define COLLECTION_SYM_COUNTER_STEP2 (16) // Increment of the symbol timer 2 counter #define COLLECTION_SYM_COUNTER_ID2 (4) // Symbol timer 2 counter ID //--- Collection list IDs #define COLLECTION_HISTORY_ID (0x7778+1) // Historical collection list ID #define COLLECTION_MARKET_ID (0x7778+2) // Market collection list ID #define COLLECTION_EVENTS_ID (0x7778+3) // Event collection list ID #define COLLECTION_ACCOUNT_ID (0x7778+4) // Account collection list ID #define COLLECTION_SYMBOLS_ID (0x7778+5) // Symbol collection list ID //--- Data parameters for file operations #define DIRECTORY ("DoEasy\\") // Library directory for storing object folders //--- Symbol parameters #define CLR_DEFAULT (0xFF000000) // Default color //+------------------------------------------------------------------+
Ich habe bereits die Modi der Arbeit mit der Symbolkollektion erwähnt: Arbeiten mit dem aktuellen Symbol, Arbeiten mit einer Liste von im
Programm vordefinierten Symbolen, Arbeiten mit dem Fenster Marktübersicht und Arbeiten mit der vollständigen Liste der auf dem Server
verfügbaren Symbole.
Lassen Sie alle diese Modi in der Enumeration eintragen:
//+------------------------------------------------------------------+ //| Data for working with symbols | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Modes of working with symbols | //+------------------------------------------------------------------+ enum ENUM_SYMBOLS_MODE { SYMBOLS_MODE_CURRENT, // Work with the current symbol only SYMBOLS_MODE_DEFINES, // Work with the specified symbol list SYMBOLS_MODE_MARKET_WATCH, // Work with the Market Watch window symbols SYMBOLS_MODE_ALL // Work with the full symbol list }; //+------------------------------------------------------------------+
Im vorherigen Artikel haben wir die Symbolkategorien identifiziert, nach denen Symbole sortiert werden sollen. Ganz am Anfang dieses Artikels haben wir eine leicht erweiterte Liste von Symbolkategorien untersucht, die wir verwenden werden.
Fügen wir die Aufzählung der Symbolkategorien (Zustände) hinzu:
//+------------------------------------------------------------------+ //| Abstract symbol type (status) | //+------------------------------------------------------------------+ enum ENUM_SYMBOL_STATUS { SYMBOL_STATUS_FX, // Forex symbol SYMBOL_STATUS_FX_MAJOR, // Major Forex symbol SYMBOL_STATUS_FX_MINOR, // Minor Forex symbol SYMBOL_STATUS_FX_EXOTIC, // Exotic Forex symbol SYMBOL_STATUS_FX_RUB, // Forex symbol/RUB SYMBOL_STATUS_METAL, // Metal SYMBOL_STATUS_INDEX, // Index SYMBOL_STATUS_INDICATIVE, // Indicative SYMBOL_STATUS_CRYPTO, // Cryptocurrency symbol SYMBOL_STATUS_COMMODITY, // Commodity symbol SYMBOL_STATUS_EXCHANGE, // Exchange symbol SYMBOL_STATUS_FUTURES, // Futures SYMBOL_STATUS_CFD, // CFD SYMBOL_STATUS_STOCKS, // Security SYMBOL_STATUS_BONDS, // Bond SYMBOL_STATUS_OPTION, // Option SYMBOL_STATUS_COLLATERAL, // Non-tradable asset SYMBOL_STATUS_CUSTOM, // Custom symbol SYMBOL_STATUS_COMMON // General category }; //+------------------------------------------------------------------+
Wir haben die Daten für die Symbolkollektion vorbereitet und alle Änderungen in der Datei Defines.mqh vorgenommen.
Die Änderungen betrafen auch die Klasse CSymbol, die wir im vorherigen
Artikel.
angelegt haben. Da wir nun mit der Funktion SymbolInfoMarginRate()
Daten über Margenverhältnisse
für verschiedene Auftragstypen erhalten, während die über den Link an die Funktion übergebenen Variablen dazu verwendet werden, von ihr
angeforderte Werte zurückzugeben, müssen wir diese Variablen nun erstellen.
Unter der Annahme, dass wir acht Aufträge und zwei Verhältnistypen für jeden von ihnen haben (Anfangs- und Wartungsspanne), sollte es 16 Variablen für den Empfang dieser Werte geben. Daher wäre es sinnvoller, die Struktur aus zwei verschachtelten Strukturen zu erstellen: in der ersten Struktur sind zwei 'double' Variablen zum Speichern der Verhältnisse von Anfangs- und Wartungsmargen definiert, während die zweite die zuerst deklarierten Strukturen zum Speichern von Daten nach Auftragsarten enthält, für die die Verhältnisse erhalten werden sollen.
Deklarieren wir diese Strukturen und die Klassenvariable mit dem zweiten Strukturtyp im privaten Abschnitt der Klasse CSymbol der Symbolklassendatei Symbol.mqh:
//+------------------------------------------------------------------+ //| Abstract symbol class | //+------------------------------------------------------------------+ class CSymbol : public CObject { private: struct SMarginRate { double Initial; // initial margin rate double Maintenance; // maintenance margin rate }; struct SMarginRateMode { SMarginRate Long; // MarginRate of long positions SMarginRate Short; // MarginRate of short positions SMarginRate BuyStop; // MarginRate of BuyStop orders SMarginRate BuyLimit; // MarginRate of BuyLimit orders SMarginRate BuyStopLimit; // MarginRate of BuyStopLimit orders SMarginRate SellStop; // MarginRate of SellStop orders SMarginRate SellLimit; // MarginRate of SellLimit orders SMarginRate SellStopLimit; // MarginRate of SellStopLimit orders }; SMarginRateMode m_margin_rate; // Margin ratio structure
Lassen Sie uns die den 'private' Abschnitt der Klasse mit der Methode
ergänzen, die alle Symboleigenschaften für jedes Margenverhältnis ausfüllt, die
Methode initialisiert die Variablen von Strukturen, die alle Margenverhältnisse speichern. Fügen wir auch zwei Hilfsmethoden
hinzu
für den Empfang des aktuellen Wochentages und die
Anzahl der Dezimalstellen in einem 'double' Wert:
SMarginRateMode m_margin_rate; // Margin ratio structure MqlTick m_tick; // Symbol tick structure MqlBookInfo m_book_info_array[]; // Array of the market depth data structures string m_symbol_name; // Symbol name long m_long_prop[SYMBOL_PROP_INTEGER_TOTAL]; // Integer properties double m_double_prop[SYMBOL_PROP_DOUBLE_TOTAL]; // Real properties string m_string_prop[SYMBOL_PROP_STRING_TOTAL]; // String properties int m_digits_currency; // Number of decimal places in an account currency int m_global_error; // Global error code //--- Return the index of the array the symbol's (1) double and (2) string properties are located at int IndexProp(ENUM_SYMBOL_PROP_DOUBLE property) const { return(int)property-SYMBOL_PROP_INTEGER_TOTAL; } int IndexProp(ENUM_SYMBOL_PROP_STRING property) const { return(int)property-SYMBOL_PROP_INTEGER_TOTAL-SYMBOL_PROP_DOUBLE_TOTAL; } //--- (1) Fill in all the "margin ratio" symbol properties, (2) initialize the ratios bool MarginRates(void); void InitMarginRates(void); //--- Reset all symbol object data void Reset(void); //--- Return the current day of the week ENUM_DAY_OF_WEEK CurrentDayOfWeek(void) const; //--- Returns the number of decimal places in the 'double' value int GetDigits(const double value) const; public:
Deklarieren Sie im gleichen 'private' Abschnitt der Klasse die Methoden, die Daten über Margenverhältnisse für jeden
Auftragstyp zurückgeben:.
//--- 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
Manchmal muss ein Programm wissen, ob ein Symbol auf dem Server existiert. Diese kann durch einen Symbolnamen geschehen. Wir haben bereits die Methode Exist(), die solche Daten nach Klassensymbolen zurückgibt. Überladen Sie die Methode so, dass sie Daten über den übergebenen Symbolnamen zurückgeben kann. Um dies zu tun, deklarieren Sie noch einen weiteren Methodenaufruf in dem privaten Bereich der Klasse:
//--- Search for a symbol and return the flag indicating its presence on the server bool Exist(void) const; bool Exist(const string name) const;
und deklarieren Sie die überladene Methode im geschützten Bereich der Klasse. Die Methode gibt den Symbolwert mit ihrem Namen zurück, abhängig vom Programmtyp MQL5 oder MQL4:
protected: //--- 'Protected' Konstruktor CSymbol(ENUM_SYMBOL_STATUS symbol_status,const string name); //--- Get and return integer properties of a selected symbol from its parameters bool SymbolExists(const string name) const; long SymbolExists(void) const;
Deklarieren Sie die virtuelle Methode zum Anzeigen einer kurzen Symbolbeschreibung
im Abschnitt für die Methoden zur Beschreibung von Eigenschaften des öffentlichen Abschnitts der Klasse.
Implementieren wir diese virtuelle Methode in den Nachkommen der Klasse, in der die klärenden Daten zum Symbolobjekt gesetzt sind.
//+------------------------------------------------------------------+ //| Description of symbol object properties | //+------------------------------------------------------------------+ //--- Get description of a symbol (1) integer, (2) real and (3) string properties string GetPropertyDescription(ENUM_SYMBOL_PROP_INTEGER property); string GetPropertyDescription(ENUM_SYMBOL_PROP_DOUBLE property); string GetPropertyDescription(ENUM_SYMBOL_PROP_STRING property); //--- Send description of symbol properties to the journal (full_prop=true - all properties, false - only supported ones) void Print(const bool full_prop=false); //--- Display a short symbol description in the journal (implementation in the descendants) virtual void PrintShort(void) {;} //--- Compare CSymbol objects by all possible properties (for sorting lists by a specified symbol object property)
Im vorherigen Artikel haben wir bei der Implementierung eines Symbolobjekts einige Servicemethoden hinzugefügt.
Fügen wir noch ein paar weitere Methoden hinzu, um die Start- und Endzeiten von
Kurs- und Handels-Sitzungen
sowie die
'private' Methoden, die eine ganzzahlige Anzahl von Stunden, Minuten und Sekunden in
einer Sitzung zurückgeben, und die Methode, die eine Beschreibung der
Sitzungs-Dauer im "HH:MM:SS"-Format liefert:
//--- (1) Add, (2) remove a symbol from the Market Watch window, (3) return the data synchronization flag by a symbol bool SetToMarketWatch(void) const { return ::SymbolSelect(this.m_symbol_name,true); } bool RemoveFromMarketWatch(void) const { return ::SymbolSelect(this.m_symbol_name,false); } bool IsSynchronized(void) const { return ::SymbolIsSynchronized(this.m_symbol_name); } //--- Return the (1) start and (2) end time of the week day's quote session, (3) the start and end time of the required quote session long SessionQuoteTimeFrom(const uint session_index,ENUM_DAY_OF_WEEK day_of_week=WRONG_VALUE) const; long SessionQuoteTimeTo(const uint session_index,ENUM_DAY_OF_WEEK day_of_week=WRONG_VALUE) const; bool GetSessionQuote(const uint session_index,ENUM_DAY_OF_WEEK day_of_week,datetime &from,datetime &to); //--- Return the (1) start and (2) end time of the week day's trading session, (3) the start and end time of the required trading session long SessionTradeTimeFrom(const uint session_index,ENUM_DAY_OF_WEEK day_of_week=WRONG_VALUE) const; long SessionTradeTimeTo(const uint session_index,ENUM_DAY_OF_WEEK day_of_week=WRONG_VALUE) const; bool GetSessionTrade(const uint session_index,ENUM_DAY_OF_WEEK day_of_week,datetime &from,datetime &to); //--- (1) Arrange a (1) subscription to the market depth, (2) close the market depth, (3) fill in the market depth data to the structure array bool BookAdd(void) const; bool BookClose(void) const; //--- Return (1) a session duration description in the hh:mm:ss format, number of (1) hours, (2) minutes and (3) seconds in the session duration time string SessionDurationDescription(const ulong duration_sec) const; private: int SessionHours(const ulong duration_sec) const; int SessionMinutes(const ulong duration_sec) const; int SessionSeconds(const ulong duration_sec) const; public: //+------------------------------------------------------------------+
Im 'public' Abschnitt der Methoden für einen vereinfachten Zugriff auf Symbolobjekteigenschaften fügen Sie
die zweite Form des Aufrufs der Methode hinzu, die das Flag einer Symbolpräsenz auf dem Server zurückgibt (zuvor haben wir die
private überladene Methode erklärt, die nach einem Symbol auf dem Server durch ihren Namen sucht und das Flag mit dem Suchergebnis
zurückgibt).
//+------------------------------------------------------------------+ //| Methods of a simplified access to the order object properties | //+------------------------------------------------------------------+ //--- Integer properties long Status(void) const { return this.GetProperty(SYMBOL_PROP_STATUS); } 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); }
Fügen Sie in der Unterteilung der Methoden für einen vereinfachten Zugriff auf symbolische reale Eigenschaften im öffentlichen Bereich
die Methoden hinzu, die alle Margenverhältnisse zurückgeben:
//--- 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; //--- String properties
Um Daten über die Symboleigenschaften zu erhalten, stellen Sie sicher, dass das Symbol im Fenster Marktübersicht ausgewählt ist. Es kann Fälle geben, in denen ein Symbol nicht im Fenster ausgewählt ist, aber seine Eigenschaften doch benötigt werden. Für solche Fälle müssen wir das Flag erstellen, das angibt, ob ein Symbol in der Marktübersicht ausgewählt wurde, bevor wir auf seine Eigenschaften zugreifen. Als Nächstes gehen Sie wie folgt vor: Wenn ein Symbol nicht ausgewählt ist, wählen Sie es, holen Sie die Eigenschaften und blenden Sie es in der Marktübersicht aus. Wenn ein Symbol bereits ausgewählt ist, erhalten Sie einfach seine Eigenschaften.
Außerdem müssen wir Margenverhältnisdaten initialisieren und
sie
für MQL5 dem Klassenkonstruktor übergeben. Es gibt keine solchen
Daten für MQL4 und ihre Werte bleiben nach der Initialisierung Null.
Außerdem ergänzen Sie die Methoden zum Speichern dieser Eigenschaften in den
Klasseneigenschaftenfeldern.
Um dies zu erreichen, fügen Sie den notwendigen Code im Klassenkonstruktor hinzu:
//+------------------------------------------------------------------+ //| Closed parametric constructor | //+------------------------------------------------------------------+ CSymbol::CSymbol(ENUM_SYMBOL_STATUS symbol_status,const string name) : m_global_error(ERR_SUCCESS) { this.m_symbol_name=name; if(!this.Exist()) { ::Print(DFUN_ERR_LINE,"\"",this.m_symbol_name,"\"",": ",TextByLanguage("Ошибка. Такого символа нет на сервере","Error. There is no such symbol on the server")); this.m_global_error=ERR_MARKET_UNKNOWN_SYMBOL; } bool select=::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SELECT); ::ResetLastError(); if(!select) { if(!this.SetToMarketWatch()) { this.m_global_error=::GetLastError(); ::Print(DFUN_ERR_LINE,"\"",this.m_symbol_name,"\": ",TextByLanguage("Не удалось поместить в обзор рынка. Ошибка: ","Failed to put in the market watch. Error: "),this.m_global_error); } } ::ResetLastError(); if(!::SymbolInfoTick(this.m_symbol_name,this.m_tick)) { this.m_global_error=::GetLastError(); ::Print(DFUN_ERR_LINE,"\"",this.m_symbol_name,"\": ",TextByLanguage("Не удалось получить текущие цены. Ошибка: ","Could not get current prices. Error: "),this.m_global_error); } //--- Initialize data ::ZeroMemory(this.m_tick); this.Reset(); this.m_digits_currency=(#ifdef __MQL5__ (int)::AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS) #else 2 #endif); this.InitMarginRates(); ::ResetLastError(); #ifdef __MQL5__ if(!this.MarginRates()) { this.m_global_error=::GetLastError(); ::Print(DFUN_ERR_LINE,this.Name(),": ",TextByLanguage("Не удалось получить коэффициенты взимания маржи. Ошибка: ","Failed to get margin rates. Error: "),this.m_global_error); return; } #endif //--- Sichern der ganzzahligen Eigenschaften this.m_long_prop[SYMBOL_PROP_STATUS] = symbol_status; this.m_long_prop[SYMBOL_PROP_VOLUME] = (long)this.m_tick.volume; this.m_long_prop[SYMBOL_PROP_TIME] = #ifdef __MQL5__ this.m_tick.time_msc #else this.m_tick.time*1000 #endif ; this.m_long_prop[SYMBOL_PROP_SELECT] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SELECT); this.m_long_prop[SYMBOL_PROP_VISIBLE] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_VISIBLE); this.m_long_prop[SYMBOL_PROP_SESSION_DEALS] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SESSION_DEALS); this.m_long_prop[SYMBOL_PROP_SESSION_BUY_ORDERS] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SESSION_BUY_ORDERS); this.m_long_prop[SYMBOL_PROP_SESSION_SELL_ORDERS] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SESSION_SELL_ORDERS); this.m_long_prop[SYMBOL_PROP_VOLUMEHIGH] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_VOLUMEHIGH); this.m_long_prop[SYMBOL_PROP_VOLUMELOW] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_VOLUMELOW); this.m_long_prop[SYMBOL_PROP_DIGITS] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_DIGITS); this.m_long_prop[SYMBOL_PROP_SPREAD] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SPREAD); this.m_long_prop[SYMBOL_PROP_SPREAD_FLOAT] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SPREAD_FLOAT); this.m_long_prop[SYMBOL_PROP_TICKS_BOOKDEPTH] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TICKS_BOOKDEPTH); this.m_long_prop[SYMBOL_PROP_TRADE_MODE] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TRADE_MODE); this.m_long_prop[SYMBOL_PROP_START_TIME] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_START_TIME); this.m_long_prop[SYMBOL_PROP_EXPIRATION_TIME] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_EXPIRATION_TIME); this.m_long_prop[SYMBOL_PROP_TRADE_STOPS_LEVEL] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TRADE_STOPS_LEVEL); this.m_long_prop[SYMBOL_PROP_TRADE_FREEZE_LEVEL] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TRADE_FREEZE_LEVEL); this.m_long_prop[SYMBOL_PROP_TRADE_EXEMODE] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TRADE_EXEMODE); this.m_long_prop[SYMBOL_PROP_SWAP_ROLLOVER3DAYS] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SWAP_ROLLOVER3DAYS); this.m_long_prop[SYMBOL_PROP_EXIST] = this.SymbolExists(); this.m_long_prop[SYMBOL_PROP_CUSTOM] = this.SymbolCustom(); this.m_long_prop[SYMBOL_PROP_MARGIN_HEDGED_USE_LEG] = this.SymbolMarginHedgedUseLEG(); this.m_long_prop[SYMBOL_PROP_ORDER_MODE] = this.SymbolOrderMode(); this.m_long_prop[SYMBOL_PROP_FILLING_MODE] = this.SymbolOrderFillingMode(); this.m_long_prop[SYMBOL_PROP_EXPIRATION_MODE] = this.SymbolExpirationMode(); this.m_long_prop[SYMBOL_PROP_ORDER_GTC_MODE] = this.SymbolOrderGTCMode(); this.m_long_prop[SYMBOL_PROP_OPTION_MODE] = this.SymbolOptionMode(); this.m_long_prop[SYMBOL_PROP_OPTION_RIGHT] = this.SymbolOptionRight(); this.m_long_prop[SYMBOL_PROP_BACKGROUND_COLOR] = this.SymbolBackgroundColor(); this.m_long_prop[SYMBOL_PROP_CHART_MODE] = this.SymbolChartMode(); this.m_long_prop[SYMBOL_PROP_TRADE_CALC_MODE] = this.SymbolCalcMode(); this.m_long_prop[SYMBOL_PROP_SWAP_MODE] = this.SymbolSwapMode(); //--- Sichern der Double-Eigenschaften this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKHIGH)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_ASKHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKLOW)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_ASKLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTHIGH)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_LASTHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTLOW)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_LASTLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_POINT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_POINT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE_PROFIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_LOSS)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE_LOSS); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_SIZE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_SIZE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_CONTRACT_SIZE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_CONTRACT_SIZE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_MIN)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_VOLUME_MIN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_MAX)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_VOLUME_MAX); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_STEP)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_VOLUME_STEP); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_LIMIT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_VOLUME_LIMIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SWAP_LONG)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SWAP_LONG); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SWAP_SHORT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SWAP_SHORT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_INITIAL)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_MARGIN_INITIAL); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_MAINTENANCE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_MARGIN_MAINTENANCE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_VOLUME)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_TURNOVER)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_TURNOVER); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_INTEREST)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_INTEREST); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_BUY_ORDERS_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_SELL_ORDERS_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_OPEN)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_OPEN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_CLOSE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_CLOSE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_AW)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_AW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_SETTLEMENT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_PRICE_SETTLEMENT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_LIMIT_MIN)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_PRICE_LIMIT_MIN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_LIMIT_MAX)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_PRICE_LIMIT_MAX); this.m_double_prop[this.IndexProp(SYMBOL_PROP_BID)] = this.m_tick.bid; this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASK)] = this.m_tick.ask; this.m_double_prop[this.IndexProp(SYMBOL_PROP_LAST)] = this.m_tick.last; this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDHIGH)] = this.SymbolBidHigh(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDLOW)] = this.SymbolBidLow(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_REAL)] = this.SymbolVolumeReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUMEHIGH_REAL)] = this.SymbolVolumeHighReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUMELOW_REAL)] = this.SymbolVolumeLowReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_OPTION_STRIKE)] = this.SymbolOptionStrike(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_ACCRUED_INTEREST)] = this.SymbolTradeAccruedInterest(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_FACE_VALUE)] = this.SymbolTradeFaceValue(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_LIQUIDITY_RATE)] = this.SymbolTradeLiquidityRate(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_HEDGED)] = this.SymbolMarginHedged(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LONG_INITIAL)] = this.m_margin_rate.Long.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOP_INITIAL)] = this.m_margin_rate.BuyStop.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_LIMIT_INITIAL)] = this.m_margin_rate.BuyLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_INITIAL)] = this.m_margin_rate.BuyStopLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LONG_MAINTENANCE)] = this.m_margin_rate.Long.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOP_MAINTENANCE)] = this.m_margin_rate.BuyStop.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_LIMIT_MAINTENANCE)] = this.m_margin_rate.BuyLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_MAINTENANCE)] = this.m_margin_rate.BuyStopLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT_INITIAL)] = this.m_margin_rate.Short.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOP_INITIAL)] = this.m_margin_rate.SellStop.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_LIMIT_INITIAL)] = this.m_margin_rate.SellLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_INITIAL)] = this.m_margin_rate.SellStopLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT_MAINTENANCE)] = this.m_margin_rate.Short.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOP_MAINTENANCE)] = this.m_margin_rate.SellStop.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_LIMIT_MAINTENANCE)] = this.m_margin_rate.SellLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_MAINTENANCE)]= this.m_margin_rate.SellStopLimit.Maintenance; //--- Sichern der String-Eigenschaften this.m_string_prop[this.IndexProp(SYMBOL_PROP_NAME)] = this.m_symbol_name; this.m_string_prop[this.IndexProp(SYMBOL_PROP_CURRENCY_BASE)] = ::SymbolInfoString(this.m_symbol_name,SYMBOL_CURRENCY_BASE); this.m_string_prop[this.IndexProp(SYMBOL_PROP_CURRENCY_PROFIT)] = ::SymbolInfoString(this.m_symbol_name,SYMBOL_CURRENCY_PROFIT); this.m_string_prop[this.IndexProp(SYMBOL_PROP_CURRENCY_MARGIN)] = ::SymbolInfoString(this.m_symbol_name,SYMBOL_CURRENCY_MARGIN); this.m_string_prop[this.IndexProp(SYMBOL_PROP_DESCRIPTION)] = ::SymbolInfoString(this.m_symbol_name,SYMBOL_DESCRIPTION); this.m_string_prop[this.IndexProp(SYMBOL_PROP_PATH)] = ::SymbolInfoString(this.m_symbol_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(); //--- Sichern weiterer ganzzahliger Eigenschaften this.m_long_prop[SYMBOL_PROP_DIGITS_LOTS] = this.SymbolDigitsLot(); //--- if(!select) this.RemoveFromMarketWatch(); } //+------------------------------------------------------------------+
Jetzt müssen wir Implementierungen aller deklarierten Methoden schreiben.
Implementieren Sie die Methode zum Ausfüllen aller Variablen, die die Margenverhältnisse außerhalb des
Klassenkörpers speichern:
//+------------------------------------------------------------------+ //| Fill in the margin ratio variables | //+------------------------------------------------------------------+ bool CSymbol::MarginRates(void) { bool res=true; #ifdef __MQL5__ res &=this.SymbolMarginLong(); res &=this.SymbolMarginBuyStop(); res &=this.SymbolMarginBuyLimit(); res &=this.SymbolMarginBuyStopLimit(); res &=this.SymbolMarginShort(); res &=this.SymbolMarginSellStop(); res &=this.SymbolMarginSellLimit(); res &=this.SymbolMarginSellStopLimit(); #else this.InitMarginRates(); res=false; #endif return res; } //+------------------------------------------------------------------+
Die Methode MQL5 ruft einfach die Methoden auf, die die
Verhältnisdaten aus den Symboleigenschaften lesen und in die entsprechenden Strukturvariablen schreiben. Das Ergebnis der Rückgabe
aller Methoden wird summiert und an das aufrufende Programm zurückgegeben. Die Methoden sollen im Folgenden erläutert werden.
Für MQL4 werden alle Strukturfelder einfach auf Null gesetzt.
Das Verfahren zur Initialisierung der Felder der Eigenschaftsstrukturen der Margenverhältnisse:
//+------------------------------------------------------------------+ //| Initialize margin ratios | //+------------------------------------------------------------------+ void CSymbol::InitMarginRates(void) { this.m_margin_rate.Long.Initial=0; this.m_margin_rate.Long.Maintenance=0; this.m_margin_rate.BuyStop.Initial=0; this.m_margin_rate.BuyStop.Maintenance=0; this.m_margin_rate.BuyLimit.Initial=0; this.m_margin_rate.BuyLimit.Maintenance=0; this.m_margin_rate.BuyStopLimit.Initial=0; this.m_margin_rate.BuyStopLimit.Maintenance=0; this.m_margin_rate.Short.Initial=0; this.m_margin_rate.Short.Maintenance=0; this.m_margin_rate.SellStop.Initial=0; this.m_margin_rate.SellStop.Maintenance=0; this.m_margin_rate.SellLimit.Initial=0; this.m_margin_rate.SellLimit.Maintenance=0; this.m_margin_rate.SellStopLimit.Initial=0; this.m_margin_rate.SellStopLimit.Maintenance=0; } //+------------------------------------------------------------------+
Alle Felder der Struktur m_margin_rate werden hier einfach zurückgesetzt.
Implementierung der zweiten Form des Aufrufs der Methode, die das Flag des Symbolanwesens auf dem Server zurückgibt:
//+------------------------------------------------------------------+ //| Return the symbol existence flag | //+------------------------------------------------------------------+ long CSymbol::SymbolExists(void) const { return(#ifdef __MQL5__ ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_EXIST) #else this.Exist() #endif); } //+------------------------------------------------------------------+ bool CSymbol::SymbolExists(const string name) const { return(#ifdef __MQL5__ (bool)::SymbolInfoInteger(name,SYMBOL_EXIST) #else this.Exist(name) #endif); } //+------------------------------------------------------------------+
Hier wird die Symbol-Eigenschaft SYMBOL_EXIST für MQL5 zurückgegeben, während die Suche nach einem Symbol auf dem Server mit der zweiten Form des Aufrufs der Methode Exist(const string name) für MQL4 durchgeführt wird.
Implementierung der Methoden zum Ausfüllen der Margenverhältnisse für alle Auftragsarten in der Struktur:
//+------------------------------------------------------------------+ //| Fill in the margin ratios for long positions | //+------------------------------------------------------------------+ bool CSymbol::SymbolMarginLong(void) { return(#ifdef __MQL5__ ::SymbolInfoMarginRate(this.m_symbol_name,ORDER_TYPE_BUY,this.m_margin_rate.Long.Initial,this.m_margin_rate.Long.Maintenance) #else false #endif); } //+------------------------------------------------------------------+ //| Fill in the margin ratios for short positions | //+------------------------------------------------------------------+ bool CSymbol::SymbolMarginShort(void) { return(#ifdef __MQL5__ ::SymbolInfoMarginRate(this.m_symbol_name,ORDER_TYPE_SELL,this.m_margin_rate.Short.Initial,this.m_margin_rate.Short.Maintenance) #else false #endif); } //+------------------------------------------------------------------+ //| Fill in the margin ratios for BuyStop orders | //+------------------------------------------------------------------+ bool CSymbol::SymbolMarginBuyStop(void) { return(#ifdef __MQL5__ ::SymbolInfoMarginRate(this.m_symbol_name,ORDER_TYPE_BUY_STOP,this.m_margin_rate.BuyStop.Initial,this.m_margin_rate.BuyStop.Maintenance) #else false #endif); } //+------------------------------------------------------------------+ //| Fill in the margin ratios for BuyLimit orders | //+------------------------------------------------------------------+ bool CSymbol::SymbolMarginBuyLimit(void) { return(#ifdef __MQL5__ ::SymbolInfoMarginRate(this.m_symbol_name,ORDER_TYPE_BUY_LIMIT,this.m_margin_rate.BuyLimit.Initial,this.m_margin_rate.BuyLimit.Maintenance) #else false #endif); } //+------------------------------------------------------------------+ //| Fill in the margin ratios for BuyStopLimit orders | //+------------------------------------------------------------------+ bool CSymbol::SymbolMarginBuyStopLimit(void) { return(#ifdef __MQL5__ ::SymbolInfoMarginRate(this.m_symbol_name,ORDER_TYPE_BUY_STOP_LIMIT,this.m_margin_rate.BuyStopLimit.Initial,this.m_margin_rate.BuyStopLimit.Maintenance) #else false #endif); } //+------------------------------------------------------------------+ //| Fill in the margin ratios for SellStop orders | //+------------------------------------------------------------------+ bool CSymbol::SymbolMarginSellStop(void) { return(#ifdef __MQL5__ ::SymbolInfoMarginRate(this.m_symbol_name,ORDER_TYPE_SELL_STOP,this.m_margin_rate.SellStop.Initial,this.m_margin_rate.SellStop.Maintenance) #else false #endif); } //+------------------------------------------------------------------+ //| Fill in the margin ratios for SellLimit orders | //+------------------------------------------------------------------+ bool CSymbol::SymbolMarginSellLimit(void) { return(#ifdef __MQL5__ ::SymbolInfoMarginRate(this.m_symbol_name,ORDER_TYPE_SELL_LIMIT,this.m_margin_rate.SellLimit.Initial,this.m_margin_rate.SellLimit.Maintenance) #else false #endif); } //+------------------------------------------------------------------+ //| Fill in the margin ratios for SellStopLimit orders | //+------------------------------------------------------------------+ bool CSymbol::SymbolMarginSellStopLimit(void) { return(#ifdef __MQL5__ ::SymbolInfoMarginRate(this.m_symbol_name,ORDER_TYPE_SELL_STOP_LIMIT,this.m_margin_rate.SellStopLimit.Initial,this.m_margin_rate.SellStopLimit.Maintenance) #else false #endif); } //+------------------------------------------------------------------+
Hier wird für MQL5 die Funktion SymbolInfoMarginRate()
aufgerufen, in der die in der Struktur m_margin_rate gespeicherten erforderlichen Eigenschaften ausgefüllt und das
Ergebnis der Funktionsoperation zurückgegeben werden.
Für MQL4, wird false
zurückgegeben.
Nehmen Sie die Änderungen an der Methode vor, die die Beschreibung der Symboleigenschaften im Block zurückgibt, der eine Beschreibung eines Symbolhintergrunds im Fenster Marktübersicht zurückgibt:
property==SYMBOL_PROP_BACKGROUND_COLOR ? TextByLanguage("Цвет фона символа в Market Watch","Background color of symbol in Market Watch")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : #ifdef __MQL5__ (this.GetProperty(property)==CLR_DEFAULT || this.GetProperty(property)==CLR_NONE ? TextByLanguage(": (Отсутствует)",": (Not set)") : ": "+::ColorToString((color)this.GetProperty(property),true)) #else TextByLanguage(": Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) :
Bisher haben wir die Farbe mit Weiß (clrWhite) verglichen, und wenn der Farbwert den "weißen" Farbwert überschreitet, wurde die Farbe als nicht gesetzt angesehen. Die Nachteile dieser Vergleichsmethode haben wir bereits erwähnt. Vergleichen Sie daher die Farbe mit der "Standardfarbe" oder mit "Keine-Farbe", um das Fehlen einer bestimmten Hintergrundfarbe für ein Symbol im Fenster Marktübersicht zu definieren.
Fügt der Methode, die Beschreibungen aller Margenverhältnissen der Methode hinzu, die die Beschreibung der 'double'-Eigenschaften von GetPropertyDescription(ENUM_SYMBOL_PROP_DOUBLE) zurückgibt:
//--- Initial margin requirement of a Long position property==SYMBOL_PROP_MARGIN_LONG_INITIAL ? TextByLanguage("Коэффициент взимания начальной маржи по длинным позициям","Coefficient of margin initial charging for long positions")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : //--- Initial margin requirement of a Short position property==SYMBOL_PROP_MARGIN_SHORT_INITIAL ? TextByLanguage("Коэффициент взимания начальной маржи по коротким позициям","Coefficient of margin initial charging for short positions")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : //--- Maintenance margin requirement of a Long position property==SYMBOL_PROP_MARGIN_LONG_MAINTENANCE ? TextByLanguage("Коэффициент взимания поддерживающей маржи по длинным позициям","Coefficient of margin maintenance charging for long positions")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : //--- Maintenance margin requirement of a Short position property==SYMBOL_PROP_MARGIN_SHORT_MAINTENANCE ? TextByLanguage("Коэффициент взимания поддерживающей маржи по коротким позициям","Coefficient of margin maintenance charging for short positions")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : //--- Initial margin requirements of Long orders property==SYMBOL_PROP_MARGIN_BUY_STOP_INITIAL ? TextByLanguage("Коэффициент взимания начальной маржи по BuyStop ордерам","Coefficient of margin initial charging for BuyStop orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_MARGIN_BUY_LIMIT_INITIAL ? TextByLanguage("Коэффициент взимания начальной маржи по BuyLimit ордерам","Coefficient of margin initial charging for BuyLimit orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_INITIAL ? TextByLanguage("Коэффициент взимания начальной маржи по BuyStopLimit ордерам","Coefficient of margin initial charging for BuyStopLimit orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : //--- Initial margin requirements of Short orders property==SYMBOL_PROP_MARGIN_SELL_STOP_INITIAL ? TextByLanguage("Коэффициент взимания начальной маржи по SellStop ордерам","Coefficient of margin initial charging for SellStop orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_MARGIN_SELL_LIMIT_INITIAL ? TextByLanguage("Коэффициент взимания начальной маржи по SellLimit ордерам","Coefficient of margin initial charging for SellLimit orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_INITIAL ? TextByLanguage("Коэффициент взимания начальной маржи по SellStopLimit ордерам","Coefficient of margin initial charging for SellStopLimit orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : //--- Maintenance margin requirements of Long orders property==SYMBOL_PROP_MARGIN_BUY_STOP_MAINTENANCE ? TextByLanguage("Коэффициент взимания поддерживающей маржи по BuyStop ордерам","Coefficient of margin maintenance charging for BuyStop orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_MARGIN_BUY_LIMIT_MAINTENANCE ? TextByLanguage("Коэффициент взимания поддерживающей маржи по BuyLimit ордерам","Coefficient of margin maintenance charging for BuyLimit orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_MAINTENANCE ? TextByLanguage("Коэффициент взимания поддерживающей маржи по BuyStopLimit ордерам","Coefficient of margin maintenance charging for BuyStopLimit orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : //--- Maintenance margin requirements of Short orders property==SYMBOL_PROP_MARGIN_SELL_STOP_MAINTENANCE ? TextByLanguage("Коэффициент взимания поддерживающей маржи по SellStop ордерам","Coefficient of margin maintenance charging for SellStop orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_MARGIN_SELL_LIMIT_MAINTENANCE ? TextByLanguage("Коэффициент взимания поддерживающей маржи по SellLimit ордерам","Coefficient of margin maintenance charging for SellLimit orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_MAINTENANCE ? TextByLanguage("Коэффициент взимания поддерживающей маржи по SellStopLimit ордерам","Coefficient of margin maintenance charging for SellStopLimit orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__ (this.GetProperty(property)==0 ? TextByLanguage(": (Не задан)",": (Not set)") : (::DoubleToString(this.GetProperty(property),8))) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : //---
Implementierung der zweiten Form des Aufrufs der Methode, die nach einem Symbol mit seinem Namen auf dem Server sucht und das Symbolpräsenz-Flag zurückgibt:
//+-------------------------------------------------------------------------------+ //| Search for a symbol and return the flag indicating its presence on the server | //+-------------------------------------------------------------------------------+ bool CSymbol::Exist(void) const { int total=::SymbolsTotal(false); for(int i=0;i<total;i++) if(::SymbolName(i,false)==this.m_symbol_name) return true; return false; } //+------------------------------------------------------------------+ bool CSymbol::Exist(const string name) const { int total=::SymbolsTotal(false); for(int i=0;i<total;i++) if(::SymbolName(i,false)==name) return true; return false; } //+------------------------------------------------------------------+
Implementieren Sie das Verfahren zum Berechnen und Rückgeben der Anzahl der Ziffern in einem 'double' Wert:
//+------------------------------------------------------------------+ //| Return the number of decimal places in the 'double' value | //+------------------------------------------------------------------+ int CSymbol::GetDigits(const double value) const { string val_str=(string)value; int len=::StringLen(val_str); int n=len-::StringFind(val_str,".",0)-1; if(::StringSubstr(val_str,len-1,1)=="0") n--; return n; } //+------------------------------------------------------------------+
Wir haben diese Methode im vorherigen Artikel besprochen. Hier ist es einfach in einem separaten Verfahren implementiert, da eine wiederholte Berechnung für mehrere Werte erforderlich ist — für das Mindestlos und die Schrittweite der Losgröße.
Implementierung der Methoden, die die Startzeit einer Kurssitzung vom Beginn eines Tages, die Endzeit einer Kurssitzung vom Beginn eines Tages und
die Start- und Endzeit der Kurssitzung zurückgeben:
//+------------------------------------------------------------------+ //| Return the quote session start time | //| in seconds from the beginning of a day | //+------------------------------------------------------------------+ long CSymbol::SessionQuoteTimeFrom(const uint session_index,ENUM_DAY_OF_WEEK day_of_week=WRONG_VALUE) const { MqlDateTime time={0}; datetime from=0,to=0; ENUM_DAY_OF_WEEK day=(day_of_week<0 || day_of_week>SATURDAY ? this.CurrentDayOfWeek() : day_of_week); return(::SymbolInfoSessionQuote(this.m_symbol_name,day,session_index,from,to) ? from : WRONG_VALUE); } //+------------------------------------------------------------------+ //| Return the time in seconds since the day start | //| up to the end of a quote session | //+------------------------------------------------------------------+ long CSymbol::SessionQuoteTimeTo(const uint session_index,ENUM_DAY_OF_WEEK day_of_week=WRONG_VALUE) const { MqlDateTime time={0}; datetime from=0,to=0; ENUM_DAY_OF_WEEK day=(day_of_week<0 || day_of_week>SATURDAY ? this.CurrentDayOfWeek() : day_of_week); return(::SymbolInfoSessionQuote(this.m_symbol_name,day,session_index,from,to) ? to : WRONG_VALUE); } //+------------------------------------------------------------------+ //| Return the start and end time of a required quote session | //+------------------------------------------------------------------+ bool CSymbol::GetSessionQuote(const uint session_index,ENUM_DAY_OF_WEEK day_of_week,datetime &from,datetime &to) { ENUM_DAY_OF_WEEK day=(day_of_week<0 || day_of_week>SATURDAY ? this.CurrentDayOfWeek() : day_of_week); return ::SymbolInfoSessionQuote(this.m_symbol_name,day,session_index,from,to); } //+------------------------------------------------------------------+
Der Session-Index und der Wochentag werden an die ersten beiden Methoden übergeben, während die dritte zusätzlich die Variable vom Typ 'datetime' erhält, die Daten zu Beginn und am Ende der gewünschten Sitzung speichern sollen, die mit der Funktion SymbolInfoSessionQuote() empfangen werden.
Wenn -1 als Wochentag ausgewählt ist, werden die Sitzungsdaten für den aktuellen Wochentag übernommen. Der Session-Index sollte bei Null
beginnen. Die Zeit wird als Anzahl von Sekunden ab Beginn des durch den Parameter
day_of_week definierten Tages zurückgegeben. So können Sie immer die tatsächlich benötigte Zeit ermitteln, indem Sie die Anzahl
der von der Methode empfangenen Sekunden zur Zeit des Tagesbeginns addieren.
Die Methoden zum Empfangen von Trade Session Zeiten sind auf die gleiche Weise implementiert:
//+------------------------------------------------------------------+ //| Return the trading session start time | //| in seconds from the beginning of a day | //+------------------------------------------------------------------+ long CSymbol::SessionTradeTimeFrom(const uint session_index,ENUM_DAY_OF_WEEK day_of_week=WRONG_VALUE) const { MqlDateTime time={0}; datetime from=0,to=0; ENUM_DAY_OF_WEEK day=(day_of_week<0 || day_of_week>SATURDAY ? this.CurrentDayOfWeek() : day_of_week); return(::SymbolInfoSessionTrade(this.m_symbol_name,day,session_index,from,to) ? from : WRONG_VALUE); } //+------------------------------------------------------------------+ //| Return the time in seconds since the day start | //| up to the end of a trading session | //+------------------------------------------------------------------+ long CSymbol::SessionTradeTimeTo(const uint session_index,ENUM_DAY_OF_WEEK day_of_week=WRONG_VALUE) const { MqlDateTime time={0}; datetime from=0,to=0; ENUM_DAY_OF_WEEK day=(day_of_week<0 || day_of_week>SATURDAY ? this.CurrentDayOfWeek() : day_of_week); return(::SymbolInfoSessionTrade(this.m_symbol_name,day,session_index,from,to) ? to : WRONG_VALUE); } //+------------------------------------------------------------------+ //| Return the start and end time of a required trading session | //+------------------------------------------------------------------+ bool CSymbol::GetSessionTrade(const uint session_index,ENUM_DAY_OF_WEEK day_of_week,datetime &from,datetime &to) { ENUM_DAY_OF_WEEK day=(day_of_week<0 || day_of_week>SATURDAY ? this.CurrentDayOfWeek() : day_of_week); return ::SymbolInfoSessionTrade(this.m_symbol_name,day,session_index,from,to); } //+------------------------------------------------------------------+
Diese Methoden ähneln den oben beschriebenen Methoden, mit der Ausnahme, dass hier die Funktion SymbolInfoSessionTrade()
verwendet wird, um die notwendigen Daten zu erhalten.
Implementierung der Methode, die den aktuellen Wochentag als ENUM_DAY_OF_WEEK Enumerationswert zurückgibt:
//+------------------------------------------------------------------+ //| Return the current day of the week | //+------------------------------------------------------------------+ ENUM_DAY_OF_WEEK CSymbol::CurrentDayOfWeek(void) const { MqlDateTime time={0}; ::TimeCurrent(time); return(ENUM_DAY_OF_WEEK)time.day_of_week; } //+------------------------------------------------------------------+
Hier ist alles einfach: Deklarieren der Datums- und Zeitstruktur,
Zugriff auf die Funktion
TimeCurrent(), deren zweites Aufrufform die an die Funktion
übergebene Datums- und Zeitstruktur ausfüllt und Rückgabe schließlich
eines Wochentages aus der gefüllten
Struktur.
Implementieren des Verfahrens, das die Anzahl von Sekunden in der Dauer einer bestimmten Sitzung zurückgibt:
//+------------------------------------------------------------------+ //| Return the number of seconds in a session duration time | //+------------------------------------------------------------------+ int CSymbol::SessionSeconds(const ulong duration_sec) const { return int(duration_sec % 60); } //+------------------------------------------------------------------+
Das Verfahren empfängt die Anzahl der Sekunden und gibt den Rest der Division durch die Anzahl der Minuten in dieser Zeitspanne zurück.
Implementierung der Methode, die die Anzahl der Minuten zurückgibt in Dauerzeit einer bestimmten Sitzung:.
//+------------------------------------------------------------------+ //| Return the number of minutes in a session duration time | //+------------------------------------------------------------------+ int CSymbol::SessionMinutes(const ulong duration_sec) const { return int((duration_sec-this.SessionSeconds(duration_sec)) % 3600)/60; } //+------------------------------------------------------------------+
Das Verfahren empfängt die Anzahl der Sekunden und gibt die berechnete Anzahl der Minuten in der Zeitspanne zurück ohne die Sekunden letzten Minute.
Implementierung der Methode, die die Anzahl der Stunden zurückgibt in Dauer Zeit einer bestimmten Sitzung:
//+------------------------------------------------------------------+ //| Return the number of hours in a session duration time | //+------------------------------------------------------------------+ int CSymbol::SessionHours(const ulong duration_sec) const { return int(duration_sec-this.SessionSeconds(duration_sec)-this.SessionMinutes(duration_sec))/3600; } //+------------------------------------------------------------------+
Das Verfahren erhält die Anzahl der Sekunden und gibt die
Anzahl der Stunden in der Zeitspanne
ohne die Sekunden der letzten, offenen Minute und die
Anzahl der Minuten der letzten, offenen Stunde.
Implementierung der Methode, die die Beschreibung einer Sitzungsdauer im Format "HH:MM:SS" zurückgibt:
//+---------------------------------------------------------------------+ //| Return the description of a session duration in the hh:mm:ss format | //+---------------------------------------------------------------------+ string CSymbol::SessionDurationDescription(const ulong duration_sec) const { int sec=this.SessionSeconds(duration_sec); int min=this.SessionMinutes(duration_sec); int hour=this.SessionHours(duration_sec); return ::IntegerToString(hour,2,'0')+":"+::IntegerToString(min,2,'0')+":"+::IntegerToString(sec,2,'0'); } //+------------------------------------------------------------------+
Hier erhalten wir einfach die Sitzungsdauer in Sekunden,
sowie eine berechnete Sitzungsdauer in Sekunden, Minuten
und
Stunden, und zeigen eine formatierte Nachricht im Format
Stunden:Minuten:Sekunden mit der Funktion
IntegerToString() und mit
der Zeichenkettengröße für Stunden, Minuten und Sekunden gleich zwei
Ziffern und dem Füllzeichen "0", falls es eine einstellige
Zahl im Stunden-, Minuten- oder Sekundenwert gibt.
Wenn wir zum Beispiel 2 Stunden erhalten würden, wird es als 02 angezeigt.
Da wir die Zustände von Symbolobjekten leicht überarbeitet haben, korrigieren wir die Methode, die eine Beschreibung eines Symbolobjektstatus anzeigt:
//+------------------------------------------------------------------+ //| Return the status description | //+------------------------------------------------------------------+ string CSymbol::GetStatusDescription() const { return ( this.Status()==SYMBOL_STATUS_FX ? TextByLanguage("Форекс символ","Forex symbol") : this.Status()==SYMBOL_STATUS_FX_MAJOR ? TextByLanguage("Форекс символ-мажор","Forex major symbol") : this.Status()==SYMBOL_STATUS_FX_MINOR ? TextByLanguage("Форекс символ-минор","Forex minor symbol") : this.Status()==SYMBOL_STATUS_FX_EXOTIC ? TextByLanguage("Форекс символ-экзотик","Forex Exotic Symbol") : this.Status()==SYMBOL_STATUS_FX_RUB ? TextByLanguage("Форекс символ/рубль","Forex symbol RUB") : this.Status()==SYMBOL_STATUS_METAL ? TextByLanguage("Металл","Metal") : this.Status()==SYMBOL_STATUS_INDEX ? TextByLanguage("Индекс","Index") : this.Status()==SYMBOL_STATUS_INDICATIVE ? TextByLanguage("Индикатив","Indicative") : this.Status()==SYMBOL_STATUS_CRYPTO ? TextByLanguage("Криптовалютный символ","Crypto symbol") : this.Status()==SYMBOL_STATUS_COMMODITY ? TextByLanguage("Товарный символ","Commodity symbol") : this.Status()==SYMBOL_STATUS_EXCHANGE ? TextByLanguage("Биржевой символ","Exchange symbol") : this.Status()==SYMBOL_STATUS_FUTURES ? TextByLanguage("Фьючерс","Futures") : this.Status()==SYMBOL_STATUS_CFD ? TextByLanguage("Контракт на разницу","Contract For Difference") : this.Status()==SYMBOL_STATUS_STOCKS ? TextByLanguage("Ценная бумага","Stocks") : this.Status()==SYMBOL_STATUS_BONDS ? TextByLanguage("Облигация","Bonds") : this.Status()==SYMBOL_STATUS_OPTION ? TextByLanguage("Опцион","Option") : this.Status()==SYMBOL_STATUS_COLLATERAL ? TextByLanguage("Неторгуемый актив","Collateral") : this.Status()==SYMBOL_STATUS_CUSTOM ? TextByLanguage("Пользовательский символ","Custom symbol") : this.Status()==SYMBOL_STATUS_COMMON ? TextByLanguage("Символ общей группы","Common group symbol") : ::EnumToString((ENUM_SYMBOL_STATUS)this.Status()) ); } //+------------------------------------------------------------------+
In der Methode zur Aktualisierung aller Symboldaten, fügen wir den
Empfang der Margenverhältnisse für MQL5 für alle Auftrags- und Positionstypen hinzu.
Im Falle von MQL4 bleiben
ihre Werte nach der Initialisierung im Klassenkonstruktor Null, da sie in MQL4 nicht verwendet werden:
//+------------------------------------------------------------------+ //| Update all symbol data that can change | //+------------------------------------------------------------------+ void CSymbol::Refresh(void) { ::ResetLastError(); if(!::SymbolInfoTick(this.m_symbol_name,this.m_tick)) { this.m_global_error=::GetLastError(); return; } #ifdef __MQL5__ ::ResetLastError(); if(!this.MarginRates()) { this.m_global_error=::GetLastError(); return; } #endif //--- Update integer properties this.m_long_prop[SYMBOL_PROP_VOLUME] = (long)this.m_tick.volume; this.m_long_prop[SYMBOL_PROP_TIME] = #ifdef __MQL5__ this.m_tick.time_msc #else this.m_tick.time*1000 #endif ; this.m_long_prop[SYMBOL_PROP_SELECT] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SELECT); this.m_long_prop[SYMBOL_PROP_VISIBLE] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_VISIBLE); this.m_long_prop[SYMBOL_PROP_SESSION_DEALS] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SESSION_DEALS); this.m_long_prop[SYMBOL_PROP_SESSION_BUY_ORDERS] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SESSION_BUY_ORDERS); this.m_long_prop[SYMBOL_PROP_SESSION_SELL_ORDERS] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SESSION_SELL_ORDERS); this.m_long_prop[SYMBOL_PROP_VOLUMEHIGH] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_VOLUMEHIGH); this.m_long_prop[SYMBOL_PROP_VOLUMELOW] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_VOLUMELOW); this.m_long_prop[SYMBOL_PROP_SPREAD] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SPREAD); this.m_long_prop[SYMBOL_PROP_TICKS_BOOKDEPTH] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TICKS_BOOKDEPTH); this.m_long_prop[SYMBOL_PROP_START_TIME] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_START_TIME); this.m_long_prop[SYMBOL_PROP_EXPIRATION_TIME] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_EXPIRATION_TIME); this.m_long_prop[SYMBOL_PROP_TRADE_STOPS_LEVEL] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TRADE_STOPS_LEVEL); this.m_long_prop[SYMBOL_PROP_TRADE_FREEZE_LEVEL] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TRADE_FREEZE_LEVEL); this.m_long_prop[SYMBOL_PROP_BACKGROUND_COLOR] = this.SymbolBackgroundColor(); //--- Update real properties this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKHIGH)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_ASKHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKLOW)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_ASKLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTHIGH)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_LASTHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTLOW)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_LASTLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE_PROFIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_LOSS)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE_LOSS); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_SIZE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_SIZE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_CONTRACT_SIZE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_CONTRACT_SIZE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_MIN)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_VOLUME_MIN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_MAX)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_VOLUME_MAX); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_STEP)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_VOLUME_STEP); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_LIMIT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_VOLUME_LIMIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SWAP_LONG)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SWAP_LONG); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SWAP_SHORT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SWAP_SHORT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_INITIAL)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_MARGIN_INITIAL); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_MAINTENANCE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_MARGIN_MAINTENANCE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_VOLUME)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_TURNOVER)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_TURNOVER); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_INTEREST)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_INTEREST); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_BUY_ORDERS_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_SELL_ORDERS_VOLUME); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_OPEN)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_OPEN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_CLOSE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_CLOSE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_AW)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_AW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_SETTLEMENT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_PRICE_SETTLEMENT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_LIMIT_MIN)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_PRICE_LIMIT_MIN); this.m_double_prop[this.IndexProp(SYMBOL_PROP_SESSION_PRICE_LIMIT_MAX)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_SESSION_PRICE_LIMIT_MAX); this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASK)] = this.m_tick.ask; this.m_double_prop[this.IndexProp(SYMBOL_PROP_BID)] = this.m_tick.bid; this.m_double_prop[this.IndexProp(SYMBOL_PROP_LAST)] = this.m_tick.last; this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDHIGH)] = this.SymbolBidHigh(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDLOW)] = this.SymbolBidLow(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_REAL)] = this.SymbolVolumeReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUMEHIGH_REAL)] = this.SymbolVolumeHighReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUMELOW_REAL)] = this.SymbolVolumeLowReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_OPTION_STRIKE)] = this.SymbolOptionStrike(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_ACCRUED_INTEREST)] = this.SymbolTradeAccruedInterest(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_FACE_VALUE)] = this.SymbolTradeFaceValue(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_LIQUIDITY_RATE)] = this.SymbolTradeLiquidityRate(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_HEDGED)] = this.SymbolMarginHedged(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LONG_INITIAL)] = this.m_margin_rate.Long.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOP_INITIAL)] = this.m_margin_rate.BuyStop.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_LIMIT_INITIAL)] = this.m_margin_rate.BuyLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_INITIAL)] = this.m_margin_rate.BuyStopLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LONG_MAINTENANCE)] = this.m_margin_rate.Long.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOP_MAINTENANCE)] = this.m_margin_rate.BuyStop.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_LIMIT_MAINTENANCE)] = this.m_margin_rate.BuyLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_MAINTENANCE)] = this.m_margin_rate.BuyStopLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT_INITIAL)] = this.m_margin_rate.Short.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOP_INITIAL)] = this.m_margin_rate.SellStop.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_LIMIT_INITIAL)] = this.m_margin_rate.SellLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_INITIAL)] = this.m_margin_rate.SellStopLimit.Initial; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT_MAINTENANCE)] = this.m_margin_rate.Short.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOP_MAINTENANCE)] = this.m_margin_rate.SellStop.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_LIMIT_MAINTENANCE)] = this.m_margin_rate.SellLimit.Maintenance; this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_MAINTENANCE)]= this.m_margin_rate.SellStopLimit.Maintenance; } //+------------------------------------------------------------------+
Hier für MQL5 rufen wir die Methode zum Empfangen von Daten über die
Margenverhältnisse der MarginRates() auf. Wenn mindestens eines der Verhältnisse nicht empfangen wird (das Verfahren gab
false zurück), schreiben Sie einfach den
Fehlercode in die Variable, die den Klassenfehlercode speichert, und verlassen Sie die Methode ohne eine Nachricht.
Eine Fehlermeldung wird im Journal nicht angezeigt, da das Verfahren im Timer arbeitet. Im Falle eines fehlerhaften Dateneingangs wird
das Journal schnell mit Garbage-Meldungen über den gleichen Fehler gefüllt. Da dieser Fehlercode in der Klasse CEngine immer empfangen
werden kann, überlassen wir ihm die Verantwortung für den Empfang und die Handhabung.
Am Ende der Methode werden alle erhaltenen Verhältnisdaten in die Felder
der entsprechenden Symbolobjekteigenschaften geschrieben.
Aus dem gleichen Grund entfernen Sie die Zeichenkette, die eine Fehlermeldung
im Journal anzeigt, aus der Kursdatenaktualisierungsmethode :
//+------------------------------------------------------------------+ //| Update quote data by a symbol | //+------------------------------------------------------------------+ void CSymbol::RefreshRates(void) { ::ResetLastError(); if(!::SymbolInfoTick(this.m_symbol_name,this.m_tick)) { this.m_global_error=::GetLastError(); ::Print(DFUN_ERR_LINE,this.Name(),": ",TextByLanguage("Не удалось получить текущие цены. Ошибка: ","Could not get current prices. Error: "),this.m_global_error); return; } //--- Update integer properties this.m_long_prop[SYMBOL_PROP_VOLUME] = (long)this.m_tick.volume; this.m_long_prop[SYMBOL_PROP_TIME] = #ifdef __MQL5__ this.m_tick.time_msc #else this.m_tick.time*1000 #endif ; this.m_long_prop[SYMBOL_PROP_SPREAD] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SPREAD); this.m_long_prop[SYMBOL_PROP_TRADE_STOPS_LEVEL] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TRADE_STOPS_LEVEL); this.m_long_prop[SYMBOL_PROP_TRADE_FREEZE_LEVEL] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TRADE_FREEZE_LEVEL); //--- Update real properties this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKHIGH)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_ASKHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKLOW)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_ASKLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTHIGH)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_LASTHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTLOW)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_LASTLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE_PROFIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_LOSS)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE_LOSS); this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASK)] = this.m_tick.ask; this.m_double_prop[this.IndexProp(SYMBOL_PROP_BID)] = this.m_tick.bid; this.m_double_prop[this.IndexProp(SYMBOL_PROP_LAST)] = this.m_tick.last; this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDHIGH)] = this.SymbolBidHigh(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDLOW)] = this.SymbolBidLow(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_REAL)] = this.SymbolVolumeReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_OPTION_STRIKE)] = this.SymbolOptionStrike(); } //+------------------------------------------------------------------+
Nun sieht die Methode wie folgt aus:
//+------------------------------------------------------------------+ //| Update quote data by a symbol | //+------------------------------------------------------------------+ void CSymbol::RefreshRates(void) { ::ResetLastError(); if(!::SymbolInfoTick(this.m_symbol_name,this.m_tick)) { this.m_global_error=::GetLastError(); return; } //--- Update integer properties this.m_long_prop[SYMBOL_PROP_VOLUME] = (long)this.m_tick.volume; this.m_long_prop[SYMBOL_PROP_TIME] = #ifdef __MQL5__ this.m_tick.time_msc #else this.m_tick.time*1000 #endif ; this.m_long_prop[SYMBOL_PROP_SPREAD] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SPREAD); this.m_long_prop[SYMBOL_PROP_TRADE_STOPS_LEVEL] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TRADE_STOPS_LEVEL); this.m_long_prop[SYMBOL_PROP_TRADE_FREEZE_LEVEL] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TRADE_FREEZE_LEVEL); //--- Update real properties this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKHIGH)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_ASKHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASKLOW)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_ASKLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTHIGH)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_LASTHIGH); this.m_double_prop[this.IndexProp(SYMBOL_PROP_LASTLOW)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_LASTLOW); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE_PROFIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_TRADE_TICK_VALUE_LOSS)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_TICK_VALUE_LOSS); this.m_double_prop[this.IndexProp(SYMBOL_PROP_ASK)] = this.m_tick.ask; this.m_double_prop[this.IndexProp(SYMBOL_PROP_BID)] = this.m_tick.bid; this.m_double_prop[this.IndexProp(SYMBOL_PROP_LAST)] = this.m_tick.last; this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDHIGH)] = this.SymbolBidHigh(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_BIDLOW)] = this.SymbolBidLow(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_VOLUME_REAL)] = this.SymbolVolumeReal(); this.m_double_prop[this.IndexProp(SYMBOL_PROP_OPTION_STRIKE)] = this.SymbolOptionStrike(); } //+------------------------------------------------------------------+
Damit ist die Verbesserung der abstrakten Symbolklasse CSymbol abgeschlossen.
Wir haben die wichtigen und wichtigsten Änderungen an den Klassenmethoden untersucht, mit Ausnahme von kleinen Korrekturen, die vorgenommen, aber hier nicht beschrieben wurden, da es sich hierbei nur um einige Rechtschreib- und "semantische" Fehler handelt, die sich im Wesentlichen auf die Methoden der Objektbeschreibung beziehen. Sie finden sie in den angehängten Dateien.
Nun müssen wir abgeleitete Objekte der abstrakten Symbol-Basisklasse erstellen, sie nach Kategorien unterteilen und in die
Symbolobjektsammlung stellen.
Abgeleitete Objekte des abstrakten Basisobjekts "Symbol".
Gehen wir ein wenig zurück und schauen wir uns die genannten Symbolkategorien an. Außerdem werden wir die Namen der entsprechenden abgeleiteten Klassen der Basisklasse CSymbol festlegen:
- Forex Symbol — CSymbolFX class
- Major Forex Symbol — CSymbolFXMajor class
- Minor Forex Symbol — CSymbolFXMinor class
- Exotic Forex Symbol — CSymbolFXExotic class
- Forex Symbol/RUB — CSymbolFXRub class
- Metal — CSymbolMetall class
- Index — CSymbolIndex class
- Indicative — CSymbolIndicative class
- Kryptowährungssymbol — CSymbolCrypto class
- Rohstoffsymbol — CSymbolCommodity class
- Börsensymbol — CSymbolExchange class
- Futures — CSymbolFutures class
- CFD — CSymbolCFD class
- Stock (Aktien) — CSymbolStocks class
- Bond (Anleihen) — CSymbolBonds class
- Option — CSymbolOption class
- Nicht handelbare Finanzinstrumente — CSymbolCollateral class
- Nutzerdefiniertes Symbol — CSymbolCustom class
- Allgemeine Kategorie — CSymbolCommon class
Erstellen wir im Bibliotheksordner \MQL5\Include\DoEasy\Symbols\ die neue Klasse CSymbolFX mit der Datei SymbolFX.mqh.
Die abstrakte Symbolklasse
CSymbol soll als Basisklasse für sie verwendet werden.
Deklarieren
wir alle für die Klassenoperation notwendigen Methoden:
//+------------------------------------------------------------------+ //| SymbolFX.mqh | //| Copyright 2018, MetaQuotes Software Corp. | //| https://mql5.com/de/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://mql5.com/de/users/artmedia70" #property version "1.00" //+------------------------------------------------------------------+ //| Include-Dateien | //+------------------------------------------------------------------+ #include "Symbol.mqh" //+------------------------------------------------------------------+ //| Forex symbol | //+------------------------------------------------------------------+ class CSymbolFX : public CSymbol { public: //--- Konstructor CSymbolFX(const string name) : CSymbol(SYMBOL_STATUS_FX,name) {} //--- Supported integer properties of a symbol virtual bool SupportProperty(ENUM_SYMBOL_PROP_INTEGER property); //--- Supported real properties of a symbol virtual bool SupportProperty(ENUM_SYMBOL_PROP_DOUBLE property); //--- Supported string properties of a symbol virtual bool SupportProperty(ENUM_SYMBOL_PROP_STRING property); //--- Display a short symbol description in the journal virtual void PrintShort(void); }; //+------------------------------------------------------------------+
Der Klassenkonstruktor soll einen Symbolnamen
erhalten, während die Initialisierungsliste des Klassenkonstruktors verwendet wird, um
eine Kategorie "Forex symbol" (dessen Status) an die Basisklasse zusammen mit einem Symbolnamen,
der beim Anlegen an den CSymbolFX-Klassenkonstruktor übergeben wird,
zu senden.
Die virtuellen Methoden zur Unterstützung von integer, real
und string Eigenschaften durch ein Objekt wurden in der Basisklasse
deklariert, während ihre Implementierung in den nachfolgenden Klassen durchgeführt wird. Die virtuelle Methode
PrintShort(), die ebenfalls in der Basisklasse deklariert und in der
Nachkommenklasse implementiert ist, zeigt kurze Symboldaten im Journal an.
Fast alle Methoden der abgeleiteten Klasse sind ähnlich und können in der Basisklasse implementiert werden, ohne dass abgeleitete Klassen benötigt werden. Allerdings verlieren wir in diesem Fall die Flexibilität, für jede Symbolgruppe Änderungen an diesen Methoden vorzunehmen. Deshalb habe ich mich entschieden, eine Aufteilung nach Kategorien über abgeleitete Klassen vorzunehmen, um jede abgeleitete Klasse separat ändern zu können, was viel einfacher und schneller ist.
Die Implementierung des Verfahrens, das das Flag zurückgibt, um eine ganzzahlige Eigenschaft durch ein Symbolobjekt zu unterstützen:
//+------------------------------------------------------------------+ //| Return 'true' if a symbol supports a passed | //| Integer-Eigenschaft unterstützt, sonst 'false' | //+------------------------------------------------------------------+ bool CSymbolFX::SupportProperty(ENUM_SYMBOL_PROP_INTEGER property) { if(property==SYMBOL_PROP_EXIST #ifdef __MQL4__ || property==SYMBOL_PROP_CUSTOM || property==SYMBOL_PROP_SESSION_DEALS || property==SYMBOL_PROP_SESSION_BUY_ORDERS || property==SYMBOL_PROP_SESSION_SELL_ORDERS || property==SYMBOL_PROP_VOLUME || property==SYMBOL_PROP_VOLUMEHIGH || property==SYMBOL_PROP_VOLUMELOW || property==SYMBOL_PROP_TICKS_BOOKDEPTH || property==SYMBOL_PROP_OPTION_MODE || property==SYMBOL_PROP_OPTION_RIGHT || property==SYMBOL_PROP_BACKGROUND_COLOR #endif ) return false; return true; } //+------------------------------------------------------------------+
Eine geprüfte ganzzahlige Eigenschaft wird der Methode
übergeben.
Wenn die übergebene Eigenschaft "Symbol existent" ist, geben wir false
zurück — wenn ein Symbol erstellt wird, existiert es, und wir brauchen diese Eigenschaft nicht, weder für die Anzeige im Journal, noch für
die Suche und Sortierung. Alle anderen Prüfungen werden
nur auf MQL4 angewendet. False
wird zurückgegeben, wenn eine bewusst nicht unterstützte Symboleigenschaft an die Methode in MQL4 übergeben wird.
Wenn eine übergebene Eigenschaft bei der Überprüfung der Eigenschaften nicht unter den aufgelisteten vorhanden war, wird sie nicht
unterstützt. Rückgabe
wahr.
Die Implementierung des Verfahrens zur Rückgabe des Flags zur Unterstützung einer Eigenschaft von einem Symbolobjekt:
//+------------------------------------------------------------------+ //| Return 'true' if a symbol supports a passed | //| Double-Eigenschaft, sonst 'false' | //+------------------------------------------------------------------+ bool CSymbolFX::SupportProperty(ENUM_SYMBOL_PROP_DOUBLE property) { if( #ifdef __MQL5__ (this.ChartMode()==SYMBOL_CHART_MODE_BID && ( property==SYMBOL_PROP_LAST || property==SYMBOL_PROP_LASTHIGH || property==SYMBOL_PROP_LASTLOW ) ) || (this.ChartMode()==SYMBOL_CHART_MODE_LAST && ( property==SYMBOL_PROP_BID || property==SYMBOL_PROP_BIDHIGH || property==SYMBOL_PROP_BIDLOW || property==SYMBOL_PROP_ASK || property==SYMBOL_PROP_ASKHIGH || property==SYMBOL_PROP_ASKLOW ) ) //--- __MQL4__ #else property==SYMBOL_PROP_ASKHIGH || property==SYMBOL_PROP_ASKLOW || property==SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT || property==SYMBOL_PROP_TRADE_TICK_VALUE_LOSS || property==SYMBOL_PROP_LAST || property==SYMBOL_PROP_LASTHIGH || property==SYMBOL_PROP_LASTLOW || property==SYMBOL_PROP_VOLUME_LIMIT || property==SYMBOL_PROP_MARGIN_LONG_INITIAL || property==SYMBOL_PROP_MARGIN_BUY_STOP_INITIAL || property==SYMBOL_PROP_MARGIN_BUY_LIMIT_INITIAL || property==SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_INITIAL || property==SYMBOL_PROP_MARGIN_LONG_MAINTENANCE || property==SYMBOL_PROP_MARGIN_BUY_STOP_MAINTENANCE || property==SYMBOL_PROP_MARGIN_BUY_LIMIT_MAINTENANCE || property==SYMBOL_PROP_MARGIN_BUY_STOPLIMIT_MAINTENANCE || property==SYMBOL_PROP_MARGIN_SHORT_INITIAL || property==SYMBOL_PROP_MARGIN_SELL_STOP_INITIAL || property==SYMBOL_PROP_MARGIN_SELL_LIMIT_INITIAL || property==SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_INITIAL || property==SYMBOL_PROP_MARGIN_SHORT_MAINTENANCE || property==SYMBOL_PROP_MARGIN_SELL_STOP_MAINTENANCE || property==SYMBOL_PROP_MARGIN_SELL_LIMIT_MAINTENANCE || property==SYMBOL_PROP_MARGIN_SELL_STOPLIMIT_MAINTENANCE || property==SYMBOL_PROP_SESSION_VOLUME || property==SYMBOL_PROP_SESSION_TURNOVER || property==SYMBOL_PROP_SESSION_INTEREST || property==SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME || property==SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME || property==SYMBOL_PROP_SESSION_OPEN || property==SYMBOL_PROP_SESSION_CLOSE || property==SYMBOL_PROP_SESSION_AW || property==SYMBOL_PROP_SESSION_PRICE_SETTLEMENT || property==SYMBOL_PROP_SESSION_PRICE_LIMIT_MIN || property==SYMBOL_PROP_SESSION_PRICE_LIMIT_MAX || property==SYMBOL_PROP_VOLUME_REAL || property==SYMBOL_PROP_VOLUMEHIGH_REAL || property==SYMBOL_PROP_VOLUMELOW_REAL || property==SYMBOL_PROP_OPTION_STRIKE || property==SYMBOL_PROP_TRADE_ACCRUED_INTEREST || property==SYMBOL_PROP_TRADE_FACE_VALUE || property==SYMBOL_PROP_TRADE_LIQUIDITY_RATE #endif ) return false; return true; } //+------------------------------------------------------------------+
Die Logik ist hier die gleiche wie bei der vorherigen Methode. Aber zuerst überprüfen wir die erhaltene Eigenschaft auf MQL5.
Wenn es sich um eine der letzten Transaktionspreiseigenschaften (Last) handelt, während
das Diagramm auf Geldkurse basiert, sind alle diese Eigenschaften
gleich Null und werden in diesem Fall nicht unterstützt.
Das Gleiche gilt für die Eigenschaften des Bid-Preises für den Fall,
dass das Chart auf den letzten Preisen basiert — alle Angebotspreiseigenschaften werden nicht unterstützt.
Im
Falle von MQL4 verfahren Sie genau wie in der vorherigen Methode — wenn Sie eine wissentlich nicht unterstützte Symboleigenschaft
an die Methode übergeben, geben Sie
false zurück.
Die Implementierung des Verfahrens zur Rückgabe des Flags zur Unterstützung einer String-Eigenschaft durch ein Symbolobjekt:
//+------------------------------------------------------------------+ //| Return 'true' if a symbol supports a passed | //| String-Eigenschaft, sonst 'false' | //+------------------------------------------------------------------+ bool CSymbolFX::SupportProperty(ENUM_SYMBOL_PROP_STRING property) { if( #ifdef __MQL5__ property==SYMBOL_PROP_FORMULA && !this.IsCustom() #else property==SYMBOL_PROP_BASIS || property==SYMBOL_PROP_BANK || property==SYMBOL_PROP_ISIN || property==SYMBOL_PROP_FORMULA || property==SYMBOL_PROP_PAGE #endif ) return false; return true; } //+------------------------------------------------------------------+
Hier ist alles ähnlich: im Falle von MQL5 — wenn
die übergebene Eigenschaft "Equation for custom symbol calculation"
ist, während ein Symbol nicht nutzerdefiniert ist, geben Sie false zurück, — die
Eigenschaft wird nicht unterstützt. Als Nächstes überprüfen wir die wissentlich nicht unterstützten Symboleigenschaften
für MQL4 und geben false
zurück, wenn eine nicht in MQL4 unterstützte Eigenschaft übergeben wird.
Verfahren zur Darstellung einer kurzen Symbolbeschreibung im Journal:
//+------------------------------------------------------------------+ //| Display a short symbol description in the journal | //+------------------------------------------------------------------+ void CSymbolFX::PrintShort(void) { ::Print(this.GetStatusDescription()+" "+this.Name()); } //+------------------------------------------------------------------+
Das Verfahren zeigt einfach eine Zeile an, die aus einer Symbol-Statuszeichenkettenbeschreibung und seinem Namen besteht.
Die übrigen abgeleiteten Klasse sind auf die gleiche Weise aufgebaut und haben die gleichen Methoden mit der gleichen Implementierung.
Der Unterschied liegt in der
kundenspezifischen Symbolklasse — ein solcher Symboltyp ist in MQL4 nicht vorhanden, daher werden alle Prüfungen nur auf MQL5
angewendet:
//+------------------------------------------------------------------+ //| SymbolCustom.mqh | //| Copyright 2018, MetaQuotes Software Corp. | //| https://mql5.com/de/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://mql5.com/de/users/artmedia70" #property version "1.00" //+------------------------------------------------------------------+ //| Include-Dateien | //+------------------------------------------------------------------+ #include "Symbol.mqh" //+------------------------------------------------------------------+ //| Custom symbol | //+------------------------------------------------------------------+ class CSymbolCustom : public CSymbol { public: //--- Konstructor CSymbolCustom(const string name) : CSymbol(SYMBOL_STATUS_CUSTOM,name) {} //--- Supported integer properties of a symbol virtual bool SupportProperty(ENUM_SYMBOL_PROP_INTEGER property); //--- Supported real properties of a symbol virtual bool SupportProperty(ENUM_SYMBOL_PROP_DOUBLE property); //--- Supported string properties of a symbol virtual bool SupportProperty(ENUM_SYMBOL_PROP_STRING property); //--- Display a short symbol description in the journal virtual void PrintShort(void); }; //+------------------------------------------------------------------+ //| Return 'true' if a symbol supports a passed | //| Integer-Eigenschaft unterstützt, sonst 'false' | //+------------------------------------------------------------------+ bool CSymbolCustom::SupportProperty(ENUM_SYMBOL_PROP_INTEGER property) { if(property==SYMBOL_PROP_EXIST) return false; return true; } //+------------------------------------------------------------------+ //| Return 'true' if a symbol supports a passed | //| Double-Eigenschaft, sonst 'false' | //+------------------------------------------------------------------+ bool CSymbolCustom::SupportProperty(ENUM_SYMBOL_PROP_DOUBLE property) { if( (this.ChartMode()==SYMBOL_CHART_MODE_BID && ( property==SYMBOL_PROP_LAST || property==SYMBOL_PROP_LASTHIGH || property==SYMBOL_PROP_LASTLOW ) ) || (this.ChartMode()==SYMBOL_CHART_MODE_LAST && ( property==SYMBOL_PROP_BID || property==SYMBOL_PROP_BIDHIGH || property==SYMBOL_PROP_BIDLOW || property==SYMBOL_PROP_ASK || property==SYMBOL_PROP_ASKHIGH || property==SYMBOL_PROP_ASKLOW ) ) ) return false; return true; } //+------------------------------------------------------------------+ //| Return 'true' if a symbol supports a passed | //| String-Eigenschaft, sonst 'false' | //+------------------------------------------------------------------+ bool CSymbolCustom::SupportProperty(ENUM_SYMBOL_PROP_STRING property) { return true; } //+------------------------------------------------------------------+ //| Display a short symbol description in the journal | //+------------------------------------------------------------------+ void CSymbolCustom::PrintShort(void) { ::Print(this.GetStatusDescription()+" "+this.Name()); } //+------------------------------------------------------------------+
Dies ist der Abschluss der Entwicklung der abgeleiteten Klassen von CSymbol.
Die Implementierung der
restlichen abgeleiteten Klassen finden Sie am Ende des Artikels und in den angehängten Dateien.
Da wir die Symbolkollektion suchen und sortieren müssen, sollten wir alle notwendigen Funktionen dafür schaffen. Öffnen Sie die Datei Select.mqh,
die sich in der Datei
\MQL5\Include\DoEasy\Services\ Bibliotheksordner befindet, und machen Sie Ergänzungen.
Zuerst muss die
abstrakte Symbolklasse:
eingebunden werden.
//+------------------------------------------------------------------+ //| Select.mqh | //| Copyright 2018, MetaQuotes Software Corp. | //| https://mql5.com/de/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://mql5.com/de/users/artmedia70" #property version "1.00" //+------------------------------------------------------------------+ //| Include-Dateien | //+------------------------------------------------------------------+ #include <Arrays\ArrayObj.mqh> #include "..\Objects\Orders\Order.mqh" #include "..\Objects\Events\Event.mqh" #include "..\Objects\Accounts\Account.mqh" #include "..\Objects\Symbols\Symbol.mqh" //+------------------------------------------------------------------+
Deklarieren aller notwendigen Methoden zum Suchen und Sortieren
im 'public' Bereich der Klasse:
//+------------------------------------------------------------------+ //| Klasse zum Sortieren der Objekte, die dem Kriterium entsprechen | //+------------------------------------------------------------------+ class CSelect { private: //| Vergleichsmethode von zwei Werten template<typename T> static bool CompareValues(T value1,T value2,ENUM_COMPARER_TYPE mode); public: //+------------------------------------------------------------------+ //| Methods of working with orders | //+------------------------------------------------------------------+ //--- Rückgabe der Auftragsliste mit der (1) Integer-, (2) Double- und (3) String-Eigenschaft, die dem angegebenen Kriterium entspricht static CArrayObj *ByOrderProperty(CArrayObj *list_source,ENUM_ORDER_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode); static CArrayObj *ByOrderProperty(CArrayObj *list_source,ENUM_ORDER_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode); static CArrayObj *ByOrderProperty(CArrayObj *list_source,ENUM_ORDER_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode); //--- Return the order index with the maximum value of the order's (1) integer, (2) real and (3) string properties static int FindOrderMax(CArrayObj *list_source,ENUM_ORDER_PROP_INTEGER property); static int FindOrderMax(CArrayObj *list_source,ENUM_ORDER_PROP_DOUBLE property); static int FindOrderMax(CArrayObj *list_source,ENUM_ORDER_PROP_STRING property); //--- Return the order index with the minimum value of the order's (1) integer, (2) real and (3) string properties static int FindOrderMin(CArrayObj *list_source,ENUM_ORDER_PROP_INTEGER property); static int FindOrderMin(CArrayObj *list_source,ENUM_ORDER_PROP_DOUBLE property); static int FindOrderMin(CArrayObj *list_source,ENUM_ORDER_PROP_STRING property); //+------------------------------------------------------------------+ //| Methods of working with events | //+------------------------------------------------------------------+ //--- Return the list of events with one out of (1) integer, (2) real and (3) string properties meeting a specified criterion static CArrayObj *ByEventProperty(CArrayObj *list_source,ENUM_EVENT_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode); static CArrayObj *ByEventProperty(CArrayObj *list_source,ENUM_EVENT_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode); static CArrayObj *ByEventProperty(CArrayObj *list_source,ENUM_EVENT_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode); //--- Return the event index with the maximum value of the event's (1) integer, (2) real and (3) string properties static int FindEventMax(CArrayObj *list_source,ENUM_EVENT_PROP_INTEGER property); static int FindEventMax(CArrayObj *list_source,ENUM_EVENT_PROP_DOUBLE property); static int FindEventMax(CArrayObj *list_source,ENUM_EVENT_PROP_STRING property); //--- Return the event index with the minimum value of the event's (1) integer, (2) real and (3) string properties static int FindEventMin(CArrayObj *list_source,ENUM_EVENT_PROP_INTEGER property); static int FindEventMin(CArrayObj *list_source,ENUM_EVENT_PROP_DOUBLE property); static int FindEventMin(CArrayObj *list_source,ENUM_EVENT_PROP_STRING property); //+------------------------------------------------------------------+ //| Methods of working with accounts | //+------------------------------------------------------------------+ //--- Return the list of accounts with one out of (1) integer, (2) real and (3) string properties meeting a specified criterion static CArrayObj *ByAccountProperty(CArrayObj *list_source,ENUM_ACCOUNT_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode); static CArrayObj *ByAccountProperty(CArrayObj *list_source,ENUM_ACCOUNT_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode); static CArrayObj *ByAccountProperty(CArrayObj *list_source,ENUM_ACCOUNT_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode); //--- Return the event index with the maximum value of the event's (1) integer, (2) real and (3) string properties static int FindAccountMax(CArrayObj *list_source,ENUM_ACCOUNT_PROP_INTEGER property); static int FindAccountMax(CArrayObj *list_source,ENUM_ACCOUNT_PROP_DOUBLE property); static int FindAccountMax(CArrayObj *list_source,ENUM_ACCOUNT_PROP_STRING property); //--- Return the event index with the minimum value of the event's (1) integer, (2) real and (3) string properties static int FindAccountMin(CArrayObj *list_source,ENUM_ACCOUNT_PROP_INTEGER property); static int FindAccountMin(CArrayObj *list_source,ENUM_ACCOUNT_PROP_DOUBLE property); static int FindAccountMin(CArrayObj *list_source,ENUM_ACCOUNT_PROP_STRING property); //+------------------------------------------------------------------+ //| Methods of working with symbols | //+------------------------------------------------------------------+ //--- Return the list of symbols with one out of (1) integer, (2) real and (3) string properties meeting a specified criterion static CArrayObj *BySymbolProperty(CArrayObj *list_source,ENUM_SYMBOL_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode); static CArrayObj *BySymbolProperty(CArrayObj *list_source,ENUM_SYMBOL_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode); static CArrayObj *BySymbolProperty(CArrayObj *list_source,ENUM_SYMBOL_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode); //--- Return the symbol index with the maximum value of the order's (1) integer, (2) real and (3) string properties static int FindSymbolMax(CArrayObj *list_source,ENUM_SYMBOL_PROP_INTEGER property); static int FindSymbolMax(CArrayObj *list_source,ENUM_SYMBOL_PROP_DOUBLE property); static int FindSymbolMax(CArrayObj *list_source,ENUM_SYMBOL_PROP_STRING property); //--- Return the symbol index with the minimum value of the order's (1) integer, (2) real and (3) string properties static int FindSymbolMin(CArrayObj *list_source,ENUM_SYMBOL_PROP_INTEGER property); static int FindSymbolMin(CArrayObj *list_source,ENUM_SYMBOL_PROP_DOUBLE property); static int FindSymbolMin(CArrayObj *list_source,ENUM_SYMBOL_PROP_STRING property); //--- }; //+------------------------------------------------------------------+
Lasst uns ihre Implementierung außerhalb der Klasse schreiben:
//+------------------------------------------------------------------+ //| Methods of working with symbol lists | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Return the list of symbols with one integer | //| property meeting the specified criterion | //+------------------------------------------------------------------+ CArrayObj *CSelect::BySymbolProperty(CArrayObj *list_source,ENUM_SYMBOL_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode) { if(list_source==NULL) return NULL; CArrayObj *list=new CArrayObj(); if(list==NULL) return NULL; list.FreeMode(false); ListStorage.Add(list); int total=list_source.Total(); for(int i=0; i<total; i++) { CSymbol *obj=list_source.At(i); if(!obj.SupportProperty(property)) continue; long obj_prop=obj.GetProperty(property); if(CompareValues(obj_prop,value,mode)) list.Add(obj); } return list; } //+------------------------------------------------------------------+ //| Return the list of symbols with one real | //| property meeting the specified criterion | //+------------------------------------------------------------------+ CArrayObj *CSelect::BySymbolProperty(CArrayObj *list_source,ENUM_SYMBOL_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode) { if(list_source==NULL) return NULL; CArrayObj *list=new CArrayObj(); if(list==NULL) return NULL; list.FreeMode(false); ListStorage.Add(list); for(int i=0; i<list_source.Total(); i++) { CSymbol *obj=list_source.At(i); if(!obj.SupportProperty(property)) continue; double obj_prop=obj.GetProperty(property); if(CompareValues(obj_prop,value,mode)) list.Add(obj); } return list; } //+------------------------------------------------------------------+ //| Return the list of symbols with one string | //| property meeting the specified criterion | //+------------------------------------------------------------------+ CArrayObj *CSelect::BySymbolProperty(CArrayObj *list_source,ENUM_SYMBOL_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode) { if(list_source==NULL) return NULL; CArrayObj *list=new CArrayObj(); if(list==NULL) return NULL; list.FreeMode(false); ListStorage.Add(list); for(int i=0; i<list_source.Total(); i++) { CSymbol *obj=list_source.At(i); if(!obj.SupportProperty(property)) continue; string obj_prop=obj.GetProperty(property); if(CompareValues(obj_prop,value,mode)) list.Add(obj); } return list; } //+------------------------------------------------------------------+ //| Return the listed symbol index | //| mit dem Maximum der Integer-Eigenschaft | //+------------------------------------------------------------------+ int CSelect::FindSymbolMax(CArrayObj *list_source,ENUM_SYMBOL_PROP_INTEGER property) { if(list_source==NULL) return WRONG_VALUE; int index=0; CSymbol *max_obj=NULL; int total=list_source.Total(); if(total==0) return WRONG_VALUE; for(int i=1; i<total; i++) { CSymbol *obj=list_source.At(i); long obj1_prop=obj.GetProperty(property); max_obj=list_source.At(index); long obj2_prop=max_obj.GetProperty(property); if(CompareValues(obj1_prop,obj2_prop,MORE)) index=i; } return index; } //+------------------------------------------------------------------+ //| Return the listed symbol index | //| mit dem Maximum der Double-Eigenschaft | //+------------------------------------------------------------------+ int CSelect::FindSymbolMax(CArrayObj *list_source,ENUM_SYMBOL_PROP_DOUBLE property) { if(list_source==NULL) return WRONG_VALUE; int index=0; CSymbol *max_obj=NULL; int total=list_source.Total(); if(total==0) return WRONG_VALUE; for(int i=1; i<total; i++) { CSymbol *obj=list_source.At(i); double obj1_prop=obj.GetProperty(property); max_obj=list_source.At(index); double obj2_prop=max_obj.GetProperty(property); if(CompareValues(obj1_prop,obj2_prop,MORE)) index=i; } return index; } //+------------------------------------------------------------------+ //| Return the listed symbol index | //| mit dem Maximum der String-Eigenschaft | //+------------------------------------------------------------------+ int CSelect::FindSymbolMax(CArrayObj *list_source,ENUM_SYMBOL_PROP_STRING property) { if(list_source==NULL) return WRONG_VALUE; int index=0; CSymbol *max_obj=NULL; int total=list_source.Total(); if(total==0) return WRONG_VALUE; for(int i=1; i<total; i++) { CSymbol *obj=list_source.At(i); string obj1_prop=obj.GetProperty(property); max_obj=list_source.At(index); string obj2_prop=max_obj.GetProperty(property); if(CompareValues(obj1_prop,obj2_prop,MORE)) index=i; } return index; } //+------------------------------------------------------------------+ //| Return the listed symbol index | //| mit dem Minimum der Integer-Eigenschaft | //+------------------------------------------------------------------+ int CSelect::FindSymbolMin(CArrayObj* list_source,ENUM_SYMBOL_PROP_INTEGER property) { int index=0; CSymbol *min_obj=NULL; int total=list_source.Total(); if(total==0) return WRONG_VALUE; for(int i=1; i<total; i++){ CSymbol *obj=list_source.At(i); long obj1_prop=obj.GetProperty(property); min_obj=list_source.At(index); long obj2_prop=min_obj.GetProperty(property); if(CompareValues(obj1_prop,obj2_prop,LESS)) index=i; } return index; } //+------------------------------------------------------------------+ //| Return the listed symbol index | //| mit dem Minimum der Double-Eigenschaft | //+------------------------------------------------------------------+ int CSelect::FindSymbolMin(CArrayObj* list_source,ENUM_SYMBOL_PROP_DOUBLE property) { int index=0; CSymbol *min_obj=NULL; int total=list_source.Total(); if(total== 0) return WRONG_VALUE; for(int i=1; i<total; i++){ CSymbol *obj=list_source.At(i); double obj1_prop=obj.GetProperty(property); min_obj=list_source.At(index); double obj2_prop=min_obj.GetProperty(property); if(CompareValues(obj1_prop,obj2_prop,LESS)) index=i; } return index; } //+------------------------------------------------------------------+ //| Return the listed symbol index | //| mit dem Minimum der String-Eigenschaft | //+------------------------------------------------------------------+ int CSelect::FindSymbolMin(CArrayObj* list_source,ENUM_SYMBOL_PROP_STRING property) { int index=0; CSymbol *min_obj=NULL; int total=list_source.Total(); if(total==0) return WRONG_VALUE; for(int i=1; i<total; i++){ CSymbol *obj=list_source.At(i); string obj1_prop=obj.GetProperty(property); min_obj=list_source.At(index); string obj2_prop=min_obj.GetProperty(property); if(CompareValues(obj1_prop,obj2_prop,LESS)) index=i; } return index; } //+------------------------------------------------------------------+
Wir haben ähnliche Methoden für jede der Kollection-Klassen. Sie wurden im dritten
Teil der Bibliotheksbeschreibung beim Erstellen der Klasse CSelect berücksichtigt. Deshalb werden wir hier nicht auf sie eingehen.
Jetzt ist alles bereit für die Erstellung der Klasse der Symbolkollektion.
Die vier Modi können für die Arbeit
mit der Symbolsammlung aus dem Programm verwendet werden:
- Nur mit einem einzigen Symbol arbeiten,
- Arbeiten mit einer Liste von Symbolen,
- Arbeiten mit dem Fenster Marktübersicht,
- Arbeiten mit einer vollständigen Liste der auf dem Server verfügbaren Symbole.
Damit die Klasse der Symbolsammlung "weiß", womit sie arbeiten soll, werden wir dieses Schema verwenden:
Stellen Sie in den Programmeinstellungen die Bedienung der Methoden zum Arbeiten mit Symbolen ein. Dies kann eine der vier
angekündigten Betriebsarten sein.
Das Programm sollte auch das String-Array haben, das mit der Bibliotheksfunktion nach dem gleichen Prinzip gefüllt werden soll:
- Wenn mit einem einzelnen Symbol gearbeitet wird, enthält das Array nur das aktuelle Symbol,
- wenn mit einer nutzerdefinierten Symbolliste gearbeitet wird, die sich auch in den Programmeinstellungen befinden kann, wobei
die notwendigen kommagetrennten Symbole definiert sind, wird das Array mit Symbolen aus der Zeichenkette gefüllt; wenn nur ein
aktuelles Symbol in der Zeichenkette gesetzt ist oder die Liste leer ist, dann wird das aktuelle Symbol für die Arbeit verwendet.
- Wenn Sie mit der Marktbeobachtung arbeiten, wird in der einzigen Array-Zelle "MARKET_WATCH" anstelle eines Symbolnamens gesetzt.
- Wenn mit der vollständigen Liste von Symbolen des Servers gearbeitet wird, wird im Array "ALL" anstelle eines Symbolnamens gesetzt.
All dies geschieht automatisch. Ein Nutzer muss nur die Auswahl des notwendigen Modus für die Arbeit mit einer Symbolsammlung veranlassen und mindestens ein String-Array oder ein String-Array und eine Reihe vordefinierter Symbole in den Einstellungen erstellen.
Die Klasse der Symbolkollektion
Erstellen Sie in dem Bibliotheksordner \MQL5\Include\DoEasy\Collections\ die neue Klasse CSymbolsCollection in der Datei SymbolsCollection.mqh.
Das CObject
Klassenobjekt der Standardbibliothek ist als Basisklasse dafür zu verwenden.
Fügen wir alle notwendigen Klassendateien in eine neu erstellte Datei ein:
//+------------------------------------------------------------------+ //| SymbolsCollection.mqh | //| Copyright 2018, MetaQuotes Software Corp. | //| https://mql5.com/de/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://mql5.com/de/users/artmedia70" #property version "1.00" //+------------------------------------------------------------------+ //| Include-Dateien | //+------------------------------------------------------------------+ #include "ListObj.mqh" #include "..\Services\Select.mqh" #include "..\Objects\Symbols\Symbol.mqh" #include "..\Objects\Symbols\SymbolFX.mqh" #include "..\Objects\Symbols\SymbolFXMajor.mqh" #include "..\Objects\Symbols\SymbolFXMinor.mqh" #include "..\Objects\Symbols\SymbolFXExotic.mqh" #include "..\Objects\Symbols\SymbolFXRub.mqh" #include "..\Objects\Symbols\SymbolMetall.mqh" #include "..\Objects\Symbols\SymbolIndex.mqh" #include "..\Objects\Symbols\SymbolIndicative.mqh" #include "..\Objects\Symbols\SymbolCrypto.mqh" #include "..\Objects\Symbols\SymbolCommodity.mqh" #include "..\Objects\Symbols\SymbolExchange.mqh" #include "..\Objects\Symbols\SymbolFutures.mqh" #include "..\Objects\Symbols\SymbolCFD.mqh" #include "..\Objects\Symbols\SymbolStocks.mqh" #include "..\Objects\Symbols\SymbolBonds.mqh" #include "..\Objects\Symbols\SymbolOption.mqh" #include "..\Objects\Symbols\SymbolCollateral.mqh" #include "..\Objects\Symbols\SymbolCustom.mqh" #include "..\Objects\Symbols\SymbolCommon.mqh" //+------------------------------------------------------------------+ //| Kollektion der historischen Aufträge und Deals | //+------------------------------------------------------------------+ class CSymbolsCollection : public CObject { private: public: //--- Konstructor CSymbolsCollection(); }; //+------------------------------------------------------------------+
Fügen Sie die Werte und Methoden der Klassenmitglieder hinzu, die bereits zum Standard für die Klassen der Bibliotheksbestände geworden sind:
//+------------------------------------------------------------------+ //| SymbolsCollection.mqh | //| Copyright 2018, MetaQuotes Software Corp. | //| https://mql5.com/de/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://mql5.com/de/users/artmedia70" #property version "1.00" //+------------------------------------------------------------------+ //| Include-Dateien | //+------------------------------------------------------------------+ #include "ListObj.mqh" #include "..\Services\Select.mqh" #include "..\Objects\Symbols\Symbol.mqh" #include "..\Objects\Symbols\SymbolFX.mqh" #include "..\Objects\Symbols\SymbolFXMajor.mqh" #include "..\Objects\Symbols\SymbolFXMinor.mqh" #include "..\Objects\Symbols\SymbolFXExotic.mqh" #include "..\Objects\Symbols\SymbolFXRub.mqh" #include "..\Objects\Symbols\SymbolMetall.mqh" #include "..\Objects\Symbols\SymbolIndex.mqh" #include "..\Objects\Symbols\SymbolIndicative.mqh" #include "..\Objects\Symbols\SymbolCrypto.mqh" #include "..\Objects\Symbols\SymbolCommodity.mqh" #include "..\Objects\Symbols\SymbolExchange.mqh" #include "..\Objects\Symbols\SymbolFutures.mqh" #include "..\Objects\Symbols\SymbolCFD.mqh" #include "..\Objects\Symbols\SymbolStocks.mqh" #include "..\Objects\Symbols\SymbolBonds.mqh" #include "..\Objects\Symbols\SymbolOption.mqh" #include "..\Objects\Symbols\SymbolCollateral.mqh" #include "..\Objects\Symbols\SymbolCustom.mqh" #include "..\Objects\Symbols\SymbolCommon.mqh" //+------------------------------------------------------------------+ //| Kollektion der historischen Aufträge und Deals | //+------------------------------------------------------------------+ class CSymbolsCollection : public CObject { private: CListObj m_list_all_symbols; // The list of all symbol objects public: //--- Rückgabe der ganzen Collection 'wie besehen' CArrayObj *GetList(void) { return &this.m_list_all_symbols; } //--- Rückgabe der Auswahlliste von (1) Integer-, (2) Double- und (3) String-Eigenschaften, die dem Vergleichskriterium entsprechen CArrayObj *GetList(ENUM_SYMBOL_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::BySymbolProperty(this.GetList(),property,value,mode); } CArrayObj *GetList(ENUM_SYMBOL_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::BySymbolProperty(this.GetList(),property,value,mode); } CArrayObj *GetList(ENUM_SYMBOL_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::BySymbolProperty(this.GetList(),property,value,mode); } //--- Konstructor CSymbolsCollection(); }; //+------------------------------------------------------------------+
Wir haben all diese Variablen und Methoden bereits bei der Erstellung früherer Kollektionen berücksichtigt. Es besteht keine Notwendigkeit, sie hier zu diskutieren.
Fügen Sie die restlichen Variablen und Methoden für das Arbeiten mit der Klasse Symbol Collection hinzu:
//+------------------------------------------------------------------+ //| SymbolsCollection.mqh | //| Copyright 2018, MetaQuotes Software Corp. | //| https://mql5.com/de/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://mql5.com/de/users/artmedia70" #property version "1.00" //+------------------------------------------------------------------+ //| Include-Dateien | //+------------------------------------------------------------------+ #include "ListObj.mqh" #include "..\Services\Select.mqh" #include "..\Objects\Symbols\Symbol.mqh" #include "..\Objects\Symbols\SymbolFX.mqh" #include "..\Objects\Symbols\SymbolFXMajor.mqh" #include "..\Objects\Symbols\SymbolFXMinor.mqh" #include "..\Objects\Symbols\SymbolFXExotic.mqh" #include "..\Objects\Symbols\SymbolFXRub.mqh" #include "..\Objects\Symbols\SymbolMetall.mqh" #include "..\Objects\Symbols\SymbolIndex.mqh" #include "..\Objects\Symbols\SymbolIndicative.mqh" #include "..\Objects\Symbols\SymbolCrypto.mqh" #include "..\Objects\Symbols\SymbolCommodity.mqh" #include "..\Objects\Symbols\SymbolExchange.mqh" #include "..\Objects\Symbols\SymbolFutures.mqh" #include "..\Objects\Symbols\SymbolCFD.mqh" #include "..\Objects\Symbols\SymbolStocks.mqh" #include "..\Objects\Symbols\SymbolBonds.mqh" #include "..\Objects\Symbols\SymbolOption.mqh" #include "..\Objects\Symbols\SymbolCollateral.mqh" #include "..\Objects\Symbols\SymbolCustom.mqh" #include "..\Objects\Symbols\SymbolCommon.mqh" //+------------------------------------------------------------------+ //| Kollektion der historischen Aufträge und Deals | //+------------------------------------------------------------------+ class CSymbolsCollection : public CObject { private: CListObj m_list_all_symbols; // The list of all symbol objects ENUM_SYMBOLS_MODE m_mode_list; // Mode of working with symbol lists int m_delta_symbol; // Difference in the number of symbols compared to the previous check int m_last_num_symbol; // Number of symbols in the Market Watch window during the previous check int m_global_error; // Global error code //--- Return the flag of a symbol object presence by its name in the list of all symbols bool IsPresentSymbolInList(const string symbol_name); //--- Create the symbol object and place it to the list bool CreateNewSymbol(const ENUM_SYMBOL_STATUS symbol_status,const string name); //--- Return the type of a used symbol list (Market watch/Server) ENUM_SYMBOLS_MODE TypeSymbolsList(const string &symbol_used_array[]); //--- Define a symbol affiliation with a group by name and return it ENUM_SYMBOL_STATUS SymbolStatus(const string symbol_name) const; //--- Return a symbol affiliation with a category by custom criteria ENUM_SYMBOL_STATUS StatusByCustomPredefined(const string symbol_name) const; //--- Return a symbol affiliation with categories by margin calculation ENUM_SYMBOL_STATUS StatusByCalcMode(const string symbol_name) const; //--- Return a symbol affiliation with pre-defined (1) majors, (2) minors, (3) exotics, (4) RUB, //--- (5) indicatives, (6) metals, (7) commodities, (8) indices, (9) cryptocurrency, (10) options bool IsPredefinedFXMajor(const string name) const; bool IsPredefinedFXMinor(const string name) const; bool IsPredefinedFXExotic(const string name) const; bool IsPredefinedFXRUB(const string name) const; bool IsPredefinedIndicative(const string name) const; bool IsPredefinedMetall(const string name) const; bool IsPredefinedCommodity(const string name) const; bool IsPredefinedIndex(const string name) const; bool IsPredefinedCrypto(const string name) const; bool IsPredefinedOption(const string name) const; //--- Search for a symbol and return the flag indicating its presence on the server bool Exist(const string name) const; public: //--- Rückgabe der ganzen Collection 'wie besehen' CArrayObj *GetList(void) { return &this.m_list_all_symbols; } //--- Rückgabe der Auswahlliste von (1) Integer-, (2) Double- und (3) String-Eigenschaften, die dem Vergleichskriterium entsprechen CArrayObj *GetList(ENUM_SYMBOL_PROP_INTEGER property,long value,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::BySymbolProperty(this.GetList(),property,value,mode); } CArrayObj *GetList(ENUM_SYMBOL_PROP_DOUBLE property,double value,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::BySymbolProperty(this.GetList(),property,value,mode); } CArrayObj *GetList(ENUM_SYMBOL_PROP_STRING property,string value,ENUM_COMPARER_TYPE mode=EQUAL) { return CSelect::BySymbolProperty(this.GetList(),property,value,mode); } //--- Return the number of new symbols in the Market Watch window int NewSymbols(void) const { return this.m_delta_symbol; } //--- Return the mode of working with symbol lists ENUM_SYMBOLS_MODE ModeSymbolsList(void) const { return this.m_mode_list; } //--- Konstructor CSymbolsCollection(); //--- Set the list of used symbols bool SetUsedSymbol(const string &symbol_used_array[]); //--- Update (1) all, (2) quote data of the collection symbols void Refresh(void); void RefreshRates(void); }; //+------------------------------------------------------------------+
Die Klasse sollte wissen, mit welcher Symbolklasse sie arbeiten soll: dem aktuellen Symbol, einem angegebenen Symbolsatz, einer
Symbolliste im Fenster Marktübersicht oder der vollständigen Liste aller Symbole des Servers. Die Klassenvariable
m_m_mode_list speichert einen der aufgeführten Modi für die
Arbeit mit Symbolen.
Wenn wir mit einer Liste der Symbole aus der Marktübersicht arbeiten, müssen wir diese Liste ständig verfolgen (wird im nächsten
Artikel implementiert), die
Anzahl der Symbole während der letzten Überprüfung kennen und
uns entsprechend bewusst sein
wie viel sich diese Zahl beim Hinzufügen/Löschen eines oder mehrerer Symbole von
der Liste der Marktübersicht geändert hat, um die Kollektionsliste der Symbole m_list_all_symbols rechtzeitig
neu anzuordnen und weiterhin mit den Symbolen korrekt zu arbeiten.
Wie in den vorherigen Kollektionen haben wir eine neue Klassenvariable eingeführt, die den Fehlercode
speichert, den Sie in der Basisklasse der CEngine Bibliothek sehen und bearbeiten können.
Wenn Sie ein neues
Symbolobjekt erstellen und es der Kollektion hinzufügen, müssen wir sicherstellen, dass es kein solches Symbol in der Liste gibt. Dies
geschieht mit der Methode
IsPresentSymbolInList().
Mit der Methode CreateNewSymbol()
wird ein neues Symbol erstellt und zur Kollektion hinzugefügt.
Da das Arbeiten in vier Symbollistenmodi in der
Symbolkollektion angeordnet ist, wird mit der Methode
TypeSymbolsList() der Modus für die Arbeit mit.
definiert.
Bevor wir ein neues Symbol erstellen, müssen wir zuerst eine Gruppe definieren und einstellen, der es zugeordnet wird (oder eine Gruppe,
der ein Nutzer es zuweist). Mit der Methode
SymbolStatus() wird eine Symbolgruppe (deren Status) definiert.
Bei der Definition eines Symbolstatus wird sein Name zunächst in bestimmten nutzerdefinierten Arrays mit der Methode
StatusByCustomPredefined() gesucht.
Wenn die Methode den
Status "general" zurückgibt, wird ein Symbolstatus durch die Art der Margenberechnung durch die Methode
StatusByCalcMode() definiert.
Die
zusätzlichen Methoden werden verwendet, um eine Suche nach Nutzerarrays durchzuführen und zu definieren, zu welcher nutzerdefinierten
Kategorie ein Symbol gehört. Diese Methoden geben Flags zurück, die anzeigen, ob ein Symbol zu den Hauptgruppen, Minderjährigen, Indizes
und anderen Gruppen gehört.
Die Methode Exist() gibt
das Flag einer Symbolexistenz auf dem Server zurück.
Die Methode NewSymbols() gibt die Anzahl der neu hinzugefügten
oder aus dem Fenster Marktübersicht entfernten Symbole zurück, während die Methode
ModeSymbolsList() den Modus der Arbeit mit einer der vier Listen (das
aktuelle Symbol, ein vordefinierter Symbolsatz, die Liste der Marktübersicht und die aller Symbole des Servers) an das aufrufende
Programm zurückgibt.
Die Methode SetUsedSymbol() akzeptiert ein Symbol-Array oder
eine Beschreibung einer Betriebsart mit einer Liste von Symbolen innerhalb eines übergebenen Arrays und erstellt eine Kollektionsliste
der Symbole.
Die Methode Refresh() aktualisiert alle Daten aller
Kollektionssymbole, die sich ändern können, während die Methode
RefreshRates() nur Kursdaten aller Kollektionssymbole
aktualisiert. Beide Methoden werden aus dem Hauptobjekt-Timer der Bibliothek CEngine aufgerufen.
Wir haben zu diesem Zeitpunkt alle Methoden definiert, die für die Arbeit mit der Klasse Symbol Collection notwendig sind. Lassen Sie uns einen Blick auf ihre Struktur werfen.
Implementierung des Klassenkonstruktors:
//+------------------------------------------------------------------+ //| Konstruktor | //+------------------------------------------------------------------+ CSymbolsCollection::CSymbolsCollection(void) : m_last_num_symbol(0),m_delta_symbol(0),m_mode_list(SYMBOLS_MODE_CURRENT) { this.m_list_all_symbols.Sort(SORT_BY_SYMBOL_NAME); this.m_list_all_symbols.Clear(); this.m_list_all_symbols.Type(COLLECTION_SYMBOLS_ID); } //+------------------------------------------------------------------+
Initialisieren wir in der Konstruktor-Initialisierungsliste die Anzahl
der Symbole während der letzten Prüfung und die Differenz zwischen der
aktuellen und der vorherigen Anzahl der Symbole. Weiters setzen wir den
Arbeitsmodus mit einer Symbolliste auf "Arbeiten mit dem aktuellen Symbol".
Im Klassenkörper wird
die Symbolkollektion nach dem Namen sortiert, die Liste gelöscht
und die ID der Symbolkollektion hinzugefügt.
Das Verfahren zum Aktualisieren aller Daten aller Kollektionssymbole:
//+------------------------------------------------------------------+ //| Update all collection symbol data | //+------------------------------------------------------------------+ void CSymbolsCollection::Refresh(void) { int total=this.m_list_all_symbols.Total(); if(total==0) return; for(int i=0;i<total;i++) { CSymbol *symbol=this.m_list_all_symbols.At(i); if(symbol==NULL) continue; symbol.Refresh(); } } //+------------------------------------------------------------------+
In der Schleife über die Anzahl aller Kollektionsymbole, holen wir das nächste Symbol aus der Symbolkollektion und aktualisieren seine Daten mit der Methode Refresh() der CS-Symbolklasse, die im vorigen Artikel berücksichtigt wird.
Das Verfahren zum Aktualisieren von Kursdaten aller Kollektionssymbole:
//+------------------------------------------------------------------+ //| Update quote data of the collection symbols | //+------------------------------------------------------------------+ void CSymbolsCollection::RefreshRates(void) { int total=this.m_list_all_symbols.Total(); if(total==0) return; for(int i=0;i<total;i++) { CSymbol *symbol=this.m_list_all_symbols.At(i); if(symbol==NULL) continue; symbol.RefreshRates(); } } //+------------------------------------------------------------------+
In der Schleife über die Anzahl aller Kollektionssymbole, nehmen wirt das nächste Symbol aus der Kollektionsliste und aktualisieren seine Daten mit der Methode RefreshRates() der Klasse CSymbol.
Die Methode zum Erstellen eines neuen Symbolobjekts und zum Platzieren in der Liste der Symbolkollektion:
//+------------------------------------------------------------------+ //| Create a symbol object and place it to the list | //+------------------------------------------------------------------+ bool CSymbolsCollection::CreateNewSymbol(const ENUM_SYMBOL_STATUS symbol_status,const string name) { if(this.IsPresentSymbolInList(name)) { return true; } if(#ifdef __MQL5__ !::SymbolInfoInteger(name,SYMBOL_EXIST) #else !this.Exist(name) #endif ) { string t1=TextByLanguage("Ошибка входных данных: нет символа ","Input error: no "); string t2=TextByLanguage(" на сервере"," symbol on the server"); ::Print(DFUN,t1,name,t2); this.m_global_error=ERR_MARKET_UNKNOWN_SYMBOL; return false; } CSymbol *symbol=NULL; switch(symbol_status) { case SYMBOL_STATUS_FX : symbol=new CSymbolFX(name); break; // Forex symbol case SYMBOL_STATUS_FX_MAJOR : symbol=new CSymbolFXMajor(name); break; // Major Forex symbol case SYMBOL_STATUS_FX_MINOR : symbol=new CSymbolFXMinor(name); break; // Minor Forex symbol case SYMBOL_STATUS_FX_EXOTIC : symbol=new CSymbolFXExotic(name); break; // Exotic Forex symbol case SYMBOL_STATUS_FX_RUB : symbol=new CSymbolFXRub(name); break; // Forex symbol/RUR case SYMBOL_STATUS_METAL : symbol=new CSymbolMetall(name); break; // Metal case SYMBOL_STATUS_INDEX : symbol=new CSymbolIndex(name); break; // Index case SYMBOL_STATUS_INDICATIVE : symbol=new CSymbolIndicative(name); break; // Indicative case SYMBOL_STATUS_CRYPTO : symbol=new CSymbolCrypto(name); break; // Cryptocurrency symbol case SYMBOL_STATUS_COMMODITY : symbol=new CSymbolCommodity(name); break; // Commodity case SYMBOL_STATUS_EXCHANGE : symbol=new CSymbolExchange(name); break; // Exchange symbol case SYMBOL_STATUS_FUTURES : symbol=new CSymbolFutures(name); break; // Futures case SYMBOL_STATUS_CFD : symbol=new CSymbolCFD(name); break; // CFD case SYMBOL_STATUS_STOCKS : symbol=new CSymbolStocks(name); break; // Stock case SYMBOL_STATUS_BONDS : symbol=new CSymbolBonds(name); break; // Bond case SYMBOL_STATUS_OPTION : symbol=new CSymbolOption(name); break; // Option case SYMBOL_STATUS_COLLATERAL : symbol=new CSymbolCollateral(name); break; // Non-tradable asset case SYMBOL_STATUS_CUSTOM : symbol=new CSymbolCustom(name); break; // Custom symbol default : symbol=new CSymbolCommon(name); break; // The rest } if(symbol==NULL) { ::Print(DFUN,TextByLanguage("Не удалось создать объект-символ ","Failed to create symbol object "),name); return false; } if(!this.m_list_all_symbols.Add(symbol)) { string t1=TextByLanguage("Не удалось добавить символ ","Failed to add "); string t2=TextByLanguage(" в список"," symbol to the list"); ::Print(DFUN,t1,name,t2); delete symbol; return false; } return true; } //+------------------------------------------------------------------+
Das Verfahren übergibt Status und Name
des Symbols. Wenn ein solches Symbol bereits in der Symbolkollektion vorhanden
ist, wird "still" wahr
zurückgeben — es gibt keinen Fehler, aber es besteht keine Notwendigkeit, ein Symbol hinzuzufügen, da es bereits existiert.
Als Nächstes
überprüfen wir
, ob ein Symbol auf dem Server mit seinem Namen existiert. Wenn es kein solches
Symbol gibt, zeigen wir die Abwesenheitsmeldung des Symbols an, weisen
den Wert "unbekanntes Symbol" dem Fehlercode zu und geben false
zurück.
Wenn das Symbol existiert, erstellen wir ein neues Symbolobjekt abhängig
vom Status, der an die Methode übergeben wird. Um ein Symbolobjekt zu erstellen, verwenden Sie abgeleitete Klasse des abstrakten
Symbols, die dem übergebenen Status entsprechen.
Im Falle eines Fehlers bei der Erstellung eines Objekts, zeigen
wir die entsprechende Meldung an und
geben false zurück.
Wenn ein neues Symbolobjekt erfolgreich erstellt wurde, fügen wir es
zur Symbolkollektion hinzu und geben
wahr zurück im Falle eines
erfolgreichen Hinzufügens, oder zeigen eine Fehlermeldung an und
geben false
zurück, wenn es nicht erfolgreich war.
Implementierung der Methode, die das Symbol Präsenz-Flag in der Kollektionsliste zurückgibt:
//+------------------------------------------------------------------+ //| Return the symbol object presence flag | //| by its name in the list of all symbols | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPresentSymbolInList(const string symbol_name) { CArrayObj *list=dynamic_cast<CListObj*>(&this.m_list_all_symbols); list.Sort(SORT_BY_SYMBOL_NAME); list=CSelect::BySymbolProperty(list,SYMBOL_PROP_NAME,symbol_name,EQUAL); return(list==NULL || list.Total()==0 ? false : true); } //+------------------------------------------------------------------+
Der Name eines benötigten Symbols wird an die Methode übergeben, dann wird die Liste nach einem Symbolnamen und einem übergebenen Namen sortiert. Wenn die Liste nicht leer ist, wurde das Symbol mit einem solchen Namen gefunden — Rückgabe von true. Andernfalls wird false zurückgegeben — es gibt kein Symbol in der Liste.
Implementierung der Methode zum Einstellen der Liste der Kollektionssymbole:
//+------------------------------------------------------------------+ //| Set the list of used symbols | //+------------------------------------------------------------------+ bool CSymbolsCollection::SetUsedSymbol(const string &symbol_used_array[]) { this.m_mode_list=this.TypeSymbolsList(symbol_used_array); this.m_list_all_symbols.Clear(); this.m_list_all_symbols.Sort(SORT_BY_SYMBOL_NAME); //--- Use only the current symbol if(this.m_mode_list==SYMBOLS_MODE_CURRENT) { string name=::Symbol(); ENUM_SYMBOL_STATUS status=this.SymbolStatus(name); return this.CreateNewSymbol(status,name); } else { bool res=true; //--- Use the pre-defined symbol list if(this.m_mode_list==SYMBOLS_MODE_DEFINES) { int total=::ArraySize(symbol_used_array); for(int i=0;i<total;i++) { string name=symbol_used_array[i]; ENUM_SYMBOL_STATUS status=this.SymbolStatus(name); bool add=this.CreateNewSymbol(status,name); res &=add; if(!add) continue; } return res; } //--- Use the full list of the server symbols else if(this.m_mode_list==SYMBOLS_MODE_ALL) { int total=::SymbolsTotal(false); for(int i=0;i<total;i++) { string name=::SymbolName(i,false); ENUM_SYMBOL_STATUS status=this.SymbolStatus(name); bool add=this.CreateNewSymbol(status,name); res &=add; if(!add) continue; } return res; } //--- Use the symbol list from the Market Watch window else if(this.m_mode_list==SYMBOLS_MODE_MARKET_WATCH) { int total=::SymbolsTotal(true); for(int i=0;i<total;i++) { string name=::SymbolName(i,true); ENUM_SYMBOL_STATUS status=this.SymbolStatus(name); bool add=this.CreateNewSymbol(status,name); res &=add; if(!add) continue; } return res; } } return false; } //+------------------------------------------------------------------+
Das Verfahren erstellt die Kollektionsliste der Symbole in Abhängigkeit vom Inhalt des an sie übergebenen Symbolarrays.
Zuerst
definieren wir die Arbeitsweise mit einer Symbolliste (ein
Symbol/Nutzerset von Symbolen/Marktübersicht/Gesamtliste), dann wird die
Liste gelöscht und nach
Name sortiert.
Wenn nur das aktuelle Symbol verwendet wird,
- definieren des Symbolstatus' durch seinen Namen und
- Rückgabe des Ergebnisses der Erstellung eines neuen Symbolobjekts und Einfügen in die Liste der Symbolkollektion.
Wenn eine vordefinierte Symbolliste verwendet
- erhalten wir einen Symbolnamen aus dem Array in einer Schleife durch ein an das Verfahren übergebenes Array mit dem Symbolnamen,
- definieren wir den Symbolstatus über seinen Namen,
- fügen wir das Ergebnis der Erstellung und Hinzufügen eines Symbolobjekts zur Kollektionsliste der Symbole zur zurückgegebenen Variablen hinzu,
- wenn es nicht gelungen ist, ein Symbol zu erstellen oder es der Liste hinzuzufügen, gehen wir zum nächsten,
- geben wir nach dem Ende der Schleife den Status der Variablen zurück, in die
die Ergebnisse der Erstellung der Kollektionssymbole geschrieben wurden.
Die restlichen beiden Modi werden ähnlich wie beim Arbeiten mit einer vordefinierten Liste behandelt. Anstelle des an die Methode übergebenen Arrays werden die Symbole jedoch entweder von der Marktübersicht oder von der vollständigen Liste der Symbole auf dem Server übernommen.
Implementierung der Methode, die den Modus des Arbeitens mit Symbollisten zurückgibt:
//+------------------------------------------------------------------+ //|Return the type of a used symbol list (Market watch/Server) | //+------------------------------------------------------------------+ ENUM_SYMBOLS_MODE CSymbolsCollection::TypeSymbolsList(const string &symbol_used_array[]) { int total=::ArraySize(symbol_used_array); if(total<1) return SYMBOLS_MODE_CURRENT; string type=::StringSubstr(symbol_used_array[0],13); return ( type=="MARKET_WATCH" ? SYMBOLS_MODE_MARKET_WATCH : type=="ALL" ? SYMBOLS_MODE_ALL : (total==1 && symbol_used_array[0]==::Symbol() ? SYMBOLS_MODE_CURRENT : SYMBOLS_MODE_DEFINES) ); } //+------------------------------------------------------------------+
Das Verfahren empfängt das Array mit Symbolnamen oder mit
einer Beschreibung der Arbeitsmodi mit Listen.
Wenn ein leeres Array übergeben wird, geben wir die Betriebsart nur mit dem
aktuellen Symbol zurück.
Als Nächstes empfangen wir den Inhalt des Arrays von seiner Nullzelle und,
- wenn wir vom Index 13 des Substrings ausgehen und es den Eintrag "MARKET_WATCH" gibt, geben wir den Modus der Arbeit mit dem Fenster Marktübersicht zurück.
- wenn dort die Zeichenkette "ALL" vorhanden ist, geben wir den Modus der Arbeit mit der vollständigen Liste der Symbole zurück.
- andernfalls,
- wenn das Array einen einzelnen Eintrag enthält mit
dem aktuellen Symbolnamen, geben wir nur den Modus der Arbeit mit dem aktuellen Symbol zurück,
- geben wir in der letzten der möglichen Optionen die
Betriebsart mit einer vordefinierten Liste zurück.
Implementierung des Verfahrens zur Rückgabe einer Symbolzuordnung zu einer Gruppe über ihren Namen:
//+------------------------------------------------------------------+ //| Define a symbol affiliation with a group by name and return it | //+------------------------------------------------------------------+ ENUM_SYMBOL_STATUS CSymbolsCollection::SymbolStatus(const string symbol_name) const { ENUM_SYMBOL_STATUS status=this.StatusByCustomPredefined(symbol_name); return(status==SYMBOL_STATUS_COMMON ? this.StatusByCalcMode(symbol_name) : status); } //+------------------------------------------------------------------+
Ein Symbolname wird an die Methode übergeben. Als Nächstes wird seine
Zugehörigkeit zu bestimmten nutzerdefinierten Gruppen überprüft. Wenn
der Status "Allgemeine Gruppe" zurückgegeben wird, wird nach einer
Gruppe über die Symboleigenschaft "Margin Calculation Mode" gesucht. Infolgedessen wird der
erhaltene Status zurückgegeben. Übrigens kann sie nach dem Gewinn- und Margenrechnungsmodus mit einer der Gruppen
gleichgesetzt werden, oder sie kann in der allgemeinen Symbolgruppe verbleiben.
Dadurch erhält das Symbol einen nutzerdefinierten Gruppenstatus. Wenn sie in den nutzerdefinierten Gruppen nicht vorhanden ist,
kann ihr eine Gruppe nach
eine
Margenberechnungsmethode zugeordnet werden. Wenn es nicht gelungen ist, es innerhalb dieser Gruppe zu definieren, bleibt es in der
allgemeinen Gruppe.
Implementierung der Methoden, die das Flag der Symbolzuordnung zu bestimmten nutzerdefinierten Gruppen zurückgeben:
//+------------------------------------------------------------------+ //| Return a symbol affiliation with majors | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPredefinedFXMajor(const string name) const { int total=::ArraySize(DataSymbolsFXMajors); for(int i=0;i<total;i++) if(name==DataSymbolsFXMajors[i]) return true; return false; } //+------------------------------------------------------------------+ //| Return a symbol affiliation with minors | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPredefinedFXMinor(const string name) const { int total=::ArraySize(DataSymbolsFXMinors); for(int i=0;i<total;i++) if(name==DataSymbolsFXMinors[i]) return true; return false; } //+------------------------------------------------------------------+ //| Return a symbol affiliation with exotic symbols | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPredefinedFXExotic(const string name) const { int total=::ArraySize(DataSymbolsFXExotics); for(int i=0;i<total;i++) if(name==DataSymbolsFXExotics[i]) return true; return false; } //+------------------------------------------------------------------+ //| Return a symbol affiliation with RUB symbols | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPredefinedFXRUB(const string name) const { int total=::ArraySize(DataSymbolsFXRub); for(int i=0;i<total;i++) if(name==DataSymbolsFXRub[i]) return true; return false; } //+------------------------------------------------------------------+ //| Return a symbol affiliation with indicative symbols | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPredefinedIndicative(const string name) const { int total=::ArraySize(DataSymbolsFXIndicatives); for(int i=0;i<total;i++) if(name==DataSymbolsFXIndicatives[i]) return true; return false; } //+------------------------------------------------------------------+ //| Return a symbol affiliation with metals | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPredefinedMetall(const string name) const { int total=::ArraySize(DataSymbolsMetalls); for(int i=0;i<total;i++) if(name==DataSymbolsMetalls[i]) return true; return false; } //+------------------------------------------------------------------+ //| Return a symbol affiliation with commodities | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPredefinedCommodity(const string name) const { int total=::ArraySize(DataSymbolsCommodities); for(int i=0;i<total;i++) if(name==DataSymbolsCommodities[i]) return true; return false; } //+------------------------------------------------------------------+ //| Return a symbol affiliation with indices | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPredefinedIndex(const string name) const { int total=::ArraySize(DataSymbolsIndexes); for(int i=0;i<total;i++) if(name==DataSymbolsIndexes[i]) return true; return false; } //+------------------------------------------------------------------+ //| Return a symbol affiliation with a cryptocurrency | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPredefinedCrypto(const string name) const { int total=::ArraySize(DataSymbolsCrypto); for(int i=0;i<total;i++) if(name==DataSymbolsCrypto[i]) return true; return false; } //+------------------------------------------------------------------+ //| Return a symbol affiliation with options | //+------------------------------------------------------------------+ bool CSymbolsCollection::IsPredefinedOption(const string name) const { int total=::ArraySize(DataSymbolsOptions); for(int i=0;i<total;i++) if(name==DataSymbolsOptions[i]) return true; return false; } //+------------------------------------------------------------------+
Abhängig von einem Methodennamen (einer angekreuzten nutzerdefinierten Gruppe) wird die Suche nach einem Symbol, dessen Name an die Methode
übergeben wurde, in dem der Gruppe entsprechenden nutzerdefinierten Array durchgeführt.
Wenn ein solches Symbol im Array gefunden wird, wird true
zurückgegeben. Andernfalls — falsch.
Das Verfahren gibt einen Symbolstatus durch seine Anwesenheit in den nutzerdefinierten Gruppen zurück:
//+------------------------------------------------------------------+ //| Return a category by custom criteria | //+------------------------------------------------------------------+ ENUM_SYMBOL_STATUS CSymbolsCollection::StatusByCustomPredefined(const string symbol_name) const { return ( this.IsPredefinedFXMajor(symbol_name) ? SYMBOL_STATUS_FX_MAJOR : this.IsPredefinedFXMinor(symbol_name) ? SYMBOL_STATUS_FX_MINOR : this.IsPredefinedFXExotic(symbol_name) ? SYMBOL_STATUS_FX_EXOTIC : this.IsPredefinedFXRUB(symbol_name) ? SYMBOL_STATUS_FX_RUB : this.IsPredefinedOption(symbol_name) ? SYMBOL_STATUS_OPTION : this.IsPredefinedCommodity(symbol_name) ? SYMBOL_STATUS_COMMODITY : this.IsPredefinedCrypto(symbol_name) ? SYMBOL_STATUS_CRYPTO : this.IsPredefinedMetall(symbol_name) ? SYMBOL_STATUS_METAL : this.IsPredefinedIndex(symbol_name) ? SYMBOL_STATUS_INDEX : this.IsPredefinedIndicative(symbol_name) ? SYMBOL_STATUS_INDICATIVE : SYMBOL_STATUS_COMMON ); } //+------------------------------------------------------------------+
Ein Symbolname wird an die Methode übergeben und seine
Anwesenheit in jeder der nutzerdefinierten Gruppen wird nacheinander mit den obigen Methoden überprüft. Sobald ein Symbol in
einer der Gruppen erscheint, wird ein Status zurückgegeben, der der Gruppe entspricht, in der es gefunden wurde.
Wenn das Symbol in keiner der Gruppen gefunden wird, wird der Status "Allgemeine
Symbolgruppe" zurückgegeben.
Das Verfahren, das eine Symbolzugehörigkeit zu einer Gruppe nach der Margenberechnungsmethode zurückgibt:
//+------------------------------------------------------------------+ //|Return affiliation with a margin calculation category | //+------------------------------------------------------------------+ ENUM_SYMBOL_STATUS CSymbolsCollection::StatusByCalcMode(const string symbol_name) const { ENUM_SYMBOL_CALC_MODE calc_mode=(ENUM_SYMBOL_CALC_MODE)::SymbolInfoInteger(symbol_name,SYMBOL_TRADE_CALC_MODE); return ( calc_mode==SYMBOL_CALC_MODE_EXCH_OPTIONS_MARGIN ? SYMBOL_STATUS_OPTION : calc_mode==SYMBOL_CALC_MODE_SERV_COLLATERAL ? SYMBOL_STATUS_COLLATERAL : calc_mode==SYMBOL_CALC_MODE_FUTURES ? SYMBOL_STATUS_FUTURES : calc_mode==SYMBOL_CALC_MODE_CFD || calc_mode==SYMBOL_CALC_MODE_CFDINDEX || calc_mode==SYMBOL_CALC_MODE_CFDLEVERAGE ? SYMBOL_STATUS_CFD : calc_mode==SYMBOL_CALC_MODE_FOREX || calc_mode==SYMBOL_CALC_MODE_FOREX_NO_LEVERAGE ? SYMBOL_STATUS_FX : calc_mode==SYMBOL_CALC_MODE_EXCH_STOCKS || calc_mode==SYMBOL_CALC_MODE_EXCH_STOCKS_MOEX ? SYMBOL_STATUS_STOCKS : calc_mode==SYMBOL_CALC_MODE_EXCH_BONDS || calc_mode==SYMBOL_CALC_MODE_EXCH_BONDS_MOEX ? SYMBOL_STATUS_BONDS : calc_mode==SYMBOL_CALC_MODE_EXCH_FUTURES || calc_mode==SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS ? SYMBOL_STATUS_FUTURES : SYMBOL_STATUS_COMMON ); } //+------------------------------------------------------------------+
Das Verfahren empfängt einen Symbolnamen, als Nächstes
erhalten wir
die Margenberechnungsmethode für das Symbol und geben
den Symbolstatus abhängig von einem erhaltenen Wert zurück. Wenn keine
der Berechnungsmethoden identifiziert wurde, wird der Status "Allgemeine Symbolgruppe" zurückgegeben.
Das Verfahren sucht nach einem Symbol auf dem Server und gibt das Flag seiner Anwesenheit zurück:
//+---------------------------------------------------------------------------------+ //| Search for a symbol and return the flag indicating its presence on the server | //+---------------------------------------------------------------------------------+ bool CSymbolsCollection::Exist(const string name) const { int total=::SymbolsTotal(false); for(int i=0;i<total;i++) if(::SymbolName(i,false)==name) return true; return false; } //+------------------------------------------------------------------+
Die Klasse der Symbolkollektion ist fertig. Jetzt müssen wir ihn starten. Der Start und die Handhabung erfolgen wie gewohnt in der Klasse CEngine. Lassen Sie uns die notwendigen Änderungen daran vornehmen.
Einbinden der Klassendatei der Symbolsammlung in die Klassendatei CEngine ein und deklarieren eines Symbolsammelobjekts sowie der notwendigen Methoden:
//+------------------------------------------------------------------+ //| Engine.mqh | //| Copyright 2018, MetaQuotes Software Corp. | //| https://mql5.com/de/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, 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" //+------------------------------------------------------------------+ //| Bibliothek der Basisklasse | //+------------------------------------------------------------------+ class CEngine : public CObject { 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 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 ENUM_TRADE_EVENT m_last_trade_event; // Last account trading event ENUM_ACCOUNT_EVENT m_last_account_event; // Last event in the account properties //--- Rückgabe des Zählerindex über die ID int CounterIndex(const int id) const; //--- Rückgabe (1) des Flag des Erststarts, (2) der Existenz des Flags eines Handelsereignisses bool IsFirstStart(void); //--- Work with (1) order, deal and position, (2) account events void TradeEventsControl(void); void AccountEventsControl(void); //--- (1) Working with a symbol collection and (2) symbol list events in the market watch window void SymbolEventsControl(void); void MarketWatchEventsControl(void); //--- Rückgabe der letzten (1) Pending-Order, (2) Marktorder, (3) letzten Position, (4) Position nach Ticket COrder *GetLastMarketPending(void); COrder *GetLastMarketOrder(void); COrder *GetLastPosition(void); COrder *GetPosition(const ulong ticket); //--- Rückgabe der letzten (1) gelöschten Pending-Order, (2) historischen Marktorder, (3) historischen Aufträge (Markt- oder Pending-Orders) nach Ticket COrder *GetLastHistoryPending(void); COrder *GetLastHistoryOrder(void); COrder *GetHistoryOrder(const ulong ticket); //--- Rückgabe des (1) ersten und (2) des letzten historischen Marktorder aus der Liste aller Positionen, (3) des letzten Deals COrder *GetFirstOrderPosition(const ulong position_id); COrder *GetLastOrderPosition(const ulong position_id); COrder *GetLastDeal(void); public: //--- Rückgabe der Liste aller (1) Positionen, (2) Pending-Order und (3) Marktorders CArrayObj *GetListMarketPosition(void); CArrayObj *GetListMarketPendings(void); CArrayObj *GetListMarketOrders(void); //--- Rückgabe der Liste aller historischen (1) Aufträge, (2) gelöschten Pending-Orders, (3) Deals, (4) Positionen nach deren ID CArrayObj *GetListHistoryOrders(void); CArrayObj *GetListHistoryPendings(void); CArrayObj *GetListDeals(void); CArrayObj *GetListAllOrdersByPosID(const ulong position_id); //--- Return the list of (1) accounts, (2) account events, (3) account change event by its index in the list //--- (4) the current account, (5) event description CArrayObj *GetListAllAccounts(void) { return this.m_accounts.GetList(); } CArrayInt *GetListAccountEvents(void) { return this.m_accounts.GetListChanges(); } ENUM_ACCOUNT_EVENT GetAccountEventByIndex(const int index) { return this.m_accounts.GetEvent(index); } CAccount *GetAccountCurrent(void); string GetAccountEventDescription(ENUM_ACCOUNT_EVENT event); //--- Return the list of used symbols CArrayObj *GetListAllUsedSymbols(void) { return this.m_symbols.GetList(); } //--- Return the list of order, deal and position events CArrayObj *GetListAllOrdersEvents(void) { return this.m_events.GetList(); } //--- Rücksetzen des letzten Handelsereignisses void ResetLastTradeEvent(void) { this.m_events.ResetLastTradeEvent(); } //--- Return the (1) last trading event, (2) the last event in the account properties, (3) hedging account flag, (4) flag of working in the tester ENUM_TRADE_EVENT LastTradeEvent(void) const { return this.m_last_trade_event; } ENUM_ACCOUNT_EVENT LastAccountEvent(void) const { return this.m_last_account_event; } bool IsHedge(void) const { return this.m_is_hedge; } bool IsTester(void) const { return this.m_is_tester; } bool IsAccountsEvent(void) const { return this.m_accounts.IsAccountEvent(); } //--- Return an account event code int GetAccountEventsCode(void) const { return this.m_accounts.GetEventCode(); } //--- Return CEngine global error code int GetError(void) const { return this.m_global_error; } //--- Erstellen der Timerzählers void CreateCounter(const int id,const ulong frequency,const ulong pause); //--- Timer void OnTimer(void); //--- Set the list of used symbols bool SetUsedSymbols(const string &array_symbols[]) { return this.m_symbols.SetUsedSymbol(array_symbols); } //--- Constructor/Destructor CEngine(); ~CEngine(); }; //+------------------------------------------------------------------+
Die Methode SymbolEventsControl() wird verwendet, um Kursdaten
aller Kollektionssymbole zu aktualisieren, während die Methode
MarketWatchEventsControl() verwendet wird, um die restlichen Daten
aller Kollektionssymbole und Verfolgungsereignisse im Fenster Marktübersicht zu aktualisieren (zu berücksichtigen in der Klasse der
Ereignisse der Kollektionssymbole des nächsten Artikels).
Die Methode GetListAllUsedSymbols() gibt dem aufrufenden
Programm die vollständige Liste der Kollektionssymbole mit der Methode GetList() der Klasse CSymbolsCollection zurück.
Die Methode SetUsedSymbols() ruft die gleichnamige Methode
SetUsedSymbol() der Klasse CSymbolsCollection auf, die wiederum die Kollektionsliste mit Symbolobjekten aller im Programm
verwendeten Symbole füllt.
Lassen Sie uns die Struktur dieser Methoden betrachten.
Im Klassenkonstruktor erstellen wir die Zähler der ersten
und zweiten Timer der Kollektionssymbole. Im ersten Timer
aktualisieren wir die Kursdaten aller Kollektionssymbole, während im zweiten die restlichen Symboldaten aktualisiert und die
Ereignisse im Fenster der Marktübersicht verwaltet werden.
//+------------------------------------------------------------------+ //| CEngine Konstruktor | //+------------------------------------------------------------------+ CEngine::CEngine() : m_first_start(true),m_last_trade_event(TRADE_EVENT_NO_EVENT),m_last_account_event(ACCOUNT_EVENT_NO_EVENT),m_global_error(ERR_SUCCESS) { this.m_is_hedge=#ifdef __MQL4__ true #else bool(::AccountInfoInteger(ACCOUNT_MARGIN_MODE)==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING) #endif; this.m_is_tester=::MQLInfoInteger(MQL_TESTER); this.m_list_counters.Sort(); this.m_list_counters.Clear(); this.CreateCounter(COLLECTION_ORD_COUNTER_ID,COLLECTION_ORD_COUNTER_STEP,COLLECTION_ORD_PAUSE); this.CreateCounter(COLLECTION_ACC_COUNTER_ID,COLLECTION_ACC_COUNTER_STEP,COLLECTION_ACC_PAUSE); this.CreateCounter(COLLECTION_SYM_COUNTER_ID1,COLLECTION_SYM_COUNTER_STEP1,COLLECTION_SYM_PAUSE1); this.CreateCounter(COLLECTION_SYM_COUNTER_ID2,COLLECTION_SYM_COUNTER_STEP2,COLLECTION_SYM_PAUSE2); ::ResetLastError(); #ifdef __MQL5__ if(!::EventSetMillisecondTimer(TIMER_FREQUENCY)) { ::Print(DFUN_ERR_LINE,"Не удалось создать таймер. Ошибка: ","Could not create timer. Error: ",(string)::GetLastError()); this.m_global_error=::GetLastError(); } //---__MQL4__ #else if(!this.IsTester() && !::EventSetMillisecondTimer(TIMER_FREQUENCY)) { ::Print(DFUN_ERR_LINE,"Не удалось создать таймер. Ошибка: ","Could not create timer. Error: ",(string)::GetLastError()); this.m_global_error=::GetLastError(); } #endif } //+------------------------------------------------------------------+
Hinzufügen von Zeichenketten für die Arbeit mit zwei Timern der Kollektionssymbole zum Class OnTimer() Handler:
//+------------------------------------------------------------------+ //| CEngine Timer | //+------------------------------------------------------------------+ void CEngine::OnTimer(void) { //--- Timer der Collection der historischen Aufträge und Deals, und aus der Marktorders und Positionen int index=this.CounterIndex(COLLECTION_ORD_COUNTER_ID); if(index>WRONG_VALUE) { CTimerCounter* counter=this.m_list_counters.At(index); if(counter!=NULL) { //--- If this is not a tester if(!this.IsTester()) { //--- If unpaused, work with the order, deal and position collections events if(counter.IsTimeDone()) this.TradeEventsControl(); } //--- If this is a tester, work with collection events by tick else this.TradeEventsControl(); } } //--- Account collection timer index=this.CounterIndex(COLLECTION_ACC_COUNTER_ID); if(index>WRONG_VALUE) { CTimerCounter* counter=this.m_list_counters.At(index); if(counter!=NULL) { //--- If this is not a tester if(!this.IsTester()) { //--- If unpaused, work with the account collection events if(counter.IsTimeDone()) this.AccountEventsControl(); } //--- If this is a tester, work with collection events by tick else this.AccountEventsControl(); } } //--- Timer 1 of the symbol collection (updating symbol quote data in the collection) index=this.CounterIndex(COLLECTION_SYM_COUNTER_ID1); if(index>WRONG_VALUE) { CTimerCounter* counter=this.m_list_counters.At(index); if(counter!=NULL) { //--- If this is not a tester if(!this.IsTester()) { //--- If the pause is over, update quote data of all symbols in the collection if(counter.IsTimeDone()) this.SymbolEventsControl(); } //--- In case of a tester, update quote data of all collection symbols by tick else this.SymbolEventsControl(); } } //--- Timer 2 of the symbol collection (updating all data of all symbols in the collection and track symbol search events in the market watch window) index=this.CounterIndex(COLLECTION_SYM_COUNTER_ID2); if(index>WRONG_VALUE) { CTimerCounter* counter=this.m_list_counters.At(index); if(counter!=NULL) { //--- If this is not a tester if(!this.IsTester()) { //--- If the pause is over if(counter.IsTimeDone()) { //--- update data of all symbols in the collection this.m_symbols.Refresh(); //--- When workign with the market watch list, check the market watch window events if(this.m_symbols.ModeSymbolsList()==SYMBOLS_MODE_MARKET_WATCH) this.MarketWatchEventsControl(); } } //--- In case of a tester, update data of all collection symbols by tick else this.m_symbols.Refresh(); } } } //+------------------------------------------------------------------+
Die gesamte Logik ist in den Codekommentaren enthalten. Es hat keinen Sinn, hier darauf einzugehen.
In der aktuellen Implementierung aktualisiert die Methode, die mit einer Symbolsammlung arbeitet, einfach die
aktualisierten Kursdaten aller Kollektionssymbole mit der RefreshRates-Methode der CSymbolsCollection-Klasse:
//+------------------------------------------------------------------+ //| Working with a symbol collection | //+------------------------------------------------------------------+ void CEngine::SymbolEventsControl(void) { this.m_symbols.RefreshRates(); } //+------------------------------------------------------------------+
In der aktuellen Implementierung überprüft die Methode zum Arbeiten mit den Fensterereignissen der Marktübersicht
nur , dass sie vom Tester aufgerufen wurde und beendet wird, wenn sie im Tester
funktioniert (es macht keinen Sinn, die Ereignisse im Fenster der Marktübersicht im Tester zu verfolgen):
//+------------------------------------------------------------------+ //| Working with symbol list events in the market watch window | //+------------------------------------------------------------------+ void CEngine::MarketWatchEventsControl(void) { if(this.IsTester()) return; //--- Tracking Market Watch window events //--- } //+------------------------------------------------------------------+
Wir werden die gesamte Arbeit im Zusammenhang mit Ereignissen der Symbolsammlung im nächsten Artikel erledigen.
Dies sind alle notwendigen Änderungen an der Klasse CEngine.
Da wir den erforderlichen Modus der Arbeit mit Symbolen an die Klasse der Symbolsammlung übergeben müssen, benötigen wir die Funktion, die die Betriebsart definiert und das an das Hauptobjekt der Bibliothek CEngine zu übergebende Symbol-Array korrekt ausfüllt.
Öffnen Sie die Datei DELib.mqh Servicefunktionen aus \MQL5\Include\DoEasy\Services\ und fügen Sie die erforderliche Funktion hinzu:
//+------------------------------------------------------------------+ //| Prepare the symbol array for a symbol collection | //+------------------------------------------------------------------+ bool CreateUsedSymbolsArray(const ENUM_SYMBOLS_MODE mode_used_symbols,string defined_used_symbols,string &used_symbols_array[]) { //--- When working with the current symbol if(mode_used_symbols==SYMBOLS_MODE_CURRENT) { //--- Write the name of the current symbol to the only array cell ArrayResize(used_symbols_array,1); used_symbols_array[0]=Symbol(); return true; } //--- If working with a predefined symbol set (from the defined_used_symbols string) else if(mode_used_symbols==SYMBOLS_MODE_DEFINES) { //--- Set a comma as a separator string separator=","; //--- Replace erroneous separators with correct ones if(StringFind(defined_used_symbols,";")>WRONG_VALUE) StringReplace(defined_used_symbols,";",separator); if(StringFind(defined_used_symbols,":")>WRONG_VALUE) StringReplace(defined_used_symbols,":",separator); if(StringFind(defined_used_symbols,"|")>WRONG_VALUE) StringReplace(defined_used_symbols,"|",separator); if(StringFind(defined_used_symbols,"/")>WRONG_VALUE) StringReplace(defined_used_symbols,"/",separator); if(StringFind(defined_used_symbols,"\\")>WRONG_VALUE) StringReplace(defined_used_symbols,"\\",separator); if(StringFind(defined_used_symbols,"'")>WRONG_VALUE) StringReplace(defined_used_symbols,"'",separator); if(StringFind(defined_used_symbols,"-")>WRONG_VALUE) StringReplace(defined_used_symbols,"-",separator); if(StringFind(defined_used_symbols,"`")>WRONG_VALUE) StringReplace(defined_used_symbols,"`",separator); //--- Delete as long as there are spaces while(StringFind(defined_used_symbols," ")>WRONG_VALUE && !IsStopped()) StringReplace(defined_used_symbols," ",""); //--- As soon as there are double separators (after removing spaces between them), replace them with a separator while(StringFind(defined_used_symbols,separator+separator)>WRONG_VALUE && !IsStopped()) StringReplace(defined_used_symbols,separator+separator,separator); //--- If a single separator remains before the first symbol in the string, replace it with a space if(StringFind(defined_used_symbols,separator)==0) StringSetCharacter(defined_used_symbols,0,32); //--- If a single separator remains after the last symbol in the string, replace it with a space if(StringFind(defined_used_symbols,separator)==StringLen(defined_used_symbols)-1) StringSetCharacter(defined_used_symbols,StringLen(defined_used_symbols)-1,32); //--- Remove all redundant things to the left and right #ifdef __MQL5__ StringTrimLeft(defined_used_symbols); StringTrimRight(defined_used_symbols); //--- __MQL4__ #else defined_used_symbols=StringTrimLeft(defined_used_symbols); defined_used_symbols=StringTrimRight(defined_used_symbols); #endif //--- Prepare the array ArrayResize(used_symbols_array,0); ResetLastError(); //--- divide the string by separators (comma) and add all found substrings to the array int n=StringSplit(defined_used_symbols,StringGetCharacter(separator,0),used_symbols_array); //--- if nothing is found, display the appropriate message (working with the current symbol is selected automatically) if(n<1) { string err= (n==0 ? DFUN_ERR_LINE+TextByLanguage("Ошибка. Строка предопределённых символов пустая, будет использоваться ","Error. String of predefined symbols empty, symbol will be used: ")+Symbol() : DFUN_ERR_LINE+TextByLanguage("Не удалось подготовить массив используемых символов. Ошибка ","Failed to create array of used characters. Error ")+(string)GetLastError() ); Print(err); return false; } } //--- If working with the Market Watch window or the full list else { //--- Add the (mode_used_symbols) working mode to the only array cell ArrayResize(used_symbols_array,1); used_symbols_array[0]=EnumToString(mode_used_symbols); } return true; } //+------------------------------------------------------------------+
Das Verfahren erhält den Modus des Arbeitens mit der Symbolkollektion,
der entweder in den Programmeinstellungen einzustellen oder fest definiert ist (wenn keine Modusauswahl erforderlich ist),
die kommagetrennte Liste der Symbole, mit denen Sie arbeiten
möchten (oder eine leere Zeichenkette) und das
Array, dem die Symbolliste hinzugefügt werden soll, oder der Arbeitsmodus
(für das Arbeiten mit der Marktbeobachtung und der vollständigen Liste der Serversymbole), der an die Klasse CEngine gesendet werden
soll, um den Bibliotheksmodus für das Arbeiten mit Symbolen einzustellen.
Alle Aktionen der auf die Liste und das Array gerichteten Funktion werden direkt in der Liste ausführlich beschrieben. Es hat keinen
Sinn, sie getrennt zu betrachten.
Damit ist die Entwicklung der Klasse der Symbolkollektion abgeschlossen. Alles ist bereit zum Testen.
Test der Symbolkollektion
Um die Kollektion zu testen, werden wir den EA vom vorherigen Artikel verwenden und es in \MQL5\Experts\TestDoEasy\ unter dem Namen Part15\TestDoEasyPart15_1.mq5 speichern.
Fügen Sie in den Eingaben die Auswahl des Arbeitsmodus mit der Symbolsammlung der Bibliothek und eine String-Variable hinzu, die die Liste der nutzerdefinierten Symbole speichert, mit denen Sie arbeiten sollten, falls dieser Modus in den Einstellungen ausgewählt ist:
//--- Eingabeparameter input ulong InpMagic = 123; // Magic number input double InpLots = 0.1; // Lots input uint InpStopLoss = 50; // StopLoss in points input uint InpTakeProfit = 50; // TakeProfit in points input uint InpDistance = 50; // Pending orders distance (points) input uint InpDistanceSL = 50; // StopLimit orders distance (points) input uint InpSlippage = 0; // Slippage in points input double InpWithdrawal = 10; // Withdrawal funds (in tester) input uint InpButtShiftX = 40; // Buttons X shift input uint InpButtShiftY = 10; // Buttons Y shift input uint InpTrailingStop = 50; // Trailing Stop (points) input uint InpTrailingStep = 20; // Trailing Step (points) input uint InpTrailingStart = 0; // Trailing Start (points) input uint InpStopLossModify = 20; // StopLoss for modification (points) input uint InpTakeProfitModify = 60; // TakeProfit for modification (points) input ENUM_SYMBOLS_MODE InpModeUsedSymbols = SYMBOLS_MODE_CURRENT; // Mode of used symbols list input string InpUsedSymbols = "EURUSD,AUDUSD,EURAUD,EURCAD,EURGBP,EURJPY,EURUSD,GBPUSD,NZDUSD,USDCAD,USDJPY"; // List of used symbols (comma - separator) //--- Globale Variablen
Fügen wir in der Liste der globalen Variablen die Variable Variable zum
Speichern einer benutzerdefinierten Symbolleiste und ein String-Array hinzu, um die
Liste der Symbole an die Bibliothek zu übergeben:
//--- Globale Variablen CEngine engine; #ifdef __MQL5__ CTrade trade; #endif SDataButt butt_data[TOTAL_BUTT]; string prefix; double lot; double withdrawal=(InpWithdrawal<0.1 ? 0.1 : InpWithdrawal); ulong magic_number; uint stoploss; uint takeprofit; uint distance_pending; uint distance_stoplimit; uint slippage; bool trailing_on; double trailing_stop; double trailing_step; uint trailing_start; uint stoploss_to_modify; uint takeprofit_to_modify; string used_symbols; string array_used_symbols[]; //+------------------------------------------------------------------+
Weisen Sie im OnInit() des EAs die nutzerdefinierte Liste der
Variablen zu, um sie zu speichern, füllen Sie das Array der verwendeten
Symbole und senden Sie es an die Bibliothek:
//+------------------------------------------------------------------+ //| 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; //--- Fill in the array of used symbols used_symbols=InpUsedSymbols; CreateUsedSymbolsArray(InpModeUsedSymbols,used_symbols,array_used_symbols); //--- Set the type of the used symbol list in the symbol collection engine.SetUsedSymbols(array_used_symbols); //--- Check and remove remaining EA graphical objects
Die oben betrachtete Funktion SetUsedSymbols() erstellt das Symbol-Array, das an die Kollektionsklasse der Symbole gesendet wird. Abhängig vom gewählten Modus enthält das Array entweder das aktuelle Symbol oder die benutzerdefinierte Symbolliste oder eine Text-Beschreibung des Arbeitsmodus mit dem Fenster Market Watch oder mit einer vollständigen Symbolliste auf dem Server.
Fügen wir am Ende des OnInit()-Handlers den Code für die Schnellprüfung der von der Symbol Collection-Klasse erstellten Symbollisten hinzu:
//--- Set CTrade trading class parameters #ifdef __MQL5__ trade.SetDeviationInPoints(slippage); trade.SetExpertMagicNumber(magic_number); trade.SetTypeFillingBySymbol(Symbol()); trade.SetMarginMode(); trade.LogLevel(LOG_LEVEL_NO); #endif //--- Fast check of the symbol object collection CArrayObj *list=engine.GetListAllUsedSymbols(); CSymbol *symbol=NULL; if(list!=NULL) { int total=list.Total(); for(int i=0;i<total;i++) { symbol=list.At(i); if(symbol==NULL) continue; symbol.Refresh(); symbol.RefreshRates(); symbol.PrintShort(); if(InpModeUsedSymbols<SYMBOLS_MODE_MARKET_WATCH) symbol.Print(); } } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+
Hier erhalten wir die vollständige Liste aller Kollektionssymbole. In der Schleife über die erhaltene Liste, holen Sie das nächste Symbol, aktualisieren Sie alle Daten und drucken Sie die Beschreibung des Symbols im Journal aus. Zuerst wird die Kurzinfo angezeigt. Wenn dann der Modus "Working with the market watch window" oder "Working with the full list of symbols on the server" nicht ausgewählt ist , wird die vollständige Beschreibung der Symboleigenschaften im Journal angezeigt.
Starten Sie den EA im Terminalfenster und wählen Sie in den Einstellungen den Modus "Working with symbols from the Market Watch window". Dadurch wird im Journal die Liste mit Kurzbeschreibungen aller von der Klasse der Symbolkollektion angelegten Kollektionssymbole angezeigt:
2019.06.27 10:01:52.756 Stock ALNU 2019.06.27 10:01:52.756 Stock SU25075RMFS1 2019.06.27 10:01:52.756 Bond SU46022RMFS8 2019.06.27 10:01:52.756 Bond SU26214RMFS5 2019.06.27 10:01:52.756 Stock AESL 2019.06.27 10:01:52.756 Stock 123456.bin 2019.06.27 10:01:52.756 Stock ARMD 2019.06.27 10:01:52.757 Bond SU46018RMFS6 2019.06.27 10:01:52.757 Stock GAZP 2019.06.27 10:01:52.757 Metal XAUUSD 2019.06.27 10:01:52.757 Stock EURRUB_TOD 2019.06.27 10:01:52.757 Stock GBPRUB_TOM 2019.06.27 10:01:52.757 Futures Si-9.19 2019.06.27 10:01:52.757 Futures RTS-3.20 2019.06.27 10:01:52.758 Minor Forex symbol USDNOK 2019.06.27 10:01:52.758 Major Forex symbol USDJPY 2019.06.27 10:01:52.758 Major Forex symbol EURUSD 2019.06.27 10:01:52.758 Minor Forex symbol USDCZK 2019.06.27 10:01:52.758 Major Forex symbol USDCAD 2019.06.27 10:01:52.758 Minor Forex symbol USDZAR 2019.06.27 10:01:52.758 Minor Forex symbol USDSEK 2019.06.27 10:01:52.758 Major Forex symbol AUDUSD 2019.06.27 10:01:52.758 Minor Forex symbol USDDKK 2019.06.27 10:01:52.758 Major Forex symbol NZDUSD 2019.06.27 10:01:52.759 Minor Forex symbol USDPLN 2019.06.27 10:01:52.759 Major Forex symbol GBPUSD 2019.06.27 10:01:52.759 Forex symbol USDRUR 2019.06.27 10:01:52.759 Exotic Forex symbol USDMXN 2019.06.27 10:01:52.759 Forex symbol USDHUF 2019.06.27 10:01:52.759 Minor Forex symbol USDTRY 2019.06.27 10:01:52.759 Minor Forex symbol USDHKD 2019.06.27 10:01:52.760 Major Forex symbol USDCHF 2019.06.27 10:01:52.760 Minor Forex symbol USDSGD
Nun überprüfen wir die Suche nach bestimmten Werten in der Symbolkollektion.
Benennen Sie den EA um und
speichern Sie ihn in \MQL5\Experts\TestDoEasy\ unter dem Namen
Part15\TestDoEasyPart15_2.mq5.
Ändern Sie den Code der Schnellprüfung der Symbolkollektion in OnInit(). Verschieben Sie die Liste der Symbole in das Journal und lassen Sie nur das Aktualisierung der Daten der Kollektionssymbole und das Hinzufügen der Zeichenketten für den Empfang der maximalen und minimalen Swaps einer Long- und Short-Position sowie der maximalen und minimalen Spreads der Kollektionssymbole übrig. Geben Sie die erhaltenen Daten in das Journal ein:
//--- Set CTrade trading class parameters #ifdef __MQL5__ trade.SetDeviationInPoints(slippage); trade.SetExpertMagicNumber(magic_number); trade.SetTypeFillingBySymbol(Symbol()); trade.SetMarginMode(); trade.LogLevel(LOG_LEVEL_NO); #endif //--- Fast check of the symbol object collection CArrayObj *list=engine.GetListAllUsedSymbols(); CSymbol *symbol=NULL; if(list!=NULL) { int total=list.Total(); for(int i=0;i<total;i++) { symbol=list.At(i); if(symbol==NULL) continue; symbol.Refresh(); symbol.RefreshRates(); } } //--- Get the minimum and maximum values //--- get the current account properties (we need the number of decimal places for the account currency) CAccount *account=engine.GetAccountCurrent(); if(account!=NULL) { int index_min=0, index_max=0, dgc=(int)account.CurrencyDigits(); //--- If working with the Market Watch window, leave only visible symbols in the list if(InpModeUsedSymbols==SYMBOLS_MODE_MARKET_WATCH) list=CSelect::BySymbolProperty(list,SYMBOL_PROP_VISIBLE,true,EQUAL); //--- min/max swap long index_min=CSelect::FindSymbolMin(list,SYMBOL_PROP_SWAP_LONG); // symbol index in the collection list with the minimum swap long index_max=CSelect::FindSymbolMax(list,SYMBOL_PROP_SWAP_LONG); // symbol index in the collection list with the maximum swap long if(index_max!=WRONG_VALUE && index_min!=WRONG_VALUE) { symbol=list.At(index_min); if(symbol!=NULL) Print("Minimum swap long for a symbol ",symbol.Name()," = ",NormalizeDouble(symbol.SwapLong(),dgc)); symbol=list.At(index_max); if(symbol!=NULL) Print("Maximum swap long for a symbol ",symbol.Name()," = ",NormalizeDouble(symbol.SwapLong(),dgc)); } //--- min/max swap short index_min=CSelect::FindSymbolMin(list,SYMBOL_PROP_SWAP_SHORT); // symbol index in the collection list with the minimum swap short index_max=CSelect::FindSymbolMax(list,SYMBOL_PROP_SWAP_SHORT); // symbol index in the collection list with the maximum swap short if(index_max!=WRONG_VALUE && index_min!=WRONG_VALUE) { symbol=list.At(index_min); if(symbol!=NULL) Print("Minimum swap short for a symbol ",symbol.Name()," = ",NormalizeDouble(symbol.SwapShort(),dgc)); symbol=list.At(index_max); if(symbol!=NULL) Print("Maximum swap short for a symbol ",symbol.Name()," = ",NormalizeDouble(symbol.SwapShort(),dgc)); } //--- min/max spread index_min=CSelect::FindSymbolMin(list,SYMBOL_PROP_SPREAD); // symbol index in the collection list with the minimum spread index_max=CSelect::FindSymbolMax(list,SYMBOL_PROP_SPREAD); // symbol index in the collection list with the maximum spread if(index_max!=WRONG_VALUE && index_min!=WRONG_VALUE) { symbol=list.At(index_min); if(symbol!=NULL) Print("Minimum symbol spread ",symbol.Name()," = ",symbol.Spread()); symbol=list.At(index_max); if(symbol!=NULL) Print("Maximum symbol spread ",symbol.Name()," = ",symbol.Spread()); } } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+
Kompilieren und starten Sie den EA auf dem Chart des Terminals. Wählen Sie in den Einstellungen die Arbeit mit der vollständigen Liste der Symbole auf dem Server. Nach der Erstellung der Kollektionsliste aller Symbole auf dem Server (was einige Zeit in Anspruch nimmt) werden im Journal Daten über den maximalen und minimalen Long/Short-Tausch sowie die maximalen und minimalen Spreads aller Symbole in der Liste der Kollektionssymbole angezeigt:
2019.06.27 10:36:28.885 Minimum long position swap for USDZAR = -192.9 2019.06.27 10:36:28.885 Maximum long position swap for USDMXN = 432.7 2019.06.27 10:36:28.886 Minimum short position swap for XAUUSD = -17.8 2019.06.27 10:36:28.886 Maximum short position swap for USDMXN = 200.0 2019.06.27 10:36:28.886 Minimum spread for SU52001RMFS3 = 0 2019.06.27 10:36:28.886 Maximum spread for GBPRUB_TOM = 3975
Was kommt als Nächstes?
Im nächsten Artikel werden wir die Klasse der Ereignisse der Kollektionssymbole entwickeln.
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
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/7041
- 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.
Sehr gerne, wie schaffst du eine so gute Übersetzung ?
Sehr gerne, wie schaffst du eine so gute Übersetzung ?
Mit der Übersetzung von Artikeln? Das macht MetaQuotes.
Mit der Übersetzung von Artikeln? Das macht MetaQuotes.
Ok, ich dachte das macht der Artikel Ersteller.
Also arbeitet im Hintergrund noch ein externer Übersetzer ?
Ok, ich dachte das macht der Artikel Ersteller.
Also arbeitet im Hintergrund noch ein externer Übersetzer ?
Das MetaQuotes-Team verfügt über eigene Vollzeitübersetzer. Sie befassen sich mit der Übersetzung von Artikeln.
Das MetaQuotes-Team verfügt über eigene Vollzeitübersetzer. Sie befassen sich mit der Übersetzung von Artikeln.
Gut , danke für die Info