![Experto comercial universal: Acceso a las propiedades de los instrumentos (parte 8)](https://c.mql5.com/i/articles/overlay.png)
Experto comercial universal: Acceso a las propiedades de los instrumentos (parte 8)
Introducción
Ya ha pasado cierto tiempo desde la publicación de la última parte del artículo dedicado al motor comercial CStrategy. Este tiempo ha sido necesario para reflexionar sobre el camino que ha recorrido CStrategy desde una pequeña biblioteca comercial auxiliar hasta convertirse un complejo comercial completo que incluye la mayoría de los instrumentos usados con frecuencia para construir una estrategia comercial completa. Transcurrido este tiempo, ha surgido un nuevo concepto sobre la dirección en la que se debe desarrollar CStrategy más adelante. La aplicación práctica de CStrategy durante este tiempo ha descubierto asimismo varios defectos propios de la última versión del motor. La corrección de estos defectos ha derivado en un nuevo grupo de artículos pertenecientes a la serie "Experto comercial universal". En este octavo artículo se aclarará el trabajo con instrumentos comerciales a través de la clase orientada a objetos CStrategy.
Vista general del trabajo con el instrumento en las versiones anteriores de CStrategy
El entorno comercial del experto es diverso y voluminoso. Se trata de información variada sobre la cuenta, datos de las cotizaciones, funciones del trabajo con el tiempo y, por supuesto, la información accesible en el terminal sobre los instrumentos comerciales. La mayoría de esta información se centra en las funciones para trabajar con instrumentos comerciales: la obtención de las cotizaciones actuales y el trabajo con las propiedades del instrumento de trabajo. Normalmente, todos los expertos operan de forma muy activa con la información sobre el precio. Calculan sobre la base de los últimos datos un cierto patrón de precio o señal comercial y realizan la transacción basándose en ellos. Para que se forme correctamente la solicitud comercial, también utilizan información sobre las propiedades del actual símbolo de trabajo: por ejemplo, el volumen mínimo de la transacción realizada o el nivel "freeze level", el diapasón del precio actual dentro del cual está prohibido colocar órdenes pendientes.
Está claro que esta información deberá ser de fácil acceso y estar siempre "a mano". Sin embargo, ¿ha resultado esto así en las anteriores ediciones de CStrategy? Vamos a aclarar esto, haciendo una pequeña digresión en la historia: describiremos cómo ha tenido lugar el trabajo con el símbolo comercial anteriormente. En la tercera parte del artículo se propone un sistema de acceso a las cotizaciones a través del indexador [] acostumbrado. En la clase CStrategy se han incluido varias clases auxiliares COpen, CHigh, CLow, CClose, CVolume, CTime, cada una de las cuales ha retornado el resultado correspondiente sobre el índice solicitado. Esto ha permitido obtener con bastante comodidad información sobre el símbolo actual en el código del experto. Por ejemplo, para conocer el precio de cierre de la barra actual, basta con escribir:
...
double close = Close[0];
...
Sin embargo, el acceso a los precios en el formato OHLC ha resultado insuficiente, y la clase CStrategy se ha debido equipar con los métodos adicionales Ask(), Bid(), Last(). Muy pronto estos métodos también resultaron insuficientes. Fue necesario añadir varios métodos más del tipo FreezeLevel(), que obtenían la información principal sobre el instrumento actual. El volumen de la clase básica CStrategy comenzó a crecer a un gran ritmo. La abundancia de métodos accesibles dentro de CStrategy comenzó a provocar confusión. Pero las principales dificultades comenzaron cuando se intentó crear con la ayuda de CStrategy un experto que comerciase en varios instrumentos de forma simultánea. Formalmente, CStrategy es un motor multiinstrumental. Esto significa que con su ayudan se puede crear tanto varios expertos que comercien en diferentes instrumentos independientemente unos de otros, como un experto que comercie en dos o más instrumentos. Sin embargo, esto último no fue tan fácil de conseguir, puesto que en este caso fue necesario reconfigurar sobre la marcha las clases de las series temporales, presentando este u otro símbolo por turnos:
string symbol1 = "EURUSD"; string symbol2 = "GBPUSD"; Close.Symbol(symbol1); double close_eurusd = Close[0]; Close.Symbol(symbol2); double close_gbpusd = Close[0]; ...
Todas estas dificultades han servido para comprender que la información sobre el instrumento de trabajo es demasiado amplia y variada como para que CStrategy pueda implementarla. La propia clase CStrategy ya ejecuta un trabajo voluminoso y complejo de organización de la secuencia de las acciones comerciales, por lo que armarla con una funcionalidad adicional solo provocaría la reducción del nivel de control sobre el código. En lugar de ello, se ha decido seleccionar un método para trabajar con el instrumento en una clase aparte CSymbol.
Primer contacto con el objeto WS y la clase CSymbol
Ahora, en lugar de métodos dispersos como Ask(), Bid(), Last y clases especiales como CHigh y CLow, con la estrategia comercial cimentada sobre CStrategy está disponible el objeto especial WS, creado sobre la base de la clase CSymbol. Esta clase, perteneciente al conjunto de bibliotecas CStrategy, dispone de una serie de métodos que la hace semejante a la clase estándar СSymbolInfo. Sin embargo, se trata de otra clase que trabaja solo con las propiedades del instrumento, y que también permite recibir sus cotizaciones, incluyendo la información sobre las solicitudes límite (profundidad de mercado). El nombre del objeto WS es la abreviatura de "Work Symbol", y está disponible directamente en el código de la estrategia. No se ha elegido un nombre así de corto por casualidad. En el proceso de trabajo se necesita con mucha frecuencia recurrir a esta u otra propiedad del instrumento, por eso, la abreviatura de dos símbolos permite al código permanecer compacto y expresivo.
Como ya se ha dicho en las anteriores partes del artículo, antes de transmitir el control al experto, el motor comercial CStrategy realiza una serie de inicializaciones de los objetos del entorno interno. Se recuerda el nombre del instrumento de trabajo y el marco temporal, se crean las clases que realizan el seguimiento de la llegada de nuevos eventos (por defecto, se trata del nuevo tick y la nueva barra). Se establece el logueo, se colocan las banderas de los modos de trabajo. En este momento se inicializa el objeto WS de la clase CSymbol. Su construcción interna es bastante sencilla. Contiene dos campos internos: el símbolo del instrumento y su marco temporal, además de objetos especiales para acceder a las cotizaciones del instrumento. El propio objeto WS se inicializa con el método InitSeries. Conociendo el símbolo de trabajo y el marco temporal del experto, no será ningún problema inicializarlo:
CStrategy::CStrategy(void)
{
WS.InitSeries(ExpertSymbol(), Timeframe());
}
Después de que el objeto esté inicializado, con su ayuda se puede obtener la propiedad requerida del instrumento. Por ejemplo, para obtener el precio máximo de la barra actual, basta con escribir lo siguiente:
double max = WS.High[0];
El objeto WS posee una serie adicional de propiedades que hacen su uso en los cálculos directos un recurso muy cómodo y autosuficiente. Vamos a analizar un caso muy extendido, cuando necesitamos una orden BuyStop un poco por encima del precio del máximo de la barra anterior. Supongamos que estamos comerciando con EURUSD y queremos que nuestra orden stop sea colocada a una distancia de tres puntos de cinco dígitos del máximo de la barra anterior, necesitaremos escribir el código siguiente:
void CMovingAverage::InitBuy(const MarketEvent &event) { ... Trade.BuyStop(1.0, WS.High[1] + WS.StepToPrice(3), WS.Name()); ... }
Así, en una sola línea de código hemos ubicado un gran volumen de acciones:
- Obtenemos el extremo de la barra anterior (WS.High[1]);
- El valor de un punto lo hemos multiplicado por tres, obteniendo una distancia de precio de tres puntos (WS.StepToPrice(3));
- Hemos añadido al precio del extremo la distancia de precio obtenida (WS.High[1] + WS.StepToPrice(3));
- Hemos enviado una orden comercial BuyStop, cuyo nivel de activación ahora es el precio obtenido, indicando como símbolo el nombre del instrumento actual (WS.Name()).
El método StepToPrice puede parecer demasiado distinto del sistema de denominaciones adoptado en MetaTrader. En otras plataformas comerciales se entiende por price step el cambio mínimo del precio. Su equivalente en MetaTrader se llama SYMBOL_TRADE_TICK_SIZE. Este nombre se puede confundir fácilmente con el tamaño o el precio de un tick SYMBOL_TRADE_TICK_VALUE, por eso en CSymbol se usa otro nombre para este parámetro. Sin embargo, la mayoría de los nombres de los otros métodos CSymbol coincide con los modificadores de sistema y los métodos MQL5, pero, como muestra el ejemplo con StepToPrice, no siempre son idénticos. Y es que el principal objetivo de CSymbol es proporcionar un conjunto comprensible e intuitivo de métodos para obtener información completa sobre el instrumento comercial.
Estructura de la clase CSymbol. Tabla comparativa de métodos
El instrumento comercial en MetaTrader posee un gran conjunto de propiedades. Ante que nada, las propiedades se pueden dividir condicionalmente en propiedades de número entero, reales y de línea. A las propiedades de número entero pertenecen las propiedades lógicas (bool), los modificadores de sistema en forma de enumeraciones (enum), la fecha y la hora (datetime) y propiamente las propiedades de número entero (int y long). A las propiedades de tipo real pertenecen diferentes valores fraccionados (double). Al fin, a las propiedades de línea o cadena (string) pertenecen las propiedades que retornan líneas: el nombre del instrumento, la descripción de línea de un símbolo, etcétera. A fin de cuentas, el instrumento tiene acceso a una serie de propiedades específicas para un determinado segmento de mercado. Así, para el mercado FORTS, están disponibles las propiedades adicionales de la sesión comercial actual. Para los mercados de opciones están disponibles sus propiedades únicas. La clase CSymbol determina las propiedades de la sesión comercial actual de FORTS en la clase interna adicional SessionInfo. El resto de las propiedades no se dividen en clases y están presentes "tal cual" en forma de métodos homónimos.
Lo que es más, en la clase CSymbol se contienen colecciones adicionales que hacen posible recurrir a las cotizaciones del instrumento. Así, para acceder a las series OHLCV se han definido públicamente las clases COpen, CHigh, CLow, CClose, CVolume, y para acceder a la profundidad de mercado, se usa la clase especial CMarketWatch, cuya descripción detallada está disponible en el artículo: "Recetas MQL5 - Escribiendo nuestra propia profundidad de mercado". Aparte de los métodos homónimos y las clases-indexadores como CClose, la clase CSymbol contiene varios métodos que no disponen de análogos obvios en las funciones estándar de MQL5 o en la clase SymbolInfo. Los describiremos con más detalle.
Available — este método retorna true, si el instrumento con el nombre indicado existe en el terminal. Si tal instrumento no existe, retorna false.
IndexByTime — retorna el índice de la barra que corresponde a la hora indicada. Por ejemplo, a la variable index en el código siguiente se le asignará el valor 1:
int index = WS.IndexByTime(WS.Time[1]); // index = 1;
Este método es cómodo de usar si conocemos la hora y queremos obtener el número de la barra que corresponde a esta hora. Supongamos que el experto comercial debe cerrar la posición tras haberla mantenido durante BarsHold barras. Entonces el código que hace esto tendrá el aspecto siguiente:
//+------------------------------------------------------------------+ //| Acompaña con una posición larga según la media móvil Moving | //+------------------------------------------------------------------+ void CImpulse::SupportBuy(const MarketEvent &event,CPosition *pos) { int bar_open = WS.IndexByTime(pos.TimeOpen()); if(bar_open >= BarsHold) pos.CloseAtMarket("Exit by time hold"); }
StepToPrice — valor del cambio mínimo del precio, expresado en puntos del instrumento. Más arriba se ha escrito con más detalle sobre las tareas de este método.
La lista completa de los métodos CSymbol se muestra en el recuadro unificado de abajo. En el campo "Descripción" se da una breve descripción del método. En la mayoría de los casos, coincide con la descripción oficial de la propiedad análoga del instrumento en el apartado correspondiente de la documentación, sin embargo, para algunos métodos se da, a mi juicio, una descripción más acertada de sus posibilidades.
El campo "Tipo" del valor retornado muestra, propiamente, el tipo retornado por un método o colección.
El campo "función o indentificador de sistema MQL5" contiene el nombre del identificador de sistema o función MQL5 que ejecuta funciones análogas. Si se indica una función de sistema, al final de su nombre se ponen paréntesis, por ejemplo, CopyOpen() o MarketBookGet(). Se entiende por identificador de sistema uno de los tres modificadores que se debe indicar al llamar las funciones SymbolInfoInteger, SymbolInfoDouble o SymbolInfoString. Este identificador debe pertenecer a uno de las tres enumeraciones de sistema correspondientes: ENUM_SYMBOL_INFO_INTEGER, ENUM_SYMBOL_INFO_DOUBLE o ENUM_SYMBOL_INFO_STRING. Por ejemplo, si en la columna "función o indentificador de sistema MQL5" se indica el modificador SYMBOL_TRADE_STOPS_LEVEL, esto significa que para obtener esta propiedad es necesario llamar la función SymbolInfoInteger:
int stop_level = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL);
La columna "Nombre del método CSymbol" contiene propiamente el nombre del método responsable de retornar la propiedad correspondiente. Por ejemplo, para obtener el día de la semana cuando se carga el swap triple, es necesario llamar el método:
ENUM_DAY_OF_WEEK day = WS.DayOfSwap3x();
Y bien, aquí tenemos el recuadro de métodos:
Descripción | Tipo de valor retornado | Función o indentificador de sistema MQL5 | Nombre del método CSymbol |
---|---|---|---|
ACCESO A LAS COTIZACIONES HISTÓRICAS DEL INSTRUMENTO | |||
Obtiene el precio de apertura según el índice de la barra dado, con el marco temporal preestablecido para el instrumento | double | CopyOpen() | Open[] |
Obtiene el precio del máximo según el índice de la barra dado, con el marco temporal preestablecido para el instrumento | double | CopyHigh() | High[] |
Obtiene el precio del mínimo según el índice de la barra dado, con el marco temporal preestablecido para el instrumento | double | CopyLow() | Low[] |
Obtiene el precio de cierre según el índice de la barra dado, con el marco temporal preestablecido para el instrumento | double | CopyClose() | Close[] |
Obtiene el volumen correspondiente a la barra con el índice dado | double | CopyVolume() | Volume[] |
Obtiene las propiedades de la profundidad de mercado del instrumento dado, acceso a las cotizaciones de segundo nivel | MqlBookInfo | MarketBookGet() | MarketBook |
PROPIEDADES DE NÚMERO ENTERO DEL INSTRUMENTO | |||
Señal de que este instrumento está presente en el terminal | bool | No hay análogos | Available |
Número de barras de este símbolo y marco temporal | int | Bars() | BarsTotal |
Marco temporal del instrumento | ENUM_TIMEFRAMES | Period() | Period |
Señal de que el símbolo está seleccionado en Market Watch | bool | SYMBOL_SELECT | SelectInMarketWatch |
Señal de spread flotante | bool | SYMBOL_SPREAD_FLOAT | SpreadFloat |
Tamaño del spread en puntos | int | SYMBOL_SPREAD | Spread |
Distancia mínima en puntos con respecto al precio actual de cierre para colocar el Stop Loss | int | SYMBOL_TRADE_STOPS_LEVEL | StopLevel |
Distancia de congelación de las operaciones comerciales (en puntos) | int | SYMBOL_TRADE_FREEZE_LEVEL | FreezeLevel |
Banderas de los modos permitidos de expiración de la orden | int | SYMBOL_EXPIRATION_MODE | FlagsExpirationOrders |
Banderas de los modos permitidos de ejecución de la orden | int | SYMBOL_FILLING_MODE | FlagsExecutionOrders |
Banderas de los tipos de orden permitidos | int | SYMBOL_ORDER_MODE | FlagsAllowedOrders |
Retorna el índice de la barra cuya hora de apertura corresponde al argumento transmitido | int | No hay análogos | IndexByTime |
Método de cálculo del coste del contrato | ENUM_SYMBOL_CALC_MODE | SYMBOL_TRADE_CALC_MODE | CalcContractType |
Tipo de ejecución de las órdenes | ENUM_SYMBOL_TRADE_MODE | SYMBOL_TRADE_MODE | ExecuteOrderType |
Modo de ejecución de las transacciones | ENUM_SYMBOL_TRADE_EXECUTION | SYMBOL_TRADE_EXEMODE | ExecuteDealsType |
Modelo de cálculo del swap | ENUM_SYMBOL_SWAP_MODE | SYMBOL_SWAP_MODE | CalcSwapMode |
Día de la semana para la carga del swap triple | ENUM_DAY_OF_WEEK | SYMBOL_SWAP_ROLLOVER3DAYS | DayOfSwap3x |
Tipo de opción | ENUM_SYMBOL_OPTION_MODE | SYMBOL_OPTION_MODE | OptionType |
Derecho de opción (Call/Put) | ENUM_SYMBOL_OPTION_RIGHT | SYMBOL_OPTION_RIGHT | OptionRight |
Hora de la última cotización | datetime | SYMBOL_TIME | TimeOfLastQuote |
Hora de comienzo de las transacciones del instrumento (normalmente se usa para los futuros) | datetime | SYMBOL_START_TIME | StartDate |
Hora de finalización de las transacciones del instrumento (normalmente se usa para los futuros) | datetime | SYMBOL_EXPIRATION_TIME | ExpirationDate |
PROPIEDADES DE LA ACTUAL SESIÓN COMERCIAL DE LOS INSTRUMENTOS DE FUTUROS MOEX | |||
Número de transacciones en la sesión actual | long | SYMBOL_SESSION_DEALS | SymbolInfo.DealsTotal |
Número total de órdenes de compra en el momento actual | long | SYMBOL_SESSION_BUY_ORDERS | SymbolInfo.BuyOrdersTotal |
Número total de órdenes de venta en el momento actual | long | SYMBOL_SESSION_SELL_ORDERS | SymbolInfo.SellOrdersTotal |
Volumen máximo durante la sesión comercial actual | long | SYMBOL_VOLUMEHIGH | SymbolInfo.HighVolume |
Volumen mínimo durante la sesión comercial actual | long | SYMBOL_VOLUMELOW | SymbolInfo.LowVolume |
Bid máximo del día | double | SYMBOL_BIDHIGH | SymbolInfo.BidHigh |
Ask máximo del día | double | SYMBOL_ASKHIGH | SymbolInfo.AskHigh |
Bid mínimo del día | double | SYMBOL_BIDLOW | SymbolInfo.BidLow |
Ask mínimo del día | double | SYMBOL_ASKLOW | SymbolInfo.AskLow |
Last máximo del día | double | SYMBOL_LASTHIGH | SymbolInfo.LastHigh |
Last mínimo del día | double | SYMBOL_LASTLOW | SymbolInfo.LastLow |
Volumen total de transacciones de la sesión actual | double | SYMBOL_SESSION_VOLUME | SymbolInfo.VolumeTotal |
Circulación total en la sesión actual | double | SYMBOL_SESSION_TURNOVER | SymbolInfo.TurnoverTotal |
Volumen total de las posiciones abiertas | double | SYMBOL_SESSION_INTEREST | SymbolInfo.OpenInterestTotal |
Volumen total de las órdenes de compra en el momento actual | double | SYMBOL_SESSION_BUY_ORDERS_VOLUME | SymbolInfo.BuyOrdersVolume |
Volumen total de órdenes de venta en el momento actual | double | SYMBOL_SESSION_SELL_ORDERS_VOLUME | SymbolInfo.SellOrdersVolume |
Precio de apertura de la sesión | double | SYMBOL_SESSION_OPEN | SymbolInfo.PriceSessionOpen |
Precio de cierre de la sesión | double | SYMBOL_SESSION_CLOSE | SymbolInfo.PriceSessionClose |
Precio medio ponderado de la sesión | double | SYMBOL_SESSION_AW | SymbolInfo.PriceSessionAverage |
Precio de entrega de la sesión actual | double | SYMBOL_SESSION_PRICE_SETTLEMENT | SymbolInfo.PriceSettlement |
Valor máximo aceptable del precio para la sesión | double | SYMBOL_SESSION_PRICE_LIMIT_MAX | SymbolInfo.PriceLimitMax |
Valor mínimo aceptable del precio para la sesión | double | SYMBOL_SESSION_PRICE_LIMIT_MIN | SymbolInfo.PriceLimitMin |
PROPIEDADES REALES DEL INSTRUMENTO | |||
Ask — mejor oferta de compra | double | SYMBOL_ASK | Ask |
Bid — mejor oferta de venta | double | SYMBOL_BID | Bid |
Precio al que se ha realizado la última transacción | double | SYMBOL_LAST | Last |
Valor del cambio mínimo de precio, multiplicado por el número transmitido de saltos del precio | double | No hay análogos | StepToPrice |
Valor de un punto (tick) | double | SYMBOL_POINT | PriceStep |
Coste de un punto (tick), expresado en la divisa del depósito | double | SYMBOL_TRADE_TICK_VALUE | TickValue |
Precio de ejecución de la opción | double | SYMBOL_OPTION_STRIKE | OptionStrike |
Tamaño del contrato comercial | double | SYMBOL_TRADE_CONTRACT_SIZE | ContractSize |
Volumen mínimo para la ejecución de la transacción | double | SYMBOL_VOLUME_MIN | VolumeContractMin |
Volumen máximo para la ejecución de la transacción | double | SYMBOL_VOLUME_MAX | VolumeContractMax |
Salto mínimo de cambio del volumen para la ejecución de la transacción | double | SYMBOL_VOLUME_STEP | VolumeContractStep |
Volumen conjunto máximo permitido de posición abierta y órdenes pendientes en una dirección para el símbolo dado (compra o venta) | double | SYMBOL_VOLUME_LIMIT | VolumeContractLimit |
Valor del swap cargado al mantener una posición larga con un volumen de un contrato | double | SYMBOL_SWAP_LONG | SwapLong |
Valor del swap cargado al mantener una posición corta con un volumen de un contrato | double | SYMBOL_SWAP_SHORT | SwapShort |
Margen necesario para abrir una posición con un tamaño de un lote | double | SYMBOL_MARGIN_INITIAL | MarginInit |
Margen necesario para mantener un lote de una posición abierta | double | SYMBOL_MARGIN_MAINTENANCE | MarginMaintenance |
Margen necesario para mantener un lote de una posición cubierta | double | SYMBOL_MARGIN_HEDGED | MarginHedged |
PROPIEDADES DE LÍNEA DEL INSTRUMENTO | |||
Nombre del instrumento | string | Symbol() | Name |
Nombre del activo básico para un instrumento derivado | string | SYMBOL_BASIS | NameBasisSymbol |
Divisa básica del instrumento | string | SYMBOL_CURRENCY_BASE | NameBasisCurrency |
Divisa del beneficio | string | SYMBOL_CURRENCY_PROFIT | NameCurrencyProfit |
Divisa en la que se calcula el margen | string | SYMBOL_CURRENCY_MARGIN | NameCurrencyMargin |
Fuente de la cotización actual | string | SYMBOL_BANK | NameBank |
Descripción de línea del símbolo | string | SYMBOL_DESCRIPTION | Description |
Nombre del símbolo comercial en el sistema internacional de números de identificación de valores ISIN | string | SYMBOL_ISIN | NameISIN |
Ruta en el árbol de símbolos | string | SYMBOL_PATH | SymbolPath |
Uso de varios instrumentos simultáneamente
Puesto que CSymbol es una clase normal, se puede crear un número ilimitado de objetos de esta clase dentro de su experto. El objeto WS es solo uno de estos objetos, creado de antemano por el motor CStrategy, y que además indica el símbolo de trabajo actual y el marco temporal. Nada impide al propio experto crear un símbolo adicional que proporcione acceso a cualquier otro instrumento. Supongamos que nuestro experto comercia en la sección urgente de la bolsa de Moscú y simultáneamente realiza el seguimiento de dos instrumentos Si y Brent. Entonces, en su código se pueden ubicar dos símbolos CSymbol, llamándolos respectivamente Si y Brent:
//+------------------------------------------------------------------+ //| EventListener.mqh | //| Copyright 2017, Vasiliy Sokolov, St-Petersburg, Russia | //| https://www.mql5.com/ru/users/c-4 | //+------------------------------------------------------------------+ #property copyright "Copyright 2017, Vasiliy Sokolov." #property link "https://www.mql5.com/ru/users/c-4" #include <Strategy\Strategy.mqh> //+------------------------------------------------------------------------------+ //| Plantilla de la estrategia que trabaja con dos instrumentos simultáneamente | //+------------------------------------------------------------------------------+ class CIntRate : public CStrategy { CSymbol Si; // Rublo-dólar CSymbol Brent; // Petróleo public: virtual void OnEvent(const MarketEvent& event); virtual bool OnInit(); }; //+------------------------------------------------------------------+ //| Inicializa los instrumentos petróleo y rublo | //+------------------------------------------------------------------+ bool CIntRate::OnInit(void) { Si.InitSeries("Si Splice", Timeframe()); Brent.InitSeries("BR Splice", Timeframe()); return true; } //+------------------------------------------------------------------+ //| Coste del petróleo expresado en rublos | //+------------------------------------------------------------------+ void CIntRate::OnEvent(const MarketEvent &event) { double brent_in_rub = Brent.Last()*Si.Last()/Si.ContractSize(); } //+------------------------------------------------------------------+
Este código del experto recibe los últimos precios de los futuros actuales del petróleo y el rublo y calcula la fórmula conocida del coste del petróleo expresado en rublos. Puesto que un contrado de futuros de Si es igual a 1000$, tendremos que dividir adicionalmente el resultado por el tamaño de un contrato. Sin embargo, gracias a que todas las propiedades del instrumento están reunidas en una clase única de CSymbol, se trata de una operación sencilla. El resto del código es también simple y expresivo. Lo más importante es no olvidar inicializar los objetos Si y Brent en el momento de inicio del experto, en el método OnInit.
Construyendo el perfil de la tasa de interés con la ayuda de CSymbol
El último ejemplo del uso de CSymbol, que estamos analizando, será un poco más complejo, pero también más interesante. Ya se sabe que los contratos de futuros se negocian con un cierto contango con respecto al activo básico. Esto está relacionado con el hecho de que el precio de una mercancía en el futuro normalmente es mayor que el precio actual. En esencia, esta diferencia determina la tasa de interés de mercado para una mercancía o un activo. Vamos a analizar un ejemplo con un futuro rublo/dólar. Su precio actual al momento de escribirse estas líneas era de 56.2875 rublos por 1 dólar, y el precio del contrato de futuros más cercano de Si-6.17 era de 56682 rublos por 1000$ o 56,682 rublos por 1 dólar. Es decir, la diferencia entre el precio actual y el precio dentro de 30 días (al 16.05.2017 Si-6.17 expira dentro de 30 días) constituye 0,395 rublos, o 39,5 kópeks. Es decir, en 1 mes, en opinión del mercado, el rublo se devaluará en 39,5 kópeks, lo que constituye un 0.7% de su precio actual. No resulata complicado calcular que en 12 meses de inflación, en opinión del mercado, constituirá un 8,42%. Pero esto sería el nivel de inflación calculado solo para el futuro más cercano. Si en lugar de Si-6.17, ponemos Si-9.17, la inflación será inferior y constituirá un 7.8% de interés. De esta forma, comparando todos los futuros Si con el precio básico del activo, podremos obtener el perfil de la tasa de interés. Este perfil tendrá el aspecto de un recuadro que mostrará la esperanza de los inversores dependiendo del tiempo. Por ejemplo, conocemos el interés para los próximos 30, 100, 200, 300, 400 y 500 días.
Para calcular estos valores, tenemos que utilizar activamente las diversas propiedades de los instrumentos, y también manipular la propia lista de estos instrumentos. Este es el aspecto que tiene la tarea del cálculo del perfil de la tasa de interés por puntos.
- El experto se carga en cualquier instrumento de futuros. Analiza el nombre del instrumento y carga todos los futuros relacionados con él.
- Cada futuro cargado supone un objeto CSymbol, que se ubica en la lista de instrumentos.
- En el momento de llegada del tick, el experto trabaja con la colección de instrumentos. Para cada instrumento se encuentra su símbolo básico.
- Se lleva a cabo el cálculo de la diferencia entre el instrumento elegido y el precio de su símbolo básico. Esta diferencia se convierte a tanto por ciento, y después se transforma en equivalente anual: para ello, se tiene en cuenta el tiempo de vida restante del contrato de futuros.
- La diferencia obtenida se muestra en el panel en forma de líneas en un recuadro. Cada línea tiene la forma: "Nombre del futuro — Número de días hasta la expiración — tasa de interés".
Como podemos ver por la descripción, el algoritmo no resulta en realidad tan sencillo como podría parecer. Sin embargo, gracias al motor CStrategy y al objeto CSymbol, reduciremos sustancialmente la complejidad del cálculo para el experto. Nuestro código se implementará en forma de experto, sin embargo, el propio experto no ejecutará ninguna acción comercial. En lugar de ello, simplemente mostrará el valor de las tasas de interés en el panel. Vamos a ver el código resultante:
//+------------------------------------------------------------------+ //| EventListener.mqh | //| Copyright 2017, Vasiliy Sokolov, St-Petersburg, Russia | //| https://www.mql5.com/ru/users/c-4 | //+------------------------------------------------------------------+ #property copyright "Copyright 2017, Vasiliy Sokolov." #property link "https://www.mql5.com/ru/users/c-4" #include <Strategy\Strategy.mqh> #include <Arrays\ArrayObj.mqh> #include "Panel.mqh" //+------------------------------------------------------------------+ //| Perfil de la tasa de interés | //+------------------------------------------------------------------+ class CIntRate : public CStrategy { CArrayObj Symbols; // Lista de símbolos CPercentPanel Panel; // Panel de dibujado de las tasas de interés double BaseRate(CSymbol* fut); public: virtual void OnEvent(const MarketEvent& event); virtual bool OnInit(); }; //+------------------------------------------------------------------------------+ //| Añade los futuros necesarios para calcular el perfil de la tasa de interés | //+------------------------------------------------------------------------------+ bool CIntRate::OnInit(void) { string basis = WS.NameBasisSymbol(); for(int i = 0; i < SymbolsTotal(false); i++) { string name = SymbolName(i, false); int index = StringFind(name, basis, 0); if(index != 0) continue; CSymbol* Fut = new CSymbol(name, Timeframe()); if(Fut.ExpirationDate() == 0 || Fut.ExpirationDate() < TimeCurrent()) { delete Fut; continue; } string text = "Add new symbol " + Fut.Name() + " in symbols list"; CMessage* msg = new CMessage(MESSAGE_INFO, __FUNCTION__, text); Log.AddMessage(msg); Symbols.Add(Fut); } string text = "Total add symbols " + (string)Symbols.Total(); CMessage* msg = new CMessage(MESSAGE_INFO, __FUNCTION__, text); Log.AddMessage(msg); if(Symbols.Total() > 0) { Panel.Show(); } return true; } //+------------------------------------------------------------------+ //| Calcula el perfil y lo muestra en un recuadro | //+------------------------------------------------------------------+ void CIntRate::OnEvent(const MarketEvent &event) { double sec_one_day = 60*60*24; //86 400 for(int i = 0; i < Symbols.Total(); i++) { CSymbol* Fut = Symbols.At(i); double brate = BaseRate(Fut); double days = (Fut.ExpirationDate()-TimeCurrent())/sec_one_day; if(Fut.Last() == 0.0) continue; double per = (Fut.Last() - brate)/brate*100.0; double per_in_year = per/days*365; Panel.SetLine(i, Fut.NameBasisSymbol() + " " + DoubleToString(days, 0) + " Days:", DoubleToString(per_in_year, 2)+"%"); } } //+------------------------------------------------------------------+ //| Retorna la cotización spot del futuro | //+------------------------------------------------------------------+ double CIntRate::BaseRate(CSymbol* fut) { string name = fut.NameBasisSymbol(); if(StringFind(name, "Si", 0) == 0) return SymbolInfoDouble("USDRUB_TOD", SYMBOL_LAST)*fut.ContractSize(); return SymbolInfoDouble(name, SYMBOL_LAST)*fut.ContractSize(); } //+------------------------------------------------------------------+
La funcionalidad principal se ha implementado en OnInit. Recibe el nombre del símbolo básico a través de WS.NameBasisSymbol() y, tras comprobar todos los instrumentos, encuentra todos los futuros que se correspondan con el símbolo básico dado. Cada futuro semejante se forma en el objeto CSymbol y se ubica en la lista de símbolos CArrayObj. Sin embargo, se hace una comprobación preliminar sobre si este futuro es válido, y si su tiempo de expiración se encuentra en el futuro, significará que se trata precisamente del futuro que necesitamos.
En el método OnEvent se hace propiamente el cálculo de la tasa de interés para cada futuro ubicado en la colección Symbols. Se calcula el número de días hasta la expiración, delta entre el futuro y el precio del swap. La diferencia de precios se transforma en tanto por ciento, y el tanto por ciento se normaliza de acuerdo con el rendimiento anual. El valor obtenido se introduce en el recuadro Panel (método SetLine).
El propio recuadro está construido de una forma bastante sencilla y se basa en el mismo complejo de clases gráficas que el panel CStrategy que aparece junto con el experto. El código del componente gráfico del experto se muestra más abajo:
//+------------------------------------------------------------------+ //| Panel.mqh | //| Copyright 2017, Vasiliy Sokolov. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2017, Vasiliy Sokolov." #property link "https://www.mql5.com" #include <Panel\ElChart.mqh> class CPercentPanel : public CElChart { private: CArrayObj m_fields; CArrayObj m_values; public: CPercentPanel(void); void SetLine(int index, string field, string value); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CPercentPanel::CPercentPanel(void) : CElChart(OBJ_RECTANGLE_LABEL) { Width(200); Height(200); } //+------------------------------------------------------------------+ //| Establece la línea | //+------------------------------------------------------------------+ void CPercentPanel::SetLine(int index,string field,string value) { if(m_fields.Total() <= index) { CElChart* sfield = new CElChart(OBJ_LABEL); sfield.XCoord(XCoord()+10); sfield.YCoord(YCoord()+21*index+10); sfield.Text(field); m_fields.Add(sfield); m_elements.Add(sfield); CElChart* svalue = new CElChart(OBJ_LABEL); svalue.YCoord(YCoord()+21*index+10); svalue.XCoord(XCoord()+132); svalue.Text(value); svalue.TextColor(clrGreen); m_values.Add(svalue); m_elements.Add(svalue); if(IsShowed()) { sfield.Show(); svalue.Show(); } Height(m_fields.Total()*20 + m_fields.Total()*2 + 10); } else { CElChart* el = m_fields.At(index); el.Text(field); el = m_values.At(index); el.Text(value); } ChartRedraw(); }
Después de que este experto sea compilado e iniciado en uno de los gráficos del contrato de futuros Si, deberá aparecer un recuadro así:
Perfil de la tasa de interés Rublo/Dólar en forma de recuadro
Como podemos ver por el recuadro, las tasas de interés en prácticamente todas las secciones temporales son iguales y están un poco por encima del 7% anual. El futuro más cercano muestra una tasa de interés un poco superior.
Un observación importante: antes de iniciar el experto en el gráfico, asegúrese de que las cotizaciones de todos los futuros necesarios están disponibles y han sido cargadas con anterioridad. En caso contrario, el resultado puede ser indeterminado.
Conclusión
Hemos analizado la nueva clase CSymbol incluida en las clases de CStrategy. Gracias a esta clase, resulta más sencillo trabajar con los instrumentos comerciales, obteniendo varias propiedades de los mismos. Gracias a CSymbol, hemos construido un indicador bastante interesante y revelador del perfil de la tasa de interés. Este ejemplo es muy representativo. Hemos obtenido con facilidad multitud de propiedades de los objetos CSymbol, y el propio cálculo no ha resultado tan complicado. El experto ha manipulado simultáneamente seis instrumentos, sin embargo, el código no ha aumentado por ello. Gracias a que CStrategy se hereda de CObject, los ejemplares de esta clase son fáciles de ubicar en las colecciones estándar, haciendo el procesamiento de datos bastante escalable y universal. Además, CStrategy ha delegado en CSymbol la funcionalidad menos propia de ella, gracias a lo cual, la propia clase CStrategy es ahora más ligera y manejable.
Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/3270
![El patrón Bandera](https://c.mql5.com/2/28/MQL5-avatar-flag-001__1.png)
![Asesor Experto multiplataforma: Gestión de capital (money management)](https://c.mql5.com/2/28/Cross_Platform_Expert_Advisor__1.png)
![Asesor Experto multiplataforma: Filtros temporales](https://c.mql5.com/2/28/Cross_Platform_Expert_Advisor__3.png)
![Patrones disponibles al comerciar con cestas de divisas. Parte III](https://c.mql5.com/2/28/articles_234.png)
![MQL5 - Lenguaje de estrategias comerciales para el terminal de cliente MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso