English Русский 中文 Español Deutsch 日本語
Abordagem do objeto no MQL

Abordagem do objeto no MQL

MetaTrader 4Sistemas de negociação | 22 fevereiro 2016, 14:33
985 0
---
---

Introdução

Este artigo vai ser interessante, em primeiro lugar, para programadores novatos e profissionais que trabalham no ambiente MQL. Também seria útil se este artigo fosse lido por desenvolvedores e ideólogos do ambiente MQL pois as questões aqui analisadas podem tornar-se projetos para uma futura implementação do MetaTrader e da MQL. Ideias parecidas podem ser encontradas nos artigos Modelo Universal de Expert Advisor e Envio de sinais de trading em um Expert advisor Universal.

Então,

Uma das desvantagens da MQL, na minha opinião de programador, é a ausência de objecto de abordagem na construção do modelo do sistema de trading. Os desenvolvedores da MQL nos oferecem duas saídas: utilizar a chamada de funções externas ou utilizar o parâmetro MAGIA para identificação da ordem pertencente.

Na verdade, se apenas um sistema opera em uma conta, nós não precisamos de identificação. Mas quando temos a opção do programa de anexar a uma conta vários sistemas de trading automatizados, então não podemos fazer isto sem MAGIA. Mesmo ao chamar funções externas, é preciso determiná-las. Claro que podemos construir uma matriz OrderTicket e identificar a matriz pertencente a um único sistema de trading, mas como sabemos, em algumas corretoras a ordem de crédito alterar a troca (na verdade, uma é fechada, a outra é aberta). É por isso que não podemos fazer isto sem utilizar MAGIA.

Assim, enquanto os desenvolvedores estão ocupados melhorando a linguagem MQL e tornando-a mais flexível, vamos tentar implementar já agora a abordagem do objeto na construção de um modelo de trading.

Este é um sistema de trading de acordo com o meu modelo de objeto. Claro, ele não é universal, mas até agora eu não vi outras abordagens.


Então, vamos analisar este modelo.

A) Sistema do sinal (SS).

Objeto deste processo de módulo e interpretação de cotações recebidas. Normalmente, o "objeto" do sistema de sinal é um conjunto de indicadores, por exemplo, de médias móveis. Como resultado do processamento dos valores de cotações e indicadores, "o objeto" (ou semáforo) produz sinais de entrada/saída ou modificação de ordens.

O semáforo forma seu sinal e o envia para outro objeto do módulo de entrada/saída (EE).

Definir o semáforo em MQL é bastante fácil.

1. Defina um identificador global usando #define.

É melhor definir números não consecutivos como 1, 2, 3, 4 ..., mas em 5-10, de modo que em um Expert Advisor poderíamos utilizar um sinal para vários processos (ver o segundo módulo).

//+------------------------------------------------------------------+
//|                                                      Signals.mqh |
//|                                    Copyright © 2007 Сергеев Алексей |
//|                                                los@we.kherson.ua |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, Сергеев Алексей "
#property link      "mailto: los@we.kherson.ua"
#property library
 
#define BLACKSYS   10
#define BORCHAN    20
#define ELDER      80
#define ENVELOP    90

2. Em seguida, na função global deste módulo devemos habilitar seu processador.

int CheckSignal(bool bEntry, int SignalID)
{
      switch (SignalID)
      {
                  case BLACKSYS:             return (BlackSys(bEntry)); break;
                  case BORCHAN:              return (BorChan(bEntry)); break;
                  case ELDER:                   return (Elder(bEntry)); break;
                  case ENVELOP:              return (Envelop(bEntry)); break;
                  default:                                     return (-1);
      }
}

3. E a última etapa é a descrição das funções.

Aqui está um exemplo para sinais de processamento de um objeto que herda as características do indicador Envelope.

int Envelope(bool bEntry)
{
      int MA=21;
      double Deviation=0.6;
      int Mode=MODE_SMA;//0-sma, 1-ema, 2-smma, 3-lwma
      int Price=PRICE_CLOSE;//0-close, 1-open, 2-high, 3-low, 4-median, 5-typic, 6-wieight
      
      double envH0, envL0, m0;
      double envH1, envL1, m1;
      envH0=iEnvelopes(NULL, 0, MA, Mode, 0, Price, Deviation, MODE_UPPER, 0); 
      envL0=iEnvelopes(NULL, 0, MA, Mode, 0, Price, Deviation, MODE_LOWER, 0); 
      envH1=iEnvelopes(NULL, 0, MA, Mode, 0, Price, Deviation, MODE_UPPER, 1); 
      envL1=iEnvelopes(NULL, 0, MA, Mode, 0, Price, Deviation, MODE_LOWER, 1); 
 
      m0 = (Low[0]+High[0])/2;          m1 = (Low[1]+High[1])/2;
      //----- condition for operation execution
      if (bEntry)   //for opening
      {          
                  if (envH0<m0 && envH1<m1) return (OP_SELL);
                  if (envL0>m0 && envL1>m1) return (OP_BUY);
      }
      else //for closing
      {
                  if (envH0<m0 && envH1<m1) return (OP_BUY);
                  if (envL0>m0 && envL1>m1) return (OP_SELL);
      }
 
   return (-1); //no signal
}

Assim, temos um módulo que irá conter diferentes sinais-objetos.


B) Objetos do bloco EE têm tarefas mínimas:
Em primeiro lugar, seus objetos interagem com sinais-objetos - observe-os. O ciclo de vida e a interação é a seguinte:
Verificação do semáforo -> se existirem sinais positivos, abrir/fechar/ modificar posições -> Passe o controle para os objetos no módulo PS.
Todos os objetos no módulo EE ter um processo de prefixo ..., que determina seu comportamento mais especificamente.

Por exemplo:

ProcessAvgLim         //  -  the object processes signals with opening pending limit-orders and positions averaging
ProcessTurn           //  -  the object processes signals with position turning

Cada amostra de uma classe de sistema de trading (todos nós entendemos isso e utilizamos em nossos módulos) deve ter suas próprias características individuais, tais como lucro, stop-loss, sua própria gestão financeira, bem como outros parâmetros adicionais implementados em diferentes variantes de rastreamento etc.

Ao implementar esses recursos, tentei várias variantes da abordagem e a mais adequada em MQL, na minha opinião, é a criação de uma matriz bidimensional. Aqui está a descrição:

double SysPar[nSignal][11];
 
#define _TP        0 // Profit
#define _NullTP    1 // profit level, after which we set into losslessness 
#define _NullTP2   2 // profit level, after which we set into losslessness 
#define _TS        3 // distance of the trailing stop 
#define _NullSL    4 // level, after achieving which the expected profit is transfered into opening point
#define _SL        5 // level, after achieving which the expected profit is transfered into opening point
#define _dSL       6 // the initial step upon the opening level of the next order in the position support
#define _dStep     7 // The step is increased in .. times upon the level of the next opening 
#define _dLot      8 // In how many times (as compared to the last one) we increase the lot on the next one 
#define _nLot      9 // In how many times (as compared to the initial one) we increase the lot on the next one
 
string SysParName[nSignal];

onde nSignal é o identificador dos sinais-objeto.

Por exemplo:

SysPar[ENVELOP][_TS] = 40.0;    // distance of the trailing stop 
SysPar[ENVELOP][_NullSL] = 20.0;// level, after achieving which the expected profit is transfered into opening point
SysPar[ENVELOP][_SL] = 70;      // changing stop-loss

Se desejar, você pode aumentar o número de parâmetros definidos desta estrutura de matriz.

Então, depois de definir os parâmetros, chamamos a função de processamento do semáforo. Em outras palavras: nós interagimos com o sinal do sistema. Isto é feito na minha função favorita start()

void start()
{
      ProcessAvgLim(ENVELOP, ENVELOP, Green, Red);
… …

Como se vê no esquema, no sistema de trading temos 4 semáforos registrados e 3 observadores. Cada semáforo é baseado em sua própria variante da interpretação das cotações.

Por exemplo, o Semáforo 1 envia sinais analisando o indicador MACD. O Observador 1 , por sua vez, após receber estes sinais, abre ordens em um simples esquema ProcessSimple.

Os observadores 2 e 3 são mais difíceis. Cada um controla sinais de dois semáforos. E, consequentemente, a abordagem para a ordem de abertura é diferente.

Então, depois de definir os parâmetros do observador e anexar um semáforo para isso, precisamos controlar e rastrear as posições de abertura.

Os objetos do módulo Suporte de Posição (PS) são "responsáveis" pelo estado das ordens abertas.


C) OBloco PS , na minha opinião, é o mais interessante e não menos importante que os semáforos.

Aqui diferentes variantes de rastreamento são implementadas: as ordens pendentes são abertas, suporte de posição e bloqueio, controle de lucro e perda e assim por diante. Tal PS deve reagir adequadamente aos sinais EE sobre sair do mercado em caso de perda de posições com perdas mínimas.

Neste site há uma biblioteca interessante de rastreamento Library of Functions and Expert Advisors for trailing / Yury Dzyuban. Todos os tipos de rastreamento são facilmente anexados no sistema.

Para uma percepção mais fácil, todos os objetos de suporte iniciam do prefixo rastreamento...

Ele possui o seguinte esquema:


A chamada da transferência de controle a partir de um observador para o rastreamento é feita na mesma função Start()

void start()
{
      ProcessSimple(MACD, MACD, Black, Plum); TrailingSimple(MACD, Black, Plum);
      ProcessAvgLim(ENVELOPE, ENVELOPE, Green, Red);  TrailingAvgLim(ENVELOPE, Green, Red);
}

Portanto, este foi uma variante de exemplo da abordagem do objeto para a construção do sistema. Aqueles que quiserem, podem usá-la.

E mais uma vez eu gostaria de pedir aos desenvolvedores da MQL para aumentarem as opções da linguagem. E como exemplo, aqui está uma variante de implementação de classes de objetos escrita na linguagem C++.

struct SystemParam
{
    double TP;        // profit
    double NullTP;    // profit level, after which we set into losslessness 
    double NullTP2;   // profit level, after which we set into losslessness a set of one-direction orders
    double TS;        // distance of the trailing stop 
    double NullSL;    // loss level, at which we transfer the expected profit into losslessness
    double SL;        // stop-loss
    double dSL;       // a step upon the opening level of the next order for the position support
    double dStep;     // In how many times we increase the step upon the opening level of the next order
    double dLot;      // In how many times we increase the lot on the next order
}
 
 
class MTS 
{
    public:
    string m_NameTS;    // system name (for making comments for the order)
    int m_SignalID;     // identifier of trading signals (for semaphore inquiry)
 
    long int Tickets[1000];    // array of order tickets, selected upon m_SignalID (MAGIC)
 
    SystemParam SysPar;    // Trading system parameters
    color ClrBuy;         // color for indicating BUY order
    color ClrSell;        // color for indicating SELL order
 
    // Initialization
    void MyMTS ();            // standard function that sets initial values of the system
    void MyMTS (int aSignalID, int nProcessMode, int nTrailingMode); // standard function 
                                    // that sets initial values of the system
    
    
    // Implementation
    int CheckSignal();     //function of checking state of market signals
 
    // Processing
    int m_nProcessMode;          // identifier of observation mode
    int m_nTrailingMode;         // identifier of trailing mode
    void Process();         // EE function - processing CheckSignal()
    void Trailing();        // PS function - order trailing
 
    // Special functions
    bool CreatTicketArray(int dir);    // creating an array of tickets, selected upon m_SignalID (MAGIC) 
                    // and desired type dir: buy, sell, buylim, buystop, sellim, sellstop
    bool ArrangeOrderBy(int iSort);  // arranging array Tickets upon the parameter (date, profit, price...)
 
};
 
…
 
MTS MyTS; // our trading systemint init()  
{   
…
    MyTS.m_SignalID = SIGNAL_MACD; // our system is based on MACD signals
    MyTS.m_NameTS = "MACD";
    MyTS.SysPar.TP = 500;    
    MyTS.SysPar.NullTP = 20;
    MyTS.SysPar.TS = 50;
    MyTS.SysPar.SL = 1000;
 
    MyTS.SetProcess (MODE_AVGLIM);
    MyTS.SetTrailing (MODE_AVGLIM);
…
}
 
void start()
{
…
    MyTS.Process ();        
    MyTS.Trailing ();
…
}
 
…
 
void MTS::Process()
{
…
    int Signal = CheckSignal(true, m_SignalID); //calling the global function of signal processing
    if (Signal == -1) return; // if no signal, do nothing
    
//----- for buying
    if(Signal == OP_BUY)
    {    
    }
 
    if(Signal == OP_SELL)
    {    
    }
…
}
 
…
// global processor of semaphores
 
int CheckSignal(bool bEntry, int SignalID)
{
    switch (SignalID)
    {
        case ELDER:    return (Elder(bEntry)); break;
        case ENVELOP:    return (Envelop(bEntry)); break;
        case LAGUER:    return (Laguer(bEntry)); break;
        case MACD:    return (Macd(bEntry)); break;
        …
    }
}
 
// calling a certain semaphore
int Macd(bool bEntry)
{
    double MACDOpen=3;
    double MACDClose=2;
    double MA=26;
    int MODE_MA    = MODE_EMA; // method of the calculation of averages
    int PRICE_MA   = PRICE_CLOSE; // method of the calculation of averages
    int PERIOD     = PERIOD_H1; // the period to work with
 
    //parameters of averages
    double MacdCur, MacdPre, SignalCur;
    double SignalPre, MaCur, MaPre;
 
    //---- get the value
    MacdCur=iMACD(NULL,0,8,17,9,PRICE_MA,MODE_MAIN,0);   MacdPre=iMACD(NULL,0,8,17,9,PRICE_MA,MODE_MAIN,1);
    SignalCur=iMACD(NULL,0,8,17,9,PRICE_MA,MODE_SIGNAL,0);   SignalPre=iMACD(NULL,0,8,17,9,PRICE_MA,MODE_SIGNAL,1);
    MaCur=iMA(NULL,0,MA,0,MODE_MA,PRICE_MA,0);   MaPre=iMA(NULL,0,MA,0,MODE_MA,PRICE_MA,1);
 
    //----- condition for the operation execution
    if (bEntry)   //for buying bEntry==true
    {     
        if(MacdCur<0 && MacdCur>SignalCur && MacdPre<SignalPre && MathAbs(MacdCur)>(MACDOpen*Point) && MaCur>MaPre) 
         return (OP_BUY);
        if(MacdCur>0 && MacdCur<SignalCur && MacdPre>SignalPre && MacdCur>(MACDOpen*Point) && MaCur<MaPre) 
         return (OP_SELL);
    }
    else //for closing bEntry==false
    {    
        if(MacdCur>0 && MacdCur<SignalCur && MacdPre>SignalPre && MacdCur>(MACDClose*Point)) 
         return (OP_BUY);
        if(MacdCur>0 && MacdCur<SignalCur && MacdPre>SignalPre && MacdCur>(MACDOpen*Point) && MaCur<MaPre) 
         return (OP_BUY);
 
        if(MacdCur<0 && MacdCur>SignalCur && MacdPre<SignalPre && MathAbs(MacdCur)>(MACDClose*Point))  
         return (OP_SELL);
        if(MacdCur<0 && MacdCur>SignalCur && MacdPre<SignalPre && MathAbs(MacdCur)>(MACDOpen*Point) && MaCur>MaPre) 
         return (OP_SELL);
    }
 
    return (-1); //no signal
}

A lógica do sistema no idioma MQL não será muito diferente. Todas as funções se tornam globais. E para diferenciar as ordens de um sistema de trading das ordens de outro, teremos de adicionar o parâmetro SignalID (isto é, MAGIA) em todas as funções que trabalham com ordens.


Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/1499

Arquivos anexados |
Signals.mqh (30.61 KB)
TradeSystem.mq4 (17.78 KB)
Traling.mqh (21.5 KB)
Linguagem MQL4 para Iniciantes. Indicadores personalizados (Parte 1) Linguagem MQL4 para Iniciantes. Indicadores personalizados (Parte 1)
Este é o quarto artigo da série "Linguagem MQL4 para Iniciantes". Hoje aprenderemos a escrever indicadores personalizados. Iremos nos familiarizar com a classificação das características indicadoras, veremos como essas características influenciam o indicador, aprenderemos sobre novas funções e otimização, e, finalmente, escreveremos nossos próprios indicadores. Além disso, no final do artigo você vai encontrará dicas sobre o estilo de programação. Se este é o primeiro artigo "para iniciantes" que você está lendo, talvez seja melhor você ler os anteriores. Além disso, certifique-se que você tenha entendido corretamente o material anterior pois este artigo não explica o básico.
Como implementar seus próprios critérios de otimização Como implementar seus próprios critérios de otimização
Neste artigo um exemplo de otimização com critérios de lucro/levantamento de crédito com resultados retornados em um arquivo é desenvolvido para um Expert Advisor Padrão - Média Móvel.
Indicador Taichi - uma ideia simples de formalizar os valores do Ichimoku Kinko Hyo Indicador Taichi - uma ideia simples de formalizar os valores do Ichimoku Kinko Hyo
Dificuldades para interpretar os sinais Ichimoku? Este artigo apresenta alguns princípios de formalização de valores e sinais de Ichimoku Kinko Hyo. Para visualização de seu uso o autor escolheu o par de moedas EURUSD com base em suas próprias preferências. No entanto, o indicador pode ser usado em qualquer par de moedas.
Linguagem MQL4 para Iniciantes. Indicadores técnicos e funções integradas Linguagem MQL4 para Iniciantes. Indicadores técnicos e funções integradas
Este é o terceiro artigo da série "Linguagem MQL4 para Iniciantes". Agora, vamos aprender a utilizar funções integradas e funções para trabalhar com indicadores técnicos. Estes últimas serão essenciais para o desenvolvimento futuro de seus próprios Advisors e indicadores. Além disso, veremos em um exemplo simples, como rastrear sinais de trading para entrar no mercado, assim, você entenderá como usar indicadores corretamente. E no final do artigo você aprenderá algo novo e interessante sobre a própria linguagem.