English Русский 中文 Español Deutsch 日本語
preview
Aprendendo a construindo um Expert Advisor que opera de forma automática (Parte 14): Automação (VI)

Aprendendo a construindo um Expert Advisor que opera de forma automática (Parte 14): Automação (VI)

MetaTrader 5Negociação | 8 fevereiro 2023, 10:00
1 044 1
Daniel Jose
Daniel Jose

Introdução

No artigo anterior, Aprendendo a construindo um EA que opera de forma automática (Parte 13): Automação (V), expliquei como você, mesmo sem ter conhecimento em programação, pode conseguir criar as bases necessárias, para poder tornar o EA, que estou mostrando nesta sequencia, em um EA automático. Mas todos estes conceitos e informações, se aplicam a qualquer EA, seja este, ou outro no qual você possa a vim a construir. Aqui estou apenas mostrando, uma entre tantas forma, de você fazer isto.

O correto e completo entendimento do conteúdo, presente no artigo anterior, é essencialmente importante, para que você consiga de fato entender, o que será criado aqui. Sem aquele conhecimento, o conteúdo deste artigo, se tornará confuso e de difícil compreensão. Então se você acabou de cair de paraquedas neste artigo, recomendo que leia o artigo anterior. Disto isto, vamos ao que interessa de fato. Como tornar um EA, incialmente manual, em um EA automático.


O nascimento da classe C_Automaton

No artigo anterior, foi mostrado a seguinte figura:

Figura 01

Figura 01 : Modo de funcionamento manual.

Esta figura, representa a forma como um operador, faz para interagir com a plataforma, a fim de conseguir, que o EA abra ou feche uma posição, no servidor de negociação. Pois bem, para automatizar isto, a fim de que o EA, consiga fazer isto sozinho, é preciso mudar algumas coisas nesta figura. Desta forma, a figura 01, que representa um modelo manual, passará a ser a figura 02. Esta já representa um EA, operando automaticamente, baseado em algum tipo de operacional, definido no momento de sua programação.

Figura 02

Figura 02: Modo de operação automatizada.

Observem que na figura 02, temos uma imagem de ser humano, como sendo um supervisor do sistema, isto é extremamente importante. Você nunca deve deixar de fato um sistema automático, operando sem nenhum tipo de supervisão, é imprescindível, que ele seja sempre supervisionado por um operador humano. Mesmo que este fique ali, apenas olhando, sem fazer absolutamente nada.

Nesta mesma figura, observem que entre o EA e a classe C_Manager, apareceu uma outra classe, a classe C_Automaton. Este artigo, irá basicamente tratar desta classe, e como ela se relaciona com o EA, e a classe C_Manager, a fim de que substitua o operador, no que tange abrir e fechar posições, ou enviar ordens pendentes para o book.

Notem mais uma vez, que não iremos fazer nenhuma modificação no sistema já presente, o mesmo já deverá estar funcionando de forma adequada, segura, robusta, estável e confiável, antes mesmo da criação da classe C_Automaton. Então se você modificar algo no sistema, que está sendo mostrado, remova a classe C_Automaton, volte com a classe C_Mouse, e passe a testar o sistema com as mudanças feitas. Somente depois, que ele de fato, estiver funcionando perfeitamente, você poderá colocar a classe C_Automaton, para que o EA funcione sem intervenção humana. Mas lembre-se sempre de que é preciso supervisão, a intervenção é em último caso, mas a supervisão deverá sempre acontecer.

Antes de vermos como é programada a classe C_Automaton, vamos dar uma rápida passada pelo código do EA, agora já modificado, para ser usado de forma automática. O código COMPLETO do EA, pode ser visto logo abaixo, na integra:

#property copyright "Daniel Jose"
#property description "This one is an automatic Expert Advisor"
#property description "for demonstration. To understand how to"
#property description "develop yours in order to use a particular"
#property description "operational, see the articles where there"
#property description "is an explanation of how to proceed."
#property version   "1.14"
#property link      "https://www.mql5.com/pt/articles/11318"
//+------------------------------------------------------------------+
#include <Generic Auto Trader\C_Automaton.mqh>
//+------------------------------------------------------------------+
C_Automaton *automaton;
//+------------------------------------------------------------------+
input int       user01   = 1;           //Leverage Factor
input double    user02   = 100;         //Take Profit ( FINANCE )
input double    user03   = 75;          //Stop Loss ( FINANCE )
input bool      user04   = true;        //Day Trade ?
input double    user08   = 35;          //BreakEven ( FINANCE )
//+------------------------------------------------------------------+
input string    user90  = "00:00 - 00:00";      //Sunday
input string    user91  = "09:05 - 17:35";      //Monday
input string    user92  = "10:05 - 16:50";      //Tuesday
input string    user93  = "09:45 - 13:38";      //Wednesday
input string    user94  = "11:07 - 15:00";      //Thursday
input string    user95  = "12:55 - 16:25";      //Friday
input string    user96  = "00:00 - 00:00";      //Saturday
//+------------------------------------------------------------------+
#define def_MAGIC_NUMBER 987654321
//+------------------------------------------------------------------+
int OnInit()
{
        string szInfo;
        
        automaton = new C_Automaton(def_MAGIC_NUMBER, user03, user02, user01, user04, user08, PERIOD_M5);
        for (ENUM_DAY_OF_WEEK c0 = SUNDAY; c0 <= SATURDAY; c0++)
        {
                switch (c0)
                {
                        case SUNDAY     : szInfo = user90; break;
                        case MONDAY     : szInfo = user91; break;
                        case TUESDAY    : szInfo = user92; break;
                        case WEDNESDAY  : szInfo = user93; break;
                        case THURSDAY   : szInfo = user94; break;
                        case FRIDAY     : szInfo = user95; break;
                        case SATURDAY   : szInfo = user96; break;
                }
                (*automaton).SetInfoCtrl(c0, szInfo);
        }
        (*automaton).CheckToleranceLevel();
        EventSetMillisecondTimer(100);

        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        delete automaton;
        EventKillTimer();
}
//+------------------------------------------------------------------+
void OnTick() { }
//+------------------------------------------------------------------+
void OnTimer()
{
        (*automaton).Triggers();
}
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans, const MqlTradeRequest &request, const MqlTradeResult &result)
{
        switch (trans.type)
        {
                case TRADE_TRANSACTION_POSITION:
                        (*automaton).UpdatePosition(trans.position);
                        break;
                case TRADE_TRANSACTION_ORDER_DELETE:
                        if (trans.order == trans.position) (*automaton).PendingToPosition();
                        else
                        {
                                (*automaton).UpdatePosition(trans.position);
                                (*automaton).EraseTicketPending(trans.order);
                        }
                        break;
                case TRADE_TRANSACTION_ORDER_UPDATE:
                        (*automaton).UpdatePending(trans.order);
                        break;
                case TRADE_TRANSACTION_REQUEST: if ((request.symbol == _Symbol) && (result.retcode == TRADE_RETCODE_DONE) && (request.magic == def_MAGIC_NUMBER)) switch (request.action)
                        {
                                case TRADE_ACTION_DEAL:
                                        (*automaton).UpdatePosition(request.order);
                                        break;
                                case TRADE_ACTION_SLTP:
                                        (*automaton).UpdatePosition(trans.position);
                                        break;
                                case TRADE_ACTION_REMOVE:
                                        (*automaton).EraseTicketPending(request.order);
                                        break;
                        }
                        break;
        }
}
//+------------------------------------------------------------------+

Notem que ele sofreu apenas alguma modificações, como a retirada do tratador de eventos OnChartEvent, que não é mais necessário, e surgiu uma nova função no evento OnTime. Esta será vista em mais detalhes um pouco mais a frente. No demais, o código permaneceu igual aos código anteriores, quando o EA era operado de forma manual. Isto é extremamente importante, o momento que for tornar um EA automático, e volto a repetir isto, não faça isto mudando o código do mesmo. Você deve apenas modificar, o que é extremamente necessário, e no caso foi apenas o fato, de que apareceu uma nova função no evento de tempo, fora isto, o código permaneceu idêntico.

Apesar de tudo, este código do EA, não é, vou repetir, NÃO É, um código definitivo e imutável. Dependendo do sistema que você for usar, pode haver mais ou menos coisa a serem definidas pelo usuário, e isto irá aparecer aqui, e pode haver variações no constructor da classe C_Automaton. Desta forma, podem ser necessários, mais ou menos parâmetros aqui. Então, não tomem este código, como sendo um código a ser utilizado em todos os casos.

Mas fora estes pontos que defini, ele basicamente irá se manter sem grandes mudanças. Então fica a dica, estude o que realmente será preciso, no sistema que irá ser usado. Deixe configurado as partes que não precisam ser ajustadas pelo operador, e permita, que ele ajuste apenas as partes realmente necessárias. Dependendo do tipo de cenário usado.

Uma outra coisa, você deve ter notado, que a classe C_Automaton, está herdando a classe C_Manager. Por conta disto, que o código praticamente não sofreu nenhuma mudança.

Então, como deve ter dado para notar, tudo se passará dentro da classe C_Automaton, de forma que se você desejar usar estas mesma estrutura de EA, e classes que estou demonstrando, bastará modificar a classe C_Automaton, de forma que o seu sistema operacional, seja desenvolvido dentro dela. Assim a confecção de novos EA, usando operacionais diferentes, será extremamente mais rápido, seguro e consistente, já que a única coisa que irá fazer a diferença, entre eles, é a própria classe C_Automaton. E no momento de criar a classe, isto usando o constructor, você pode informar algumas coisas particulares, do próprio sistema operacional. Desta forma o nível de flexibilidade, usabilidade, robustez e reutilização de software, será imensa.

E seus EA, terão sempre um bom nível de qualidade, exigidos por quem realmente irá utilizá-los. Mas de qualquer forma, você pode fazer algumas mudanças, a fim de deixar a coisa bem mais interessante. Talvez futuramente, eu venha a trazer a publico, algumas destas modificações. Mas de uma forma ou de outra, sinta-se a vontade em modificar, e adaptar o sistema ao seu modo de operar. Afinal de contas, é para isto que estou fazendo estes artigos, e permitindo o acesso livre ao código.

Meu único pedido, é que caso você faça qualquer uso, mesmo de apenas parte dele, diga a origem do conteúdo. Não é vergonhoso fazer tal coisa, mas é de péssima conduta, usar ou distribuir algo sem informar a fonte.

Então vamos olhar, o que tem dentro da caixa preta da classe, chamada C_Automaton.


Analisando o código da classe C_Automaton

Como foi dito acima, tanto o código do EA, quanto o código da classe C_Automaton, serão dependentes do que você irá operar, como irá operar, e quando irá operar. Mas independentemente disto, a classe C_Automaton, terá basicamente 3 funções internas: Um constructor, uma função que será chamada pelo evento de tempo do EA, e uma outra função interna e privativa da classe.

É importante você se atentar a isto, basicamente serão apenas, e somente estas 3 funções. Pode acontecer de por algum outro motivo, ser preciso mais ou menos funções para auxiliar estas 3, mas em essência teremos sempre estas 3.

Para não ficar apenas, e somente na teoria, veja no vídeo abaixo, sei que ele é bem longo, no ponto de vista de muitos. Mas quero que você saiba, que não importa qual seja o sistema a ser operado, todos e absolutamente todos, terão algum tipo de perda, seja maior ou menor, mas tentem ver o vídeo, para entender o que será explicado logo abaixo:


Video 01 : Demonstrando o EA automático ( Cerca de 25 minutos de gravação )

No vídeo, estou utilizando um sistema operacional, em que o EA faz uso da média móvel exponencial de 9, para gerar as entradas a cada inicio da uma nova barra. A forma de criar este sistema, foi visto no artigo anterior, então leia o artigo anterior para entender o processo por de traz do que será visto aqui. Mas para não deixar a coisa apenas na teoria, ou para que você, entusiasta, compreenda como a classe C_Automaton, consegue fazer com que o EA crie, gerencie, e finalize uma operação. Vamos ver alguns exemplos de código, de criação de setup, de forma que você, consiga compreender como desenvolver, e codificar o seu setup especifico.

Acompanhe a explicação, de cada um dos métodos, veja como ele foi desenvolvido e codificado. Assim você irá conseguir desenvolver praticamente qualquer setup, se bem que existem casos, bastante específicos, que será preciso um pouco mais de código. Mas já que eles são poucos, e a grande maioria de fato irá usar indicadores, estes daqui, já ajudaram bastante a confecção de seu modelo operacional, 100% automático. Antes de entrar no código em si, vamos ver alguns pequenos detalhes no sobre o código.


Partes comuns, partes dependentes

Para que você, não fique perdido na explicação do código da classe, quando os exemplos forem mostrados. Vamos primeiro, fazer uma diferenciação aqui.

O código da classe C_Automaton, é um código bem peculiar, mas para programadores experientes, é algo bastante comum, que é o fato de que existem partes comuns, em todo e qualquer operacional, e existem partes dependentes do operacional. É importante você se atentar a isto, quando for desenvolver a descrição do seu método, conforme mostrado no artigo anterior. Pois se você não entender, e perceber que existem coisas comuns, em todo e qualquer modelo, poderá achar que a classe C_Automaton, não conseguirá cobrir o seu modelo, quando na verdade, ela conseguirá de fato cobrir qualquer modelo. As vezes será necessário, adicionar uma ou outra variável, mas irei mostrar também como fazer isto, de forma que você poderá cobrir qualquer tipo de modelo.

As partes comuns do código, são as partes que sempre irão se repetir. Não importa qual modelo você esteja querendo utilizar, estas partes sempre se repetirão. Já as partes dependentes, são justamente as que torna o seu modelo único, não sendo assim partes, que irão se repetir em um outro modelo.

Vamos então, ver o código comum para qualquer modelo. Este pode ser visto logo abaixo:

#property copyright "Daniel Jose"
//+------------------------------------------------------------------+
#include "C_Manager.mqh"
//+------------------------------------------------------------------+
class C_Automaton : public C_Manager

{
        protected:
                enum eTrigger {TRIGGER_NONE, TRIGGER_BUY, TRIGGER_SELL};
        private :
                struct st00
                {
                        int     Shift,
                                nBars;
                        double  OverBought,
                                OverSold;
                }m_Infos;
                double  m_Buff[];
                int     m_nBars,
                        m_Handle;
                ENUM_TIMEFRAMES m_TF;
//+------------------------------------------------------------------+
static eTrigger m_Memory;
//+------------------------------------------------------------------+  
inline eTrigger CheckTrigger(void)
                        {
                               int iRet;

                               if (((iRet = iBars(NULL, m_TF)) > m_nBars) && (m_Handle != INVALID_HANDLE))
			       {
			       }

                               return TRIGGER_NONE;
                        }
//+------------------------------------------------------------------+  
        public  :
//+------------------------------------------------------------------+
                C_Automaton(const ulong magic, double FinanceStop, double FinanceTake, uint Leverage,
                                                bool IsDayTrade, double Trailing, const ENUM_TIMEFRAMES iPeriod,
                                                const double OverBought = 70, const double OverSold = 30, const int iShift = 1)
                        :C_Manager(magic, FinanceStop, FinanceTake, Leverage, IsDayTrade, Trailing, true, 10),
                         m_TF(iPeriod),
                         m_Handle(INVALID_HANDLE)
                        {
                                m_Infos.Shift      = iShift;
                                m_Infos.OverBought = OverBought;
                                m_Infos.OverSold   = OverSold;
                                ArraySetAsSeries(m_Buff, true);
                                m_nBars = iBars(NULL, m_TF);
                        }
//+------------------------------------------------------------------+
inline virtual void Triggers(void) final
                        {
                                if (!CtrlTimeIsPassed()) ClosePosition(); else switch (CheckTrigger())
                                {
                                        case TRIGGER_BUY:
                                                if (m_Memory == TRIGGER_SELL) ClosePosition();
                                                if (m_Memory != TRIGGER_BUY) ToMarket(ORDER_TYPE_BUY);
                                                m_Memory = TRIGGER_BUY;
                                                break;
                                        case TRIGGER_SELL:
                                                if (m_Memory == TRIGGER_BUY) ClosePosition();
                                                if (m_Memory != TRIGGER_SELL) ToMarket(ORDER_TYPE_SELL);
                                                m_Memory = TRIGGER_SELL;
                                                break;
                                }
                        };
//+------------------------------------------------------------------+  
};
//+------------------------------------------------------------------+
static C_Automaton::eTrigger C_Automaton::m_Memory = TRIGGER_NONE;
//+------------------------------------------------------------------+

Tudo, e absolutamente tudo, que você está vendo no código acima, faz parte do código comum, que estará presente em qualquer modelo. Não importa qual ele seja, este código sempre estará presente. É bem verdade, que pode aparecer uma ou outra variável nova, e uma ou outra chamada a classe C_Manager, como você verá nos códigos de exemplo. Mas essencialmente o código acima, irá se manter praticamente intacto.

Tudo que não estiver presente neste código acima, faz parte do código dependente do modelo, que você estará projetando. Então vamos dissecar o código acima, para que você entenda como ele funciona. Desta forma, você poderá entender o que adicionar, ou não ao código, de forma a cobrir um modelo mais especifico.

Vamos começar com a declaração da classe, esta pode ser melhor observada no fragmento abaixo:

#include "C_Manager.mqh"
//+------------------------------------------------------------------+
class C_Automaton : public C_Manager
{
        protected:
                enum eTrigger {TRIGGER_NONE, TRIGGER_BUY, TRIGGER_SELL};

Aqui declaramos que a classe C_Automaton, irá herdar de forma publica a classe C_Manager. Isto irá fazer, com que ao usar a classe C_Automaton, possamos ter acesso os procedimentos da classe C_Manager. Isto é importante para inicializar algumas coisas, pertinentes a classe de controle. Se você observar o código do EA, irá notar estes pontos, onde existem procedimentos, sendo acessados. Mesmo não estando declarados na classe C_Automaton, tais procedimentos, estão vindo de outras classes. Já expliquei sobre isto, em outro artigo desta sequencia.

Também criamos um enumerador, de forma que teremos uma programação em alto nível, a fim de trabalhar na classe. Esta enumeração, diz qual o tipo de gatilho foi acionado. Um detalhe: Apesar desta enumeração, esta sendo declarada na clausula protegida, de fato ela não será utilizada fora da classe. Mas foi necessário colocar ela nesta clausula, a fim de poder inicializar um variável estática da classe, mas isto será visto mais a frente.

A próxima coisa a ser vista, são as variáveis, estas podem ser observadas no fragmento abaixo:

        private :
                struct st00
                {
                        int     Shift,
                                nBars;
                        double  OverBought,
                                OverSold;
                }m_Infos;
                double  m_Buff[];
                int     m_nBars,
                        m_Handle;
                ENUM_TIMEFRAMES m_TF;
//+------------------------------------------------------------------+
static eTrigger m_Memory;

Aqui temos uma estrutura, na qual dificilmente, precisaremos fazer algum tipo de adição, já que ela consegue cobrir uma ampla gama de casos, envolvendo indicadores. Talvez seja necessário, adicionar mais estruturas, caso você esteja utilizando mais de um indicador, no seu modelo. Mas os elementos da estrutura, não precisarão ser modificados.

Para entender o que acabei de dizer, vamos exemplificar : a estrutura, é referenciada, por apenas uma única variável. Isto permite que usemos apenas 1 indicador, seja ele qual for. Mas e se precisarmos usar mais de 1 indicador ?!?! Como proceder ?!?! Neste caso, teríamos que adicionar algumas coisas aqui, estas mudanças serão vista nos exemplos. Mas por enquanto, vamos nos ater apenas no básico, e entender este sistema mais simples.

Também temos uma variável, que servirá de buffer, a fim de receber os valores do indicador. Uma para servir de memória do numero de barras no gráfico. Uma para poder referenciar o indicador. Uma outra para sabermos, qual o tempo gráfico a ser usado no indicador, e uma última, que neste caso, é uma variável estática, que armazena o último estado de disparo. Esta variável estática, é inicializada fora do corpo da classe, conforme mostrado o fragmento abaixo:

static C_Automaton::eTrigger C_Automaton::m_Memory = TRIGGER_NONE;

Note que ela deverá ser inicializada, com um disparo neutro, o motivo é que não foi feito nenhum tipo de consulta, ao sistema de disparo. Então não queremos, que um disparo acidental aconteça, apesar de que dependendo do modelo operacional, esta variável estática, não será tão útil, já que o próprio modelo, gera disparos sempre de forma cruzada. Mas para evitar que tenhamos disparos aleatórios, logo que o EA seja colocado no gráfico, usamos esta variável para assegurar que as coisas não serão aleatórias na inicialização, ou durante a mudança de mão.

O próximo ponto a ser visto, é a função privativa da classe. Esta pode ser vista no fragmento a seguir:

inline eTrigger CheckTrigger(void)
                        {
                                int iRet;
                                        
                                if (((iRet = iBars(NULL, m_TF)) > m_nBars) && (m_Handle != INVALID_HANDLE))
                                {
                                };
                                return TRIGGER_NONE;
                        }

Por padrão, esta função irá sempre retorna um disparo nulo, ou seja, não iremos comprar ou vender. Mas aqui nesta função, irá ser de fato feito, o cálculo envolvido no seu sistema operacional especifico, já que o cálculo é dependente do operacional. Você verá coisas diferentes aqui, nesta função.

Mas independente do tipo de cálculo a ser feito, iremos sempre testar o sistema da seguinte forma: O calculo somente será efetuado em uma nova barra, caso não tenhamos uma nova barra, o calculo será ignorado. Um outro ponto, é que o handle, deverá estar apontando para algo válido, caso contrário, também não será calculado nada. É importante definir estas regras de forma bastante clara, para evitar dores de cabeça, no momento que o EA estiver em execução.

A próxima função, é o constructor da classe. Este pode ser melhor observado no fragmento abaixo:

                C_Automaton(const ulong magic, double FinanceStop, double FinanceTake, uint Leverage,
                            bool IsDayTrade, double Trailing, const ENUM_TIMEFRAMES iPeriod,
                            const double OverBought = 70, const double OverSold = 30, const int iShift = 1)
                        :C_Manager(magic, FinanceStop, FinanceTake, Leverage, IsDayTrade, Trailing, true, 10),
                         m_TF(iPeriod),
                         m_Handle(INVALID_HANDLE)
                        {
                                m_Infos.Shift      = iShift;
                                m_Infos.OverBought = OverBought;
                                m_Infos.OverSold   = OverSold;
                                ArraySetAsSeries(m_Buff, true);
                                m_nBars = iBars(NULL, m_TF);
                        }

É extremamente importante, que você entenda de fato este constructor, sei que o seu código parece muito confuso, e de difícil compreensão, para que não tem costume com programação, ou está iniciando na área. Mas entender este código, é de suma importância, para que você consiga tirar proveito da classe C_Automaton, a fim de tornar o seu EA 100% automático. Então vamos começar, entendendo o que esta aparente confusão de texto, está de fato fazendo.

Como a classe C_Automaton, está herdando a classe C_Manager, ela precisa inicializar o constructor de C_Manager. Por conta disto, ela estará recebendo dados do EA, estes são repassados integralmente para a classe C_Manager, a fim de que ela seja inicializada.

Mas notem que existem 2 parâmetros extras aqui. Estes se você desejar, pode fazer com que sejam repassados pelo EA, mas de uma forma ou de outra, eles podem vim a ser dependentes do tipo de operacional, que estará sendo criado aqui na classe C_Automaton. Prefiro indicar aqui tais parâmetros, para entender o que estes parâmetros estão dizendo, observe a classe C_Manager. Lá ficará mais claro qual valor usar aqui, o código descrevendo o constructor da classe, pode ser visto em artigos anteriores. Então não irei repetir a explicação aqui novamente.

O EA também irá informar qual deverá ser o período gráfico, a ser usado pela classe C_Automaton, para isto usaremos este parâmetro.

É importante que o sistema de automação, funcione sempre em um tempo gráfico, independente do que está sendo observado, pelo supervisor. Se você usar o mesmo tempo gráfico, que está sendo observado pelo supervisor, aqui na classe de automação, poderá fazer com que o EA, dispare acidentalmente em momentos inadequados. Este é um erro muito comum em alguns EA, onde o programador não tem a devida noção, de que o usuário pode vim a mudar o tempo do gráfico, durante o período que o EA está em funcionamento. O que causa imensos transtornos, mas fazendo assim, garantimos que o EA irá sempre observar o mesmo tempo gráfico, independente do que estará sendo observado pelo operador supervisor.

Neste ponto, temos alguns parâmetros, que contem valores default. Por conta disto, eles podem ou não, esta sendo declarados no código do EA.

O fato de usar valores default, não impede que no código do EA, você indique algum valor diferente, ou mesmo que permita, que o operador quando for colocar o EA em funcionamento, defina tais valores. Mas já que em grande maioria dos casos, estes valores, praticamente irão se manter, e em outros casos, se quer iremos de fato usá-los. Então para evitar sobrecarregar o constructor, defino estes parâmetros com algum valor default, assim torno o código mais compacto, ao mesmo tempo que mais simples de ser analisado e compreendido. Notem que tais valores, são armazenados aqui, na nossa estrutura interna, a fim de que possam ser utilizados depois.

Um detalhe importante: Caso você use um sistema, que estes valores, poderão se modificados pelo operador. Mas irão depender do tipo de indicador usado, este código poderá sofre mudanças, a fim de comportar mais variáveis. Aqui no caso, ele é adequado para ser usado em um único indicador, ou vários, caso todos utilizem os mesmos dados indicados.

E por último, inicializamos o valor do handle, para que ele não aponte para nenhum indicador. Isto é importante, para evitar quebra da segurança, caso tenhamos o handle, apontando para algo desconhecido, e ajustamos as últimas variáveis do sistema. Este constructor é o básico, do básico, ele irá receber mais algumas linhas de código, dependendo do tipo de sistema que será implementado. Mas isto será visto nos código de exemplo.

E para terminar o código base, da classe C_Automaton. Vamos ver o último fragmento, logo abaixo:

inline virtual void Triggers(void) final
                        {
                                if (!CtrlTimeIsPassed()) ClosePosition(); else switch (CheckTrigger())
                                {
                                        case TRIGGER_BUY:
                                                if (m_Memory == TRIGGER_SELL) ClosePosition();
                                                if (m_Memory != TRIGGER_BUY) ToMarket(ORDER_TYPE_BUY);
                                                m_Memory = TRIGGER_BUY;
                                                break;
                                        case TRIGGER_SELL:
                                                if (m_Memory == TRIGGER_BUY) ClosePosition();
                                                if (m_Memory != TRIGGER_SELL) ToMarket(ORDER_TYPE_SELL);
                                                m_Memory = TRIGGER_SELL;
                                                break;
                                }
                        };

Este procedimento acima, não é um código 100% terminado, ele pode sofrer algumas pequenas mudanças, dependo do sistema operacional que será implementado. Mas basicamente, ele mostra o que irá acontecer durante cada chamada, vinda do evento OnTime, onde ele deverá estar, muitos irão querer colocar ele no evento OnTick. Mas em artigos anteriores, já expliquei o motivo de não fazer isto, leia os mesmos para entender os motivos.

Mas basicamente, este código diz a classe C_Manager, para trabalhar sempre com requerimentos a mercado. Por isto digo, que este código, não está 100% terminado, já que dependendo do modelo que você estará implantando, o sistema de ordens, pode ser diferente, ou mesmo a forma como a mudança de mão irá acontecer, fará este código ficar diferente.

Uma outra coisa sobre este código acima, ele não permite ao EA, ir aumentando a mão, conforme novos sinais vão surgindo. Isto por conta do fato de estarmos usando uma variável de memória.

Ela impede que o EA, aumente a mão, caso um novo sinal de entrada venha a surgir. Mas quem de fato compreende, um pouco de programação, irá conseguir contornar este bloqueio, que adicionei propositalmente. Já que, se você não tem a mínima ideia, do que está sendo programado, não irá de forma alguma, conseguir contornar este bloqueio. Mas se tentar fazer isto, sem o devido conhecimento, irá com toda a certeza, ter sérios prejuízos em sua conta, já que o EA, poderá vim a disparar ordens, feito um maluco insano, querendo acabar com todo o dinheiro disponível na conta do usuário, e isto em poucos segundos, não será uma questão de se ... mas sim, uma questão de quando. Então não mude este código, se não souber exatamente, o que esta fazendo.

Por este motivo, não irei me aprofundar muito na explicação deste código. Mas existe algo, que quero dar uma pincelada, antes de partirmos para os código de exemplo. É o fato da declaração deste procedimento, esta declaração, a primeira vista, parece ser tão estranha, e sem sentido, que mal dá para de fato compreender, por que de ela ter sido feita assim.

Vamos então entender o motivo, da declaração ter sido feita desta forma. Todo o sistema, foi pensado de uma maneira, a se utilizar um sistema de classes, isto além de tornar o código mais confiável, seguro e robusto, nos permite fazer, com que ele vá se expandindo com o tempo, se tornando algo absolutamente, muito mais complexo, do que foi inicialmente projetado. Mas este aumento na complexidade, não vem aliado a um considerável aumento no código, o sistema de classes, nos permite tornar a coisa bem mais modular, reduzindo assim, este aumento do código, enquanto o aumento da complexidade vai se dando.

Já que esta classe C_Automaton, não é de fato uma classe final, em um sistema mais amplo, fazendo a declaração do procedimento, da forma como se encontra. Dizemos ao compilador, para nos ajudar a assegurar, que este procedimento especifico, não será de forma alguma, modificado em uma outra classe, nos assegurando assim, de que ele será único, em todo o sistema de classe herdado.

Este tipo de coisa, é muito importante quando se lida com código, extremamente modulares, e muito bem estruturados. Pois, por mais que você os estruture, mais hora ou menos hora, você acaba por cometer o erro, de sobrescrever um procedimento herdado. Se isto acontece, sem que percebamos, e muitas vezes acontece, iremos por todo o nosso código em risco. Mas felizmente, a linguagem MLQ5, nos dá o recurso, que precisamos a fim de evitar este tipo de problema.

Para que você de fato compreenda, como esta classe C_Automaton, pode vim a lhe ajudar a automatizar o EA, que está sendo demonstrado. Vamos ver alguns exemplos de código, onde iremos forcar, agora a explicação, a respeito do como implementar o sistema operacional. Antes de começarmos, vamos a algumas explicações:

  • Nenhum sistema operacional, automático é 100% seguro;
  • Não existe, de forma alguma um sistema, que garanta lucro em uma operação;
  • Não se iluda, ao ver o sistema funcionando no primeiro momento, isto pode ser visto no video 01;
  • Somente opere, ou automatize, um sistema que você já conhece, não tente usar uma salada de frutas, imaginando que irá dar melhores resultados, simplicidade é tudo;
  • Use os modelo aqui mostrados, por sua conta e risco, sabendo que eles podem gerar lucro, mas também prejuízo.

Para que o entendimento seja o melhor possível de como promover o código. Cada um dos modelos, terá um EA exclusivo para eles, assim você poderá comparar os código e aprender com eles.


Conclusão

Mas como o assunto é bastante extenso, e isto apenas para mostrar 3 exemplos de automação, os códigos serão vistos no próximo artigo, que será muito provavelmente, o último e derradeiro artigo desta sequencia. Então não perca o próximo artigo desta sequencia. Pois ali, realmente iremos ver como tudo isto se encaixa de maneira harmônica, a fim de fazer com que o EA pareça vivo, operando de forma totalmente automática, e seguindo um modelo que você irá definir.


Últimos Comentários | Ir para discussão (1)
1226820
1226820 | 12 fev 2023 em 16:25
parabéns pelo excelente conteúdo.
DoEasy. Controles (Parte 25): Objeto WinForms Tooltip DoEasy. Controles (Parte 25): Objeto WinForms Tooltip
Neste artigo, começaremos a desenvolver o controle Tooltip (dica de ferramenta) e começaremos a criar novas primitivas gráficas para a biblioteca. Naturalmente, nem todo elemento tem uma dica de ferramenta, mas todo objeto gráfico pode ter uma.
Ciência de dados e Aprendizado de Máquina (parte 09): O algoritmo K-vizinhos mais próximos (KNN) Ciência de dados e Aprendizado de Máquina (parte 09): O algoritmo K-vizinhos mais próximos (KNN)
Este é um algoritmo preguiçoso que não aprende com o conjunto de dados de treinamento, ele armazena o conjunto de dados e age imediatamente quando ele recebe uma nova amostra. Por mais simples que ele seja, ele é usado em uma variedade de aplicações do mundo real
Funcionalidades do assistente MQL5 que você precisa conhecer (Parte 04): Análise discriminante linear Funcionalidades do assistente MQL5 que você precisa conhecer (Parte 04): Análise discriminante linear
O trader moderno está quase sempre à procura de novas ideias. Para isso, tenta novas estratégias, modifica e descarta aquelas que não funcionam. Nesta série de artigos, tentarei provar que o assistente MQL5 é a verdadeira espinha dorsal de um trader moderno.
Ciência de Dados e Aprendizado de Máquina (Parte 08): Agrupamento K-Means em MQL5 Ciência de Dados e Aprendizado de Máquina (Parte 08): Agrupamento K-Means em MQL5
A mineração de dados é crucial para um cientista de dados e um trader porque, muitas vezes, os dados não são tão diretos quanto pensamos, o olho humano não consegue entender o padrão subjacente menor e as relações no conjunto de dados, talvez o algoritmo K-means pode nos ajudar com isso. Vamos descobrir...