交易的品种在交易中起着至关重要作用。 首先,将程序加载到品种图表上(服务除外)。 此外,它会基于该交易品种操作,并执行交易和其他操作。 因此,合理地创造条件来方便地获得有关品种的必要数据,并具有分析和比较它们的能力。 为达此目的,我们将开发一个品种对象,一个品种对象集合,和品种集合事件。
我们将品种对象分为几类:
当然,所有这些类别都是任意的。 将某个品种置于特定类别中是非常主观的,并取决于用户的偏好。 可以从品种属性的“品种树路径”获得一些清晰概念。 它包含某个品种树文件夹中的品种位置路径,令您可把与文件夹名称匹配的类别分配给品种。
但是,终端所连接的每台服务器可能都有其自己的文件夹,用于存储具有匹配名称的品种。 文件夹的名称可能因服务器而异。
在我们所拥有的基础上,我们要做的第一件事是从类别的自定义列表中确定品种的类别,如果在自定义类别中找不到该品种,那么我们应该查看它在品种树中所处的文件夹。
如果无法从其位置文件夹中定义类别,则交易品种的最终选择是其“合约价格计算方法”属性,该属性令我们可以定义并选择两个交易品种之一 — 证券所或外汇。
不过,所有这些将在以后开发品种对象集合时完成。 现在我们需要开始创建基本品种对象。
我们从定义品种对象属性的枚举和宏替换开始。 打开 Defines.mqh 文件,并在清单的末尾添加操控品种的必要数据:
//+------------------------------------------------------------------+ //| Data for working with symbols | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| 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_FX_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_BIN_OPTION, // Binary option SYMBOL_STATUS_CUSTOM, // Custom symbol }; //+------------------------------------------------------------------+
品种状态是其所属的品种类别,从基本品种对象创建派生的对象之前将对其进行选择。 我们将在讲述品种集合开发时进行此操作。
我们添加品种整数型属性:
//+------------------------------------------------------------------+ //| Symbol integer properties | //+------------------------------------------------------------------+ enum ENUM_SYMBOL_PROP_INTEGER { SYMBOL_PROP_STATUS = 0, // Symbol status SYMBOL_PROP_CUSTOM, // Custom symbol flag SYMBOL_PROP_CHART_MODE, // The price type used for generating bars – Bid or Last (from the ENUM_SYMBOL_CHART_MODE enumeration) SYMBOL_PROP_EXIST, // Flag indicating that the symbol under this name exists SYMBOL_PROP_SELECT, // An indication that the symbol is selected in Market Watch SYMBOL_PROP_VISIBLE, // An indication that the symbol is displayed in Market Watch SYMBOL_PROP_SESSION_DEALS, // The number of deals in the current session SYMBOL_PROP_SESSION_BUY_ORDERS, // The total number of Buy orders at the moment SYMBOL_PROP_SESSION_SELL_ORDERS, // The total number of Sell orders at the moment SYMBOL_PROP_VOLUME, // Last deal volume SYMBOL_PROP_VOLUMEHIGH, // Maximum volume within a day SYMBOL_PROP_VOLUMELOW, // Minimum volume within a day SYMBOL_PROP_TIME, // Latest quote time SYMBOL_PROP_DIGITS, // Number of decimal places SYMBOL_PROP_DIGITS_LOTS, // Number of decimal places for a lot SYMBOL_PROP_SPREAD, // Spread in points SYMBOL_PROP_SPREAD_FLOAT, // Floating spread flag SYMBOL_PROP_TICKS_BOOKDEPTH, // Maximum number of orders displayed in the Depth of Market SYMBOL_PROP_TRADE_CALC_MODE, // Contract price calculation method (from the ENUM_SYMBOL_CALC_MODE enumeration) SYMBOL_PROP_TRADE_MODE, // Order execution type (from the ENUM_SYMBOL_TRADE_MODE enumeration) SYMBOL_PROP_START_TIME, // Symbol trading start date (usually used for futures) SYMBOL_PROP_EXPIRATION_TIME, // Symbol trading end date (usually used for futures) SYMBOL_PROP_TRADE_STOPS_LEVEL, // Minimum distance in points from the current close price for setting Stop orders SYMBOL_PROP_TRADE_FREEZE_LEVEL, // Freeze distance for trading operations (in points) SYMBOL_PROP_TRADE_EXEMODE, // Deal execution mode (from the ENUM_SYMBOL_TRADE_EXECUTION enumeration) SYMBOL_PROP_SWAP_MODE, // Swap calculation model (from the ENUM_SYMBOL_SWAP_MODE enumeration) SYMBOL_PROP_SWAP_ROLLOVER3DAYS, // Triple-day swap (from the ENUM_DAY_OF_WEEK enumeration) SYMBOL_PROP_MARGIN_HEDGED_USE_LEG, // Calculating hedging margin using the larger leg (Buy or Sell) SYMBOL_PROP_EXPIRATION_MODE, // Flags of allowed order expiration modes SYMBOL_PROP_FILLING_MODE, // Flags of allowed order filling modes SYMBOL_PROP_ORDER_MODE, // Flags of allowed order types SYMBOL_PROP_ORDER_GTC_MODE, // StopLoss and TakeProfit orders lifetime if SYMBOL_EXPIRATION_MODE=SYMBOL_EXPIRATION_GTC (from the ENUM_SYMBOL_ORDER_GTC_MODE enumeration) SYMBOL_PROP_OPTION_MODE, // Option type (from the ENUM_SYMBOL_OPTION_MODE enumeration) SYMBOL_PROP_OPTION_RIGHT, // Option right (Call/Put) (from the ENUM_SYMBOL_OPTION_RIGHT enumeration) SYMBOL_PROP_BACKGROUND_COLOR // The color of the background used for the symbol in Market Watch }; #define SYMBOL_PROP_INTEGER_TOTAL (35) // Total number of integer properties #define SYMBOL_PROP_INTEGER_SKIP (1) // Number of symbol integer properties not used in sorting //+------------------------------------------------------------------+
我们已经在函数库论述的第六部分的“ 在净持帐户上实现事件处理”章节中研究了对象属性的枚举,因此,我们不再赘述定义宏替换属性数量,以及搜索和排序中未使用的对象属性数量。
然而,我应提请注意,除了来自
ENUM_SYMBOL_INFO_INTEGER
枚举的标准品种对象整数型属性外,还添加了额外两个:
符号状态和品种手数值的小数位数。
我们添加品种实数型属性的枚举:
//+------------------------------------------------------------------+ //| 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 of the day SYMBOL_PROP_VOLUMELOW_REAL, // Minimum Volume of the day SYMBOL_PROP_OPTION_STRIKE, // Option execution price SYMBOL_PROP_POINT, // 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 price set by an issuer SYMBOL_PROP_TRADE_LIQUIDITY_RATE, // Liquidity rate – share of an asset value that can be used as a collateral 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 a deal SYMBOL_PROP_VOLUME_LIMIT, // Maximum acceptable total volume of an open position and pending orders in one direction (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, // Margin requirement applicable to long positions SYMBOL_PROP_MARGIN_SHORT, // Margin requirement applicable to short positions SYMBOL_PROP_MARGIN_STOP, // Margin requirement applicable to Stop orders SYMBOL_PROP_MARGIN_LIMIT, // Margin requirement applicable to Limit orders SYMBOL_PROP_MARGIN_STOPLIMIT, // Margin requirement applicable to Stop Limit 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, // The open price of the session SYMBOL_PROP_SESSION_CLOSE, // The 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, // The minimum allowable price value for the session SYMBOL_PROP_SESSION_PRICE_LIMIT_MAX, // The 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 (47) // Total number of event's real properties #define SYMBOL_PROP_DOUBLE_SKIP (0) // Number of symbol real properties not used in sorting //+------------------------------------------------------------------+
除了来自 ENUM_SYMBOL_INFO_DOUBLE枚举中列举的属性外,我们还添加了五个新品种属性,出于某些原因,这些属性未包含在已描述过的实数型属性枚举当中,但它们仍然存在,并属于该枚举。
我们添加品种的字符型属性枚举和可能的品种排序标准:
//+------------------------------------------------------------------+ //| Symbol string properties | //+------------------------------------------------------------------+ enum ENUM_SYMBOL_PROP_STRING { SYMBOL_PROP_NAME = (SYMBOL_PROP_INTEGER_TOTAL+SYMBOL_PROP_DOUBLE_TOTAL), // Symbol name SYMBOL_PROP_BASIS, // The name of the underlaying asset for a derivative symbol SYMBOL_PROP_CURRENCY_BASE, // The base currency of an instrument SYMBOL_PROP_CURRENCY_PROFIT, // Profit currency SYMBOL_PROP_CURRENCY_MARGIN, // Margin currency SYMBOL_PROP_BANK, // The source of the current quote SYMBOL_PROP_DESCRIPTION, // The string description of a symbol SYMBOL_PROP_FORMULA, // The formula used for custom symbol pricing SYMBOL_PROP_ISIN, // The name of a trading symbol in the international system of securities identification numbers (ISIN) SYMBOL_PROP_PAGE, // The address of the web page containing symbol information SYMBOL_PROP_PATH, // Path in the symbol tree }; #define SYMBOL_PROP_STRING_TOTAL (11) // Total number of string properties //+------------------------------------------------------------------+ //| 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 { //--- Sort by integer properties 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) //--- Sort by real properties 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 minimal 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, // Sort by coefficient of margin charging for long positions SORT_BY_SYMBOL_MARGIN_SHORT, // Sort by coefficient of margin charging for short positions SORT_BY_SYMBOL_MARGIN_STOP, // Sort by coefficient of margin charging for Stop orders SORT_BY_SYMBOL_MARGIN_LIMIT, // Sort by coefficient of margin charging for Limit orders SORT_BY_SYMBOL_MARGIN_STOPLIMIT, // Sort by coefficient of margin charging for Stop Limit 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 an Open price of the current session SORT_BY_SYMBOL_SESSION_CLOSE, // Sort by a Close price of the current session 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 minimal price of the current session SORT_BY_SYMBOL_SESSION_PRICE_LIMIT_MAX, // Sort by a maximal 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 //--- Sort by string properties 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 basic 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 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 }; //+------------------------------------------------------------------+
现在,字符型属性的枚举拥有 ENUM_SYMBOL_INFO_STRING枚举中的相应常量,而可能的排序条件列表则包含“市场观察”窗口中除品种背景色以外的所有品种属性。
没有理由在属于终端的窗口中根据品种的背景颜色对品种进行排序和比较。
这些是操控品种对象的所有必需数据。
现在我们来开发品种对象类。
在 \MQL5\Include\DoEasy\Objects\,为 CCymbol 类创建名为 Symbol.mqh 的新文件。 立即执行标准流程,包含并用类库方法填充该类:
//+------------------------------------------------------------------+ //| Symbol.mqh | //| Copyright 2018, MetaQuotes Software Corp. | //| https://mql5.com/en/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://mql5.com/en/users/artmedia70" #property version "1.00" #property strict // Necessary for mql4 //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include <Object.mqh> #include "..\..\Services\DELib.mqh" //+------------------------------------------------------------------+ //| Abstract symbol class | //+------------------------------------------------------------------+ class CSymbol : public CObject { private: 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 //--- 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; } public: //--- Default constructor CSymbol(void){;} protected: //--- Protected parametric constructor CSymbol(ENUM_SYMBOL_STATUS symbol_status,const string name); public: //--- Set (1) integer, (2) real and (3) string symbol properties void SetProperty(ENUM_SYMBOL_PROP_INTEGER property,long value) { this.m_long_prop[property]=value; } void SetProperty(ENUM_SYMBOL_PROP_DOUBLE property,double value) { this.m_double_prop[this.IndexProp(property)]=value; } void SetProperty(ENUM_SYMBOL_PROP_STRING property,string value) { this.m_string_prop[this.IndexProp(property)]=value; } //--- Return (1) integer, (2) real and (3) string symbol properties from the properties array long GetProperty(ENUM_SYMBOL_PROP_INTEGER property) const { return this.m_long_prop[property]; } double GetProperty(ENUM_SYMBOL_PROP_DOUBLE property) const { return this.m_double_prop[this.IndexProp(property)]; } string GetProperty(ENUM_SYMBOL_PROP_STRING property) const { return this.m_string_prop[this.IndexProp(property)]; } //--- Return the flag of a symbol supporting the property virtual bool SupportProperty(ENUM_SYMBOL_PROP_INTEGER property) { return true; } virtual bool SupportProperty(ENUM_SYMBOL_PROP_DOUBLE property) { return true; } virtual bool SupportProperty(ENUM_SYMBOL_PROP_STRING property) { return true; } //+------------------------------------------------------------------+ //| 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); //--- Return symbol status name string StatusDescription(void) const; //--- Send description of symbol properties to the journal (full_prop=true - all properties, false - only supported ones) void Print(const bool full_prop=false); //--- Compare CSymbol objects by all possible properties (for sorting lists by a specified symbol object property) virtual int Compare(const CObject *node,const int mode=0) const; //--- Compare CSymbol objects by all properties (for searching for equal event objects) bool IsEqual(CSymbol* compared_symbol) const; };
我们已在函数库论述的第一部分当中研究了所有这些方法。 在此啰嗦没有意义。
现在,将类操作所需的变量添加到私有部分:
//+------------------------------------------------------------------+ //| Symbol.mqh | //| Copyright 2018, MetaQuotes Software Corp. | //| https://mql5.com/en/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://mql5.com/en/users/artmedia70" #property version "1.00" #property strict // Necessary for mql4 //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include <Object.mqh> #include "..\..\Services\DELib.mqh" //+------------------------------------------------------------------+ //| Abstract symbol class | //+------------------------------------------------------------------+ class CSymbol : public CObject { private: 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; } //--- Reset all symbol object data void Reset(void); public: //--- Default constructor CSymbol(void){;} protected: //--- Protected parametric constructor CSymbol(ENUM_SYMBOL_STATUS symbol_status,const string name);
我们将从 即时报价结构获取要价,出价,最后价格和即时报价的时间数据 — MQL5 以毫秒为单位,MQL4 以秒为单位。 尽管毫秒字段在 MQL4
的即时报价结构中存在,但并未使用。 所以,对于 MQL4,我们将使用秒数 * 1000 将其转换为毫秒格式。
在稍后获取市场深度内容时,我们将需要市场深度数据结构数组(不在本文之中)。
全局错误代码
— 基于函数库的程序有时会因方法或函数的错误执行而无法进一步操作。 应将错误执行的方法或函数通知程序,以便能够及时正确地处理这种情况。 这些情况令我们引入该变量。 它包含一个错误代码,而 CEngine 函数库基础对象检查该错误代码。
如果代码包含非零值,则首先在 CEngine 类中对其进行处理。 在无法通过内部手段“解决问题”的情况下,则将代码发送到调用程序,以便及时响应错误。
在创建品种对象之前,其所有字段和结构均应重设。这就是调用
Reset() 方法的原由。
在受保护的类构造函数中,使用标准函数填充所有品种属性。 但是,并非所有函数都适用于 MQL4,因此,针对 MQL5 和 MQL4 获取数据的差异,我们应在类的受保护部分中创建获取数据的必要方法:
protected: //--- Protected parametric constructor CSymbol(ENUM_SYMBOL_STATUS symbol_status,const string name); //--- Get and return integer properties of a selected symbol from its parameters long SymbolExists(void) const; long SymbolCustom(void) const; long SymbolChartMode(void) const; long SymbolMarginHedgedUseLEG(void) const; long SymbolOrderFillingMode(void) const; long SymbolOrderMode(void) const; long SymbolOrderGTCMode(void) const; long SymbolOptionMode(void) const; long SymbolOptionRight(void) const; long SymbolBackgroundColor(void) const; long SymbolCalcMode(void) const; long SymbolSwapMode(void) const; long SymbolExpirationMode(void) const; long SymbolDigitsLot(void); //--- Get and return real properties of a selected symbol from its parameters double SymbolBidHigh(void) const; double SymbolBidLow(void) const; double SymbolVolumeReal(void) const; double SymbolVolumeHighReal(void) const; double SymbolVolumeLowReal(void) const; double SymbolOptionStrike(void) const; double SymbolTradeAccruedInterest(void) const; double SymbolTradeFaceValue(void) const; double SymbolTradeLiquidityRate(void) const; double SymbolMarginHedged(void) const; //--- Get and return string properties of a selected symbol from its parameters string SymbolBasis(void) const; string SymbolBank(void) const; string SymbolISIN(void) const; string SymbolFormula(void) const; string SymbolPage(void) const; //--- Return the number of decimal places of the account currency int DigitsCurrency(void) const { return this.m_digits_currency; } //--- Search for a symbol and return the flag indicating its presence on the server bool Exist(void) const; public:
在类的公开部分中,声明返回各种状态标志的方法,这些方法描述某些品种属性的允许模式,以及这些模式的字符型描述:
public: //--- Set (1) integer, (2) real and (3) string symbol properties void SetProperty(ENUM_SYMBOL_PROP_INTEGER property,long value) { this.m_long_prop[property]=value; } void SetProperty(ENUM_SYMBOL_PROP_DOUBLE property,double value) { this.m_double_prop[this.IndexProp(property)]=value; } void SetProperty(ENUM_SYMBOL_PROP_STRING property,string value) { this.m_string_prop[this.IndexProp(property)]=value; } //--- Return (1) integer, (2) real and (3) string symbol properties from the properties array long GetProperty(ENUM_SYMBOL_PROP_INTEGER property) const { return this.m_long_prop[property]; } double GetProperty(ENUM_SYMBOL_PROP_DOUBLE property) const { return this.m_double_prop[this.IndexProp(property)]; } string GetProperty(ENUM_SYMBOL_PROP_STRING property) const { return this.m_string_prop[this.IndexProp(property)]; } //--- Return the flag of a symbol supporting the property virtual bool SupportProperty(ENUM_SYMBOL_PROP_INTEGER property) { return true; } virtual bool SupportProperty(ENUM_SYMBOL_PROP_DOUBLE property) { return true; } virtual bool SupportProperty(ENUM_SYMBOL_PROP_STRING property) { return true; } //--- Return the flag of allowing (1) market, (2) limit, (3) stop (4) and stop limit orders, //--- the flag of allowing setting (5) StopLoss and (6) TakeProfit orders, (7) as well as closing by an opposite order bool IsMarketOrdersAllowed(void) const { return((this.OrderModeFlags() & SYMBOL_ORDER_MARKET)==SYMBOL_ORDER_MARKET); } bool IsLimitOrdersAllowed(void) const { return((this.OrderModeFlags() & SYMBOL_ORDER_LIMIT)==SYMBOL_ORDER_LIMIT); } bool IsStopOrdersAllowed(void) const { return((this.OrderModeFlags() & SYMBOL_ORDER_STOP)==SYMBOL_ORDER_STOP); } bool IsStopLimitOrdersAllowed(void) const { return((this.OrderModeFlags() & SYMBOL_ORDER_STOP_LIMIT)==SYMBOL_ORDER_STOP_LIMIT); } bool IsStopLossOrdersAllowed(void) const { return((this.OrderModeFlags() & SYMBOL_ORDER_SL)==SYMBOL_ORDER_SL); } bool IsTakeProfitOrdersAllowed(void) const { return((this.OrderModeFlags() & SYMBOL_ORDER_TP)==SYMBOL_ORDER_TP); } bool IsCloseByOrdersAllowed(void) const; //--- Return the (1) FOK and (2) IOC filling flag bool IsFillingModeFOK(void) const { return((this.FillingModeFlags() & SYMBOL_FILLING_FOK)==SYMBOL_FILLING_FOK); } bool IsFillingModeIOC(void) const { return((this.FillingModeFlags() & SYMBOL_FILLING_IOC)==SYMBOL_FILLING_IOC); } //--- Return the flag of order expiration: (1) GTC, (2) DAY, (3) Specified and (4) Specified Day bool IsExipirationModeGTC(void) const { return((this.ExpirationModeFlags() & SYMBOL_EXPIRATION_GTC)==SYMBOL_EXPIRATION_GTC); } bool IsExipirationModeDAY(void) const { return((this.ExpirationModeFlags() & SYMBOL_EXPIRATION_DAY)==SYMBOL_EXPIRATION_DAY); } bool IsExipirationModeSpecified(void) const { return((this.ExpirationModeFlags() & SYMBOL_EXPIRATION_SPECIFIED)==SYMBOL_EXPIRATION_SPECIFIED); } bool IsExipirationModeSpecifiedDay(void) const { return((this.ExpirationModeFlags() & SYMBOL_EXPIRATION_SPECIFIED_DAY)==SYMBOL_EXPIRATION_SPECIFIED_DAY); } //--- Return the description of allowing (1) market, (2) limit, (3) stop and (4) stop limit orders, //--- the description of allowing (5) StopLoss and (6) TakeProfit orders, (7) as well as closing by an opposite order string GetMarketOrdersAllowedDescription(void) const; string GetLimitOrdersAllowedDescription(void) const; string GetStopOrdersAllowedDescription(void) const; string GetStopLimitOrdersAllowedDescription(void) const; string GetStopLossOrdersAllowedDescription(void) const; string GetTakeProfitOrdersAllowedDescription(void) const; string GetCloseByOrdersAllowedDescription(void) const; //--- Return the description of allowing the filling type (1) FOK and (2) IOC, (3) as well as allowed order expiration modes string GetFillingModeFOKAllowedDescrioption(void) const; string GetFillingModeIOCAllowedDescrioption(void) const; //--- Return the description of order expiration: (1) GTC, (2) DAY, (3) Specified and (4) Specified Day string GetExpirationModeGTCDescription(void) const; string GetExpirationModeDAYDescription(void) const; string GetExpirationModeSpecifiedDescription(void) const; string GetExpirationModeSpecDayDescription(void) const; //--- Return the description of the (1) status, (2) price type for constructing bars, //--- (3) method of calculating margin, (4) instrument trading mode, //--- (5) deal execution mode for a symbol, (6) swap calculation mode, //--- (7) StopLoss and TakeProfit lifetime, (8) option type, (9) option rights //--- flags of (10) allowed order types, (11) allowed filling types, //--- (12) allowed order expiration modes string GetStatusDescription(void) const; string GetChartModeDescription(void) const; string GetCalcModeDescription(void) const; string GetTradeModeDescription(void) const; string GetTradeExecDescription(void) const; string GetSwapModeDescription(void) const; string GetOrderGTCModeDescription(void) const; string GetOptionTypeDescription(void) const; string GetOptionRightDescription(void) const; string GetOrderModeFlagsDescription(void) const; string GetFillingModeFlagsDescription(void) const; string GetExpirationModeFlagsDescription(void) const;
另外,将以下元素添加到类的公开部分:
错误代码获取方法, 按品种获取所有数据的方法,
按品种更新报价数据的方法, 以及从“市场观察”窗口中添加/删除品种的其他方法,
按品种返回数据同步标志的方法, 和订阅/取消订阅市场深度的方法。
我们将在后续的文章中编排操控市场深度。
//--- Return the global error code int GetError(void) const { return this.m_global_error; } //--- Update all symbol data that can change void Refresh(void); //--- Update quote data by a symbol void RefreshRates(void); //--- (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); } //--- (1) Arrange a (1) subscription to the market depth, (2) close the market depth bool BookAdd(void) const; bool BookClose(void) const;
由于我们已有按其名称(枚举常量)返回任何属性的方法,因此我们已经可以获取任何外部属性的数据,但是从编程的角度来看这是不切实际的,因为这要求我们记住品种对象属性枚举中的所有常量名称。 因此(与前面的类一样,出于相同的原因),我们将引入其他公开方法,这些方法返回品种对象的所有属性,但名称更多。
在类实体的末尾添加它们:
//+------------------------------------------------------------------+ //| 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 IsSelect(void) const { return (bool)this.GetProperty(SYMBOL_PROP_SELECT); } bool IsVisible(void) const { return (bool)this.GetProperty(SYMBOL_PROP_VISIBLE); } long SessionDeals(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_DEALS); } long SessionBuyOrders(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_BUY_ORDERS); } long SessionSellOrders(void) const { return this.GetProperty(SYMBOL_PROP_SESSION_SELL_ORDERS); } long Volume(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME); } long VolumeHigh(void) const { return this.GetProperty(SYMBOL_PROP_VOLUMEHIGH); } long VolumeLow(void) const { return this.GetProperty(SYMBOL_PROP_VOLUMELOW); } datetime Time(void) const { return (datetime)this.GetProperty(SYMBOL_PROP_TIME); } int Digits(void) const { return (int)this.GetProperty(SYMBOL_PROP_DIGITS); } int DigitsLot(void) const { return (int)this.GetProperty(SYMBOL_PROP_DIGITS_LOTS); } int Spread(void) const { return (int)this.GetProperty(SYMBOL_PROP_SPREAD); } bool IsSpreadFloat(void) const { return (bool)this.GetProperty(SYMBOL_PROP_SPREAD_FLOAT); } int TicksBookdepth(void) const { return (int)this.GetProperty(SYMBOL_PROP_TICKS_BOOKDEPTH); } ENUM_SYMBOL_CALC_MODE TradeCalcMode(void) const { return (ENUM_SYMBOL_CALC_MODE)this.GetProperty(SYMBOL_PROP_TRADE_CALC_MODE); } ENUM_SYMBOL_TRADE_MODE TradeMode(void) const { return (ENUM_SYMBOL_TRADE_MODE)this.GetProperty(SYMBOL_PROP_TRADE_MODE); } datetime StartTime(void) const { return (datetime)this.GetProperty(SYMBOL_PROP_START_TIME); } datetime ExpirationTime(void) const { return (datetime)this.GetProperty(SYMBOL_PROP_EXPIRATION_TIME); } int TradeStopLevel(void) const { return (int)this.GetProperty(SYMBOL_PROP_TRADE_STOPS_LEVEL); } int TradeFreezeLevel(void) const { return (int)this.GetProperty(SYMBOL_PROP_TRADE_FREEZE_LEVEL); } ENUM_SYMBOL_TRADE_EXECUTION TradeExecutionMode(void) const { return (ENUM_SYMBOL_TRADE_EXECUTION)this.GetProperty(SYMBOL_PROP_TRADE_EXEMODE); } ENUM_SYMBOL_SWAP_MODE SwapMode(void) const { return (ENUM_SYMBOL_SWAP_MODE)this.GetProperty(SYMBOL_PROP_SWAP_MODE); } ENUM_DAY_OF_WEEK SwapRollover3Days(void) const { return (ENUM_DAY_OF_WEEK)this.GetProperty(SYMBOL_PROP_SWAP_ROLLOVER3DAYS); } bool IsMarginHedgedUseLeg(void) const { return (bool)this.GetProperty(SYMBOL_PROP_MARGIN_HEDGED_USE_LEG); } int ExpirationModeFlags(void) const { return (int)this.GetProperty(SYMBOL_PROP_EXPIRATION_MODE); } int FillingModeFlags(void) const { return (int)this.GetProperty(SYMBOL_PROP_FILLING_MODE); } int OrderModeFlags(void) const { return (int)this.GetProperty(SYMBOL_PROP_ORDER_MODE); } ENUM_SYMBOL_ORDER_GTC_MODE OrderModeGTC(void) const { return (ENUM_SYMBOL_ORDER_GTC_MODE)this.GetProperty(SYMBOL_PROP_ORDER_GTC_MODE); } ENUM_SYMBOL_OPTION_MODE OptionMode(void) const { return (ENUM_SYMBOL_OPTION_MODE)this.GetProperty(SYMBOL_PROP_OPTION_MODE); } ENUM_SYMBOL_OPTION_RIGHT OptionRight(void) const { return (ENUM_SYMBOL_OPTION_RIGHT)this.GetProperty(SYMBOL_PROP_OPTION_RIGHT); } //--- Real properties double Bid(void) const { return this.GetProperty(SYMBOL_PROP_BID); } double BidHigh(void) const { return this.GetProperty(SYMBOL_PROP_BIDHIGH); } double BidLow(void) const { return this.GetProperty(SYMBOL_PROP_BIDLOW); } double Ask(void) const { return this.GetProperty(SYMBOL_PROP_ASK); } double AskHigh(void) const { return this.GetProperty(SYMBOL_PROP_ASKHIGH); } double AskLow(void) const { return this.GetProperty(SYMBOL_PROP_ASKLOW); } double Last(void) const { return this.GetProperty(SYMBOL_PROP_LAST); } double LastHigh(void) const { return this.GetProperty(SYMBOL_PROP_LASTHIGH); } double LastLow(void) const { return this.GetProperty(SYMBOL_PROP_LASTLOW); } double VolumeReal(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME_REAL); } double VolumeHighReal(void) const { return this.GetProperty(SYMBOL_PROP_VOLUMEHIGH_REAL); } double VolumeLowReal(void) const { return this.GetProperty(SYMBOL_PROP_VOLUMELOW_REAL); } double OptionStrike(void) const { return this.GetProperty(SYMBOL_PROP_OPTION_STRIKE); } double Point(void) const { return this.GetProperty(SYMBOL_PROP_POINT); } double TradeTickValue(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_TICK_VALUE); } double TradeTickValueProfit(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT); } double TradeTickValueLoss(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_TICK_VALUE_LOSS); } double TradeTickSize(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_TICK_SIZE); } double TradeContractSize(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_CONTRACT_SIZE); } double TradeAccuredInterest(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_ACCRUED_INTEREST); } double TradeFaceValue(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_FACE_VALUE); } double TradeLiquidityRate(void) const { return this.GetProperty(SYMBOL_PROP_TRADE_LIQUIDITY_RATE); } double LotsMin(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME_MIN); } double LotsMax(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME_MAX); } double LotsStep(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME_STEP); } double VolumeLimit(void) const { return this.GetProperty(SYMBOL_PROP_VOLUME_LIMIT); } double SwapLong(void) const { return this.GetProperty(SYMBOL_PROP_SWAP_LONG); } double SwapShort(void) const { return this.GetProperty(SYMBOL_PROP_SWAP_SHORT); } double MarginInitial(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_INITIAL); } double MarginMaintenance(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_MAINTENANCE); } double MarginLong(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_LONG); } double MarginShort(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_SHORT); } double MarginStop(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_STOP); } double MarginLimit(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_LIMIT); } double MarginStopLimit(void) const { return this.GetProperty(SYMBOL_PROP_MARGIN_STOPLIMIT); } 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 string Name(void) const { return this.GetProperty(SYMBOL_PROP_NAME); } string Basis(void) const { return this.GetProperty(SYMBOL_PROP_BASIS); } string CurrencyBase(void) const { return this.GetProperty(SYMBOL_PROP_CURRENCY_BASE); } string CurrencyProfit(void) const { return this.GetProperty(SYMBOL_PROP_CURRENCY_PROFIT); } string CurrencyMargin(void) const { return this.GetProperty(SYMBOL_PROP_CURRENCY_MARGIN); } string Bank(void) const { return this.GetProperty(SYMBOL_PROP_BANK); } string Description(void) const { return this.GetProperty(SYMBOL_PROP_DESCRIPTION); } string Formula(void) const { return this.GetProperty(SYMBOL_PROP_FORMULA); } string ISIN(void) const { return this.GetProperty(SYMBOL_PROP_ISIN); } string Page(void) const { return this.GetProperty(SYMBOL_PROP_PAGE); } string Path(void) const { return this.GetProperty(SYMBOL_PROP_PATH); } //--- }; //+------------------------------------------------------------------+
方法已声明,其中一些方法立即在类主体中实现。 现在,我们添加和分析所有已声明方法的实现。
实现受保护的类构造函数:
//+------------------------------------------------------------------+ //| Class methods | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| 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. No such symbol on server")); this.m_global_error=ERR_MARKET_UNKNOWN_SYMBOL; } ::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); } //--- Data initialization ::ZeroMemory(this.m_tick); this.Reset(); this.m_digits_currency=(#ifdef __MQL5__ (int)::AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS) #else 2 #endif); //--- Save integer properties 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_EXPIRATION_MODE] = ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_EXPIRATION_MODE); 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_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(); this.m_long_prop[SYMBOL_PROP_EXPIRATION_MODE] = this.SymbolExpirationMode(); //--- Save 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_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_MARGIN_LONG)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_MARGIN_LONG); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_MARGIN_SHORT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_STOP)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_MARGIN_STOP); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LIMIT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_MARGIN_LIMIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_STOPLIMIT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_MARGIN_STOPLIMIT); 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(); //--- Save string properties 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(); //--- Save additional integer properties this.m_long_prop[SYMBOL_PROP_DIGITS_LOTS] = this.SymbolDigitsLot(); } //+------------------------------------------------------------------+
构造函数输入为品种状态和其名称。
创建品种集合时,我们将在循环中遍历所有必需品种,以便定义它们是否属于先前设置的类别(在 ENUM_SYMBOL_STATUS 枚举中),并从抽象品种类创建一个派生的新对象。
仅将品种名称传递给派生类,而状态将根据派生对象类型自动设置,并在创建派生对象时发送给父类的构造函数。 我们在函数库论述
第二部分中创建订单对象时已分析过了。
在构造函数初始化清单中立即初始错误代码。
在方法实体中,首先
检查服务器上是否存在该品种。 如果没有,则将错误消息发送到日志,并将“未知品种”值添加到错误代码。
实际上,该检查并非必要,因为从列表中选择的品种数据会在创建对象时传递给它。 但我认为,它应该存在,因为可能会将错误的品种传递给新创建的对象。
接下来,我们获取最后一次即时报价的数据。 如果接收到空值,则将相应的消息发送到日志,并利用 GetLastError()
将最后一个错误值赋值给错误代码。 在任何情况下都可以创建对象,而错误代码则允许由调用程序来决定是将其保留还是删除。
接下来,初始化所有品种对象数据(重置),并设置帐户货币的小数位数,以便将正确数值输出到日志。
利用 SymbolInfo 函数填充所有对象属性。 针对 MQL5 和 MQL4 在接收这些数值方面存在差异的情况下,数据将由专门创建的方法填充,稍后将对其进行阐述。
下面是比较两个品种对象以便进行搜索和排序的方法:
//+------------------------------------------------------------------+ //|Compare CSymbol objects by all possible properties | //+------------------------------------------------------------------+ int CSymbol::Compare(const CObject *node,const int mode=0) const { const CSymbol *symbol_compared=node; //--- compare integer properties of two symbols if(mode<SYMBOL_PROP_INTEGER_TOTAL) { long value_compared=symbol_compared.GetProperty((ENUM_SYMBOL_PROP_INTEGER)mode); long value_current=this.GetProperty((ENUM_SYMBOL_PROP_INTEGER)mode); return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0); } //--- compare real properties of two symbols else if(mode<SYMBOL_PROP_INTEGER_TOTAL+SYMBOL_PROP_DOUBLE_TOTAL) { double value_compared=symbol_compared.GetProperty((ENUM_SYMBOL_PROP_DOUBLE)mode); double value_current=this.GetProperty((ENUM_SYMBOL_PROP_DOUBLE)mode); return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0); } //--- compare string properties of two symbols else if(mode<SYMBOL_PROP_INTEGER_TOTAL+SYMBOL_PROP_DOUBLE_TOTAL+SYMBOL_PROP_STRING_TOTAL) { string value_compared=symbol_compared.GetProperty((ENUM_SYMBOL_PROP_STRING)mode); string value_current=this.GetProperty((ENUM_SYMBOL_PROP_STRING)mode); return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0); } return 0; } //+------------------------------------------------------------------+
下面是比较两个品种对象以便定义它们是否相等的方法:
//+------------------------------------------------------------------+ //| Compare CSymbol objects by all properties | //+------------------------------------------------------------------+ bool CSymbol::IsEqual(CSymbol *compared_symbol) const { int beg=0, end=SYMBOL_PROP_INTEGER_TOTAL; for(int i=beg; i<end; i++) { ENUM_SYMBOL_PROP_INTEGER prop=(ENUM_SYMBOL_PROP_INTEGER)i; if(this.GetProperty(prop)!=compared_symbol.GetProperty(prop)) return false; } beg=end; end+=SYMBOL_PROP_DOUBLE_TOTAL; for(int i=beg; i<end; i++) { ENUM_SYMBOL_PROP_DOUBLE prop=(ENUM_SYMBOL_PROP_DOUBLE)i; if(this.GetProperty(prop)!=compared_symbol.GetProperty(prop)) return false; } beg=end; end+=SYMBOL_PROP_STRING_TOTAL; for(int i=beg; i<end; i++) { ENUM_SYMBOL_PROP_STRING prop=(ENUM_SYMBOL_PROP_STRING)i; if(this.GetProperty(prop)!=compared_symbol.GetProperty(prop)) return false; } return true; } //+------------------------------------------------------------------+
我已在函数库论述的第一部和第五部当中介绍了这两种方法。
以下是初始化所有品种对象属性的方法:
//+------------------------------------------------------------------+ //| Reset all symbol object data | //+------------------------------------------------------------------+ void CSymbol::Reset(void) { int beg=0, end=SYMBOL_PROP_INTEGER_TOTAL; for(int i=beg; i<end; i++) { ENUM_SYMBOL_PROP_INTEGER prop=(ENUM_SYMBOL_PROP_INTEGER)i; this.SetProperty(prop,0); } beg=end; end+=SYMBOL_PROP_DOUBLE_TOTAL; for(int i=beg; i<end; i++) { ENUM_SYMBOL_PROP_DOUBLE prop=(ENUM_SYMBOL_PROP_DOUBLE)i; this.SetProperty(prop,0); } beg=end; end+=SYMBOL_PROP_STRING_TOTAL; for(int i=beg; i<end; i++) { ENUM_SYMBOL_PROP_STRING prop=(ENUM_SYMBOL_PROP_STRING)i; this.SetProperty(prop,NULL); } } //+------------------------------------------------------------------+
该方法的工作方式与之前的方法相同,但此处没有对标本对象进行比较,而是在循环中重置三个属性集中的所有类字段。
以下是接收在 MQL4 中完全或部分不存在的品种整数型属性的方法:
//+----------------------------------------------------------------------+ //| Integer properties | //+----------------------------------------------------------------------+ //+----------------------------------------------------------------------+ //| Return the symbol existence flag | //+----------------------------------------------------------------------+ long CSymbol::SymbolExists(void) const { return(#ifdef __MQL5__ ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_EXIST) #else this.Exist() #endif); } //+----------------------------------------------------------------------+ //| Return the custom symbol flag | //+----------------------------------------------------------------------+ long CSymbol::SymbolCustom(void) const { return(#ifdef __MQL5__ ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_CUSTOM) #else false #endif); } //+----------------------------------------------------------------------+ //| Return the price type for building bars - Bid or Last | //+----------------------------------------------------------------------+ long CSymbol::SymbolChartMode(void) const { return(#ifdef __MQL5__ ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_CHART_MODE) #else SYMBOL_CHART_MODE_BID #endif); } //+----------------------------------------------------------------------+ //|Return the calculation mode of a hedging margin using the larger leg | //+----------------------------------------------------------------------+ long CSymbol::SymbolMarginHedgedUseLEG(void) const { return(#ifdef __MQL5__ ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_MARGIN_HEDGED_USE_LEG) #else false #endif); } //+----------------------------------------------------------------------+ //| Return the order filling policies flags | //+----------------------------------------------------------------------+ long CSymbol::SymbolOrderFillingMode(void) const { return(#ifdef __MQL5__ ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_FILLING_MODE) #else 0 #endif ); } //+----------------------------------------------------------------------+ //| Return the flag allowing the closure by an opposite position | //+----------------------------------------------------------------------+ bool CSymbol::IsCloseByOrdersAllowed(void) const { return(#ifdef __MQL5__(this.OrderModeFlags() & SYMBOL_ORDER_CLOSEBY)==SYMBOL_ORDER_CLOSEBY #else (bool)::MarketInfo(this.m_symbol_name,MODE_CLOSEBY_ALLOWED) #endif ); } //+----------------------------------------------------------------------+ //| Return the lifetime of pending orders and | //| placed StopLoss/TakeProfit levels | //+----------------------------------------------------------------------+ long CSymbol::SymbolOrderGTCMode(void) const { return(#ifdef __MQL5__ ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_ORDER_GTC_MODE) #else SYMBOL_ORDERS_GTC #endif); } //+----------------------------------------------------------------------+ //| Return the option type | //+----------------------------------------------------------------------+ long CSymbol::SymbolOptionMode(void) const { return(#ifdef __MQL5__ ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_OPTION_MODE) #else SYMBOL_OPTION_MODE_NONE #endif); } //+----------------------------------------------------------------------+ //| Return the option right | //+----------------------------------------------------------------------+ long CSymbol::SymbolOptionRight(void) const { return(#ifdef __MQL5__ ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_OPTION_RIGHT) #else SYMBOL_OPTION_RIGHT_NONE #endif); } //+----------------------------------------------------------------------+ //|Return the background color used to highlight a symbol in Market Watch| //+----------------------------------------------------------------------+ long CSymbol::SymbolBackgroundColor(void) const { return(#ifdef __MQL5__ ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_BACKGROUND_COLOR) #else clrNONE #endif); } //+----------------------------------------------------------------------+ //| Return the margin calculation method | //+----------------------------------------------------------------------+ long CSymbol::SymbolCalcMode(void) const { return(#ifdef __MQL5__ ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_TRADE_CALC_MODE) #else (long)::MarketInfo(this.m_symbol_name,MODE_MARGINCALCMODE) #endif); } //+----------------------------------------------------------------------+ //| Return the swaps calculation method | //+----------------------------------------------------------------------+ long CSymbol::SymbolSwapMode(void) const { return(#ifdef __MQL5__ ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_SWAP_MODE) #else (long)::MarketInfo(this.m_symbol_name,MODE_SWAPTYPE) #endif); } //+----------------------------------------------------------------------+ //| Return the flags of allowed order expiration modes | //+----------------------------------------------------------------------+ long CSymbol::SymbolExpirationMode(void) const { return(#ifdef __MQL5__ ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_EXPIRATION_MODE) #else (long)SYMBOL_EXPIRATION_GTC #endif); } //+----------------------------------------------------------------------+
此处我们使用条件编译指令 #ifdef __MQL5__
— 是为 MQL5 编译,且 #else
— 是为 MQL4 编译 #endif。
对于 MQL5, 我们只需从 SymbolInfoInteger() 函数获取所需属性 ID 的数据, 而对于 MQL4, 我们返回一个严格设置的值(如果我们知道在 MQL4 中确实用到此值)或零(或 “ false”,或对于缺失值使用设置的宏替换)。
将另外两个方法的代码放在同一清单中:
以下是返回交易品种允许的订单类型标志的方法:
//+------------------------------------------------------------------+ //| Return the flags of allowed order types | //+------------------------------------------------------------------+ long CSymbol::SymbolOrderMode(void) const { return ( #ifdef __MQL5__ ::SymbolInfoInteger(this.m_symbol_name,SYMBOL_ORDER_MODE) #else (SYMBOL_ORDER_MARKET+SYMBOL_ORDER_LIMIT+SYMBOL_ORDER_STOP+SYMBOL_ORDER_SL+SYMBOL_ORDER_TP+(this.IsCloseByOrdersAllowed() ? SYMBOL_ORDER_CLOSEBY : 0)) #endif ); } //+------------------------------------------------------------------+
由于 MQL5 提供了接收每个交易品种标志的能力(表明可以放置不同的订单类型):
对于 MQL4, 我们只能按 MODE_CLOSEBY_ALLOWED
请求 ID(< 由上面清单中的 IsCloseByOrdersAllowed() 方法返回)调用 MarketInfo()
函数返回由逆向订单平仓的数据。
所以,我们需要收集必要的标志以便返回给 MQL4 程序:
下面是获取品种手数中小数位数的方法:
//+------------------------------------------------------------------+ //| Calculate and return the number of decimal places | //| in a symbol lot | //+------------------------------------------------------------------+ long CSymbol::SymbolDigitsLot(void) { if(this.LotsMax()==0 || this.LotsMin()==0 || this.LotsStep()==0) { ::Print(DFUN_ERR_LINE,TextByLanguage("Не удалось получить данные \"","Failed to get data of \""),this.Name(),"\""); this.m_global_error=ERR_MARKET_UNKNOWN_SYMBOL; return 2; } double val=::round(this.LotsMin()/this.LotsStep())*this.LotsStep(); string val_str=(string)val; int len=::StringLen(val_str); int n=len-::StringFind(val_str,".",0)-1; if(::StringSubstr(val_str,len-1,1)=="0") n--; return n; } //+------------------------------------------------------------------+
该方法计算品种手数值中的小数位数。
在 DELib.mqh 服务函数文件中我们已拥有这样的函数:
//+------------------------------------------------------------------+ //| Returns the number of decimal places in a symbol lot | //+------------------------------------------------------------------+ uint DigitsLots(const string symbol_name) { return (int)ceil(fabs(log(SymbolInfoDouble(symbol_name,SYMBOL_VOLUME_STEP))/log(10))); } //+------------------------------------------------------------------+
然而,它也有某些缺陷。 在讨论话题的文章之一当中,我得知了这些信息:如果手数的步长为 0.25,则该函数不会返回正确的数值。 因此,我决定寻找一种更准确的方法,最后决定最准确的方法是简单地计算手数减少的字符串值中的小数位数作为手数的步长:lot=MathRound(lots/lotStep)*lotStep。 该决定是由专门讨论此问题的话题(俄语)中的讨论所促成的,其中讨论了 建议的搜索方法,即在字符串中进行搜索。 但是我们只需要为每个使用的品种找到一个必要的小数位数,之后便可作为一个常数使用。 该方法避免了所有计算方法的缺点。 因此,我们使用建议的解决方案。
以下是用于接收在 MQL4 中完全或部分不存在的品种实数型和字符型属性的方法:
//+------------------------------------------------------------------+ //| Real properties | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Return maximum Bid for a day | //+------------------------------------------------------------------+ double CSymbol::SymbolBidHigh(void) const { return(#ifdef __MQL5__ ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_BIDHIGH) #else ::MarketInfo(this.m_symbol_name,MODE_HIGH) #endif); } //+------------------------------------------------------------------+ //| Return minimum Bid for a day | //+------------------------------------------------------------------+ double CSymbol::SymbolBidLow(void) const { return(#ifdef __MQL5__ ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_BIDLOW) #else ::MarketInfo(this.m_symbol_name,MODE_LOW) #endif); } //+------------------------------------------------------------------+ //| Return real Volume for a day | //+------------------------------------------------------------------+ double CSymbol::SymbolVolumeReal(void) const { return(#ifdef __MQL5__ ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_VOLUME_REAL) #else 0 #endif); } //+------------------------------------------------------------------+ //| Return real maximum Volume for a day | //+------------------------------------------------------------------+ double CSymbol::SymbolVolumeHighReal(void) const { return(#ifdef __MQL5__ ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_VOLUMEHIGH_REAL) #else 0 #endif); } //+------------------------------------------------------------------+ //| Return real minimum Volume for a day | //+------------------------------------------------------------------+ double CSymbol::SymbolVolumeLowReal(void) const { return(#ifdef __MQL5__ ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_VOLUMELOW_REAL) #else 0 #endif); } //+------------------------------------------------------------------+ //| Return an option execution price | //+------------------------------------------------------------------+ double CSymbol::SymbolOptionStrike(void) const { return(#ifdef __MQL5__ ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_OPTION_STRIKE) #else 0 #endif); } //+------------------------------------------------------------------+ //| Return accrued interest | //+------------------------------------------------------------------+ double CSymbol::SymbolTradeAccruedInterest(void) const { return(#ifdef __MQL5__ ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_ACCRUED_INTEREST) #else 0 #endif); } //+------------------------------------------------------------------+ //| Return a bond face value | //+------------------------------------------------------------------+ double CSymbol::SymbolTradeFaceValue(void) const { return(#ifdef __MQL5__ ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_FACE_VALUE) #else 0 #endif); } //+------------------------------------------------------------------+ //| Return a liquidity rate | //+------------------------------------------------------------------+ double CSymbol::SymbolTradeLiquidityRate(void) const { return(#ifdef __MQL5__ ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_TRADE_LIQUIDITY_RATE) #else 0 #endif); } //+------------------------------------------------------------------+ //| Return a contract or margin size | //| for a single lot of covered positions | //+------------------------------------------------------------------+ double CSymbol::SymbolMarginHedged(void) const { return(#ifdef __MQL5__ ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_MARGIN_HEDGED) #else ::MarketInfo(this.m_symbol_name, MODE_MARGINHEDGED) #endif); } //+------------------------------------------------------------------+ //| String properties | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Return a base asset name for a derivative instrument | //+------------------------------------------------------------------+ string CSymbol::SymbolBasis(void) const { return ( #ifdef __MQL5__ ::SymbolInfoString(this.m_symbol_name,SYMBOL_BASIS) #else ": "+TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ); } //+------------------------------------------------------------------+ //| Return a quote source for a symbol | //+------------------------------------------------------------------+ string CSymbol::SymbolBank(void) const { return ( #ifdef __MQL5__ ::SymbolInfoString(this.m_symbol_name,SYMBOL_BANK) #else ": "+TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ); } //+------------------------------------------------------------------+ //| Return a symbol name to ISIN | //+------------------------------------------------------------------+ string CSymbol::SymbolISIN(void) const { return ( #ifdef __MQL5__ ::SymbolInfoString(this.m_symbol_name,SYMBOL_ISIN) #else ": "+TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ); } //+------------------------------------------------------------------+ //| Return a formula for constructing a custom symbol price | //+------------------------------------------------------------------+ string CSymbol::SymbolFormula(void) const { return ( #ifdef __MQL5__ ::SymbolInfoString(this.m_symbol_name,SYMBOL_FORMULA) #else ": "+TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ); } //+------------------------------------------------------------------+ //| Return an address of a web page with a symbol data | //+------------------------------------------------------------------+ string CSymbol::SymbolPage(void) const { return ( #ifdef __MQL5__ ::SymbolInfoString(this.m_symbol_name,SYMBOL_PAGE) #else ": "+TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ); } //+------------------------------------------------------------------+
此处所有操作都与获取整数型属性的方法类似:获取返回值的方法由条件编译指令分支,然后使用相应的 MQL5 和 MQL4 函数返回属性值,或者针对 MQL4 返回 0(如果没有 MQL5 模拟)。 还可以针对 MQL4 返回指示不支持此字符型属性的字符串消息。
下面是将所有品种对象属性的完整列表发送到日志的方法:
//+------------------------------------------------------------------+ //| Send symbol properties to the journal | //+------------------------------------------------------------------+ void CSymbol::Print(const bool full_prop=false) { ::Print("============= ", TextByLanguage("Начало списка параметров: \"","Beginning of the parameter list: \""), this.Name(),"\""," ",(this.Description()!= #ifdef __MQL5__ "" #else NULL #endif ? "("+this.Description()+")" : ""), " ==================" ); int beg=0, end=SYMBOL_PROP_INTEGER_TOTAL; for(int i=beg; i<end; i++) { ENUM_SYMBOL_PROP_INTEGER prop=(ENUM_SYMBOL_PROP_INTEGER)i; if(!full_prop && !this.SupportProperty(prop)) continue; ::Print(this.GetPropertyDescription(prop)); } ::Print("------"); beg=end; end+=SYMBOL_PROP_DOUBLE_TOTAL; for(int i=beg; i<end; i++) { ENUM_SYMBOL_PROP_DOUBLE prop=(ENUM_SYMBOL_PROP_DOUBLE)i; if(!full_prop && !this.SupportProperty(prop)) continue; ::Print(this.GetPropertyDescription(prop)); } ::Print("------"); beg=end; end+=SYMBOL_PROP_STRING_TOTAL; for(int i=beg; i<end; i++) { ENUM_SYMBOL_PROP_STRING prop=(ENUM_SYMBOL_PROP_STRING)i; if(!full_prop && !this.SupportProperty(prop)) continue; ::Print(this.GetPropertyDescription(prop)); } ::Print("================== ", TextByLanguage("Конец списка параметров: ","End of the parameter list: \""), this.Name(),"\""," ",(this.Description()!= #ifdef __MQL5__ "" #else NULL #endif ? "("+this.Description()+")" : ""), " ==================\n" ); } //+------------------------------------------------------------------+
每个后续属性在三个循环中利用 GetPropertyDescription() 方法按其类型(整数型,实数型或字符型)返回对象属性的说明并显示:
//+------------------------------------------------------------------+ //| Return the description of the symbol integer property | //+------------------------------------------------------------------+ string CSymbol::GetPropertyDescription(ENUM_SYMBOL_PROP_INTEGER property) { return ( //--- General properties property==SYMBOL_PROP_STATUS ? TextByLanguage("Статус","Status")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(string)this.GetStatusDescription() ) : property==SYMBOL_PROP_CUSTOM ? TextByLanguage("Пользовательский символ","Custom symbol")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(this.GetProperty(property) ? TextByLanguage("Да","Yes") : TextByLanguage("Нет","No")) ) : property==SYMBOL_PROP_CHART_MODE ? TextByLanguage("Тип цены для построения баров","Price type used for generating symbols bars")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetChartModeDescription() ) : property==SYMBOL_PROP_EXIST ? TextByLanguage("Символ с таким именем существует","Symbol with this name exists")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(this.GetProperty(property) ? TextByLanguage("Да","Yes") : TextByLanguage("Нет","No")) ) : property==SYMBOL_PROP_SELECT ? TextByLanguage("Символ выбран в Market Watch","Symbol selected in Market Watch")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(this.GetProperty(property) ? TextByLanguage("Да","Yes") : TextByLanguage("Нет","No")) ) : property==SYMBOL_PROP_VISIBLE ? TextByLanguage("Символ отображается в Market Watch","Symbol visible in Market Watch")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(this.GetProperty(property) ? TextByLanguage("Да","Yes") : TextByLanguage("Нет","No")) ) : property==SYMBOL_PROP_SESSION_DEALS ? TextByLanguage("Количество сделок в текущей сессии","Number of deals in the current session")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__(string)this.GetProperty(property) #else TextByLanguage("Свойство не поддерживается в MQL4","Property is not supported in MQL4") #endif ) : property==SYMBOL_PROP_SESSION_BUY_ORDERS ? TextByLanguage("Общее число ордеров на покупку в текущий момент","Number of Buy orders at the moment")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property is not support") : ": "+ #ifdef __MQL5__(string)this.GetProperty(property) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_SESSION_SELL_ORDERS ? TextByLanguage("Общее число ордеров на продажу в текущий момент","Number of Sell orders at the moment")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__(string)this.GetProperty(property) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_VOLUME ? TextByLanguage("Объем в последней сделке","Volume of the last deal")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__(string)this.GetProperty(property) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_VOLUMEHIGH ? TextByLanguage("Максимальный объём за день","Maximum day volume")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property is not support") : ": "+ #ifdef __MQL5__(string)this.GetProperty(property) #else TextByLanguage("Свойство не поддерживается в MQL4","Property is not supported in MQL4") #endif ) : property==SYMBOL_PROP_VOLUMELOW ? TextByLanguage("Минимальный объём за день","Minimum day volume")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__(string)this.GetProperty(property) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_TIME ? TextByLanguage("Время последней котировки","Time of last quote")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(this.GetProperty(property)==0 ? TextByLanguage("(Ещё не было тиков)","(No ticks yet)") : TimeMSCtoString(this.GetProperty(property))) ) : property==SYMBOL_PROP_DIGITS ? TextByLanguage("Количество знаков после запятой","Digits after decimal point")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(string)this.GetProperty(property) ) : property==SYMBOL_PROP_DIGITS_LOTS ? TextByLanguage("Количество знаков после запятой в значении лота","Digits after decimal point in lot value")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(string)this.GetProperty(property) ) : property==SYMBOL_PROP_SPREAD ? TextByLanguage("Размер спреда в пунктах","Spread value in points")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(string)this.GetProperty(property) ) : property==SYMBOL_PROP_SPREAD_FLOAT ? TextByLanguage("Плавающий спред","Floating spread")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(this.GetProperty(property) ? TextByLanguage("Да","Yes") : TextByLanguage("Нет","No")) ) : property==SYMBOL_PROP_TICKS_BOOKDEPTH ? TextByLanguage("Максимальное количество показываемых заявок в стакане","Maximum number of requests shown in Depth of Market")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__(string)this.GetProperty(property) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_TRADE_CALC_MODE ? TextByLanguage("Способ вычисления стоимости контракта","Contract price calculation mode")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetCalcModeDescription() ) : property==SYMBOL_PROP_TRADE_MODE ? TextByLanguage("Тип исполнения ордеров","Order execution type")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetTradeModeDescription() ) : property==SYMBOL_PROP_START_TIME ? TextByLanguage("Дата начала торгов по инструменту","Date of symbol trade beginning")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : (this.GetProperty(property)==0 ? TextByLanguage(": (Отсутствует)",": (Not set)") : ": "+TimeMSCtoString(this.GetProperty(property)*1000)) ) : property==SYMBOL_PROP_EXPIRATION_TIME ? TextByLanguage("Дата окончания торгов по инструменту","Date of symbol trade end")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : (this.GetProperty(property)==0 ? TextByLanguage(": (Отсутствует)",": (Not set)") : ": "+TimeMSCtoString(this.GetProperty(property)*1000)) ) : property==SYMBOL_PROP_TRADE_STOPS_LEVEL ? TextByLanguage("Минимальный отступ от цены закрытия для установки Stop ордеров","Minimum indention from close price to place Stop orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(string)this.GetProperty(property) ) : property==SYMBOL_PROP_TRADE_FREEZE_LEVEL ? TextByLanguage("Дистанция заморозки торговых операций","Distance to freeze trade operations in points")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(string)this.GetProperty(property) ) : property==SYMBOL_PROP_TRADE_EXEMODE ? TextByLanguage("Режим заключения сделок","Deal execution mode")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetTradeExecDescription() ) : property==SYMBOL_PROP_SWAP_MODE ? TextByLanguage("Модель расчета свопа","Swap calculation model")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetSwapModeDescription() ) : property==SYMBOL_PROP_SWAP_ROLLOVER3DAYS ? TextByLanguage("День недели для начисления тройного свопа","Day of week to charge 3 days swap rollover")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+DayOfWeekDescription(this.SwapRollover3Days()) ) : property==SYMBOL_PROP_MARGIN_HEDGED_USE_LEG ? TextByLanguage("Расчет хеджированной маржи по наибольшей стороне","Calculating hedging margin using larger leg")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(this.GetProperty(property) ? TextByLanguage("Да","Yes") : TextByLanguage("Нет","No")) ) : property==SYMBOL_PROP_EXPIRATION_MODE ? TextByLanguage("Флаги разрешенных режимов истечения ордера","Flags of allowed order expiration modes")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetExpirationModeFlagsDescription() ) : property==SYMBOL_PROP_FILLING_MODE ? TextByLanguage("Флаги разрешенных режимов заливки ордера","Flags of allowed order filling modes")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetFillingModeFlagsDescription() ) : property==SYMBOL_PROP_ORDER_MODE ? TextByLanguage("Флаги разрешенных типов ордера","Flags of allowed order types")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetOrderModeFlagsDescription() ) : property==SYMBOL_PROP_ORDER_GTC_MODE ? TextByLanguage("Срок действия StopLoss и TakeProfit ордеров","Expiration of Stop Loss and Take Profit orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetOrderGTCModeDescription() ) : property==SYMBOL_PROP_OPTION_MODE ? TextByLanguage("Тип опциона","Option type")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetOptionTypeDescription() ) : property==SYMBOL_PROP_OPTION_RIGHT ? TextByLanguage("Право опциона","Option right")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetOptionRightDescription() ) : 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 ) : "" ); } //+------------------------------------------------------------------+ //| Return the description of the symbol real property | //+------------------------------------------------------------------+ string CSymbol::GetPropertyDescription(ENUM_SYMBOL_PROP_DOUBLE property) { int dg=this.Digits(); int dgl=this.DigitsLot(); int dgc=this.DigitsCurrency(); return ( property==SYMBOL_PROP_BID ? TextByLanguage("Цена Bid","Bid price")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(this.GetProperty(property)==0 ? TextByLanguage("(Ещё не было тиков)","(No ticks yet)") : ::DoubleToString(this.GetProperty(property),dg)) ) : property==SYMBOL_PROP_BIDHIGH ? TextByLanguage("Максимальный Bid за день","Maximum Bid for the day")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+::DoubleToString(this.GetProperty(property),dg) ) : property==SYMBOL_PROP_BIDLOW ? TextByLanguage("Минимальный Bid за день","Minimum Bid for the day")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+::DoubleToString(this.GetProperty(property),dg) ) : property==SYMBOL_PROP_ASK ? TextByLanguage("Цена Ask","Ask price")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+(this.GetProperty(property)==0 ? TextByLanguage("(Ещё не было тиков)","(No ticks yet)") : ::DoubleToString(this.GetProperty(property),dg)) ) : property==SYMBOL_PROP_ASKHIGH ? TextByLanguage("Максимальный Ask за день","Maximum Ask for the day")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dg) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_ASKLOW ? TextByLanguage("Минимальный Ask за день","Minimum Ask for the day")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dg) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_LAST ? TextByLanguage("Цена последней сделки","Price of the last deal")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dg) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_LASTHIGH ? TextByLanguage("Максимальный Last за день","Maximum Last for the day")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dg) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_LASTLOW ? TextByLanguage("Минимальный Last за день","Minimum Last for the day")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dg) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_VOLUME_REAL ? TextByLanguage("Реальный объём за день","Real volume of the last deal")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dgl) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_VOLUMEHIGH_REAL ? TextByLanguage("Максимальный реальный объём за день","Maximum real volume for the day")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dgl) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_VOLUMELOW_REAL ? TextByLanguage("Минимальный реальный объём за день","Minimum real volume for the day")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dgl) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_OPTION_STRIKE ? TextByLanguage("Цена исполнения опциона","Option strike price")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dg) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_POINT ? TextByLanguage("Значение одного пункта","Symbol point value")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+::DoubleToString(this.GetProperty(property),dg) ) : property==SYMBOL_PROP_TRADE_TICK_VALUE ? TextByLanguage("Рассчитанная стоимость тика для позиции","Calculated tick price for position")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+::DoubleToString(this.GetProperty(property),dgc) ) : property==SYMBOL_PROP_TRADE_TICK_VALUE_PROFIT ? TextByLanguage("Рассчитанная стоимость тика для прибыльной позиции","Calculated tick price for profitable position")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dgc) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_TRADE_TICK_VALUE_LOSS ? TextByLanguage("Рассчитанная стоимость тика для убыточной позиции","Calculated tick price for losing position")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dgc) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_TRADE_TICK_SIZE ? TextByLanguage("Минимальное изменение цены","Minimum price change")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+::DoubleToString(this.GetProperty(property),dg) ) : property==SYMBOL_PROP_TRADE_CONTRACT_SIZE ? TextByLanguage("Размер торгового контракта","Trade contract size")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+::DoubleToString(this.GetProperty(property),dgc) ) : property==SYMBOL_PROP_TRADE_ACCRUED_INTEREST ? TextByLanguage("Накопленный купонный доход","Accumulated coupon interest")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dgc) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_TRADE_FACE_VALUE ? TextByLanguage("Начальная стоимость облигации, установленная эмитентом","Initial bond value set by issuer")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dgc) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_TRADE_LIQUIDITY_RATE ? TextByLanguage("Коэффициент ликвидности","Liquidity rate")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),2) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_VOLUME_MIN ? TextByLanguage("Минимальный объем для заключения сделки","Minimum volume for a deal")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+::DoubleToString(this.GetProperty(property),dgl) ) : property==SYMBOL_PROP_VOLUME_MAX ? TextByLanguage("Максимальный объем для заключения сделки","Maximum volume for a deal")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+::DoubleToString(this.GetProperty(property),dgl) ) : property==SYMBOL_PROP_VOLUME_STEP ? TextByLanguage("Минимальный шаг изменения объема для заключения сделки","Minimum volume change step for deal execution")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+::DoubleToString(this.GetProperty(property),dgl) ) : property==SYMBOL_PROP_VOLUME_LIMIT ? TextByLanguage("Максимально допустимый общий объем позиции и отложенных ордеров в одном направлении","Maximum allowed aggregate volume of open position and pending orders in one direction")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dgl) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_SWAP_LONG ? TextByLanguage("Значение свопа на покупку","Long swap value")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+::DoubleToString(this.GetProperty(property),dgc) ) : property==SYMBOL_PROP_SWAP_SHORT ? TextByLanguage("Значение свопа на продажу","Short swap value")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+::DoubleToString(this.GetProperty(property),dgc) ) : property==SYMBOL_PROP_MARGIN_INITIAL ? TextByLanguage("Начальная (инициирующая) маржа","Initial margin")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+::DoubleToString(this.GetProperty(property),dgc) ) : property==SYMBOL_PROP_MARGIN_MAINTENANCE ? TextByLanguage("Поддерживающая маржа по инструменту","Maintenance margin")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+::DoubleToString(this.GetProperty(property),dgc) ) : property==SYMBOL_PROP_MARGIN_LONG ? TextByLanguage("Коэффициент взимания маржи по длинным позициям","Coefficient of margin charging for long positions")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dgc) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_MARGIN_SHORT ? TextByLanguage("Коэффициент взимания маржи по коротким позициям","Coefficient of margin charging for short positions")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dgc) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_MARGIN_STOP ? TextByLanguage("Коэффициент взимания маржи по Stop ордерам","Coefficient of margin charging for Stop orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dgc) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_MARGIN_LIMIT ? TextByLanguage("Коэффициент взимания маржи по Limit ордерам","Coefficient of margin charging for Limit orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dgc) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_MARGIN_STOPLIMIT ? TextByLanguage("Коэффициент взимания маржи по Stop Limit ордерам","Coefficient of margin charging for StopLimit orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dgc) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_SESSION_VOLUME ? TextByLanguage("Cуммарный объём сделок в текущую сессию","Summary volume of the current session deals")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dgl) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_SESSION_TURNOVER ? TextByLanguage("Cуммарный оборот в текущую сессию","Summary turnover of the current session")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dgc) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_SESSION_INTEREST ? TextByLanguage("Cуммарный объём открытых позиций","Summary open interest")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dgl) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_SESSION_BUY_ORDERS_VOLUME ? TextByLanguage("Общий объём ордеров на покупку в текущий момент","Current volume of Buy orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dgl) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_SESSION_SELL_ORDERS_VOLUME ? TextByLanguage("Общий объём ордеров на продажу в текущий момент","Current volume of Sell orders")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dgl) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_SESSION_OPEN ? TextByLanguage("Цена открытия сессии","Open price of the current session")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dg) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_SESSION_CLOSE ? TextByLanguage("Цена закрытия сессии","Close price of the current session")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dg) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_SESSION_AW ? TextByLanguage("Средневзвешенная цена сессии","Average weighted price of the current session")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dg) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_SESSION_PRICE_SETTLEMENT ? TextByLanguage("Цена поставки на текущую сессию","Settlement price of the current session")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dg) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_SESSION_PRICE_LIMIT_MIN ? TextByLanguage("Минимально допустимое значение цены на сессию","Minimum price of the current session")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dg) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_SESSION_PRICE_LIMIT_MAX ? TextByLanguage("Максимально допустимое значение цены на сессию","Maximum price of the current session")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+ #ifdef __MQL5__::DoubleToString(this.GetProperty(property),dg) #else TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #endif ) : property==SYMBOL_PROP_MARGIN_HEDGED ? TextByLanguage("Размер контракта или маржи для одного лота перекрытых позиций","Contract size or margin value per one lot of hedged positions")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+::DoubleToString(this.GetProperty(property),dgc) ) : "" ); } //+------------------------------------------------------------------+ //| Return the description of the symbol string property | //+------------------------------------------------------------------+ string CSymbol::GetPropertyDescription(ENUM_SYMBOL_PROP_STRING property) { return ( property==SYMBOL_PROP_NAME ? TextByLanguage("Имя символа","Symbol name")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : ": "+this.GetProperty(property) ) : property==SYMBOL_PROP_BASIS ? TextByLanguage("Имя базового актива для производного инструмента","Underlying asset of derivative")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? TextByLanguage(": (Отсутствует)",": (Not set)") : ": \""+this.GetProperty(property)+"\"") ) : property==SYMBOL_PROP_CURRENCY_BASE ? TextByLanguage("Базовая валюта инструмента","Basic currency of a symbol")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? TextByLanguage(": (Отсутствует)",": (Not set)") : ": \""+this.GetProperty(property)+"\"") ) : property==SYMBOL_PROP_CURRENCY_PROFIT ? TextByLanguage("Валюта прибыли","Profit currency")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? TextByLanguage(": (Отсутствует)",": (Not set)") : ": \""+this.GetProperty(property)+"\"") ) : property==SYMBOL_PROP_CURRENCY_MARGIN ? TextByLanguage("Валюта залоговых средств","Margin currency")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? TextByLanguage(": (Отсутствует)",": (Not set)") : ": \""+this.GetProperty(property)+"\"") ) : property==SYMBOL_PROP_BANK ? TextByLanguage("Источник текущей котировки","Feeder of the current quote")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? TextByLanguage(": (Отсутствует)",": (Not set)") : ": \""+this.GetProperty(property)+"\"") ) : property==SYMBOL_PROP_DESCRIPTION ? TextByLanguage("Описание символа","Symbol description")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? TextByLanguage(": (Отсутствует)",": (Not set)") : ": \""+this.GetProperty(property)+"\"") ) : property==SYMBOL_PROP_FORMULA ? TextByLanguage("Формула для построения цены пользовательского символа","Formula used for custom symbol pricing")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? TextByLanguage(": (Отсутствует)",": (Not set)") : ": \""+this.GetProperty(property)+"\"") ) : property==SYMBOL_PROP_ISIN ? TextByLanguage("Имя торгового символа в системе международных идентификационных кодов","Name of a symbol in ISIN system")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? TextByLanguage(": (Отсутствует)",": (Not set)") : ": \""+this.GetProperty(property)+"\"") ) : property==SYMBOL_PROP_PAGE ? TextByLanguage("Адрес интернет страницы с информацией по символу","Address of the web page containing symbol information")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? TextByLanguage(": (Отсутствует)",": (Not set)") : ": \""+this.GetProperty(property)+"\"") ) : property==SYMBOL_PROP_PATH ? TextByLanguage("Путь в дереве символов","Path in symbol tree")+ (!this.SupportProperty(property) ? TextByLanguage(": Свойство не поддерживается",": Property not supported") : (this.GetProperty(property)=="" || this.GetProperty(property)==NULL ? TextByLanguage(": (Отсутствует)",": (Not set)") : ": \""+this.GetProperty(property)+"\"") ) : "" ); } //+------------------------------------------------------------------+
尽管这些方法体量庞大,但可归结为比较传递给该方法的属性,并返回其字符串描述。 我相信,它们很容易理解,没有必要去研究它们。
以下是从服务器品种列表中搜索品种,并返回其存在/不存在标志的方法:
//+-------------------------------------------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
来自服务器上的所有品种完整列表(在 SymbolsTotal() 和 SymbolName
函数中,flag = false),在循环中顺序将列表里的每个品种(名称)与当前品种对象的名称进行比较。 如果找到,返回
true —
该品种出现在服务器上。
否则,返回 false
— 服务器上没有该品种。
以下是订阅和取消订阅市场深度的方法:
//+------------------------------------------------------------------+ //| Subscribe to the market depth | //+------------------------------------------------------------------+ bool CSymbol::BookAdd(void) const { return #ifdef __MQL5__ ::MarketBookAdd(this.m_symbol_name) #else false #endif ; } //+------------------------------------------------------------------+ //| Close the market depth | //+------------------------------------------------------------------+ bool CSymbol::BookClose(void) const { return #ifdef __MQL5__ ::MarketBookRelease(this.m_symbol_name) #else false #endif ; } //+------------------------------------------------------------------+
在 MQL5 中,这些方法仅返回 MarketBookAdd() 和 MarketBookRelease() 函数操作的结果,而在 MQL4 中立即返回 false,因为没有办法处理市场深度。 目前,这些方法已添加到品种对象中。 在后续文章中,我们将编排操控它们的能力,并添加其他方法来应对市场深度。
以下是返回品种对象属性字符串说明的方法:
//+------------------------------------------------------------------+ //| 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_FX_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_BIN_OPTION ? TextByLanguage("Бинарный опцион","Binary option") : this.Status()==SYMBOL_STATUS_CUSTOM ? TextByLanguage("Пользовательский символ","Custom symbol") : "" ); } //+------------------------------------------------------------------+ //| Return the price type description for constructing bars | //+------------------------------------------------------------------+ string CSymbol::GetChartModeDescription(void) const { return ( this.ChartMode()==SYMBOL_CHART_MODE_BID ? TextByLanguage("Бары строятся по ценам Bid","Bars based on Bid prices") : TextByLanguage("Бары строятся по ценам Last","Bars based on Last prices") ); } //+------------------------------------------------------------------+ //| Return the description of the margin calculation method | //+------------------------------------------------------------------+ string CSymbol::GetCalcModeDescription(void) const { return ( this.TradeCalcMode()==SYMBOL_CALC_MODE_FOREX ? TextByLanguage("Расчет прибыли и маржи для Форекс","Forex mode") : this.TradeCalcMode()==SYMBOL_CALC_MODE_FOREX_NO_LEVERAGE ? TextByLanguage("Расчет прибыли и маржи для Форекс без учета плеча","Forex No Leverage mode") : this.TradeCalcMode()==SYMBOL_CALC_MODE_FUTURES ? TextByLanguage("Расчет залога и прибыли для фьючерсов","Futures mode") : this.TradeCalcMode()==SYMBOL_CALC_MODE_CFD ? TextByLanguage("Расчет залога и прибыли для CFD","CFD mode") : this.TradeCalcMode()==SYMBOL_CALC_MODE_CFDINDEX ? TextByLanguage("Расчет залога и прибыли для CFD на индексы","CFD index mode") : this.TradeCalcMode()==SYMBOL_CALC_MODE_CFDLEVERAGE ? TextByLanguage("Расчет залога и прибыли для CFD при торговле с плечом","CFD Leverage mode") : this.TradeCalcMode()==SYMBOL_CALC_MODE_EXCH_STOCKS ? TextByLanguage("Расчет залога и прибыли для торговли ценными бумагами на бирже","Exchange mode") : this.TradeCalcMode()==SYMBOL_CALC_MODE_EXCH_FUTURES ? TextByLanguage("Расчет залога и прибыли для торговли фьючерсными контрактами на бирже","Futures mode") : this.TradeCalcMode()==SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS ? TextByLanguage("Расчет залога и прибыли для торговли фьючерсными контрактами на FORTS","FORTS Futures mode") : this.TradeCalcMode()==SYMBOL_CALC_MODE_EXCH_BONDS ? TextByLanguage("Расчет прибыли и маржи по торговым облигациям на бирже","Exchange Bonds mode") : this.TradeCalcMode()==SYMBOL_CALC_MODE_EXCH_STOCKS_MOEX ? TextByLanguage("Расчет прибыли и маржи при торговле ценными бумагами на MOEX","Exchange MOEX Stocks mode") : this.TradeCalcMode()==SYMBOL_CALC_MODE_EXCH_BONDS_MOEX ? TextByLanguage("Расчет прибыли и маржи по торговым облигациям на MOEX","Exchange MOEX Bonds mode") : this.TradeCalcMode()==SYMBOL_CALC_MODE_SERV_COLLATERAL ? TextByLanguage("Используется в качестве неторгуемого актива на счете","Collateral mode") : "" ); } //+------------------------------------------------------------------+ //| Return the description of a symbol trading mode | //+------------------------------------------------------------------+ string CSymbol::GetTradeModeDescription(void) const { return ( this.TradeMode()==SYMBOL_TRADE_MODE_DISABLED ? TextByLanguage("Торговля по символу запрещена","Trade disabled for symbol") : this.TradeMode()==SYMBOL_TRADE_MODE_LONGONLY ? TextByLanguage("Разрешены только покупки","Only long positions allowed") : this.TradeMode()==SYMBOL_TRADE_MODE_SHORTONLY ? TextByLanguage("Разрешены только продажи","Only short positions allowed") : this.TradeMode()==SYMBOL_TRADE_MODE_CLOSEONLY ? TextByLanguage("Разрешены только операции закрытия позиций","Only position close operations allowed") : this.TradeMode()==SYMBOL_TRADE_MODE_FULL ? TextByLanguage("Нет ограничений на торговые операции","No trade restrictions") : "" ); } //+------------------------------------------------------------------+ //| Return the description of a symbol trade execution mode | //+------------------------------------------------------------------+ string CSymbol::GetTradeExecDescription(void) const { return ( this.TradeExecutionMode()==SYMBOL_TRADE_EXECUTION_REQUEST ? TextByLanguage("Торговля по запросу","Execution by request") : this.TradeExecutionMode()==SYMBOL_TRADE_EXECUTION_INSTANT ? TextByLanguage("Торговля по потоковым ценам","Instant execution") : this.TradeExecutionMode()==SYMBOL_TRADE_EXECUTION_MARKET ? TextByLanguage("Исполнение ордеров по рынку","Market execution") : this.TradeExecutionMode()==SYMBOL_TRADE_EXECUTION_EXCHANGE ? TextByLanguage("Биржевое исполнение","Exchange execution") : "" ); } //+------------------------------------------------------------------+ //| Return the description of a swap calculation model | //+------------------------------------------------------------------+ string CSymbol::GetSwapModeDescription(void) const { return ( this.SwapMode()==SYMBOL_SWAP_MODE_DISABLED ? TextByLanguage("Нет свопов","Swaps disabled (no swaps)") : this.SwapMode()==SYMBOL_SWAP_MODE_POINTS ? TextByLanguage("Свопы начисляются в пунктах","Swaps charged in points") : this.SwapMode()==SYMBOL_SWAP_MODE_CURRENCY_SYMBOL ? TextByLanguage("Свопы начисляются в деньгах в базовой валюте символа","Swaps charged in money in base currency of symbol") : this.SwapMode()==SYMBOL_SWAP_MODE_CURRENCY_MARGIN ? TextByLanguage("Свопы начисляются в деньгах в маржинальной валюте символа","Swaps charged in money in margin currency of symbol") : this.SwapMode()==SYMBOL_SWAP_MODE_CURRENCY_DEPOSIT ? TextByLanguage("Свопы начисляются в деньгах в валюте депозита клиента","Swaps charged in money, in client deposit currency") : this.SwapMode()==SYMBOL_SWAP_MODE_INTEREST_CURRENT ? TextByLanguage("Свопы начисляются в годовых процентах от цены инструмента на момент расчета свопа","Swaps charged as specified annual interest from instrument price at calculation of swap") : this.SwapMode()==SYMBOL_SWAP_MODE_INTEREST_OPEN ? TextByLanguage("Свопы начисляются в годовых процентах от цены открытия позиции по символу","Swaps charged as specified annual interest from open price of position") : this.SwapMode()==SYMBOL_SWAP_MODE_REOPEN_CURRENT ? TextByLanguage("Свопы начисляются переоткрытием позиции по цене закрытия","Swaps charged by reopening positions by close price") : this.SwapMode()==SYMBOL_SWAP_MODE_REOPEN_BID ? TextByLanguage("Свопы начисляются переоткрытием позиции по текущей цене Bid","Swaps charged by reopening positions by the current Bid price") : "" ); } //+------------------------------------------------------------------+ //| Return the description of StopLoss and TakeProfit order lifetime | //+------------------------------------------------------------------+ string CSymbol::GetOrderGTCModeDescription(void) const { return ( this.OrderModeGTC()==SYMBOL_ORDERS_GTC ? TextByLanguage("Отложенные ордеры и уровни Stop Loss/Take Profit действительны неограниченно по времени до явной отмены","Pending orders and Stop Loss/Take Profit levels are valid for unlimited period until their explicit cancellation") : this.OrderModeGTC()==SYMBOL_ORDERS_DAILY ? TextByLanguage("При смене торгового дня отложенные ордеры и все уровни StopLoss и TakeProfit удаляются","At the end of the day, all Stop Loss and Take Profit levels, as well as pending orders are deleted") : this.OrderModeGTC()==SYMBOL_ORDERS_DAILY_EXCLUDING_STOPS ? TextByLanguage("При смене торгового дня удаляются только отложенные ордеры, уровни StopLoss и TakeProfit сохраняются","At the end of the day, only pending orders deleted, while Stop Loss and Take Profit levels preserved") : "" ); } //+------------------------------------------------------------------+ //| Return the option type description | //+------------------------------------------------------------------+ string CSymbol::GetOptionTypeDescription(void) const { return ( #ifdef __MQL4__ TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #else this.OptionMode()==SYMBOL_OPTION_MODE_EUROPEAN ? TextByLanguage("Европейский тип опциона – может быть погашен только в указанную дату","European option may only be exercised on specified date") : this.OptionMode()==SYMBOL_OPTION_MODE_AMERICAN ? TextByLanguage("Американский тип опциона – может быть погашен в любой день до истечения срока опциона","American option may be exercised on any trading day or before expiry") : "" #endif ); } //+------------------------------------------------------------------+ //| Return the option right description | //+------------------------------------------------------------------+ string CSymbol::GetOptionRightDescription(void) const { return ( #ifdef __MQL4__ TextByLanguage("Свойство не поддерживается в MQL4","Property not supported in MQL4") #else this.OptionRight()==SYMBOL_OPTION_RIGHT_CALL ? TextByLanguage("Опцион, дающий право купить актив по фиксированной цене","Call option gives you right to buy asset at specified price") : this.OptionRight()==SYMBOL_OPTION_RIGHT_PUT ? TextByLanguage("Опцион, дающий право продать актив по фиксированной цене ","Put option gives you right to sell asset at specified price") : "" #endif ); } //+------------------------------------------------------------------+ //| Return the description of the flags of allowed order types | //+------------------------------------------------------------------+ string CSymbol::GetOrderModeFlagsDescription(void) const { string first=#ifdef __MQL5__ "\n - " #else "" #endif ; string next= #ifdef __MQL5__ "\n - " #else "; " #endif ; return ( first+this.GetMarketOrdersAllowedDescription()+ next+this.GetLimitOrdersAllowedDescription()+ next+this.GetStopOrdersAllowedDescription()+ next+this.GetStopLimitOrdersAllowedDescription()+ next+this.GetStopLossOrdersAllowedDescription()+ next+this.GetTakeProfitOrdersAllowedDescription()+ next+this.GetCloseByOrdersAllowedDescription() ); } //+----------------------------------------------------------------------+ //| Return the description of the flags of allowed filling types | //+----------------------------------------------------------------------+ string CSymbol::GetFillingModeFlagsDescription(void) const { string first=#ifdef __MQL5__ "\n - " #else "" #endif ; string next= #ifdef __MQL5__ "\n - " #else "; " #endif ; return ( first+TextByLanguage("Вернуть (Да)","Return (Yes)")+ next+this.GetFillingModeFOKAllowedDescrioption()+ next+this.GetFillingModeIOCAllowedDescrioption() ); } //+----------------------------------------------------------------------+ //| Return the description of the flags of allowed order expiration modes| //+----------------------------------------------------------------------+ string CSymbol::GetExpirationModeFlagsDescription(void) const { string first=#ifdef __MQL5__ "\n - " #else "" #endif ; string next= #ifdef __MQL5__ "\n - " #else "; " #endif ; return ( first+this.GetExpirationModeGTCDescription()+ next+this.GetExpirationModeDAYDescription()+ next+this.GetExpirationModeSpecifiedDescription()+ next+this.GetExpirationModeSpecDayDescription() ); } //+----------------------------------------------------------------------+ //| Return the description of allowing to use market orders | //+----------------------------------------------------------------------+ string CSymbol::GetMarketOrdersAllowedDescription(void) const { return (this.IsMarketOrdersAllowed() ? TextByLanguage("Рыночный ордер (Да)","Market order (Yes)") : TextByLanguage("Рыночный ордер (Нет)","Market order (No)") ); } //+----------------------------------------------------------------------+ //| Return the description of allowing to use limit orders | //+----------------------------------------------------------------------+ string CSymbol::GetLimitOrdersAllowedDescription(void) const { return (this.IsLimitOrdersAllowed() ? TextByLanguage("Лимит ордер (Да)","Limit order (Yes)") : TextByLanguage("Лимит ордер (Нет)","Limit order (No)") ); } //+----------------------------------------------------------------------+ //| Return the description of allowing to use stop orders | //+----------------------------------------------------------------------+ string CSymbol::GetStopOrdersAllowedDescription(void) const { return (this.IsStopOrdersAllowed() ? TextByLanguage("Стоп ордер (Да)","Stop order (Yes)") : TextByLanguage("Стоп ордер (Нет)","Stop order (No)") ); } //+----------------------------------------------------------------------+ //| Return the description of allowing to use stop limit orders | //+----------------------------------------------------------------------+ string CSymbol::GetStopLimitOrdersAllowedDescription(void) const { return (this.IsStopLimitOrdersAllowed() ? TextByLanguage("Стоп-лимит ордер (Да)","StopLimit order (Yes)") : TextByLanguage("Стоп-лимит ордер (Нет)","StopLimit order (No)") ); } //+----------------------------------------------------------------------+ //| Return the description of allowing to set StopLoss orders | //+----------------------------------------------------------------------+ string CSymbol::GetStopLossOrdersAllowedDescription(void) const { return (this.IsStopLossOrdersAllowed() ? TextByLanguage("StopLoss (Да)","StopLoss (Yes)") : TextByLanguage("StopLoss (Нет)","StopLoss (No)") ); } //+----------------------------------------------------------------------+ //| Return the description of allowing to set TakeProfit orders | //+----------------------------------------------------------------------+ string CSymbol::GetTakeProfitOrdersAllowedDescription(void) const { return (this.IsTakeProfitOrdersAllowed() ? TextByLanguage("TakeProfit (Да)","TakeProfit (Yes)") : TextByLanguage("TakeProfit (Нет)","TakeProfit (No)") ); } //+----------------------------------------------------------------------+ //| Return the description of allowing to close by an opposite position | //+----------------------------------------------------------------------+ string CSymbol::GetCloseByOrdersAllowedDescription(void) const { return (this.IsCloseByOrdersAllowed() ? TextByLanguage("Закрытие встречным (Да)","CloseBy order (Yes)") : TextByLanguage("Закрытие встречным (Нет)","CloseBy order (No)") ); } //+----------------------------------------------------------------------+ //| Return the description of allowing FOK filling type | //+----------------------------------------------------------------------+ string CSymbol::GetFillingModeFOKAllowedDescrioption(void) const { return (this.IsFillingModeFOK() ? TextByLanguage("Всё/Ничего (Да)","Fill or Kill (Yes)") : TextByLanguage("Всё/Ничего (Нет)","Fill or Kill (No)") ); } //+----------------------------------------------------------------------+ //| Return the description of allowing IOC filling type | //+----------------------------------------------------------------------+ string CSymbol::GetFillingModeIOCAllowedDescrioption(void) const { return (this.IsFillingModeIOC() ? TextByLanguage("Всё/Частично (Да)","Immediate or Cancel order (Yes)") : TextByLanguage("Всё/Частично (Нет)","Immediate or Cancel (No)") ); } //+----------------------------------------------------------------------+ //| Return the description of GTC order expiration | //+----------------------------------------------------------------------+ string CSymbol::GetExpirationModeGTCDescription(void) const { return (this.IsExipirationModeGTC() ? TextByLanguage("Неограниченно (Да)","Unlimited (Yes)") : TextByLanguage("Неограниченно (Нет)","Unlimited (No)") ); } //+----------------------------------------------------------------------+ //| Return the description of DAY order expiration | //+----------------------------------------------------------------------+ string CSymbol::GetExpirationModeDAYDescription(void) const { return (this.IsExipirationModeDAY() ? TextByLanguage("До конца дня (Да)","Valid till the end of day (Yes)") : TextByLanguage("До конца дня (Нет)","Valid till the end of day (No)") ); } //+----------------------------------------------------------------------+ //| Return the description of Specified order expiration | //+----------------------------------------------------------------------+ string CSymbol::GetExpirationModeSpecifiedDescription(void) const { return (this.IsExipirationModeSpecified() ? TextByLanguage("Срок указывается в ордере (Да)","Time specified in order (Yes)") : TextByLanguage("Срок указывается в ордере (Нет)","Time specified in order (No)") ); } //+----------------------------------------------------------------------+ //| Return the description of Specified Day order expiration | //+----------------------------------------------------------------------+ string CSymbol::GetExpirationModeSpecDayDescription(void) const { return (this.IsExipirationModeSpecifiedDay() ? TextByLanguage("День указывается в ордере (Да)","Date specified in order (Yes)") : TextByLanguage("День указывается в ордере (Нет)","Date specified in order (No)") ); } //+------------------------------------------------------------------+
在方法中,一切都很简单:检查属性值,并返回其字符串说明。
某些方法(名义上,即标志说明)在返回的描述中显示其他方法的字符串值。 反过来,这些其他方法返回对特定标志的描述,该标志包含一个所选属性的值。
所以,我们获得了单个属性的所有标志的格式化复合说明。
在 MQL5 中,单一属性的标志显示在已说明属性的名称列中,例如:
允许的订单类型的标志: - 市价单 (Yes) - 限价单 (Yes) - 停止单 (Yes) - 停止限价单 (Yes) - 止损 (Yes) - 止盈 (Yes) - 对冲平仓 (Yes)
在 MQL4 中,这些属性显示在单个字符串中:
允许的订单类型的标志:市价订单(是); 限价单(是); 停止订单(是); 停止限价单(否); 止损(是); 止盈(是); 对冲平仓(是)
由于这是在 MQL4 中,Print() 函数不接受 “\n” 换行符。 因此,这些方法使用条件编译指令分别对 MQL5 和 MQL4
进行格式化。
以下是正叙述的品种属性返回标准化价格的服务方法:
//+------------------------------------------------------------------+ //| Return a normalized price considering symbol properties | //+------------------------------------------------------------------+ double CSymbol::NormalizedPrice(const double price) const { double tsize=this.TradeTickSize(); return(tsize!=0 ? ::NormalizeDouble(::round(price/tsize)*tsize,this.Digits()) : ::NormalizeDouble(price,this.Digits())); } //+------------------------------------------------------------------+
该方法参考最小价格变化,对价格进行常规化。
最后,有两个方法:
更新所有品种对象属性的方法,该方法将来可能会有所修改,以及更新品种报价数据的方法:
//+------------------------------------------------------------------+ //| Update all symbol data that may change | //+------------------------------------------------------------------+ void CSymbol::Refresh(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_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_MARGIN_LONG)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_MARGIN_LONG); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_SHORT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_MARGIN_SHORT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_STOP)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_MARGIN_STOP); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_LIMIT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_MARGIN_LIMIT); this.m_double_prop[this.IndexProp(SYMBOL_PROP_MARGIN_STOPLIMIT)] = ::SymbolInfoDouble(this.m_symbol_name,SYMBOL_MARGIN_STOPLIMIT); 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(); } //+------------------------------------------------------------------+ //| Update quote data by 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(); } //+------------------------------------------------------------------+
在此一切都很简单:所需的品种属性将据其数据重新填写。
两种方法都旨在获得有关品种属性的相关数据。 在获取所需数据之前,应立即调用 Refresh() 方法,而在计时器中将为稍后要处理的集合列表中的所有品种对象不断调用
RefreshRates() 方法。
至此,抽象品种对象方法的开发完毕。
现在,我们需要针对 ToMQL4.mqh 文件进行一些补充,在其中我们设置了所有必需的枚举和宏替换,以便实现 MQL4 的无错误编译。
在品种对象类中,我们用到了返回 MQL5 错误代码的方法。 我们添加它们以使 MQL4 知道其局限性:
//+------------------------------------------------------------------+ //| ToMQL4.mqh | //| Copyright 2017, Artem A. Trishkin, Skype artmedia70 | //| https://www.mql5.com/en/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2017, Artem A. Trishkin, Skype artmedia70" #property link "https://www.mql5.com/en/users/artmedia70" #property strict #ifdef __MQL4__ //+------------------------------------------------------------------+ //| Error codes | //+------------------------------------------------------------------+ #define ERR_SUCCESS (ERR_NO_ERROR) #define ERR_MARKET_UNKNOWN_SYMBOL (ERR_UNKNOWN_SYMBOL) //+------------------------------------------------------------------+
我们还用到了负责各种品种订单模式的标志。 我们一并指定它们:
//+------------------------------------------------------------------+ //| Flags of allowed order expiration modes | //+------------------------------------------------------------------+ #define SYMBOL_EXPIRATION_GTC (1) #define SYMBOL_EXPIRATION_DAY (2) #define SYMBOL_EXPIRATION_SPECIFIED (4) #define SYMBOL_EXPIRATION_SPECIFIED_DAY (8) //+------------------------------------------------------------------+ //| Flags of allowed order filling modes | //+------------------------------------------------------------------+ #define SYMBOL_FILLING_FOK (1) #define SYMBOL_FILLING_IOC (2) //+------------------------------------------------------------------+ //| Flags of allowed order types | //+------------------------------------------------------------------+ #define SYMBOL_ORDER_MARKET (1) #define SYMBOL_ORDER_LIMIT (2) #define SYMBOL_ORDER_STOP (4) #define SYMBOL_ORDER_STOP_LIMIT (8) #define SYMBOL_ORDER_SL (16) #define SYMBOL_ORDER_TP (32) #define SYMBOL_ORDER_CLOSEBY (64) //+------------------------------------------------------------------+
添加 MQL4 中不存在的枚举:
//+------------------------------------------------------------------+ //| Prices a symbol chart is based on | //+------------------------------------------------------------------+ enum ENUM_SYMBOL_CHART_MODE { SYMBOL_CHART_MODE_BID, // Bars are based on Bid prices SYMBOL_CHART_MODE_LAST // Bars are based on Last prices }; //+------------------------------------------------------------------+ //| Lifetime of pending orders and | //| placed StopLoss/TakeProfit levels | //+------------------------------------------------------------------+ enum ENUM_SYMBOL_ORDER_GTC_MODE { SYMBOL_ORDERS_GTC, // Pending orders and Stop Loss/Take Profit levels are valid for an unlimited period until their explicit cancellation SYMBOL_ORDERS_DAILY, // At the end of the day, all Stop Loss and Take Profit levels, as well as pending orders are deleted SYMBOL_ORDERS_DAILY_EXCLUDING_STOPS // At the end of the day, only pending orders are deleted, while Stop Loss and Take Profit levels are preserved }; //+------------------------------------------------------------------+ //| Option types | //+------------------------------------------------------------------+ enum ENUM_SYMBOL_OPTION_MODE { SYMBOL_OPTION_MODE_EUROPEAN, // European option may only be exercised on a specified date SYMBOL_OPTION_MODE_AMERICAN // American option may be exercised on any trading day or before expiry }; #define SYMBOL_OPTION_MODE_NONE (2) // Option type absent in MQL4 //+------------------------------------------------------------------+ //| Right provided by an option | //+------------------------------------------------------------------+ enum ENUM_SYMBOL_OPTION_RIGHT { SYMBOL_OPTION_RIGHT_CALL, // A call option gives you the right to buy an asset at a specified price SYMBOL_OPTION_RIGHT_PUT // A put option gives you the right to sell an asset at a specified price }; #define SYMBOL_OPTION_RIGHT_NONE (2) // No option - no right //+------------------------------------------------------------------+
使用宏替换为期权设置其他属性。 这些属性指示缺少期权类型。 当需要返回这些品种对象属性的数值时,我们将在 MQL4
中继续使用它们。
以下两个枚举在 MQL5 和 MQL4 中没有常量值序列。
因此,我交换了枚举中指定常量的顺序。 MQL5 和 MQL4 的相应值在注释中设置为常数。 其顺序在此将设置为与 MQL4 中的值相匹配,以便返回正确的值:
//+------------------------------------------------------------------+ //| Symbol margin calculation method | //+------------------------------------------------------------------+ enum ENUM_SYMBOL_CALC_MODE { SYMBOL_CALC_MODE_FOREX, // (MQL5 - 0, MQL4 - 0) Forex mode SYMBOL_CALC_MODE_CFD, // (MQL5 - 3, MQL4 - 1) CFD mode SYMBOL_CALC_MODE_FUTURES, // (MQL5 - 2, MQL4 - 2) Futures mode SYMBOL_CALC_MODE_CFDINDEX, // (MQL5 - 4, MQL4 - 3) CFD index mode SYMBOL_CALC_MODE_FOREX_NO_LEVERAGE, // (MQL5 - 1, MQL4 - N) Forex No Leverage mode SYMBOL_CALC_MODE_CFDLEVERAGE, // CFD Leverage mode SYMBOL_CALC_MODE_EXCH_STOCKS, // Exchange mode SYMBOL_CALC_MODE_EXCH_FUTURES, // Futures mode SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS, // FORTS Futures mode SYMBOL_CALC_MODE_EXCH_BONDS, // Exchange Bonds mode SYMBOL_CALC_MODE_EXCH_STOCKS_MOEX, // Exchange MOEX Stocks mode SYMBOL_CALC_MODE_EXCH_BONDS_MOEX, // Exchange MOEX Bonds mode SYMBOL_CALC_MODE_SERV_COLLATERAL // Collateral mode }; //+------------------------------------------------------------------+ //| Swap charging methods during a rollover | //+------------------------------------------------------------------+ enum ENUM_SYMBOL_SWAP_MODE { SYMBOL_SWAP_MODE_POINTS, // (MQL5 - 1, MQL4 - 0) Swaps are charged in points SYMBOL_SWAP_MODE_CURRENCY_SYMBOL, // (MQL5 - 2, MQL4 - 1) Swaps are charged in money in symbol base currency SYMBOL_SWAP_MODE_INTEREST_OPEN, // (MQL5 - 6, MQL4 - 2) Swaps are charged as the specified annual interest from the open price of position SYMBOL_SWAP_MODE_CURRENCY_MARGIN, // (MQL5 - 3, MQL4 - 3) Swaps are charged in money in margin currency of the symbol SYMBOL_SWAP_MODE_DISABLED, // (MQL5 - 0, MQL4 - N) No swaps SYMBOL_SWAP_MODE_CURRENCY_DEPOSIT, // Swaps are charged in money, in client deposit currency SYMBOL_SWAP_MODE_INTEREST_CURRENT, // Swaps are charged as the specified annual interest from the instrument price at calculation of swap SYMBOL_SWAP_MODE_REOPEN_CURRENT, // Swaps are charged by reopening positions by the close price SYMBOL_SWAP_MODE_REOPEN_BID // Swaps are charged by reopening positions by the current Bid price }; //+------------------------------------------------------------------+
所有品种对象数据现已全部创建完毕。
由于我们在 Engine 函数库主对象引入了自类返回的错误代码,因此我们需要为 CEngine 类添加变量成员,以便存储错误代码。 打开 \MQL5\Include\DoEasy\Engine.mqh,并在其中进行必要的修改。
在类的私有部分,声明存储错误代码的变量:
class CEngine : public CObject { private: CHistoryCollection m_history; // Collection of historical orders and deals CMarketCollection m_market; // Collection of market orders and deals CEventsCollection m_events; // Event collection CAccountsCollection m_accounts; // Account collection CArrayObj m_list_counters; // List of timer counters int m_global_error; // Global error code bool m_first_start; // First launch flag bool m_is_hedge; // Hedge account flag bool m_is_tester; // Flag of working in the tester
在类构造函数的初始化清单中,初始化错误代码。 接下来,在针对 MQL5 和 MQL4 创建毫秒计时器的模块中,将最后一个错误代码赋值给变量:
//+------------------------------------------------------------------+ //| CEngine constructor | //+------------------------------------------------------------------+ 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_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.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); ::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 } //+------------------------------------------------------------------+
现在,我们需要将新创建的类文件包含到函数库的主体对象中(临时性 — 仅用于当前检查):
//+------------------------------------------------------------------+ //| Engine.mqh | //| Copyright 2018, MetaQuotes Software Corp. | //| https://mql5.com/en/users/artmedia70 | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://mql5.com/en/users/artmedia70" #property version "1.00" //+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include "Collections\HistoryCollection.mqh" #include "Collections\MarketCollection.mqh" #include "Collections\EventsCollection.mqh" #include "Collections\AccountsCollection.mqh" #include "Services\TimerCounter.mqh" #include "Objects\Symbols\Symbol.mqh" //+------------------------------------------------------------------+ //| Library basis class | //+------------------------------------------------------------------+ class CEngine : public CObject {
现在一切准备就绪,可以测试品种对象了。
但首先,我想提请您的注意,在上一篇文章中,当创建按列表中编号返回帐户事件的方法时,我遗留了一处不引人注意的缺陷 — 在 CAccountsCollection
帐户集合类中。
当前方法版本如下:
//+------------------------------------------------------------------+ //| Return the account event by its number in the list | //+------------------------------------------------------------------+ ENUM_ACCOUNT_EVENT CAccountsCollection::GetEvent(const int shift=WRONG_VALUE) { int total=this.m_list_changes.Total(); if(total==0) return ACCOUNT_EVENT_NO_EVENT; int index=(shift<0 || shift>total-1 ? total-1 : total-shift-1); int event=this.m_list_changes.At(index); return ENUM_ACCOUNT_EVENT(event!=NULL ? event : ACCOUNT_EVENT_NO_EVENT); } //+------------------------------------------------------------------+
此处是我编写的有关从方法返回事件的内容:
帐户属性变更列表中的事件按添加顺序排列 — 第一个位于索引 0,而最后一个位于索引(list_size-1)处。 不过,我们希望让用户按时间序列获取所需事件 — 零号索引应含最后一个事件。 为达此目的,该方法具有索引计算功能:index = (list_size - desired_event_number-1)。 在这种情况下, 如果我们传递 0 或 -1,则返回列表中的最后一个事件;如果为 1,则是最早的一个,如果编号超出列表大小,则返回最后的事件。
在此,我们存在逻辑上的不一致:如果将 0 传递给方法,则会得到最后一个事件。 如果传递的值超过数组大小,则逻辑上应返回第一个事件而不是最后一个事件。 逻辑上是传递 0 或负值(默认情况下)来接收最后一个事件,然后按顺序进行:1 — 最早一个,2 —倒数第二个,依此类推。
如果我们不知道数组的大小,并传递一个已知的大数,那么我们应期望得到时间上最远的值 — 第一个,而该方法返回最后那个。 我们来解决这种不合逻辑的行为:
//+------------------------------------------------------------------+ //| Return the account event by its number in the list | //+------------------------------------------------------------------+ ENUM_ACCOUNT_EVENT CAccountsCollection::GetEvent(const int shift=WRONG_VALUE) { int total=this.m_list_changes.Total(); if(total==0) return ACCOUNT_EVENT_NO_EVENT; int index=(shift<=0 ? total-1 : shift>total-1 ? 0 : total-shift-1); int event=this.m_list_changes.At(index); return ENUM_ACCOUNT_EVENT(event!=NULL ? event : ACCOUNT_EVENT_NO_EVENT); } //+------------------------------------------------------------------+
此处:如果传递 0 或 -1,则返回最后一个事件,如果传递的值超过数组大小,则返回第一个事件。
在其他情况下,将计算返回事件的索引。
为了测试对象品种,我们将采用上一篇文章的 EA,并将其保存为 TestDoEasyPart14.mq5。
我们将在 OnInit() 处理程序中检查对象品种。 为此,只需将以下代码字符串添加到 OnInit() 的末尾:
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Calling the function displays the list of enumeration constants in the journal, //--- (the list is set in the strings 22 and 25 of the DELib.mqh file) for checking the constants validity //EnumNumbersTest(); //--- Set EA global variables prefix=MQLInfoString(MQL_PROGRAM_NAME)+"_"; for(int i=0;i<TOTAL_BUTT;i++) { butt_data[i].name=prefix+EnumToString((ENUM_BUTTONS)i); butt_data[i].text=EnumToButtText((ENUM_BUTTONS)i); } lot=NormalizeLot(Symbol(),fmax(InpLots,MinimumLots(Symbol())*2.0)); magic_number=InpMagic; stoploss=InpStopLoss; takeprofit=InpTakeProfit; distance_pending=InpDistance; distance_stoplimit=InpDistanceSL; slippage=InpSlippage; trailing_stop=InpTrailingStop*Point(); trailing_step=InpTrailingStep*Point(); trailing_start=InpTrailingStart; stoploss_to_modify=InpStopLossModify; takeprofit_to_modify=InpTakeProfitModify; //--- Check and remove remaining EA graphical objects if(IsPresentObects(prefix)) ObjectsDeleteAll(0,prefix); //--- Create the button panel if(!CreateButtons(InpButtShiftX,InpButtShiftY)) return INIT_FAILED; //--- Set trailing activation button status ButtonState(butt_data[TOTAL_BUTT-1].name,trailing_on); //--- 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 a symbol object string smb=Symbol(); CSymbol* sy=new CSymbol(SYMBOL_STATUS_FX,smb); if(sy!=NULL) { sy.Refresh(); sy.RefreshRates(); sy.Print(); delete sy; } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+
在此,我们创建一个新的品种对象。 由于我们将在下一篇文章中将品种分配到某个组,因此只需将“外汇品种”和品种名称传递给构造函数即可。
如果对象已创建,更新其所有数据,更新报价数据,在日志中显示所有品种对象属性,并删除该对象,以避免测试 EA 完成其工作时发生内存泄漏。
如果现在尝试编译 EA,则会出现访问受保护的类构造函数的错误:
'CSymbol::CSymbol' - cannot access protected member function TestDoEasyPart14.mq5 131 20
see declaration of 'CSymbol::CSymbol' Symbol.mqh 39 22
1 error(s), 0 warning(s) 2 1
转到 Symbol.mqh 文件,将受保护的参数构造函数 临时从类的受保护的部分移到公开部分:
//+------------------------------------------------------------------+ //| Abstract symbol class | //+------------------------------------------------------------------+ class CSymbol : public CObject { private: 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; } //--- Reset all symbol object data void Reset(void); public: //--- Default constructor CSymbol(void){;} CSymbol(ENUM_SYMBOL_STATUS symbol_status,const string name); protected: //--- Protected parametric constructor //--- Get and return integer properties of a selected symbol from its parameters
现在编译时全无错误。
在 MetaTrader 5 的品种图表上启动 EA。
所有品种对象属性都发送到日志:
Account 18222304: Artyom Trishkin (MetaQuotes Software Corp. 10000.00 RUR, 1:100, Demo account MetaTrader 5) ============= Beginning of the parameter list:: "EURUSD" (Euro vs US Dollar) ================== Status: Forex symbol Custom symbol: No The price type used for generating bars: Bars are based on Bid prices The symbol under this name exists: Yes The symbol is selected in Market Watch: Yes The symbol is displayed in Market Watch: Yes The number of deals in the current session: 0 The total number of Buy orders at the moment: 0 The total number of Sell orders at the moment: 0 Last deal volume: 0 Maximum volume within a day: 0 Minimum volume within a day: 0 Latest quote time: 2019.06.17 15:37:13.016 Number of decimal places: 5 Number of decimal places for a lot: 2 Spread in points: 10 Floating spread: Yes Maximum number of orders displayed in the Depth of Market: 10 Contract price calculation method: Forex mode Order execution type: No trade restrictions Symbol trading start date: (Not set) Symbol trading end date: (Not set) Minimum distance in points from the current close price for setting Stop orders: 0 Freeze distance for trading operations: 0 Deal execution mode: Instant execution Swap calculation model: Swaps are charged in points Triple-day swap: Wednesday Calculating hedging margin using the larger leg: No Flags of allowed order expiration modes: - Unlimited (Yes) - Valid till the end of the day (Yes) - Time is specified in the order (Yes) - Date is specified in the order (Yes) Flags of allowed order filling modes: - Return (Yes) - Fill or Kill (Yes) - Immediate or Cancel (No) 允许的订单类型的标志: - 市价单 (Yes) - 限价单 (Yes) - 停止单 (Yes) - 停止限价单 (Yes) - 止损 (Yes) - 止盈 (Yes) - CloseBy order (Yes) StopLoss and TakeProfit orders lifetime: Pending orders and Stop Loss/Take Profit levels are valid for an unlimited period until their explicit cancellation Option type: European option may only be exercised on a specified date Option right: A call option gives you the right to buy an asset at a specified price Background color of the symbol in Market Watch: (Not set) ------ Bid price: 1.12411 The highest Bid price of the day: 1.12467 The lowest Bid price of the day: 1.12033 Ask price: 1.12421 The highest Ask price of the day: 1.12477 The lowest Ask price of the day: 1.12043 The last deal price: 0.00000 The highest Last price of the day: 0.00000 The lowest Last price of the day: 0.00000 Volume of the day: 0.00 Maximum Volume of the day: 0.00 Minimum Volume of the day: 0.00 Option execution price: 0.00000 Point value: 0.00001 Calculated tick value for a position: 64.22 Calculated tick value for a winning position: 64.22 Calculated tick value for a losing position: 64.23 Minimum price change: 0.00001 Trade contract size: 100000.00 Accrued interest: 0.00 Face value: 0.00 Liquidity rate: 0.00 Minimum volume for a deal: 0.01 Maximum volume for a deal: 500.00 Minimum volume change step for a deal: 0.01 Maximum acceptable total volume of an open position and pending orders in one direction: 0.00 Long swap value: -0.70 Short swap value: -1.00 Initial margin: 0.00 Maintenance margin for an instrument: 0.00 Margin requirement applicable to long positions: 0.00 Margin requirement applicable to short positions: 0.00 Margin requirement applicable to Stop orders: 0.00 Margin requirement applicable to Limit orders: 0.00 Margin requirement applicable to Stop Limit orders: 0.00 The total volume of deals in the current session: 0.00 The total turnover in the current session: 0.00 The total volume of open positions: 0.00 The total volume of Buy orders at the moment: 0.00 The total volume of Sell orders at the moment: 0.00 The open price of the session: 0.00000 The close price of the session: 0.00000 The average weighted price of the session: 0.00000 The settlement price of the current session: 0.00000 The minimum allowable price value for the session: 0.00000 The maximum allowable price value for the session: 0.00000 Size of a contract or margin for one lot of hedged positions: 100000.00 ------ Symbol name: EURUSD The name of the underlaying asset for a derivative symbol: (Not set) The base currency of an instrument: "EUR" Profit currency: "USD" Margin currency: "EUR" The source of the current quote: (Not set) Symbol description: "Euro vs US Dollar" The formula used for custom symbol pricing: (Not set) The name of a trading symbol in the international system of securities identification numbers: (Not set) The address of the web page containing symbol information: "http://www.google.com/finance?q=EURUSD" Path in the symbol tree: "Forex\EURUSD" ================== End of the parameter list: EURUSD" (Euro vs US Dollar) ==================
在 MetaTrader 4 的品种图表上启动 EA。
所有品种对象属性都发送到日志:
Account 49610941: Artyom Trishkin (MetaQuotes Software Corp. 5000000.00 USD, 1:100, Hedge, Demo account MetaTrader 4) ============= Beginning of the parameter list: "EURUSD" (Euro vs US Dollar) ================== Status: Forex symbol Custom symbol: No The price type used for generating bars: Bars are based on Bid prices The symbol under this name exists: Yes The symbol is selected in Market Watch: Yes The symbol is displayed in Market Watch: Yes The number of deals in the current session: Property not supported in MQL4 The total number of Buy orders at the moment: Property not supported in MQL4 The total number of Sell orders at the moment: Property not supported in MQL4 Last deal volume: Property not supported in MQL4 Maximum volume within a day: Property not supported in MQL4 Minimum volume within a day: Property not supported in MQL4 Latest quote time: 2019.06.17 19:40:41.000 Number of decimal places: 5 Number of decimal places for a lot: 2 Spread in points: 20 Floating spread: Yes Maximum number of orders displayed in the Depth of Market: Property not supported in MQL4 Contract price calculation method: Forex mode Order execution type: No trade restrictions Symbol trading start date: (Not set) Symbol trading end date: (Not set) Minimum distance in points from the current close price for setting Stop orders: 8 Freeze distance for trading operations: 0 Deal execution mode: Instant execution Swap calculation model: Swaps are charged in points Triple-day swap: Wednesday Calculating hedging margin using the larger leg: No Flags of allowed order expiration modes: Unlimited (Yes); Valid till the end of the day (No); Time is specified in the order (No); Date is specified in the order (No) Flags of allowed order filling modes: Return (Yes); Fill or Kill (No); Immediate or Cancel (No) Flags of allowed order types: Market order (Yes); Limit order (Yes); Stop order (Yes); Stop limit order (No); StopLoss (Yes); TakeProfit (Yes); Close by (Yes) StopLoss and TakeProfit orders lifetime: Pending orders and Stop Loss/Take Profit levels are valid for an unlimited period until their explicit cancellation Option type: Property not supported in MQL4 Option right: Property not supported in MQL4 The color of the background used for the symbol in Market Watch: Property not supported in MQL4 ------ Bid price: 1.12328 The highest Bid price of the day: 1.12462 The lowest Bid price of the day: 1.12029 Ask price: 1.12348 The highest Ask price of the day: Property not supported in MQL4 The lowest Ask price of the day: Property not supported in MQL4 Last deal price: Property not supported in MQL4 The highest Last price of the day: Property not supported in MQL4 The lowest Last price of the day: Property not supported in MQL4 Volume of the day: Property not supported in MQL4 Maximum Volume of the day: Property not supported in MQL4 Minimum Volume of the day: Property not supported in MQL4 Option execution price: Property not supported in MQL4 Point value: 0.00001 Calculated tick value for a position: 1.00 Calculated tick value for a winning position: Property not supported in MQL4 Calculated tick value for a losing position: Property not supported in MQL4 Minimum price change: 0.00001 Trade contract size: 100000.00 Accrued interest: Property not supported in MQL4 Face value: Property not supported in MQL4 Liquidity rate: Property not supported in MQL4 Minimum volume for a deal: 0.01 Maximum volume for a deal: 100000.00 Minimum volume change step for a deal: 0.01 Maximum acceptable total volume of an open position and pending orders in one direction: Property not supported in MQL4 Long swap value: 0.33 Short swap value: -1.04 Initial margin: 0.00 Maintenance margin for an instrument: 0.00 Margin requirement applicable to long positions: Property not supported in MQL4 Margin requirement applicable to short positions: Property not supported in MQL4 Margin requirement applicable to Stop orders: Property not supported in MQL4 Margin requirement applicable to Limit orders: Property not supported in MQL4 Margin requirement applicable to Stop Limit orders: Property not supported in MQL4 The total volume of deals in the current session: Property not supported in MQL4 The total turnover in the current session: Property not supported in MQL4 The total volume of open positions: Property not supported in MQL4 The total volume of Buy orders at the moment: Property not supported in MQL4 EURUSD,H4: The total volume of Sell orders at the moment: Property not supported in MQL4 The open price of the session: Property not supported in MQL4 The close price of the session: Property not supported in MQL4 The average weighted price of the session: Property not supported in MQL4 The settlement price of the current session: Property not supported in MQL4 The minimum allowable price value for the session: Property not supported in MQL4 The maximum allowable price value for the session: Property not supported in MQL4 Size of a contract or margin for one lot of hedged positions: 50000.00 ------ Symbol name: EURUSD The name of the underlaying asset for a derivative symbol: ": Property not supported in MQL4" The base currency of an instrument: "EUR" Profit currency: "USD" Margin currency: "EUR" The source of the current quote: ": Property not supported in MQL4" Symbol description: "Euro vs US Dollar" The formula used for custom symbol pricing: ": Property not supported in MQL4" The name of a trading symbol in the international system of securities identification numbers: ": Property not supported in MQL4" The address of the web page containing symbol information: ": Property not supported in MQL4" Path in the symbol tree: "Forex\EURUSD" ================== End of the parameter list: EURUSD" (Euro vs US Dollar) ==================
与 MetaTrader 5 中启动不同,此处并非所有属性都支持。 因此,日志中有相应的消息。 标志列表以单行显示,这已在上面提到过。
在下一篇文章中,创建派生对象时,不会显示不支持的属性的描述字符串。
将会为每个派生对象设置指示支持某些对象属性的标志。 每个属性均会设置标志。
在下一篇文章中,我们将着手开发品种集合类,该类将令用户可以轻松地搜索数据,以及对集合列表中的品种进行排序和比较。
文后附有当前版本含糊库的所有文件,以及测试 EA 文件,供您测试和下载。
请在评论中留下您的问题、意见和建议。
返回目录
系列中的前几篇文章:
第一部分 概念,数据管理
本社区仅针对特定人员开放
查看需注册登录并通过风险意识测评
5秒后跳转登录页面...
移动端课程