Discussão do artigo "Expert Advisor Universal: Integração com os Módulos de Sinais Padrão do MetaTrader (parte 7)" - página 3

 
Amy Liu:

Agradeço a Vasiliy por sua contribuição. Aprendi muito. Baixei todo o código, mas há um erro de compilação no arquivo Panel.mqh:

'At' - ponteiro de objeto esperado Panel.mqh 210 39

'At' - object pointer expected Panel.mqh 228 37

Você pode verificar isso?


Olá, Amy. Acabei de ler os artigos de Vasiliy Sokolov. Se você ainda estiver interessada em descobrir a solução. Publique o registro de erros aqui. Eu me lembro de ter encontrado esse erro e percebi que há um ".\Panel\Panel.mqh" nas declarações do arquivo StrategiesList. Panel.mqh não existe. Em vez disso, tente acessar https://www.mql5.com/pt/articles/2411 e fazer o download do arquivo Panel de lá. Acredito que ele tenha o arquivo Panel.mqh.

Essa série do Vasiliy é muito boa como estrutura. Também aprendi muito, mas quando há problemas com uma biblioteca, se o autor não oferecer suporte, você pode ficar preso se não for um bom programador. Esse é o ponto que Alain Verleyen levantou em suas outras discussões. Mas as pessoas que dedicam tempo para compartilhar seus conhecimentos e habilidades aqui são absolutamente incríveis. Sou eternamente grato.

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.
 

O mecanismo é absolutamente maravilhoso, obrigado. É o primeiro mecanismo OOP MQL5 para o qual decidi mudar.

Mas, infelizmente, o Manager.OnTick() é muito lento. O rastreamento mostra quase 100% nele. Os testes são muito lentos em um intervalo de tempo de um minuto e com o OHLC M1. Durante 3 anos - cerca de 50 segundos. E, ao mesmo tempo, o próprio Expert Advisor não faz nada para o teste, pois eu comentei tudo o que o carrega. Ou seja, ele apenas busca as barras.

Eu realmente quero otimizar o código em Manager.OnTick()

 
Edgar:

O mecanismo é absolutamente maravilhoso, obrigado. É o primeiro mecanismo OOP MQL5 para o qual decidi mudar.

Mas, infelizmente, o Manager.OnTick() é muito lento. O rastreamento mostra quase 100% nele. Os testes são muito lentos em um intervalo de tempo de um minuto e com o OHLC M1. Durante 3 anos - cerca de 50 segundos. E, ao mesmo tempo, o próprio Expert Advisor não faz nada para o teste, pois eu comentei tudo o que o carrega. Ou seja, ele apenas busca as barras.

Eu realmente quero otimizar o código em Manager.OnTick()


Essa é a função a partir da qual todo o resto é iniciado - é claro que ela será 100%. Dê uma olhada nela para ver em que o tempo é gasto e otimize-o. Você pode publicar uma captura de tela.

 
Edgar:

O mecanismo é absolutamente maravilhoso, obrigado. É o primeiro mecanismo OOP MQL5 para o qual decidi mudar.

Mas, infelizmente, o Manager.OnTick() é muito lento. O rastreamento mostra quase 100% nele. Os testes são muito lentos em um intervalo de tempo de um minuto e com o OHLC M1. Durante 3 anos - cerca de 50 segundos. E, ao mesmo tempo, o próprio Expert Advisor não faz nada para o teste, pois eu comentei tudo o que o carrega. Ou seja, ele apenas busca as barras.

Eu realmente quero otimizar o código em Manager.OnTick()

Não há nada de surpreendente aqui. Essa velocidade é comparável à execução ociosa de um testador de estratégia. OnTick determina a ocorrência de um novo tick e a abertura de uma nova barra. Essas operações não requerem muitos recursos.

 

Oi, Vasily.

Obrigado por todos os seus artigos.

O Universal Expert Advisor é realmente impressionante em termos de complexidade e arquitetura de software.

Para essa versão específica, eu gostaria de levantar um ponto nesse trecho de código aqui:

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);
}

Observe que, depois de criar o sinal, continuamos a configurá-lo definindo nosso próprio período do indicador MACD (15, 32, 6). Isso é fácil de fazer porque o método CreateSignal retornou o objeto correspondente.<br/ translate="no">

Na verdade, os parâmetros MacD (15, 32 e 6) não estão tendo efeito aqui, pois o método CreateSignal() inicializa o sinal MacD antes que os parâmetros sejam atualizados.

Nesse caso, eu sugeriria dividir o método CSignalAdapter::CreateSignal() em duas partes, onde, na primeira, o sinal é de fato criado e retornado exatamente como está, e a segunda parte seria a inicialização do sinal, depois que todos os parâmetros "Signal Dependant" (nesse caso, PeriodFast, PeriodSlow e PeriodSignal) forem definidos:

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;
}

E, é claro, o método Init recém-criado precisa ser chamado:

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 */
}


Obrigado pelo excelente trabalho e ainda mais por compartilhá-lo, Vasily!


Obrigado,

Rodrigo Haller

 

O autor tem muito respeito. Mais uma vez me deparei com o fato de que, praticamente depois de ter feito algo, encontrei praticamente o mesmo já feito antes), como dizem que tudo foi inventado antes de nós).

Um momento que eu gostaria de observar - no trabalho de sinais para mim desde o início foi selvagem que leva a média ponderada de sinais para comprar e vender, não se encaixa com a lógica de tomada de decisão na forma canônica (árvore de decisão, que já é mencionado aqui) e eu fiz isso - o Progenitor de sinais contém, além da lista real de sinais a partir do qual a direção é tomada (de -100 a 100) slots para sinais para AND, ANDNOT, XOR. neste caso, o habitual é OR, não apenas booleano. Toda a lógica de processamento desses slots não é ambígua e é costurada na classe progenitora. Ou seja, para construir uma estratégia, você só precisa adicionar o sinal principal ao Expert Advisor e os sinais aos slots lógicos correspondentes, de acordo com o mesmo princípio do original, ou seja, para cada um, até 64 filtros adicionais. Considero essa solução a mais simples e facilmente realizável. Se estiver interessado na ideia e não entender alguma coisa, entre em contato comigo e eu lhe darei mais informações.

 

Como é possível usar a classe CSignalMACD no script?

Tentei obter o resultado do sinal apenas no local, mas sempre obtive 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());                                  // Inicialização do objeto que representa o símbolo de negociação da estratégia
   m_signal_macd.Init(GetPointer(m_info), Period(), 10);   // Inicialização do módulo de sinal pelo símbolo de negociação e pelo período de tempo
   m_signal_macd.InitIndicators(GetPointer(m_indicators)); // criação dos indicadores necessários no módulo de sinal com base na lista vazia de indicadores m_indicators
   //m_signal_macd.EveryTick(true); // Modo de teste
   m_signal_macd.Magic(42);                     // Número mágico
   m_signal_macd.PatternsUsage(8);                         // Máscara de padrão
   m_open.Create(Symbol(), Period());                      // Inicialização da série temporal dos preços de abertura
   m_high.Create(Symbol(), Period());                      // Inicialização da série temporal de preços altos
   m_low.Create(Symbol(), Period());                       // Inicialização da série temporal de preços baixos
   m_close.Create(Symbol(), Period());                     // Inicialização da série temporal dos preços de fechamento
   m_signal_macd.SetPriceSeries(GetPointer(m_open),        // Inicialização do módulo de sinal por objetos de série temporal
                              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);
                                    
  }