Discusión sobre el artículo "Experto comercial universal: integración con los módulos estándar de señales de MetaTrader (parte 7)" - página 3

 
Amy Liu:

Gracias Vasiliy por tu contribución. He aprendido mucho. He descargado todo el código pero tiene un error de compilación en el archivo Panel.mqh:

'At' - object pointer expected Panel.mqh 210 39

At' - object pointer expected Panel.mqh 228 37

¿Puedes comprobarlo?


Hola Amy. Acabo de terminar de leer los artículos de Vasiliy Sokolov. Si usted todavía está interesado en encontrar la solución. Por favor, publica aquí el registro de errores. Recuerdo que me encontré con ese error y me di cuenta de que hay un ".\Panel\Panel.mqh" en las declaraciones en el archivo StrategiesList. Panel.mqh no existe. En su lugar, trate de ir a https://www.mql5.com/es/articles/2411 y descargar el archivo del panel de allí. Creo que tiene el archivo Panel.mqh.

Esta serie de Vasiliy es realmente buena como marco de trabajo. Yo también aprendo mucho, pero cuando hay problemas con una librería, si el autor no ofrece soporte, puedes quedarte atascado si no eres un buen programador. Es lo que Alain Verleyen ha dicho en otros debates. Pero aquellos que dedican tiempo a compartir sus conocimientos y habilidades aquí son completamente increíbles. Les estoy eternamente agradecido.

Universal Expert Advisor: A Custom Trailing Stop (Part 6)
Universal Expert Advisor: A Custom Trailing Stop (Part 6)
  • 2016.06.16
  • Vasiliy Sokolov
  • www.mql5.com
The sixth part of the article about the universal Expert Advisor describes the use of the trailing stop feature. The article will guide you through how to create a custom trailing stop module using unified rules, as well as how to add it to the trading engine so that it would automatically manage positions.
 

El motor es absolutamente maravilloso, gracias. Es el primer motor MQL5 OOP que decidí cambiar.

Pero Manager.OnTick() es por desgracia muy lento. Rastreo muestra casi el 100% en él. Las pruebas son muy lentas en un marco de tiempo de un minuto y con OHLC M1. Durante 3 años - alrededor de 50 segundos. Y al mismo tiempo el Asesor Experto en sí no hace nada para las pruebas, he comentado todo lo que lo carga. Es decir, sólo busca barras.

Realmente quiero optimizar el código en Manager.OnTick()

 
Edgar:

El motor es absolutamente maravilloso, gracias. Es el primer motor MQL5 OOP que decidí cambiar.

Pero Manager.OnTick() es por desgracia muy lento. Rastreo muestra casi el 100% en él. Las pruebas son muy lentas en un marco de tiempo de un minuto y con OHLC M1. Durante 3 años - alrededor de 50 segundos. Y al mismo tiempo el Asesor Experto en sí no hace nada para las pruebas, he comentado todo lo que lo carga. Es decir, sólo busca barras.

Realmente quiero optimizar el código en Manager.OnTick()


Esta es la función desde la que se lanza todo lo demás, por supuesto estará al 100%. Mira dentro de ella a ver en qué se gasta el tiempo y optimízalo. Puedes publicar una captura de pantalla.

 
Edgar:

El motor es absolutamente maravilloso, gracias. Es el primer motor MQL5 OOP que decidí cambiar.

Pero Manager.OnTick() es por desgracia muy lento. Rastreo muestra casi el 100% en él. Las pruebas son muy lentas en un marco de tiempo de un minuto y con OHLC M1. Durante 3 años - alrededor de 50 segundos. Y al mismo tiempo el Asesor Experto en sí no hace nada para las pruebas, he comentado todo lo que lo carga. Es decir, sólo busca barras.

Realmente quiero optimizar el código en Manager.OnTick()

No hay nada sorprendente aquí. Esta velocidad es comparable a la marcha en vacío de un probador de estrategias. OnTick determina la ocurrencia de un nuevo tick y la apertura de una nueva barra. Estas operaciones no requieren muchos recursos.

 

Hola, Vasily.

Gracias por todos tus artículos.

El Asesor Experto Universal es realmente impresionante en términos de complejidad y arquitectura de software.

Para esta versión en particular, Me gustaría plantear un punto en este pedazo de código aquí:

CAdapterMACD::CAdapterMACD(void)
{
   m_params.symbol = Symbol();
   m_params.period = Period();
   m_params.every_tick = false;
   m_params.signal_type = SIGNAL_MACD;
   m_params.magic = 1234;
   m_params.point = 1.0;
   m_params.usage_pattern = 2;
   CSignalMACD* macd = m_signal.CreateSignal(m_params);
   macd.PeriodFast(15);
   macd.PeriodSlow(32);
   macd.PeriodSignal(6);
}

Tenga en cuenta que después de crear la señal, seguimos para configurarlo mediante el establecimiento de nuestro propio período del indicador MACD (15, 32, 6). Esto es fácil de hacer, porque el método CreateSignal ha devuelto el objeto correspondiente.<br/ translate="no">

En realidad, los parámetros MacD (15, 32 y 6) no están teniendo ningún efecto aquí, ya que el método CreateSignal() inicializa la señal MacD antes de que se actualicen los parámetros.

En este caso, sugeriría dividir el método CSignalAdapter::CreateSignal() en dos partes, donde en la primera, la señal es de hecho creada y devuelta tal cual, y la segunda parte sería la inicialización de la señal, después de que todos los parámetros "Signal Dependant" (en este caso, PeriodFast, PeriodSlow y PeriodSignal) sean establecidos:

CExpertSignal* CSignalAdapter::CreateSignal(MqlSignalParams& params)
{
   DeleteSignal();
   switch(params.signal_type)
   {
      case SIGNAL_AO:
         m_signal = new CSignalAO();
         break;
      case SIGNAL_AC:
         m_signal = new CSignalAC();
         break;
      case SIGNAL_ADAPTIVE_MA:
         m_signal = new CSignalAMA();
         break;
      case SIGNAL_CCI:
         m_signal = new CSignalCCI();
         break;
      case SIGNAL_DeMARKER:
         m_signal = new CSignalDeM();
         break;
      case SIGNAL_DOUBLE_EMA:
         m_signal = new CSignalDEMA();
         break;
      case SIGNAL_ENVELOPES:
         m_signal = new CSignalEnvelopes();
         break;
      case SIGNAL_FRAMA:
         m_signal = new CSignalFrAMA();
         break;
      case SIGNAL_MA:
         m_signal = new CSignalMA();
         break;
      case SIGNAL_MACD:
         m_signal = new CSignalMACD();
         break;
      case SIGNAL_PARABOLIC_SAR:
         m_signal = new CSignalSAR();
         break;
      case SIGNAL_RSI:
         m_signal = new CSignalRSI();
         break;
      case SIGNAL_RVI:
         m_signal = new CSignalRVI();
         break;
      case SIGNAL_STOCHASTIC:
         m_signal = new CSignalStoch();
         break;
      case SIGNAL_TRIPLE_EA:
         m_signal = new CSignalTriX();
         break;
      case SIGNAL_TRIPLE_EMA:
         m_signal = new CSignalTEMA();
         break;
      case SIGNAL_WILLIAMS_PER_RANGE:
         m_signal = new CSignalWPR();
         break;
   }
   if(CheckPointer(m_signal)!= POINTER_INVALID)
      m_params = params;
   
   return m_signal;
}

bool CSignalAdapter::Init()
{
   if(m_params.symbol == "") /* CreateSignal method should be called first in order to update m_params */
      return false;
   m_info.Name(m_params.symbol);
   if(!m_signal.Init(GetPointer(m_info), m_params.period, m_params.point))
      return false;
   if(!m_signal.InitIndicators(GetPointer(m_indicators)))
      return false;
   m_signal.EveryTick(m_params.every_tick);
   m_signal.Magic(m_params.magic);
   
   m_open.Create(m_params.symbol, m_params.period);
   m_high.Create(m_params.symbol, m_params.period);
   m_low.Create(m_params.symbol, m_params.period);
   m_close.Create(m_params.symbol, m_params.period);
   
   m_times.Create(m_params.symbol, m_params.period);
   m_spread.Create(m_params.symbol, m_params.period);
   m_tik_vol.Create(m_params.symbol, m_params.period);
   m_real_vol.Create(m_params.symbol, m_params.period);
   
   m_signal.SetPriceSeries(GetPointer(m_open), GetPointer(m_high), GetPointer(m_low), GetPointer(m_close));
   //m_signal.SetOtherSeries(GetPointer(m_spread), GetPointer(m_times), GetPointer(m_tik_vol), GetPointer(m_real_vol));
   int mask = 1;
   mask = mask << m_params.usage_pattern;
   m_signal.PatternsUsage(mask);
   return true;
}

Y, por supuesto, el recién creado método Init necesita ser llamado:

CAdapterMACD::CAdapterMACD(void)
{
   m_params.symbol = Symbol();
   m_params.period = Period();
   m_params.every_tick = false;
   m_params.signal_type = SIGNAL_MACD;
   m_params.magic = 1234;
   m_params.point = 1.0;
   m_params.usage_pattern = 2;
   CSignalMACD* macd = m_signal.CreateSignal(m_params);
   macd.PeriodFast(15);
   macd.PeriodSlow(32);
   macd.PeriodSignal(6);
   m_signal.Init(); /* This call is going to create the CSignalMACD object with the custom parameters */
}


¡Gracias por el gran trabajo, y aún más por compartirlo, Vasily!


Saludos,

Rodrigo Haller

 

El autor tiene mucho respeto. una vez más me enfrenté con el hecho de que prácticamente haber hecho algo, me encontré prácticamente lo mismo ya hecho antes) como dicen todo fue inventado antes que nosotros).

Un momento me gustaría señalar - en el trabajo de las señales para mí desde el principio era salvaje que toma la media ponderada de las señales de compra y venta, que no encaja con la lógica de la toma de decisiones en la forma canónica (árbol de decisión, que ya se menciona aquí) y lo hice - el Progenitor de las señales contiene, además de la lista real de las señales de las que se toma la dirección (de -100 a 100) ranuras para las señales de AND, ANDNOT, XOR. en este caso lo habitual es OR, no sólo booleana. Toda la lógica de procesamiento de estas ranuras es inequívoca y cosida en la clase progenitora. Es decir, para construir una estrategia sólo tiene que añadir la señal principal al Asesor Experto y las señales a las ranuras lógicas correspondientes, de acuerdo con el mismo principio que originalmente, es decir, para cada uno hasta 64 filtros adicionales. Veo esta solución como la más simple y fácilmente realizable. Si usted está interesado en la idea y no entiende algo, por favor póngase en contacto conmigo y le diré más.

 

¿Cómo es posible utilizar la clase CSignalMACD en el script?

He tratado de obtener el resultado de la señal sólo en el lugar, pero siempre tiene 0:

void OnStart()
{
   CSignalMACD       m_signal_macd;
   CSymbolInfo       m_info;
   CiOpen            m_open;
   CiHigh            m_high;
   CiLow             m_low;
   CiClose           m_close;
   CIndicators       m_indicators;

   m_signal_macd.Pattern_0(0);
   m_signal_macd.Pattern_1(0);
   m_signal_macd.Pattern_2(0);
   m_signal_macd.Pattern_3(100);
   m_signal_macd.Pattern_4(0);
   m_signal_macd.Pattern_5(0);
   m_info.Name(Symbol());                                  // Inicializar el objeto que representa el símbolo de negociación de la estrategia
   m_signal_macd.Init(GetPointer(m_info), Period(), 10);   // Inicialización del módulo de señales mediante el símbolo de negociación y el marco temporal
   m_signal_macd.InitIndicators(GetPointer(m_indicators)); // creación de los indicadores necesarios en el módulo de señales a partir de la lista vacía de indicadores m_indicators
   //m_signal_macd.EveryTick(true); // Modo de prueba
   m_signal_macd.Magic(42);                     // Número mágico
   m_signal_macd.PatternsUsage(8);                         // Máscara de patrón
   m_open.Create(Symbol(), Period());                      // Inicialización de la serie temporal de precios de apertura
   m_high.Create(Symbol(), Period());                      // Inicialización de la serie temporal de precios altos
   m_low.Create(Symbol(), Period());                       // Inicializar la serie temporal de precios Bajos
   m_close.Create(Symbol(), Period());                     // Inicializar la serie temporal de precios de Cierre
   m_signal_macd.SetPriceSeries(GetPointer(m_open),        // Inicialización del módulo de señales por objetos timeseries
                              GetPointer(m_high),
                              GetPointer(m_low),
                              GetPointer(m_close));
                              
   m_indicators.Refresh();
   m_signal_macd.SetDirection();
   int power_sell = m_signal_macd.ShortCondition();
   int power_buy = m_signal_macd.LongCondition();
   printf("PowerSell: " + (string)power_sell + " PowerBuy: " + (string)power_buy);
                                    
  }