Discussão do artigo "Assistente MQL5: Como criar um módulo de sinais de comércio" - página 6

 
Karputov Vladimir:
Ou um módulo de gerenciamento de dinheiro. Para saber qual deles escolher, é preciso analisar mais detalhadamente.

O conceito não é muito claro. Há sinais para abrir posições, mas também há sinais para fechá-las. Seria possível usar votação e assim por diante, e tudo isso além de trailing.

E com que frequência as classes básicas são alteradas? Se eu escrevesse meu módulo de sinais com a versão anterior do assistente, teria que reprojetá-lo agora.

Gostaria de saber se alguém usa seriamente esse assistente e as classes de base do Expert Advisors ou se é apenas para pessoas preguiçosas que não querem fazer nada sozinhas.

 
Karputov Vladimir:
Ou um módulo de gerenciamento de dinheiro. O que exatamente escolher, você precisa analisar mais detalhadamente.

Desculpe-me, mas não sou bom em OOP. Você pode me ajudar a entender isso?

Aqui eu criei um módulo de sinais de negociação chamado СMySignal.mqh. Agora quero implementar meus próprios sinais de fechamento. Para isso, criei meu próprio módulo de gerenciamento de capital CMyMoney.mqh porque o CExpert tem essa chamada:

protected:
  CExpertMoney     *m_money;

bool CExpert::CheckClose(void)

  {
   double lot;
//--- position must be selected before call
   if((lot=m_money.CheckClose(GetPointer(m_position)))!=0.0)
      return(CloseAll(lot));

Mas quero usar os métodos da classe CMySignal na lógica de fechamento, não quero fazer todos os cálculos no CMyMoney novamente. Portanto, no CMyMoney, escrevo algo assim:

class CMyMoney : public CExpertMoney

protected:

   //--- input parameters
   virtual bool      CheckCloseLong(void);
   virtual bool      CheckCloseShort(void);

   CMySignal         *filter0;

...

double CMyMoney::CheckClose(CPositionInfo *position)
  {
   double lot;
   lot=position.Volume();
   if(position.PositionType()==POSITION_TYPE_BUY)
     {
      //--- check the possibility of closing the long position
      if(filter0.CheckCloseLong(lot))
         Print(__FUNCTION__+": close long position signal detected. Lot to be closed ",lot); 
     }
   else
     {
      //--- check the possibility of closing the short position
      if(filter0.CheckCloseShort(lot))
         Print(__FUNCTION__+": close short position signal detected. Lot to be closed ",lot);
     }
   return(lot);
  }


E movo toda a lógica de fechamento para a classe CMySignal:

class CMySignal : public CExpertSignal

public:

   virtual bool      CheckCloseLong(double &lot);
   virtual bool      CheckCloseShort(double &lot);

bool CMySignal::CheckCloseLong(double &lot)

  {

   //логика закрытия Long

  }

bool CMySignal::CheckCloseShort(double &lot)

  {

   //логика закрытия Short

  }

Mas acontece que já estou lidando com um novo objeto filter0, e não com um já criado. Tenho que reinicializar os dados para ele (indicadores e assim por diante). Como faço para ter acesso ao objeto já existente da classe CMySignal? Espero ter sido claro =)

Tudo isso deve funcionar por meio do Wizard de forma padrão, para que eu não altere nenhuma classe base. Todas as alterações só são possíveis em meus módulos de sinais de negociação e gerenciamento de dinheiro.

 
t101:

Desculpe-me, mas não sou bom em OOP. Você pode me ajudar a entender isso?

Criei um módulo de sinais de negociação chamado СMySignal.mqh. Agora quero implementar meus próprios sinais de fechamento. Para isso, criei meu próprio módulo de gerenciamento de capital CMyMoney.mqh porque o CExpert tem essa chamada:

protected:
  CExpertMoney     *m_money;

bool CExpert::CheckClose(void)

  {
   double lot;
//--- position must be selected before call
   if((lot=m_money.CheckClose(GetPointer(m_position)))!=0.0)
      return(CloseAll(lot));

Mas quero usar os métodos da classe CMySignal na lógica de fechamento, não quero fazer todos os cálculos no CMyMoney novamente. Portanto, no CMyMoney, escrevo algo assim:

class CMyMoney : public CExpertMoney

protected:

   //--- input parameters
   virtual bool      CheckCloseLong(void);
   virtual bool      CheckCloseShort(void);

   CMySignal         *filter0;

...

double CMyMoney::CheckClose(CPositionInfo *position)
  {
   double lot;
   lot=position.Volume();
   if(position.PositionType()==POSITION_TYPE_BUY)
     {
      //--- check the possibility of closing the long position
      if(filter0.CheckCloseLong(lot))
         Print(__FUNCTION__+": close long position signal detected. Lot to be closed ",lot); 
     }
   else
     {
      //--- check the possibility of closing the short position
      if(filter0.CheckCloseShort(lot))
         Print(__FUNCTION__+": close short position signal detected. Lot to be closed ",lot);
     }
   return(lot);
  }


E movo toda a lógica de fechamento para a classe CMySignal:

class CMySignal : public CExpertSignal

public:

   virtual bool      CheckCloseLong(double &lot);
   virtual bool      CheckCloseShort(double &lot);

bool CMySignal::CheckCloseLong(double &lot)

  {

   //логика закрытия Long

  }

bool CMySignal::CheckCloseShort(double &lot)

  {

   //логика закрытия Short

  }

Mas acontece que já estou lidando com um novo objeto filter0, e não com um já criado. Tenho que reinicializar os dados para ele (indicadores e assim por diante). Como faço para ter acesso ao objeto já existente da classe CMySignal? Espero ter sido claro =)

Tudo isso deve funcionar por meio do Wizard de forma padrão, para que eu não altere nenhuma classe base. Todas as alterações só são possíveis em meus módulos de sinais de negociação e gerenciamento de dinheiro.

Tenho uma pergunta sobre a segunda "planilha" - por que você insere"CMySignal *filter0;" no módulo de gerenciamento de dinheiro?
 
Karputov Vladimir:
Tenho uma pergunta sobre a segunda "planilha" - por que você insere"CMySignal *filter0;" no módulo de gerenciamento de dinheiro?

filter0 é um objeto de classe do meu módulo de sinais de negociação CMySignal. Ele é criado no arquivo principal do Expert Advisor:

CMySignal *filter0=new CMySignal;

Estou tentando obter acesso a ele no módulo de gerenciamento de dinheiro para transferir todos os cálculos de fechamento para o meu módulo de sinais. Não vejo nenhuma outra maneira de implementar minha própria lógica de fechamento.
 
t101:

filter0 é um objeto de classe do meu módulo de sinais de negociação CMySignal. Ele é criado no arquivo principal do EA:

CMySignal *filter0=new CMySignal;

Estou tentando acessá-lo a partir do módulo de gerenciamento de dinheiro para transferir todos os cálculos de fechamento para o meu módulo de sinais. Não vejo nenhuma outra maneira de implementar minha própria lógica de fechamento.

Veja a implementação da transferência do ponteiro do sinal principal para o módulo de sinais(MQL5 Wizard: How to teach an Expert Advisor to open pending orders at any price):

De acordo com nosso esquema de implementação da ideia, é necessário declarar uma variável interna onde o ponteiro para o sinal principal será armazenado.

Como essa variável deve ser interna (com escopo somente dentro da classe do gerador de sinal de negociação), nós a adicionaremos ao próximo bloco de código:

protected:
   CiEnvelopes       m_env;          // indicador de objeto
   //--- parâmetros ajustados
   int               m_ma_period;    // o parâmetro "período de cálculo da média" do indicador
   int               m_ma_shift;     // o parâmetro "time shift" do indicador
   ENUM_MA_METHOD    m_ma_method;     // o parâmetro "method of averaging" (método de cálculo da média) do indicador
   ENUM_APPLIED_PRICE m_ma_applied;    // o parâmetro "objeto de cálculo de média" do indicador
   double            m_deviation;    // o parâmetro "desvio" do indicador
   //--- "pesos" dos modelos de mercado (0-100)
   int               m_pattern_0;      // modelo 0
   CExpertSignal    *m_signal;         // armazenar referência ao sinal principal

Observe também que removi as variáveis que não serão usadas no código.

Declararemos o método que será usado para armazenar o ponteiro para o sinal principal em outro bloco de código - "method of setting the pointer to the main signal". Alguns métodos desnecessários também foram removidos.

Talvez isso seja o que você precisa. Somente o ponteiro para o sinal principal será passado para o módulo de gerenciamento de capital.

 
Karputov Vladimir:

Veja a implementação da passagem do ponteiro para o sinal principal para o módulo de sinal(Assistente MQL5: Como ensinar o Expert Advisor a abrir ordens pendentes a qualquer preço):

Talvez seja isso que você precisa. Somente o ponteiro para o sinal principal será passado para o módulo de gerenciamento de dinheiro.

Por que preciso de um ponteiro para o sinal principal se preciso de um ponteiro para o meu sinal, um herdeiro da classe CExpertSignal? Eu o quero em meu módulo de gerenciamento de dinheiro, um descendente de CExpertMoney.
 
t101:
Por que preciso de um ponteiro para o sinal principal se quero um ponteiro para o meu sinal, um descendente da classe CExpertSignal? Eu o quero em meu módulo de gerenciamento de dinheiro, um herdeiro da classe CExpertMoney.

Certo. Vamos para o outro lado. Em seu módulo de gerenciamento de dinheiro, você precisa declarar uma variável como esta:

CMySignal    *m_signal;         // armazenar uma referência ao seu sinal

e um método como este:

   //--- método de definição do ponteiro para o sinal principal
   virtual bool      InitSignal(СMySignal *filter=NULL);

e sua implementação

//+------------------------------------------------------------------+
//| Objeto de sinal de inicialização|
//+------------------------------------------------------------------+
bool CMyMoney::InitSignal(СMySignal *filter)
  {
   m_signal=filter;
   return(true);
  }

Agora você pode tentar acessar seu sinal do módulo de gerenciamento de dinheiro via

m_signal.метод вашего модуля сигналов
 
Karputov Vladimir:

Muito bem. Vamos para o outro lado. Em seu módulo de gerenciamento de dinheiro, você precisa declarar uma variável como esta:

e este método:

e sua implementação

Agora posso tentar acessar meu sinal do módulo de gerenciamento de dinheiro por meio de

Acesso a ponteiro inválido ao chamar um método do meu módulo de sinal
m_signal.метод вашего модуля сигналов
InitSignal deve ser chamado em algum lugar antes?
 
t101:
Acesso a ponteiro inválido ao chamar um método do meu módulo de sinais
InitSignal deve ser chamado em algum lugar antes?
É claro que "InitSignal" deve ser chamado antes: a partir de OnInit() do EA, no final do bloco de inicialização do módulo de gerenciamento de dinheiro.
 
Karputov Vladimir:
É claro que precisamos chamar "InitSignal" antes: a partir de OnInit() do EA, no final do bloco de inicialização do módulo de gerenciamento de dinheiro.
Devo adicioná-la manualmente a OnInit()? Então não posso fazer o que quero por meio do Assistente?