Biblioteca para el desarrollo rápido y sencillo de programas para MetaTrader (Parte XIV): El objeto "Símbolo"
Artyom Trishkin | 23 septiembre, 2019
Contenido
En el trading, el símbolo comerciado tiene un valor especial: y no solo porque el programa esté fijado al gráfico del símbolo (con excepción de los servicios), sino también porque el programa depende directamente de las propiedades del símbolo en el que funciona y ejecuta operaciones comerciales y de otro tipo. Por eso, resultaría extraño no crear las condiciones necesarias para obtener cómodamente los datos de los símbolos deseados, para poder analizarlos y compararlos. Con este objetivo, vamos a crear un objeto de símbolo, una colección de objetos de símbolo y los eventos de la colección de símbolos.
El objeto de símbolo
En el presente artículo, vamos a crear un objeto que constituye un cierto símbolo "abstracto". A continuación, al crear la colección de símbolos, crearemos los objetos herederos del objeto de símbolo básico, en los que se concretará la información sobre la pertenencia de símbolo a uno u otro grupo de símbolos y se permitirán o prohibirán algunas de las propiedades del objeto básico.Vamos a dividir los objetos de símbolo en categorías:
- símbolo fórex
- símbolo fórex mayor
- símbolo fórex menor
- símbolo fórex exótico
- símbolo fórex/rublo
- Metales preciosos
- Índice
- Indicativo
- Símbolo de criptodivisa
- Símbolo comercial
- Símbolo bursátil
- Opción binaria
- Símbolo de usuario
Claro que todas estas categorías son condicionales, y la ubicación del símbolo en esta u otra categoría es bastante subjetiva, ya que
depende de las preferencias del usuario. Pero podemos sacar ciertas conclusiones sobre una categoría a partir de la propiedad del
símbolo "ruta en el árbol de símbolos", allí se encuentra el directorio de ubicación del símbolo en esta u otra carpeta del árbol de
símbolos, y podemos dar al símbolo una categoría que se corresponda con la denominación de la carpeta. Sin embargo, podemos organizar
para cada servidor al que se conecta un terminal nuestros propias carpetas de guardado de símbolos con el mismo nombre, y cuyo nombre se
diferencie de un servidor a otro.
Partiendo de lo que tenemos, primero determinaremos la categoría del símbolo según la lista de categorías personalizada, y
si el símbolo no ha sido encontrado en una categoría personalizada, miraremos su carpeta de ubicación en el árbol de símbolos. Si no
hemos logrado determinar la categoría a partir de la demonominación de su carpeta de ubicación, la selección final en cuanto a la
categoría del símbolo vendrá marcada por su propiedad "método de cálculo del coste del contrato", donde podremos determinar y
seleccionar una de las dos categorías del símbolo, o bien bursátil, o bien fórex.
Pero hablaremos de ello más tarde, al crear la colección de objetos de símbolo; ahora, debemos ocuparnos de la creación del objeto de
símbolo básico.
Comenzaremos por la definición de las enumeraciones y macrosustituciones para las propiedades del objeto de símbolo. Abrimos el archivo Defines.mqh, y luego añadimos al final del listado los datos necesarios para trabajar con el símbolo:
//+------------------------------------------------------------------+ //| 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 }; //+------------------------------------------------------------------+
El estado del símbolo será su pertenencia a la categoría del símbolo; dicha pertenencia se seleccionará antes de crear el objeto heredero a partir del objeto de símbolo básico. Nos ocuparemos de ello al describir la creación de la colección de símbolos.
Vamos a añadir las propiedades de tipo entero del símbolo:
//+------------------------------------------------------------------+ //| 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 //+------------------------------------------------------------------+
Ya analizamos la organización de las enumeraciones de las propiedades de los objetos en la sexta parte de la descripción de la
biblioteca, en el apartado "
Implementando el procesamiento de eventos en una cuenta de compensación", por eso, no vamos a
detenernos aquí en el estudio de la designación de las macrosustituciones del número de propiedades y el número de
propiedades del objeto usadas para la búsqueda y la clasificación. Solo destacaremos que, aparte de las propiedades estándar de
tipo entero del objeto de símbolo pertenecientes a la enumeración
ENUM_SYMBOL_INFO_INTEGER, hemos
añadido dos propiedades más:
el estado del símbolo y el
número de dígitos decimales tras la coma en el valor del lote del símbolo.
Añadimos la enumeración de las propiedades de tipo real del símbolo:
//+------------------------------------------------------------------+ //| 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 //+------------------------------------------------------------------+
Aquí, aparte de las propiedades descritas en la enumeración ENUM_SYMBOL_INFO_DOUBLE,
hemos añadido otras
cinco propiedades del símbolo, que por algún motivo no han entrado en
la descripción de la enumeración de las propiedades de tipo real, pero que existen en ella y pertenecen a esta enumeración.
Añadimos la enumeración de las propiedades de tipo string del símbolo y los posibles criterios de clasificación de los símbolos:
//+------------------------------------------------------------------+ //| 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 }; //+------------------------------------------------------------------+
En la enumeración de las propiedades de tipo string, simplemente hemos añadido las constantes que les corresponden de la enumeración ENUM_SYMBOL_INFO_STRING,
y hemos enumerado en la lista de posibles criterios de clasificación todas las propiedades del símbolo, con la excepción del color
del fondo en la ventana de la "Observación del mercado", ya que no existe sentido práctico en clasificar y comparar los símbolos según su
color de fondo en una ventana que pertenece al terminal.
Estos son todos los datos necesarios para trabajar con los objetos de símbolo.
Ahora, vamos a crear la clase del objeto de símbolo.
Creamos en la carpeta \MQL5\Include\DoEasy\Objects\ un nuevo archivo de la clase CCymbol, con el nombre de Symbol.mqh. Rellenamos de inmediato la clase con los métodos e inclusiones estándar para la biblioteca:
//+------------------------------------------------------------------+ //| 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; };
Ya hemos analizado estos métodos en la primera parte de la descripción de la biblioteca, así que no vamos a verlos de nuevo.
Ahora, añadimos a la sección privada las variables y métodos necesarios para el funcionamiento de la clase:
//+------------------------------------------------------------------+ //| 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);
De la estructura del tick obtendremos los datos sobre los
precios Ask, Bid, Last y la hora del tick: en milisegundos para MQL5, y en segundos para MQL4. Aunque en la estructura del tick en MQL4 existe el
campo de milisegundos, este, por desgracia, no se utiliza, así que para MQL4 tomaremos la hora en segundos * 1000, para pasarlo a
milisegundos.
La matriz de estructura de los datos de la profundidad la
necesitaremos más tarde, cuando implementemos la obtención del contenido de la profundidad (pero no en el presente artículo).
Código de error global: existen situaciones en las que,cuando
se ejecuta erróneamente algún método o función, ya no resulta posible continuar trabajando con un programa que funcione sobre la base de la
biblioteca; en ese supuesto, resulta imprescindible que el programa esté al tanto de la ejecución errónea del método o función, para
procesar la situación adecuadamente y a su debido tiempo. Precisamente para estos casos, hemos introducido esta variable: registraremos
en ella el código de error, mientras que el objeto básico de la biblioteca CEngine interrogará al código de error; si este contiene un valor
distinto a cero, este código será procesado en primer lugar en la clase CEngine, y si no existe la posibilidad de "solucionar el problema" con
los recursos internos, el código será enviado al programa que ha realizado la llamada, para reaccionar al error a su debido tiempo.
Antes de crear el objeto de símbolo, debemos resetear todos sus campos y
estructuras ; precisamente para ello se ha pensado el método Reset().
Vamos a ejecutar en el constructor protegido de la clase todas las propiedades del símbolo con la ayuda de las funciones estándar. Pero no todas las funciones pueden ser adecuadas para MQL4, por eso, para los casos en los que hay que divir la obtención de datos para MQL5 o MQL4, hemos creado en la sección protegida de la clase los métodos necesarios para obtener los datos:
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:
Declaramos en la sección pública los métodos que retornan los estados de las diferentes banderas, que describen los modos permitidos de ciertas propiedades del símbolo, así como las descripciones de línea de estos modos:
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;
Asimismo, añadimos a la sección pública de la clase:
el
método de obtención del error, el método de actualización de todos los
datos de un símbolo, el método de actualización de los datos de las
cotizaciones de un símbolo, asimismo, los métodos auxiliares para añadir/eliminar
un símbolo en la ventana de "Observación del mercado", el método que
retorna la bandera de sincronicidad de los datos de un símbolo, y los métodos
de suscripción a la profundidad de mercado y cancelación de la suscripción a la misma.
En los próximos artículos
organizaremos el trabajo con la profundidad de mercado.
//--- 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;
Dado que disponemos de métodos que retornan cualquier propiedad según su nombre (constante de enumeración), podemos obtener los datos sobre
cualquiera de las propiedades desde el exterior, pero esto no resulta muy práctico desde el punto de vista de la sencillez programática:
debemos recordar todos los nombres de las constantes de las enumeraciones de las propiedades del objeto de símbolo. Por eso (como en las
clases anteriores, y por el mismo motivo), vamos a introducir de forma adicional métodos públicos que retornan todas las propiedades del
objeto de símbolo, pero con nombres más informativos.
Los añadimos al final del cuerpo de la clase:
//+------------------------------------------------------------------+ //| 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); } //--- }; //+------------------------------------------------------------------+
Bien, ya hemos declarado los métodos, algunos de ellos directamente con su implementación en el cuerpo de la clase. Ahora, vamos a escribir y analizar la implementación de todos los métodos declarados.
Implementando el constructor protegido de la clase:
//+------------------------------------------------------------------+ //| 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(); } //+------------------------------------------------------------------+
Los parámetros de entrada del constructor son el estado del símbolo
y su nombre. Al crear la colección de símbolos, iteraremos por el ciclo
de todos los símbolos necesarios para trabajar, determinaremos su pertenencia a las categorías que hemos establecido anteriormente (en
la enumeración ENUM_SYMBOL_STATUS) y crearemos un nuevo objeto heredero de esta clase de símbolo abstracto. A continuación,
transmitiremos al heredero solo el nombre del símbolo, mientras que el estado se establecerá automáticamente según el tipo del objeto
heredero y se enviará al constructor de la clase padre al crear el objeto heredero. Ya analizamos este punto al valorar la creación de los
objetos de orden
en la segunda parte de la descripción de la biblioteca.
En la
lista de inicialización del constructor,
inicializamos de inmediato el código de error.
A
continuación, ya en el cuerpo del método, primero
comprobamos si existe ese símbolo en el servidor, y si no lo
hubiera, mostramos el mensaje sobre el error en el diario y añadimos al código del error el valor "Símbolo desconocido". Por cierto, de
entrada, esta comprobación sobra, ya que al crear un objeto, se transmitirán al mismo los datos del símbolo ya seleccionado de la lista. Aun
así, consideramos que la comprobación debe existir, dado que nadie puede prometernos que no se vaya a transmitir un símbolo erróneo al
objeto al crear el mismo.
A continuación, obtenemos los datos sobre el último tick,
y si no hemos logrado obtenerlos, mostramos igualmente un mensaje sobre ello en el diario y asignamos al código de error el valor del último
error con la ayuda de
GetLastError(). En cualquier caso, creamos el objeto, al tiempo que el
código nos permitirá determinar si dejamos o eliminamos este objeto en el programa que realiza la llamada.
Después inicializamos todos los datos del objeto de símbolo
(se resetean) y establecemos el valor del número de dígitos decimales tras la coma para la
divisa de la cuenta, de forma que se puedan mostrar correctamente los datos en el diario.
Todas las propiedades
del objeto se rellenan con la ayuda de funciones SymbolInfo, y allá donde existan diferencias en cuanto a la obtención de dichos valores
entre MQL5 y MQL4, rellenamos los datos con varios métodos creados especialmente para ello. Analizaremos dichos métodos más tarde.
Método de comparación de dos objetos de símbolo entre sí para la búsqueda y la clasificación:
//+------------------------------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
Método de comparación de dos objetos de símbolo entre sí para determinar su igualdad:
//+------------------------------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
Ya analizamos ambos métodos en la primera y la quinta parte de la descripción de la biblioteca.
Método de inicialización de todas las propiedades de un objeto de símbolo:
//+------------------------------------------------------------------+ //| 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); } } //+------------------------------------------------------------------+
El método funciona de forma idéntica al anterior, pero, en lugar de comparar con un objeto de muestra, aquí simplemente se resetean todos los campos de la clase en el ciclo por cada uno de los tres conjuntos de propiedades.
Estos son los métodos de obtención de las propiedades de tipo entero del símbolo que no existen en MQL4, ya sea de forma parcial o completa:
//+----------------------------------------------------------------------+ //| 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); } //+----------------------------------------------------------------------+
Aquí se usan las directivas de compilación condicional #ifdef
__MQL5__ para compilar en MQL5, y #elsepara
compilar en MQL4
#endif
Para MQL5, simplemente obtenemos los datos de la función SymbolInfoInteger() con el identificador de propiedad necesario, y para MQL4, retornamos la magnitud del valor rigurosamente establecida (si sabemos claramente que ese valor se usa en MQL4), o bien el valor cero (o false, o la macrosustitución establecida para el valor ausente).
Aquí mismo, más abajo en el listado, ubicamos los códigos de otros dos métodos:
Método que retorna las banderas de los tipos de órdenes permitidos para un símbolo:
//+------------------------------------------------------------------+ //| 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 ); } //+------------------------------------------------------------------+
Al igual que en MQL5, para cada uno de los símbolos existe la posibilidad de obtener banderas que indican el permiso de colocación de diferentes tipos de órdenes:
- orden de mercado (apertura o cierre según el mercado),
- orden límite,
- orden stop,
- orden stop limit,
- orden TakeProfit,
- orden StopLoss,
- orden de cierre por orden opuesta (CloseBy)
En cambio, para MQL4, solo podemos obtener los datos sobre el
permiso de cierre por orden opuesta de la función MarketInfo()
con el identificador de la solicitud MODE_CLOSEBY_ALLOWED
(se retorna con el método IsCloseByOrdersAllowed(), más arriba en
el listado).
Por eso, aquí deberemos reunir por nosotros mismos las banderas necesarias para retornar al programa MQL4:
- orden de mercado permitida — la
añadimos al valor retornado
- orden límite permitida — la añadimos al valor retornado
- orden stop permitida — la añadimos al valor retornado
- orden stop limit no permitida
- orden stop limit permitida — la añadimos al valor retornado
- orden take profit permitida — la añadimos al valor retornado
- para una orden de cierre por otra opuesta, obtenemos los datos del método IsCloseByOrdersAllowed()
y añadimos el valor de la constante SYMBOL_ORDER_CLOSEBY en el caso de
permiso, o bien 0 ,
en caso de prohibición
Método de obtención del número de dígitos decimales tras la coma en el valor del lote para el símbolo:
//+------------------------------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
Este método calcula el número de dígitos decimales tras la coma en el valor del lote del símbolo:
Ya disponemos de
esta función en el archivo de funciones de servicio 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))); } //+------------------------------------------------------------------+
Pero tiene ciertos lunares, sobre los que debatió en uno de los temas discutidos de los artículos: con valor de salto de lote igual a 0.25, la función no retorna el valor correcto. De esta forma, decidimos buscar un método más exacto, y al final llegamos a la conclusión de que el método más certero sería simplemente calcular el número de decimales tras la coma en el valor de línea del lote, convertido al salto del lote: lots=MathRound(lots/lotStep)*lotStep. Adoptamos esta solución inspirándonos en la discusión de este problema y en uno de los múltiples métodos de búsqueda propuestos. Sí se trata de la búsqueda en la línea. Pero debemos encontrar el número necesario de dígitos solo una vez para cada uno de los símbolos utilizados, y ya después usar un valor constante, y este método no tiene los defectos de todos los métodos de cálculo. Así que nos detendremos en la solución propuesta.
Estos son los métodos de obtención de las propiedades de tipo real y de tipo string del símbolo que no existen en MQL4, ya sea de forma parcial o completa:
//+------------------------------------------------------------------+ //| 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 ); } //+------------------------------------------------------------------+
Aqií, todo resulta idéntico a los métodos de obtención de las propiedades de tipo entero: la obtención del valor es dividida por directivas de compilación condicional, y los valores de las propiedades, o bien son retornados por las funciones de MQL5 y MQL4 correspondientes, o bien para MQL4 se retorna 0 (en ausencia de un análogo de MQL5) o el mensaje de línea sobre la ausencia de soporte para MQL4 de dicha propiedad de tipo string.
Método de muestra en el diario de la lista completa de todas las propiedades de un objeto de símbolo:
//+------------------------------------------------------------------+ //| 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" ); } //+------------------------------------------------------------------+
Mostramos en tres ciclos por todas las propiedades del objeto las descripciones de cada última propiedad en el ciclo con los métodos GetPropertyDescription(), que retornan la descripción de una propiedad del objeto según el tipo ( entero, real o string) transmitido al método:
//+------------------------------------------------------------------+ //| 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)+"\"") ) : "" ); } //+------------------------------------------------------------------+
Aunque los métodos son bastante voluminosos, todo en ellos se reduce a la comparación de la propiedad transmitida al método y el retorno de su valor de línea. Es de esperar que el lector pueda comprender por sí mismo su composición, sin que tengamos que detenernos en un análisis detallado.
Método para buscar un símbolo en la lista de símbolos del servidor y retornar la bandera sobre su presencia/ausencia:
//+-------------------------------------------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
Comparamos en el ciclo por la lista completa de todos los símbolos en el servidor (en las funciones SymbolsTotal()
y SymbolName() bandera = false)
cada símbolo sucesivo de la lista (su nombre) con el nombre del símbolo del objeto de símbolo actual.
Si lo encontramos, retornamos true,
el símbolo se encuentra en el servidor.
De lo contrario, retornamos false,
el símbolo no se encuentra en el servidor.
Métodos para suscribirse a la profundidad de mercado y cancelar la suscripción a la misma:
//+------------------------------------------------------------------+ //| 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 ; } //+------------------------------------------------------------------+
Los métodos simplemente retornan para MQL5 el resultado del trabajo de las funciones MarketBookAdd() y MarketBookRelease(), mientras que para MQL4 se retorna directamente false , ahí no existe la posibilidad de trabajar con la profundidad de mercado. Por el momeneto, estos métodos han sido añadidos al objeto de símbolo, pero el trabajo con ellos y el resto de los métodos para operar con la profundidad de mercado lo organizaremos ya en los siguientes artículos.
Métodos que retornan las descripciones de línea de las propiedades del objeto de símbolo:
//+------------------------------------------------------------------+ //| 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)") ); } //+------------------------------------------------------------------+
En los métodos, todo es sencillo: se comprueba el valor de una propiedad y se retorna su descripción de línea.
Algunos métodos, más concretamente los métodos de descripción de banderas, muestran dentro de la descripción retornada valores de línea
de otros métodos que, asimismo, retornan las descripciones de banderas ya concretas, de las cuales se compone la propiedad comprobada. De
esta forma, obtenemos una descripción compuesta y formateada de todas las banderas de una propiedad.
Para MQL5, las banderas de una misma propiedad se muestran en una columna con el nombre de la propiedad descrita, por ejemplo:
Banderas de los tipos de orden permitidos: - Orden de mercado (Sí) - Orden límite (Sí) - Orden stop (Sí) - Orden stop limit (Sí) - StopLoss (Sí) - TakeProfit (Sí) - Cierre por orden opuesta (Sí)
Para MQL4, estas propiedades se muestran en una línea:
Banderas de tipos de orden permitidos: Orden de mercado (Sí); Orden límite (Sí); Orden stop (Sí); Orden stop limit (No); StopLoss (Sí); TakeProfit (Sí); Cierre por orden opuesta (Sí)
Esto se debe a que en MQL4 la función Print() no percibe los códigos
de traslado de la línea "\n". Por eso, en los métodos se ha implementado un formateo aparte para MQL5 y MQL4 con directivas de la compilación
condicional.
Método de servicio que retorna el precio normalizado teniendo en cuenta las particularidades del símbolo:
//+------------------------------------------------------------------+ //| 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())); } //+------------------------------------------------------------------+
El método normaliza el precio teniendo en cuenta el cambio mínimo de precio.
Y, finalmente, dos métodos:
el método de actualización de todas
las propiedades del objeto de símbolo que pueden cambiar alguna vez, y el
método de actualización de los datos de cotización del símbolo:
//+------------------------------------------------------------------+ //| 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(); } //+------------------------------------------------------------------+
Aquí todo es sencillo: se rellenan de nuevo las propiedades necesarias del símbolo a partir de sus datos.
Ambos
métodos han sido pensados para obtener información actual sobre las propiedades del símbolo. Necesitaremos llamar al método Refresh()
justo antes de obtener la información necesaria, mientras que el método RefreshRates() se llamará constantemente en el temporizador para
todos los objetos de símbolo que componen la lista de colección de la que nos ocuparemos más tarde.
Con esto, hemos terminado la creación de los métodos del objeto de símbolo abstracto.
Ahora, necesitaremos añadir ciertos elementos al archivo ToMQL4.mqh, en el que registramos las enumeraciones y macrosustituciones
necesarias para realizar la compilación en MQL4 sin errores.
Ya hemos usado en la clase del objeto de símbolo el retorno de los códigos de error de MQL5; vamos añadirlos, para que MQL4 conozca sus valores:
//+------------------------------------------------------------------+ //| 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) //+------------------------------------------------------------------+
Asimismo, hemos usado las banderas encargadas de los diferentes modos de las órdenes en el símbolo, vamos a
denominarlos:
//+------------------------------------------------------------------+ //| 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) //+------------------------------------------------------------------+
Vamos a añadir las enumeraciones ausentes en 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 //+------------------------------------------------------------------+
Para las opciones, vamos a establecer con macrosustituciones propiedades
adicionales que indiquen la ausencia del tipo y el derecho de opciones: las usaremos en MQL4 al retornar los valores de estas
propiedades del objeto de símbolo.
Las dos últimas enumeraciones tienen ciertas particularidades: en ellas no existe correspondencia en cuanto a la secuencia de los valores de las constantes en MQL5 y MQL4.
Por eso, hemos tenido que cambiar la secuencia de indicación de las constantes incluidas en las enumeraciones. En los comentarios a los valores de las constantes, hemos registrado sus valores para MQL5 y MQL4; hemos establecido su orden de secuencia de forma que se corresponda con los valores en MQL4, para que así se retornen los valores correctos:
//+------------------------------------------------------------------+ //| 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 }; //+------------------------------------------------------------------+
Ahora, todos los datos para el objeto de símbolo han sido creados.
Necesitamos (ya que hemos introducido el código de los errores retornado desde las clases al objeto principal de la biblioteca Engine) introducir la
variable de miembro de la clase CEngine para guardar el código de error. Abrimos el archivo \MQL5\Include\DoEasy\
Engine.mqh y le añadimos los cambios necesarios.
Declaramos en la sección privada de la clase la
variable para guardar los códigos de error:
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
Inicializamos el código de error en la lista de inicialización del constructor de la clase, y a continuación, en los bloques de creación del temporizador de milisegundos para MQL5 y MQL4, añadimos a la variable el código del último error:
//+------------------------------------------------------------------+ //| 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 } //+------------------------------------------------------------------+
Solo queda incluir en el objeto principal de la biblioteca el archivo de la clase nuevamente creada (temporalmente, solo para la comprobación actual):
//+------------------------------------------------------------------+ //| 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 {
Ahora, ya está todo preparado para poner a prueba el objeto de símbolo.
Antes de proseguir, querríamos hablar de un cierto malentendido - a nuestro juicio - que se produjo en el artículo
anterior, al crear el método que retorna el evento de cuenta según su número en la lista, en la clase de colección de cuenta CAccountsCollection.
La versión actual del método tiene el aspecto siguiente:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Y esto es lo que hemo escrito sobre el principio de retorno de eventos desde el método:
Los eventos en la lista de cambios de las propiedades de la cuenta se ubican según su orden de aparición: el primero de todos se encuentra en el índice 0, y el último, en el índice (tamaño_de_la_lista-1). No necesitamos que el usuario pueda obtener el evento buscado como en las series temporales: en el índice cero debe encontrarse el último evento de todos. Para ello, en el método se ha implementado el cálculo del índice: index = (tamaño_de_la_lista - número_del_evento_buscado-1). Con estos cálculos, si transmitimos 0 o -1, se retornará el último elemento de la lista; si retornamos 1, el penúltimo; si transmitimos una cifra que supere el tamaño de la lista, se retornará el último evento.
Aquí, se ha infringido la lógica: si transmitimos 0 al método, obtendremos el último evento, y si transmitimos un valor que supere el tamaño de la
matriz, entonces, según la lógica, sería deseable retornar el primer evento, y nosotros retornamos el último, lo cual no es lógico. Lo
lógico para obtener el último evento sería transmitir o bien un valor 0, o bien inferior a 0 (por defecto), y después, por orden: 1 — el
penúltimo, 2 — el antepenúltimo, etcétera, como en las series temporales.
Y si conocemos el tamaño de la matriz, y transmitimos conscientemente un valor mayor, lo que cabría esperar por lógica sería obtener el
valor más alejado en el tiempo, es decir, el primero, y el método retorna el último. Vamos a corregir este comportamiento ilógico:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Aquí: si se transmite 0 o -1, retornaremos el último evento,
y si se transmite un valor que supere el tamaño de la matriz, retornaremos el primer evento; en
los demás casos, el índice del evento retornado se calculará.
Poniendo a prueba el objeto de símbolo
Para poner a prueba el objeto de símbolo, vamos a tomar el asesor del
artículo anterior y guardarlo con el nuevo nombre TestDoEasyPart14.mq5.
Comprobaremos el objeto de símbolo en el manejador OnInit(). Para ello, solo tenemos que añadir al final de OnInit() las siguientes líneas de código:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Aquí: creamos un nuevo objeto de símbolo, y dado que vamos a implementar la definición de la pertenencia a un determinado grupo en el próximo
artículo, simplemente transmitimos al constructor el estado "símbolo fórex" y el nombre del símbolo.
Si el objeto ha sido creado, actualizamos todos sus datos, actualizamos los datos de cotización, imprimimos en el diario todas las
propiedades del objeto de símbolo y eliminamos el objeto, para que no haya fugas de memoria al finalizar el funcionamiento del asesor de
prueba.
Si ahora tratamos de compilar el asesor, obtendremos el error de acceso al constructor protegido de la clase:
'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
Pasamos al archivo Symbol.mqh y trasladamos el constructor paramétrico protegido temporalmente desde la sección protegida a la sección pública de la clase:
//+------------------------------------------------------------------+ //| 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
Ahora, todo se compila.
Iniciamos el asesor en el gráfico del símbolo en MetaTrader 5.
En este caso, además, en el asesor se imprimen todas las
propiedades del objeto de símbolo:
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) The flags of allowed order types: - Market order (Yes) - Limit order (Yes) - Stop order (Yes) - Stop limit order (Yes) - StopLoss (Yes) - TakeProfit (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) ==================
Iniciamos el asesor en el gráfico del símbolo en MetaTrader 4.
En este caso, además, en el asesor se imprimen todas las
propiedades del objeto de símbolo:
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) ==================
Aquí, a diferencia del inicio en MetaTrader 5, no todas las propiedades tienen soporte, por eso, el diario también muestra mensajes sobre ello.
La lista de banderas se muestra en una sola línea, como ya hemos mencionado anteriormente.
En el próximo artículo, al crear los objetos herederos del objeto de símbolo básico, no se mostrarán las líneas de descripción de las
propiedades no soportadas: se establecerán para cada objeto heredero banderas de soporte de dicha propiedad por parte del objeto.
¿Qué es lo próximo?
En el siguiente artículo, comenzaremos a desarrollar la clase de colección de símbolos, que permitirá buscar con facilidad los datos, así
como clasificar y comparar los símbolos de la lista de colección entre sí.
Más abajo se adjuntan todos los archivos de la versión actual de la biblioteca y los archivos del asesor de prueba. Puede descargarlo todo
y ponerlo a prueba por sí mismo.
Si tiene cualquier duda, observación o sugerencia, podrá formularla en los comentarios al artículo.
Artículos de esta serie:
Parte 1. Concepto y organización de datosParte 2. Colecciones de las órdenes y transacciones históricas
Parte 3. Colección de órdenes y posiciones de mercado, organización de la búsqueda
Parte 4. Eventos comerciales. Concepto
Parte 5. Clases y concepto de los eventos comerciales. Envío de eventos al programa.
Parte 6. Eventos en la cuenta con compensación
Parte 7. Eventos de activación de órdenes StopLimit, preparación de la funcionalidad para el registro de los eventos de modificación de órdenes y posiciones
Parte 8. Eventos de modificación de órdenes y posiciones
Parte 9. Compatibilidad con MQL4 - Preparando los datos
Parte 10. Compatibilidad con MQL4 - Eventos de apertura de posición y activación de órdenes pendientes
Parte 11. Compatibilidad con MQL4 - Eventos de cierre de posiciones
Parte 12. Implementando la clase de objeto "cuenta" y la colección de objetos de cuenta
Parte 13. Eventos del objeto "cuenta"