English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
Outra classe OOP do MQL5

Outra classe OOP do MQL5

MetaTrader 5Exemplos | 25 março 2014, 10:13
2 175 0
laplacianlab
[Excluído]

Introdução

Construindo um CE completo orientado a objeto que funcione de fato é em minha humilde opinião uma tarefa desafiadora que requer muitas habilidades todas unidas: raciocínio lógico, pensamento divergente, capacidade para análise e síntese, imaginação, etc. Digamos que se o sistema de negociação automatizado que devemos resolver fosse um jogo de xadrez, sua ideia de negociação seria a estratégia do xadrez. E a execução da estratégia de xadrez através de táticas seria a programação do robô através do uso de indicadores técnicos, figuras de gráficos, ideias econômicas fundamentais e axiomas conceituais.

Detalhe de A escola de Atenas por Raffaello Sanzio

Figura 1. Detalhe de A escola de Atenas por Raffaello Sanzio. Nessa foto vemos os filósofos Platão e Aristóteles em profunda discussão.
Platão representa aqui o mundo conceitual e Aristóteles o mundo empiricista.

Estou ciente da dificuldade desse exercício. Um CE OO não é extremamente difícil de programar, mas é verdade que apresente um certo grau de dificuldade para pessoas com pouca experiência em desenvolvimento de aplicação. Como em qualquer outra disciplina, isso é, por sua vez, devido à falta de experiência em si, o motivo que tento ensinar a você esse tópico através de um exemplo específico que tenho certeza que você vai entender. Não desanime se você ainda se sentir inseguro em lidar com conceitos OOP, você vai achar as coisas muito mais fáceis uma vez que você implementou o seus primeiros cinco CEs, digamos. Você não tem que construir nada do início por enquanto, apenas entenda o que eu explicar aqui!

Todo o processo de conceber e implementar um sistema de negociação pode ser simplificado em várias formas quando é realizado por diversas pessoas, apesar de esse fato possuir o problema da comunicação. Quero dizer que a pessoa que conceber a estratégia de investimento não é obrigada a lidar com os conceitos de programação, quem lida é o seu interlocutor, o programador. E o desenvolvedor do MQL5 pode não entender inicialmente alguns aspectos importantes da estratégia de negociação de seu cliente.

Esse é um problema clássico em engenharia de software que levou à criação de muitas metodologias de desenvolvimento de software como Scrum, Desenvolvimento direcionado por testes (TDD), Programação extrema (XP), etc. É crucial estar atento às armadilhas de linguagem. A propósito, para o seu conhecimento, a Wikipedia diz: "metodologia de desenvolvimento de software ou metodologia de desenvolvimento de sistema em engenharia de software é uma estrutura que é utilizada para estruturar, planejar, e controlar o processo de desenvolver um sistema de informação".

Vamos presumir que somos capazes de ambos rapidamente conceber e implementar ideias de negociação bem sucedidas. Podemos também supor que estamos no fim de um processo de desenvolvimento iterativo onde o sistema de negociação pensado por nosso cliente já foi bem definido e compreendido por todos. Como você preferir. A propósito, de agora em diante irei me referir nesse texto a alguns artigos educacionais disponíveis em Artigos de programação do MQL5 de forma que você possa rapidamente verificar e relembrar algumas ideias, quando necessário, para continuar esse exercício com sucesso. Você está pronto?


1. Seus primeiros passos em adotar o novo paradigma


1,1. Por que OOP é bom para programar os seus CEs do Forex?

Talvez você está imaginando nesse ponto porque você tem que fazer algo como isso. Deixe-me dizer a você primeiramente que você não é forçado a ser OOP. De qualquer forma é altamente recomendado ser uma pessoa OOP de forma a dar um passo adiante em seu conhecimento de programação de sistemas de negociação automatizados.

A forma clássica de desenvolver aplicações, a chamada programação processual, possui essas desvantagens:

  • Ela torna difícil de modelar problemas. Sob esse paradigma antigo a solução do problema principal é reduzida a dividir ele em sub problemas mais simples que são resolvidos por módulos funcionais, isso é dizer, funções e procedimentos.
  • Ela torna difícil reutilizar o código, que por sua vez dificulta o custo, confiabilidade, flexibilidade e manutenção.

Reutilizar o código é mais fácil com o novo estilo orientado a objeto. É muito importante! Muitos especialistas acreditam que reutilizar o código é a solução real para a maioria dos problemas de desenvolvimento de software.

Nesse momento devemos mencionar os tipos de dados abstratos (ADT). OOP permite a criação de ADTs. Um ADT é uma abstração do conceito tradicional do tipo de dados que está presente em todas as linguagens de programação. Seu uso principal é definir confortavelmente o domínio de dados das aplicações. Include\Arrays\Array.mqh, Include\Arrays\List.mqh e Include\Arrays\Tree.mqh são alguns exemplos dos tipos de dados abstratos do MQL5.

Em resumo, o paradigma de programação orientada a objeto quer que você projete suas aplicações em um nível conceitual de forma a você se beneficiar da reutilização do código, confiabilidade, flexibilidade e facilidade de manutenção.

1,2. Você é um racionalizador conceitual? O UML vai te ajudar

Você já ouviu falar do UML? UML significa linguagem de modelagem unificada. É uma linguagem gráfica para projetar sistemas orientados a objeto. Nós humanos devemos primeiramente pensar em nossos sistemas na fase de análise e então codificá-los com uma linguagem de programação. Ir de cima para baixo é menos insano para desenvolvedores. Mesmo assim, minha experiência como um analista diz que algumas vezes isso não é possível devido a diversas coisas: o aplicativo deve ser feito em um tempo muito curto, não há ninguém na equipe que possa rapidamente aplicar seu conhecimento de UML, ou talvez algumas pessoas na equipe não sabem algumas partes do UML.

UML é em minha opinião uma boa ferramenta de análise que você pode utilizar se você se sentir confortável com ela, e se as circunstâncias envolvendo o projeto estão bem. Por favor, leia Como desenvolver um consultor especialista utilizando ferramentas UML se você está interessado em explorar o tópico de UML. Esse artigo é talvez um pouco esmagador mas serve para ter uma noção geral sobre como engenheiros de software profissionais trabalham a sua análise. Você precisaria completar um curso de diversas semanas para entender completamente UML! Por enquanto não te problema saber o que UML é. De acordo com minha experiência essa ferramenta de análise não é sempre utilizada em todos os projetos de software devido a diversas circunstâncias presentes no mundo real.

Logo do UML

Figura 2. Logo do UML.


1,3. Oi mundo! Sua primeira classe OO

Se você é um completo novato em programação orientada a objeto recomendo a você primeiramente ler a documentação oficial sobre OO disponível em Referências do MQL5 e então ler Escrevendo um consultor especialista utilizando a abordagem de programação orientada a objeto do MQL5 para entender o básico. Por favor se certifique de complementar essas leituras com alguns outros materiais. De agora em diante eu presumo que você já sabe um pouco de OOP, então você irá facilmente compreender o exemplo clássico da classe Person que em MQL5 é como a seguir:

//+------------------------------------------------------------------+
//| CPerson Class                                                    |
//+------------------------------------------------------------------+
class CPerson
  {
protected:
   string            m_first_name;
   string            m_surname;
   datetime          m_birth;

public:
   //--- Constructor and destructor methods
                     CPerson(void);
                    ~CPerson(void);
   //--- Getter methods
   string            GetFirstName(void);
   string            GetSurname(void);
   datetime          GetBirth(void);
   //--- Setter methods
   void              SetFirstName(string first_name);
   void              SetSurname(string surname);
   void              SetBirth(datetime birth);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CPerson::CPerson(void)
  {
   Alert("Hello world! I am run when an object of type CPerson is created!");
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CPerson::~CPerson(void)
  {
   Alert("Goodbye world! I am run when the object is destroyed!");
  }
//+------------------------------------------------------------------+
//| GetFirstName                                                     |
//+------------------------------------------------------------------+
string CPerson::GetFirstName(void)
  {
   return m_first_name;
  }
//+------------------------------------------------------------------+
//| GetSurname                                                       |
//+------------------------------------------------------------------+
string CPerson::GetSurname(void)
  {
   return m_surname;
  }
//+------------------------------------------------------------------+
//| GetBirth                                                         |
//+------------------------------------------------------------------+
datetime CPerson::GetBirth(void)
  {
   return m_birth;
  }
//+------------------------------------------------------------------+
//| SetFirstName                                                     |
//+------------------------------------------------------------------+
void CPerson::SetFirstName(string first_name)
  {
   m_first_name=first_name;
  }
//+------------------------------------------------------------------+
//| SetSurname                                                       |
//+------------------------------------------------------------------+
void CPerson::SetSurname(string surname)
  {
   m_surname=surname;
  }
//+------------------------------------------------------------------+
//| SetBirth                                                         |
//+------------------------------------------------------------------+
void CPerson::SetBirth(datetime birth)
  {
   m_birth=birth;
  }
//+------------------------------------------------------------------+

O seguinte é para desenvolvedores puristas obcecados em escrever códigos de qualidade. Ao contrário de alguns exemplos disponíveis em Artigos de programação do MQL5 e muitos outros softwares disponíveis na Base de códigos, a classe acima não utiliza as mesmas convenções de programação aplicadas pela MetaQuotes Software Corp. para codificar sua estrutura do MQL5. Encorajo você a escrever o seu código como a MetaQuotes escreve. A propósito, o tópico intitulado Sobre convenções em programas OOP do MQL5 cobre esse assunto.

Em poucas palavras, algumas convenções importantes aplicadas em escrita Person.mqh são:

  • O nome da classe CPerson começa com a letra C maiúscula.
  • Nomes dos métodos são em CamelCase, explicando, são palavras unidas e cada palavra começa com letra maiúscula, por exemplo, GetFirstName, SetSurname, etc.
  • Nomes de propriedades protegidas são precedidos pelo prefixo m_, por exemplo, m_first_name, m_surname e m_birth.
  • A palavra reservada this não é utilizada para referenciar membros da classe dentro da própria classe.

Por favor observe alguns arquivos do quadro do MQL5, por exemplo Include\Arrays\Array.mqh, Include\Arrays\List.mqh, Include\Trade\Trade.mqh, e veja como o código do MQL5 original é escrito.


2. Vamos programar o nosso primeiro CE orientado a objeto


2,1. A ideia do sistema de negociação

Nossa ideia de negociação é simples: "Tendências curtas de mercados voláteis estão próximas do aleatório". É isso! Isso foi observado por vários especialistas sob algumas circunstâncias. Se essa hipótese é verdadeira o nosso robô do Forex deve trabalhar por necessidade. Dado um ponto aleatório em m gráfico o próximo movimento pode obviamente ir para cima ou para baixo, nós não sabemos. A questão é que se a diferença entre os níveis de SL e TP estabelecidos são suficientemente pequenos então a diferença não é significante em termos absolutos, e nós portanto alcançamos a expectativa matemática. Esse sistema simplesmente vai deixei ele trabalhar a expectativa matemática. Uma vez que você pegue o código do CE nesse artigo e execute o teste retrospectivo você verá que ele necessita de uma política de gerenciamento de dinheiro muito simples.


2,2. O esqueleto OOP do robô

Nessa seção vamos desenvolver a estratégia acima através do racionamento abstrato necessário por programação orientada a objeto. Então por que não começamos a pensar em nosso CE como se fosse uma criatura viva? Sob essa visão vimos que nossa máquina do Forex pode ser composta de três partes principais: um cérebro, algo que vamos chamar de evolução, e um gráfico.

O cérebro é parte do robô que contém os dados necessários para operar, algo como uma memória somente de leitura (ROM). A tabela é o pedaço de informação emulando o gráfico no qual o robô opera. Finalmente, a chamada evolução é um pedaço de dados contendo informação temporal como o estado do robô em dado momento, o histórico das operações realizadas, etc. É como se estivéssemos projetando um ser humano através de seus órgãos, algo como um Frankenstein, porque devemos desenvolver um aplicativo para o setor de saúde. Cada órgão é nesse contexto um conceito semântico único associado com algumas outras partes do todo.

Primeiramente vamos criar a pasta MQL5\Include\Mine para armazenar nossas coisas personalizadas. Isso é apenas uma ideia para organizar nosso código. É bom saber que você pode fazer isso em seus desenvolvimentos mas claro que você não é obrigado. Vamos então criar o arquivo MQL5\Include\Mine\Enums.mqh de forma a armazenar os enums criados por nós:

//+------------------------------------------------------------------+
//| Status enumeration                                               |
//+------------------------------------------------------------------+
enum ENUM_STATUS_EA
  {
   BUY,
   SELL,
   DO_NOTHING
  };
//+------------------------------------------------------------------+
//| Lifetime enumeration                                             |
//+------------------------------------------------------------------+
enum ENUM_LIFE_EA
  {
   HOUR,
   DAY,
   WEEK,
   MONTH,
   YEAR
  };
//+------------------------------------------------------------------+

Em seguida, é hora de criar o embrião do nosso CE que será chamado ExpertSimpleRandom.mq5! Então, por favor, crie a pasta MQL5\Experts\SimpleRandom e então crie dentro dela o arquivo ExpertSimpleRandom.mq5 com esse código:

//+------------------------------------------------------------------+
//|                                           ExpertSimpleRandom.mq5 |
//|                               Copyright © 2013, Jordi Bassagañas |
//+------------------------------------------------------------------+

#property copyright     "Copyright © 2013, laplacianlab"
#property link          "https://www.mql5.com/pt/articles"
#property version       "1.00"

#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\PositionInfo.mqh>
#include <Indicators\Indicators.mqh>
#include <Mine\Enums.mqh>
#include <..\Experts\SimpleRandom\CSimpleRandom.mqh>

input int               StopLoss;
input int               TakeProfit;
input double            LotSize;
input ENUM_LIFE_EA      TimeLife;

MqlTick tick;
CSimpleRandom *SR=new CSimpleRandom(StopLoss,TakeProfit,LotSize,TimeLife);
//+------------------------------------------------------------------+
//| Initialization function                                          |
//+------------------------------------------------------------------+
int OnInit(void)
  {
   SR.Init();
   return(0);
  }
//+------------------------------------------------------------------+
//| Deinitialization function                                        |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   SR.Deinit();
   delete(SR);
  }
//+------------------------------------------------------------------+
//| OnTick event function                                            |
//+------------------------------------------------------------------+
void OnTick()
  {
   SymbolInfoTick(_Symbol,tick);
   SR.Go(tick.ask,tick.bid);
  }
//+------------------------------------------------------------------+

Isso é apenas uma abordagem das muitas possíveis lá fora. Tudo isso é basicamente para ilustrar como o OOP funciona no MQL5. Como você vê, a classe principal do consultor especialista é chamada CSimpleRandom.mqh, por favor salve ela em MQL5\Experts\SimpleRandom\CSimpleRandom.mqh:

//+------------------------------------------------------------------+
//|                                           ExpertSimpleRandom.mq5 |
//|                               Copyright © 2013, Jordi Bassagañas |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
#include <Mine\Enums.mqh>
#include <..\Experts\SimpleRandom\CBrain.mqh>
#include <..\Experts\SimpleRandom\CEvolution.mqh>
#include <..\Experts\SimpleRandom\CGraphic.mqh>
//+------------------------------------------------------------------+
//| CSimpleRandom Class                                              |
//+------------------------------------------------------------------+
class CSimpleRandom
  {
protected:
   CBrain           *m_brain;
   CEvolution       *m_evolution;
   CGraphic         *m_graphic;
   CTrade           *m_trade;
   CPositionInfo    *m_positionInfo;
public:
   //--- Constructor and destructor methods
                     CSimpleRandom(int stop_loss,int take_profit,double lot_size,ENUM_LIFE_EA time_life);
                    ~CSimpleRandom(void);
   //--- Getter methods
   CBrain           *GetBrain(void);
   CEvolution       *GetEvolution(void);
   CGraphic         *GetGraphic(void);
   CTrade           *GetTrade(void);
   CPositionInfo    *GetPositionInfo(void);
   //--- Specific methods of CSimpleRandom
   bool              Init();
   void              Deinit(void);
   bool              Go(double ask,double bid);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CSimpleRandom::CSimpleRandom(int stop_loss,int take_profit,double lot_size,ENUM_LIFE_EA time_life)
  {
   int lifeInSeconds;

   switch(time_life)
     {
      case HOUR:

         lifeInSeconds=3600;

         break;

      case DAY:

         lifeInSeconds=86400;

         break;

      case WEEK:

         lifeInSeconds=604800;

         break;

      case MONTH:

         lifeInSeconds=2592000;

         break;

         // One year

      default:

         lifeInSeconds=31536000;

         break;
     }

   m_brain=new CBrain(TimeLocal(),TimeLocal()+lifeInSeconds,lot_size,stop_loss,take_profit);
   m_evolution=new CEvolution(DO_NOTHING);
   m_graphic=new CGraphic(_Symbol);
   m_trade=new CTrade();
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CSimpleRandom::~CSimpleRandom(void)
  {
   delete(m_brain);
   delete(m_evolution);
   delete(m_graphic);
   delete(m_trade);
  }
//+------------------------------------------------------------------+
//| GetBrain                                                         |
//+------------------------------------------------------------------+
CBrain *CSimpleRandom::GetBrain(void)
  {
   return m_brain;
  }
//+------------------------------------------------------------------+
//| GetBrain                                                         |
//+------------------------------------------------------------------+
CEvolution *CSimpleRandom::GetEvolution(void)
  {
   return m_evolution;
  }
//+------------------------------------------------------------------+
//| GetGraphic                                                       |
//+------------------------------------------------------------------+
CGraphic *CSimpleRandom::GetGraphic(void)
  {
   return m_graphic;
  }
//+------------------------------------------------------------------+
//| GetTrade                                                         |
//+------------------------------------------------------------------+
CTrade *CSimpleRandom::GetTrade(void)
  {
   return m_trade;
  }
//+------------------------------------------------------------------+
//| GetPositionInfo                                                  |
//+------------------------------------------------------------------+
CPositionInfo *CSimpleRandom::GetPositionInfo(void)
  {
   return m_positionInfo;
  }
//+------------------------------------------------------------------+
//| CSimpleRandom initialization                                     |
//+------------------------------------------------------------------+
bool CSimpleRandom::Init(void)
  {
// Initialization logic here...
   return true;
  }
//+------------------------------------------------------------------+
//| CSimpleRandom deinitialization                                   |
//+------------------------------------------------------------------+
void CSimpleRandom::Deinit(void)
  {
// Deinitialization logic here...
   delete(m_brain);
   delete(m_evolution);
   delete(m_graphic);
   delete(m_trade);
  }
//+------------------------------------------------------------------+
//| CSimpleRandom Go                                                 |
//+------------------------------------------------------------------+
bool CSimpleRandom::Go(double ask,double bid)
  {
   double tp;
   double sl;

   int coin=m_brain.GetRandomNumber(0,1);

// Is there any open position?     

   if(!m_positionInfo.Select(_Symbol))
     {
      // If not, we open one

      if(coin==0)
        {
         GetEvolution().SetStatus(BUY);
        }
      else
        {
         GetEvolution().SetStatus(SELL);
        }
     }

// If so, let it work the mathematical expectation.

   else GetEvolution().SetStatus(DO_NOTHING);

   switch(GetEvolution().GetStatus())
     {
      case BUY:

         tp = ask + m_brain.GetTakeProfit() * _Point;
         sl = bid - m_brain.GetStopLoss() * _Point;

         GetTrade().PositionOpen(_Symbol,ORDER_TYPE_BUY,m_brain.GetSize(),ask,sl,tp);

         break;

      case SELL:

         sl = ask + m_brain.GetStopLoss() * _Point;
         tp = bid - m_brain.GetTakeProfit() * _Point;

         GetTrade().PositionOpen(_Symbol,ORDER_TYPE_SELL,m_brain.GetSize(),bid,sl,tp);

         break;

      case DO_NOTHING:

         // Nothing...

         break;
     }

// If there is some error we return false, for now we always return true  

   return(true);
  }
//+------------------------------------------------------------------+


2.3. Unindo CSimpleRandom a objetos do tipo complexo

Observe como os objetos personalizados do tipo CBrain, CEvolution e CGraphic são unidos a CSimpleRandom.

Primeiro definimos as propriedades protegidas correspondentes:

protected:
   CBrain           *m_brain;
   CEvolution       *m_evolution;
   CGraphic         *m_graphic; 

E logo após instanciamos esses objetos no interior do construtor:

m_brain=new CBrain(TimeLocal(), TimeLocal() + lifeInSeconds, lot_size, stop_loss, take_profit);         
m_evolution=new CEvolution(DO_NOTHING);      
m_graphic=new CGraphic(_Symbol);

O que fazemos é dinamicamente criar objetos de tipo complexo assim como os documentos oficiais explicam em Apontadores de objetos. Com esse esquema podemos acessar a funcionalidade de CBrain, CEvolution e CGraphic diretamente de CSimpleRandom. Poderíamos executar, por exemplo, o seguinte código em ExpertSimpleRandom.mq5:

//+------------------------------------------------------------------+
//| OnTick event function                                            |
//+------------------------------------------------------------------+
void OnTick()
   {              
      // ...
      
      int randNumber=SR.GetBrain().GetRandomNumber(4, 8);

      // ...          
  }

Escrevo agora o código de CBrain, CEvolution e CGraphic para concluir essa seção. Por favor, observe que há algumas partes que não são codificadas porque elas não são estritamente necessárias para fazer teste retrospectivo em SimpleRandom. É deixado como um exercício para você codificar as partes que faltam dessas classes, fique a vontade para desenvolvê-las da forma que quiser.  Por exemplo, m_death não é utilizada de fato, apesar de a ideia por trás dela é saber do inicio a data em que o robô terminará sua atividade.

//+------------------------------------------------------------------+
//|                                               ExpertSimpleRandom |
//|                               Copyright © 2013, Jordi Bassagaсas |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| CBrain Class                                                     |
//+------------------------------------------------------------------+
class CBrain
  {
protected:
   ENUM_TIMEFRAMES   m_period;               // period must always be initialized to PERIOD_M1 to fit the system's idea
   datetime          m_birth;               // The datetime in which the robot is initialized for the first time
   datetime          m_death;               // The datetime in which the robot will die
   double            m_size;                // The size of the positions
   int               m_stopLoss;            // Stop loss
   int               m_takeProfit;          // Take profit

public:
   //--- Constructor and destructor methods
                     CBrain(datetime birth,datetime death,double size,int stopLoss,int takeProfit);
                    ~CBrain(void);
   //--- Getter methods
   datetime          GetBirth(void);
   datetime          GetDeath(void);
   double            GetSize(void);
   int               GetStopLoss(void);
   int               GetTakeProfit(void);
   //--- Setter methods
   void              SetBirth(datetime birth);
   void              SetDeath(datetime death);
   void              SetSize(double size);
   void              SetStopLoss(int stopLoss);
   void              SetTakeProfit(int takeProfit);
   //--- Brain specific logic
   int               GetRandomNumber(int a,int b);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CBrain::CBrain(datetime birth,datetime death,double size,int stopLoss,int takeProfit)
  {
   MathSrand(GetTickCount());

   m_period=PERIOD_M1;
   m_birth=birth;
   m_death=death;
   m_size=size;
   m_stopLoss=stopLoss;
   m_takeProfit=takeProfit;
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CBrain::~CBrain(void)
  {
  }
//+------------------------------------------------------------------+
//| GetBirth                                                         |
//+------------------------------------------------------------------+
datetime CBrain::GetBirth(void)
  {
   return m_birth;
  }
//+------------------------------------------------------------------+
//| GetDeath                                                         |
//+------------------------------------------------------------------+
datetime CBrain::GetDeath(void)
  {
   return m_death;
  }
//+------------------------------------------------------------------+
//| GetSize                                                          |
//+------------------------------------------------------------------+
double CBrain::GetSize(void)
  {
   return m_size;
  }
//+------------------------------------------------------------------+
//| GetStopLoss                                                      |
//+------------------------------------------------------------------+
int CBrain::GetStopLoss(void)
  {
   return m_stopLoss;
  }
//+------------------------------------------------------------------+
//| GetTakeProfit                                                    |
//+------------------------------------------------------------------+
int CBrain::GetTakeProfit(void)
  {
   return m_takeProfit;
  }
//+------------------------------------------------------------------+
//| SetBirth                                                         |
//+------------------------------------------------------------------+
void CBrain::SetBirth(datetime birth)
  {
   m_birth=birth;
  }
//+------------------------------------------------------------------+
//| SetDeath                                                         |
//+------------------------------------------------------------------+
void CBrain::SetDeath(datetime death)
  {
   m_death=death;
  }
//+------------------------------------------------------------------+
//| SetSize                                                          |
//+------------------------------------------------------------------+
void CBrain::SetSize(double size)
  {
   m_size=size;
  }
//+------------------------------------------------------------------+
//| SetStopLoss                                                      |
//+------------------------------------------------------------------+
void CBrain::SetStopLoss(int stopLoss)
  {
   m_stopLoss=stopLoss;
  }
//+------------------------------------------------------------------+
//| SetTakeProfit                                                    |
//+------------------------------------------------------------------+
void CBrain::SetTakeProfit(int takeProfit)
  {
   m_takeProfit=takeProfit;
  }
//+------------------------------------------------------------------+
//| GetRandomNumber                                                  |
//+------------------------------------------------------------------+
int CBrain::GetRandomNumber(int a,int b)
  {
   return(a+(MathRand()%(b-a+1)));
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//|                                               ExpertSimpleRandom |
//|                               Copyright © 2013, Jordi Bassagaсas |
//+------------------------------------------------------------------+
#include <Indicators\Indicators.mqh>
#include <Mine\Enums.mqh>
//+------------------------------------------------------------------+
//| CEvolution Class                                                 |
//+------------------------------------------------------------------+
class CEvolution
  {
protected:
   ENUM_STATUS_EA    m_status;            // The current EA's status
   CArrayObj*        m_operations;        // History of the operations performed by the EA

public:
   //--- Constructor and destructor methods
                     CEvolution(ENUM_STATUS_EA status);
                    ~CEvolution(void);
   //--- Getter methods
   ENUM_STATUS_EA    GetStatus(void);
   CArrayObj        *GetOperations(void);
   //--- Setter methods
   void              SetStatus(ENUM_STATUS_EA status);
   void              SetOperation(CObject *operation);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CEvolution::CEvolution(ENUM_STATUS_EA status)
  {
   m_status=status;
   m_operations=new CArrayObj;
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CEvolution::~CEvolution(void)
  {
   delete(m_operations);
  }
//+------------------------------------------------------------------+
//| GetStatus                                                        |
//+------------------------------------------------------------------+
ENUM_STATUS_EA CEvolution::GetStatus(void)
  {
   return m_status;
  }
//+------------------------------------------------------------------+
//| GetOperations                                                    |
//+------------------------------------------------------------------+
CArrayObj *CEvolution::GetOperations(void)
  {
   return m_operations;
  }
//+------------------------------------------------------------------+
//| SetStatus                                                        |
//+------------------------------------------------------------------+
void CEvolution::SetStatus(ENUM_STATUS_EA status)
  {
   m_status=status;
  }
//+------------------------------------------------------------------+
//| SetOperation                                                     |
//+------------------------------------------------------------------+
void CEvolution::SetOperation(CObject *operation)
  {
   m_operations.Add(operation);
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//|                                           ExpertSimpleRandom.mq5 |
//|                               Copyright © 2013, Jordi Bassagaсas |
//+------------------------------------------------------------------+
#include <Trade\SymbolInfo.mqh>
#include <Arrays\ArrayObj.mqh>
//+------------------------------------------------------------------+
//| CGrapic Class                                                    |
//+------------------------------------------------------------------+
class CGraphic
  {
protected:
   ENUM_TIMEFRAMES   m_period;            // Graphic's timeframe
   string            m_pair;              // Graphic's pair
   CSymbolInfo*      m_symbol;            // CSymbolInfo object
   CArrayObj*        m_bars;              // Array of bars

public:
   //--- Constructor and destructor methods
                     CGraphic(string pair);
                    ~CGraphic(void);
   //--- Getter methods
   string            GetPair(void);
   CSymbolInfo      *GetSymbol(void);
   CArrayObj        *GetBars(void);
   //--- Setter methods
   void              SetPair(string pair);
   void              SetSymbol(CSymbolInfo *symbol);
   void              SetBar(CObject *bar);
  };
//+------------------------------------------------------------------+
//| Constuctor                                                       |
//+------------------------------------------------------------------+
CGraphic::CGraphic(string pair)
  {
   m_period=PERIOD_M1;
   m_pair=pair;
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CGraphic::~CGraphic(void)
  {
  }
//+------------------------------------------------------------------+
//| GetPair                                                          |
//+------------------------------------------------------------------+
string CGraphic::GetPair(void)
  {
   return m_pair;
  }
//+------------------------------------------------------------------+
//| GetSymbol                                                        |
//+------------------------------------------------------------------+
CSymbolInfo *CGraphic::GetSymbol(void)
  {
   return m_symbol;
  }
//+------------------------------------------------------------------+
//| GetBars                                                          |
//+------------------------------------------------------------------+
CArrayObj *CGraphic::GetBars(void)
  {
   return m_bars;
  }
//+------------------------------------------------------------------+
//| SetPair                                                          |
//+------------------------------------------------------------------+
void CGraphic::SetPair(string pair)
  {
   m_pair=pair;
  }
//+------------------------------------------------------------------+
//| SetSymbol                                                        |
//+------------------------------------------------------------------+
void CGraphic::SetSymbol(CSymbolInfo *symbol)
  {
   m_symbol=symbol;
  }
//+------------------------------------------------------------------+
//| SetBar                                                           |
//+------------------------------------------------------------------+
void CGraphic::SetBar(CObject *bar)
  {
   m_bars.Add(bar);
  }
//+------------------------------------------------------------------+


3. Teste retrospectivo de ExpertSimpleRandom.mq5

Esse sistema de negociação aleatório demonstrou ser válido apenas para certos níveis de stop loss e take profit, como esperado. Claro, esses intervalos SL/TP vencedores não são os mesmos para todos os símbolos. Isso é porque todo símbolo mostra sua própria personalidade em um dado momento, ou de outra forma, todos os pares se movem diferentemente com respeito ao resto. Então por favor identifique primeiro esses níveis de teste retrospectivo antes de executar ExpertSimpleRandom.mq5 em um ambiente real.

Divido aqui alguns dados amostrais para os quais a ideia exposta nesse artigo parece ser certa. Isso pode ser deduzido após executar muitas vezes ExpertSimpleRandom.mq5 no verificador de estratégia do MetaTrader 5.

Algumas entradas vencedoras para EURUSD em Janeiro de 2012 são:

  • StopLoss: 400
  • TakeProfit: 600
  • Tamanho do lote: 0,01
  • TimeLife: MÊS

Corrida número 1:

EURUSD, Janeiro de 2012

Corrida número 2:

EURUSD, Janeiro de 2012

Corrida número 3:

EURUSD, Janeiro de 2012


Conclusão

Aprendemos a aplicar programação orientada a objeto em nossos sistemas de negociação automatizados. De forma a fazer isso primeiro tivemos que definir uma estratégia de negociação mecânica. Nossa ideia de negociação foi muito simples: "Tendências curtas de mercados voláteis estão próximas do aleatório". Isso foi observado por vários especialistas sob algumas circunstâncias.

Logo após pensamos em nosso CE em termos do mundo real como se ele fosse uma criatura viva. Graças a essa visão vimos que nossa máquina do Forex pode ser composta de três partes principais: um cérebro, algo que chamamos de evolução, e um gráfico.

E finalmente programamos o consultor especialista do sistema que incorpora a lógica necessária para executar o teste retrospectivo, executamos muitas vezes o robô em janeiro de 2012 e descobrimos que a maioria das vezes o sistema está vencendo. A ideia por trás desse sistema foi provada verdadeira mas sua efetividade não é muito alta devido a sua simplicidade.


Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/703

Arquivos anexados |
cbrain.mqh (5.64 KB)
cevolution.mqh (2.97 KB)
cgraphic.mqh (3.55 KB)
enums.mqh (0.92 KB)
csimplerandom.mqh (12.79 KB)
Criando EAs de rede neural usando o assistente do MQL5 e o gerador EA Hlaiman Criando EAs de rede neural usando o assistente do MQL5 e o gerador EA Hlaiman
O artigo descreve um método de criação automatizada de EAs de rede neural usando o assistente do MQL5 e o gerador EA Hlaiman. Ele mostra como você pode facilmente começar a trabalhar com redes neurais, sem ter que aprender todo o corpo de informações teóricas, e escrever o seu próprio código.
Como instalar e utilizar o OpenCL para realizar cálculos Como instalar e utilizar o OpenCL para realizar cálculos
Já se passou mais de um ano desde que o MQL5 começou a fornecer suporte nativo para OpenCL. Porém, não muitos usuários viram o verdadeiro valor do uso de uma computação paralela em seus Expert Advisors, indicadores e scripts. Este artigo tem o propósito de ajudá-lo a instalar e configurar OpenCL no seu computador de modo que pode tentar usar esta tecnologia no terminal de negócio do MetaTrader 5.
Construindo um negociante de notícias automático Construindo um negociante de notícias automático
Essa é a continuação do artigo Outra classe orientada a objeto do MQL5, que mostrou a você como construir um CE orientado a objeto simples do inicio e deu a você algumas dicas sobre programação orientada a objeto. Hoje vou mostrar a você o fundamental técnico necessário para desenvolver um EA capaz de negociar as notícias. Meu objetivo é continuar a dar ideias a você sobre OOP e também cobrir um novo tópico nesta série de artigos, trabalhando com o sistema de arquivo.
Rede em nuvem do MQL5: Você ainda está calculando? Rede em nuvem do MQL5: Você ainda está calculando?
Logo fará um ano e meio desde que a Rede em nuvem do MQL5 foi inaugurada. Esse evento inovador nos conduziu para uma era de negócios algorítmicos - agora com poucos cliques, negociadores podem ter centenas e milhares de núcleos de computação a sua disposição para a otimização de suas estratégias de negócios.