English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
O exemplo simples da criação de um indicador utilizando a lógica Fuzzy

O exemplo simples da criação de um indicador utilizando a lógica Fuzzy

MetaTrader 5Negociação | 6 fevereiro 2014, 16:32
2 894 0
Максим Востров
Максим Востров

Introdução

O uso de vários métodos para análise de mercados financeiros torna-se cada vez mais popular entre os negociantes nos anos recentes. Gostaria de dar minha contribuição e mostrar como fazer um bom indicador escrevendo uma dúzia de linhas de código. Além disso, revelarei de forma breve o básico sobre a lógica Fuzzy.

Qualquer pessoa interessada neste assunto e que queira explorá-lo mais profundamente poderá ler os seguintes trabalhos:

1. Leonenkov А. "Fuzzy Simulation in MATLAB and fuzzyTECH (Simulação Fuzzy em MATLAB e fuzzyTECH)" (em russo).
2. Bocharnikov V."Fuzzy Technology: Mathematical Background. Simulation Practice in Economics" (Tecnologia Fuzzy: Background matemático. Prática de simulação em economia) (em Russo).
3. S.N. Sivanandam, S. Sumathi, S.N. Deepa. Introduction to Fuzzy Logic using MATLAB. (Introdução à lógica Fuzzy utilizando o MATLAB.
4. C. Kahraman. Fuzzy Engineering Economics with Applications (Studies in Fuzziness and Soft Computing). (Economia de engenharia Fuzzy com aplicações (Estudos sobre Imprecisão e Soft Computing)).


1. Básico sobre a lógica Fuzzy

Como podemos explicar aos nossos computadores os significados de expressões tão simples como "...um pouco mais...", "...muito rápido...", "...quase nada..."? Na realidade, é bastante possível utilizar os elementos da teoria de conjuntos fuzzy, ou melhor, as chamadas "funções de pertinência". Eis um exemplo do livro de A. Leonenkov:

Vamos descrever a função de pertinência para a frase "café quente": a temperatura do café deve ser considerada estar em uma faixa de 0 a 100 graus Celsius pelo simples motivo de que temperaturas abaixo de 0 graus o congelaria, enquanto temperaturas acima de 100 graus o faria evaporar. é bastante óbvio que uma xícara de café com uma temperatura de 20 graus não pode ser considerada quente, ou seja, a função de pertinência na categoria "quente" é igual a 0, enquanto uma xícara de café com uma temperatura de 70 graus definitivamente pertence à categoria "quente" e, consequentemente, o valor da função é igual a 1 neste caso.

Para os valores de temperatura que estão entre estes dois valores extremos, a situação não é tão definida. Algumas pessoas podem considerar uma xícara de chá com uma temperatura de 55 graus "quente", enquanto outras podem considerar "não muito quente". Isso é a "imprecisão".

No entanto, podemos imaginar o olhar aproximado da função de pertinência: ele está "monotonamente aumentando":


A figura acima mostra a função de pertinência "linear por partes".

Assim, a função pode ser definida pela seguinte expressão analítica:


Usaremos tais funções para nosso indicador.


2. Função de pertinência

De uma forma ou de outra, a tarefa de qualquer indicador técnico é determinar o estado atual do mercado (tendência crescente, decrescente, plana), bem como a geração de sinais de entrada e saída do mercado. Como isso pode ser feito com a ajuda das funções de pertinência? é bem fácil.

Primeiro de tudo, precisamos definir as condições limite. Teremos as seguintes condições limite: para «tendência 100% crescente» o limite será o cruzamento do EMA tendo um período 2, com base no preço típico (H+L+C)/3 com o limite superior Envelopes tendo os parâmetros 8, 0.08, SMA, Fechar, enquanto para a «tendência 100% decrescente» ele será o cruzamento do mesmo EMA com o limite inferior Envelopes. Tudo que estiver colocado entre estas duas condições será assumido como plano. Vamos acrescentar mais um envelope tendo os parâmetros 32, 0.15, SMA, Fechar.

Como resultado, teremos duas funções de pertinência idênticas. O sinal de compra será ativado quando ambas funções forem iguais a 1, enquanto o sinal de venda será ativado quando ambas funções forem iguais a -1, respectivamente. Devido a ser conveniente construir gráficos com uma faixa de -1 a 1, o gráfico resultante será obtido como a média aritmética de duas funções F(x)= (f1(x)+f2(x))/2.

é assim que fica no gráfico:


Neste caso, a função de pertinência terá a seguinte representação gráfica:


Analiticamente, ela pode ser escrita da seguinte forma:

,

onde a e b são as linhas envelope superiores e inferiores, respectivamente, enquanto x é um valor de EMA(2).

Com a função definida, podemos agora prosseguir com a escrita do código do indicador.


3. Criando o código do programa

Primeiramente, devemos definir o que e como vamos desenhar.

Os resultados dos cálculos da função de pertinência serão exibidos como a linha - vermelha e azul, respectivamente.

A média aritmética será exibida como o histograma da linha zero e colorida em uma das cinco cores dependendo do valor da função resultante:

O estilo de desenhoDRAW_COLOR_HISTOGRAM será utilizado para isso.

Vamos desenhar retângulos azuis e vermelhos como sinais de comprar e sair nas barras do histograma, os valores destes são iguais a 1 ou -1.

Agora, é hora de executar o MetaEditor e começar. New (Novo)->Custom Indicator (Personalizar indicador)->Next (Próximo)... Preencha o campo "Parâmetros":


Crie os buffers:


Após clicar no botão "Finish" (Terminar), recebemos um código fonte e começamos a melhorá-lo.

Primeiro, vamos definir o número de buffers. Sete deles já foram criados pelo Assistente (5 para dados, 2 para cor). Precisamos de 5 mais.

#property indicator_minimum -1.4 // Setting fractional values
#property indicator_maximum 1.4  // Expert Advisors wizard ignores fractional parts for some reason
#property indicator_buffers 12   // Changing the value from 7 to 12 (5 more buffers have been added)
Vamos editar os parâmetros de entrada:
input string txt1="----------";
input int                  Period_Fast=8;
input ENUM_MA_METHOD        Method_Fast = MODE_SMA; /*Smoothing method*/ //moving average smoothing method 
input ENUM_APPLIED_PRICE    Price_Fast  = PRICE_CLOSE;
input double               Dev_Fast=0.08;
input string txt2="----------";
input int                  Period_Slow=32;
input ENUM_MA_METHOD        Method_Slow = MODE_SMA;
input ENUM_APPLIED_PRICE    Price_Slow  = PRICE_CLOSE;
input double               Dev_Slow=0.15;  /*Deviation parameter*/
input string txt3="----------";
input int                  Period_Signal=2;
input ENUM_MA_METHOD        Method_Signal = MODE_EMA;
input ENUM_APPLIED_PRICE    Price_Signal  = PRICE_TYPICAL;
input string txt4="----------";

Comentários após a variável declarada são muito úteis. O texto dos comentários é inserido na janela dos parâmetros do indicador.

A possibilidade de criação de listas é também bastante útil:


Reservando as variáveis para os buffers e manipuladores do indicador:

int Envelopes_Fast;     // Fast envelope
int Envelopes_Slow;     // Slow envelope
int MA_Signal;          // Signal line

double Env_Fast_Up[];   // Fast envelope upper border
double Env_Fast_Dn[];   // Fast envelope lower border

double Env_Slow_Up[];   // Slow envelope upper border
double Env_Slow_Dn[];   // Slow envelope lower border

double Mov_Sign[];      // Signal line

Agora, vamos para a função OnInit().

Vamos adicionar um pouco de beleza: especifique o nome do indicador e remova os zeros decimais extras:

IndicatorSetInteger(INDICATOR_DIGITS,1); // setting display accuracy, we do not need some outstanding accuracy values 
string name;                           // indicator name 
StringConcatenate(name, "FLE ( ", Period_Fast, " , ", Dev_Fast, " | ", Period_Slow, " , ", Dev_Slow, " | ", Period_Signal, " )"); 
IndicatorSetString(INDICATOR_SHORTNAME,name);

e adicione os buffers faltantes:

SetIndexBuffer(7,Env_Fast_Up,INDICATOR_CALCULATIONS);
SetIndexBuffer(8,Env_Fast_Dn,INDICATOR_CALCULATIONS);
SetIndexBuffer(9,Env_Slow_Up,INDICATOR_CALCULATIONS);
SetIndexBuffer(10,Env_Slow_Dn,INDICATOR_CALCULATIONS);
SetIndexBuffer(11,Mov_Sign,INDICATOR_CALCULATIONS); 

A média do parâmetroINDICATOR_CALCULATIONS significa que os dados do buffer são necessários apenas para cálculos intermediários. Isso não será exibido no gráfico.

Observe como os indicadores com os buffers coloridos são declarados:

SetIndexBuffer(4,SignalBuffer1,INDICATOR_DATA);      // All indicator buffers at first 
SetIndexBuffer(5,SignalBuffer2,INDICATOR_DATA);      // as this is Color Histogram2, then it has 2 data buffers
SetIndexBuffer(6,SignalColors,INDICATOR_COLOR_INDEX);// the color buffer comes next.

Preenchendo os manipuladores:

Envelopes_Fast = iEnvelopes(NULL,0,Period_Fast,0,Method_Fast,Price_Fast,Dev_Fast);
Envelopes_Slow = iEnvelopes(NULL,0,Period_Slow,0,Method_Slow,Price_Slow,Dev_Slow);
MA_Signal      = iMA(NULL,0,Period_Signal,0,Method_Signal,Price_Signal);

Todo trabalho com a função OnInit() terminou.

Agora, vamos criar a função que irá calcular o valor da função de pertinência:

double Fuzzy(double x,double a, double c)
{
double F;
     if (a<x)          F=1;                 // 100% uptrend
else if (x=c)  F=(1-2*(a-x)/(a-c));// Flat
else if (x<c)           F=-1;               // 100% downtrend
return (F);
}

Os preparativos terminaram. As variáveis e buffers estão declarados, os manipuladores atribuídos.

Agora é hora de prosseguirmos com a função básica OnCalculate().

Primeiro de tudo, vamos escrever os valores dos indicadores necessários nos buffers intermediários. Use a função CopyBuffer() :

CopyBuffer(Envelopes_Fast,  // Indicator handle
           UPPER_LINE,      // Indicator buffer
           0,              // The point to start 0 - from the very beginning
           rates_total,    // How many to be copied - All 
           Env_Fast_Up);   // The buffer the values are written in
// - the rest are done in a similar way
CopyBuffer(Envelopes_Fast,LOWER_LINE,0,rates_total,Env_Fast_Dn);
CopyBuffer(Envelopes_Slow,UPPER_LINE,0,rates_total,Env_Slow_Up);
CopyBuffer(Envelopes_Slow,LOWER_LINE,0,rates_total,Env_Slow_Dn);
CopyBuffer(MA_Signal,0,0,rates_total,Mov_Sign);

Aqui devemos adicionar o código para a otimização dos cálculos (é realizado o recálculo de apenas a última barra):

// declaring start variable for storing the index of the bar, recalculation of the indicator buffers will be
// carried out from.

int start;              
if (prev_calculated==0)  // in case no bars have been calculated
    {
    start = Period_Slow; // not all indicators have been calculated up to this value, therefore, there is no point in executing the code
    }
else start=prev_calculated-1;

for (int i=start;i<rates_total;i++)
      {
      // All remaining code will be written here
      }

Não resta muito do código.

Definindo os parâmetros x, a, b, realizando o cálculo do valor da função de pertinência e o escrevendo no buffer adequado:
double x = Mov_Sign[i]; // Signal
// Setting the first membership function parameters:
double a1 = Env_Fast_Up[i]; // Upper border
double b1 = Env_Fast_Dn[i];
// setting the first membership function value and writing it to the buffer
Rule1Buffer[i] = Fuzzy(x,a1,b1);
// Setting the second membership function parameters:
double a2 = Env_Slow_Up[i]; // Upper border
double b2 = Env_Slow_Dn[i];
// setting the second membership function value and writing it to the buffer
Rule2Buffer[i] = Fuzzy(x,a2,b2);

Duas linhas do indicador estão criadas:

Agora, vamos calcular o valor resultante.

ResultBuffer[i] = (Rule1Buffer[i]+Rule2Buffer[i])/2;

Depois, devemos pintar as barras do histograma nas cores apropriadas: como temos cinco cores, então o ResultColor[i] pode ter qualquer valor de 0 a 4.

Geralmente, o número de cores possíveis é 64. Portanto, é uma grande oportunidade para aplicar habilidades e criatividade.

for (int ColorIndex=0;ColorIndex<=4;ColorIndex++) 
    { 
    if (MathAbs(ResultBuffer[i])>0.2*ColorIndex && MathAbs(ResultBuffer[i])<=0.2*(ColorIndex+1)) 
        { 
        ResultColors[i] = ColorIndex; 
        break; 
        } 
    }

Então, devemos desenhar os retângulos de sinal. Usaremos o estilo de desenho DRAW_COLOR_HISTOGRAM2 .

Ele tem dois buffers de dados com uma barra de histograma e um buffer colorido sendo inseridos entre eles.

Os valores dos buffers de dados sempre serão os mesmo: 1.1 e 1.3 para um sinal de compra, -1.1 e -1.3 para um sinal de venda, respectivamente.

EMPTY_VALUE representará a ausência de sinal.

      if (ResultBuffer[i]==1)
        {
        SignalBuffer1[i]=1.1;
        SignalBuffer2[i]=1.3;
        SignalColors[i]=1;
        }
      else if (ResultBuffer[i]==-1)
        {
        SignalBuffer1[i]=-1.1;
        SignalBuffer2[i]=-1.3;
        SignalColors[i]=0;
        }
      else
        {
        SignalBuffer1[i]=EMPTY_VALUE;
        SignalBuffer2[i]=EMPTY_VALUE;
        SignalColors[i]=EMPTY_VALUE;
        }

Clique em "Compile" (Compilar) e voilà!



Conclusão

O que mais pode ser adicionado? Neste artigo, mencionei a abordagem mais básica da lógica Fuzzy.

Existe espaço suficiente aqui para diversos experimentos. Por exemplo, podemos usar a seguinte função:


Eu acho que não será difícil para você escrever a expressão analítica para isso e descobrir as condições adequadas.

Boa sorte!

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

Arquivos anexados |
Crie seu próprio Market Watch usando as classes da biblioteca padrão Crie seu próprio Market Watch usando as classes da biblioteca padrão
O novo terminal do cliente do MetaTrader 5 e a linguagem MQL5 fornece novas oportunidades para apresentar informações visuais para o negociante. Neste artigo, propomos um conjunto de classes extensível e universal, que lida com todo o trabalho de organização de exibição da informação de texto arbitrária no gráfico. é apresentado o exemplo do indicador Maket Watch.
Assistente MQL5: criar Expert Advisors sem programação Assistente MQL5: criar Expert Advisors sem programação
Você quer experimentar uma estratégia de negócio enquanto não gasta tempo em programação? No Assistente MQL5 você pode simplesmente selecionar o tipo de sinais de negócio, adicionar módulos de posições de rastreio e gerenciamento de dinheiro - e seu trabalho está feito! Crie suas próprias implementações dos módulos ou encomende através do atendimento Jobs - e combine seus novos módulos com os já existentes.
Série de preço médio para cálculos intermediários sem utilizar buffers adicionais Série de preço médio para cálculos intermediários sem utilizar buffers adicionais
Este artigo é sobre algorítimos tradicionais e incomuns de média comprimidos em classes de tipo único e simples. Eles são destinados à utilização universal em quase todos os desenvolvimentos de indicadores. Espero que as classes sugeridas sejam uma boa alternativa para chamadas 'volumosas' e indicadores personalizados e técnicos.
Gás neural em desenvolvimento: Implementação em MQL5 Gás neural em desenvolvimento: Implementação em MQL5
Este artigo mostra um exemplo de como desenvolver um programa MQL5 implementando o algorítimo adaptável de fazer o cluster chamado gás neural em desenvolvimento (GNG). O artigo é destinado para usuários que tenham estudado a documentação de linguagem e têm determinadas habilidades de programação e conhecimento básico na área de neuroinformática.