English Русский 中文 Español Deutsch 日本語
Criação de estratégias de negociação manuais usando lógica fuzzy

Criação de estratégias de negociação manuais usando lógica fuzzy

MetaTrader 4Negociação | 19 setembro 2016, 10:53
1 547 0
Alexander Fedosov
Alexander Fedosov

Introdução

O rápido desenvolvimento das tecnologias levou aos mercados de moedas atuais a uma tendência crescente do uso de sistemas de negociação automatizados. No entanto, muitos traders ainda operam em modo manual. Há muito que são conhecidos os prós e contras de ambas as abordagens da negociação: a negociação automática não é muito flexível perante as constantes mudanças de mercado, enquanto a negociação manual, pelo contrário, pode ser excessivamente flexível devido à intervenção frequente do fator humano. Na verdade, neste aspecto, a comparação trata-se de dois extremos da mesma entidade.

No artigo anterior, em exemplos, usando a teoria da lógica fuzzy, procurei compensar as deficiências da forma automática de negociação, por exemplo, “diluir” a formalização demasiado estrita de negociação usada no robô de negociação e no indicador. Neste artigo, será dada atenção à possibilidade de melhorar a negociação manual de estratégias. Com efeito, a utilização de tecnologias modernas traz mais bem do que mal, mesmo no modo manual de negociação, onde a decisão final sempre cabe com o trader.

 

Escolha de estratégias manuais com condições claras de formalização

Muitos traders modernos se atrevem a assumir a responsabilidade pela entrada e saída de suas posições, ao invés de confiar em sistemas automáticos. Eles precisam desenvolver sua estratégia de negociação, para que leve em conta todos os resultados possíveis do comportamento do mercado. Logo ela precisa seguir estritamente e resistir a impulsos que provoquem medo ou cobiça.

Por isso, inicialmente, é necessário determinar a estratégia de negociação. Descrevo as três fases de sua construção.

  • Fase №1. Encontrar e definir os instrumentos que serão usados na nossa estratégia.
  • Fase №2. Especificar claramente as condições sob as quais o trader abrirá sua posição no mercado.
  • Fase №3. Especificar condições claras sob as quais será preciso fechar a posição com resultado positivo ou negativo.

Fase №1.

Na primeira fase, eu escolhi, como exemplo, três indicadores para construir a estratégia de negociação:

  1. Índice de Média Direcional de Movimento (Average Directional Movement Index, ADX). Este indicador de tendência determina a força da tendência atual.
  2. Oscilador Índice de Vigor Relativo (Relative Vigor Index, RVI).
  3. Indicador de Aceleração/Desaceleração Bill Williams Accelerator Oscillator(AC).

Aparência geral e configuração do terminal de negociação MQL4:

Fig. 1. Aparência geral das configurações do terminal

Fase №2.

Na segunda fase, definimos como vamos usar os instrumentos selecionados, as condições em que eles irão trabalhar, assim como os parâmetros das posições que vamos usar para entrar no mercado.

Vamos começar desde o início.

  • O ADX é nosso primeiro indicador. Como pode ser visto na Figura 1, o período especificado do indicador é 10. Além disso, um nível especialmente definido para a linha de tendência principal (verde), que é igual a 30. Vamos considerar um valor igual ou superior a isso como um sinal positivo para a entrada no mercado. Note-se que a situação quando +DI (linha pontilhada verde) é superior a -DI (linha vermelha pontilhada vai sinalizar para comprar a partir deste indicador. Nesse sentido, um sinal de venda será a situação inversa, quando -DI é superior a +DI.
  • O segundo indicador é o AC. Aqui, nós usaremos os sinais, descritos na documentação oficial. Ou seja, se o valor do indicador for inferior a 0 e crescer na barra analisada a duas anteriores, será um sinal de compra. Nesse sentido, se o valor do indicador for superior a 0 e cair na barra analisada e duas anteriores, estaremos obtendo um sinal de venda.
  • O terceiro indicador é o RVI. Definimos o período, seu trabalho é igual a 10. Como condição de compra, definimos o tempo quando a linha de sinal (vermelha fina) cruza a linha principal (verde). O valor da linha de intersecção, na barra analisada, deve estar abaixo de zero. Da mesma forma, definimos as condições de venda: a linha de sinal atravessa a linha principal, mas os valores são superiores a zero.
  • O período de hora (H1) será a seguinte condição de trabalho.
  • A condição de entrada em posição é a apresentação de sinais idênticos por todos os três indicadores selecionados.
  • E, finalmente, definimos o tamanho da posição. Como exemplo, definimos: lote 0,01, Take Profit 50 pontos, Stop Loss 30 pontos.

Por motivos de clareza, formalizamos as condições.

Entrada para a posição longa (sinal de compra)

  1. A linha verde principal do indicador ADX tem valor superior ou igual a 30, além disso, o valor +DI é superior a -DI.
  2. O valor AC cresce, na barra atual, e é superior às duas barras anteriores, que, por sua vez, também crescem consistentemente. Visualmente, trata-se de três colunas do histograma de cor verde, cada um dos quais é mais curto do que o anterior, e todos os três estão na área negativa.
  3. A linha de sinal RVI (vermelha fina) cruza a linha principal (verde), ambas as duas crescem, mas ainda se encontram abaixo de zero.
  4. Compramos com o lote 0,01, colocamos Take Profit 50 pontos e Stop Loss 30 pontos.
Entrada para a posição curta (sinal de venda)
  1. A linha verde principal do indicador ADX tem um valor que é maior que ou igual a 30, além disso, o valor +DI é inferior a -DI.
  2. Valor do AC cai na barra atual, e é inferior às duas barras anteriores, que, por sua vez, também diminuem constantemente. Visualmente, trata-se de três colunas do histograma de cor vermelha, cada um dos quais é mais curto do que o anterior, e todos os três têm valores acima de zero.
  3. A linha de sinal RVI (vermelha fina) cruza a linha principal (verde), ambas as duas descem, mas ainda se encontram abaixo de zero, mas ainda estão na área positiva.
  4. Vendemos com o lote 0,01, colocamos Take Profit 50 pontos e Stop Loss 30 pontos.

Fase №3

Resta-nos apenas determinar a saída da posição. Como condições de entrada, definimos os indicadores-alvo estabelecidos por nós anteriormente: realização de lucro em 50 pontos ou execução de Stop em 30 pontos.

Assim, nossa estratégia de negociação está definida. Definimos as condições de entrada e saída da posição, selecionamos os indicadores e definimos seus parâmetros de trabalho, decidimos sobre o tamanho da posição de entrada e seus alvos. E finalmente, decidimos sobre quais eventos ocorrerá a saída do mercado.

O próximo passo será verificar a estratégia de negociação criada em condições reais. A primeira coisa que deve ser entendida é que não há nenhuma estratégia ideal a longo prazo em todas as fases do mercado. Os traders, que usam a negociação automatizada ou manual, observam frequentemente que seu sistema se revela de forma diferente em diferentes condições. Também não é incomum que as condições iniciais, no sistema de comércio já determinado, poderiam ter mostrado um melhor resultado.

Por exemplo, sobre o nosso sistema, um trader pode ter notado que o Take Profit definido podia ter sido definido ainda maior. Não porque ele teria gostado de obter mais, senão porque ele analisou continuamente seu sistema de negociação, e suas estatísticas mostraram que, após o fechamento das transações bem-sucedidas, o preço estava se movendo por algum tempo na direção certa. É por isso que na mente do trader surge a pergunta: tendo melhorado os resultados, como aplicar corretamente as estatísticas e observações que recebi para meu sistema de negociação?

 

Desvantagens da formalização clara e a sua correção através de lógica fuzzy

Consideremos os indicadores utilizados no nosso sistema através do prisma da teoria da lógica fuzzy. Em meu artigo anterior, tentei transmitir qual é flexibilidade para analisar essas partes das estratégias de negociação onde é usada a categorização estrita. A lógica fuzzy “diluiu” os limites estritos e deu uma melhor compreensão da avaliação e resposta pelo sistema em áreas de fronteira de seu trabalho. Foi mostrado um exemplo de uma abordagem mais adaptável para o trabalho do indicador ADX que implementamos. Primeiro, foi usada uma separação rigorosa de tendências fraca, média e forte, mas, logo, estas categorias foram “diluídas”, e a definição de força de tendência não foi estritamente relacionada com a subjetividade dos valores do indicador.

Voltamos para o nosso sistema e perguntamos: como pode nos ajudar tudo isto?

Imagine que nosso trader monitora o mercado e repara num sinal a partir de seu primeiro indicador: o ADX atinge um valor, por exemplo, 32. Ele marca isto e espera por uma confirmação de outros dois indicadores. Não se faz esperar muito tempo. Chega o sinal a partir foi AC, e o ADX tem crescido até 40. Após um tempo, a linha de sinal RVI cruza a linha principal, indicando que, finalmente, foram atingidas todas as três condições para entrada na posição. Além do mais, o ADX já tem atingido 45. Mas o valor absoluto ADX não é tão relevante. O importante é que ele é superior a 30. Por isso o trader segue suas regras e entra no mercado usando lote 0,01 com Take Profit em 50 pontos e Stop Loss em 30.

Agora, vamos fazer uma outra versão dos acontecimentos. Inicialmente, a situação evolui da mesma forma como no primeiro caso. ADX=32, chega o sinal do AC, o ADX atinge paralelamente 40. Mas, quando chega o último sinal restante para abertura de posição — do RVI — o ADX pula não para 45, senão que vamos supor que para 55. Se compararmos as duas opções descritas, o segundo sinal é mais forte do que o anterior, no entanto nosso trader não se importa de abrir a posição com os mesmos lote e valores SL e TP.

Aqui aparece a primeira desvantagem de nossa estratégia: é avaliada apenas a presença do sinal que obtemos, independentemente da sua qualidade. Mesmo se avaliarmos e determinarmos as categorias, em áreas de transição, ainda a precisão da estimativa vai se perder.

Como podemos melhorar o caso especial com os indicadores ADX, RVI e associar seus indicadores à posição com que entramos no mercado? Para fazer isso, é necessário seguir os seguintes passos:

  • Definir categorias claras de avaliação de força de tendência (ADX) e de índice relativo vigor (RVI). Este será o sinal de entrada, com base no qual tomaremos decisões adicionais.
  • Definir categorias claras dos objetivos da nossa posição (em nossa estratégia é o TP e SL, embora seja possível especificar, por exemplo, o tamanho do lote). Este é o sinal de saída, que irá ajustar a nossa posição no mercado, levando em conta a força da tendência.
  • Descrever a categoria dos sinais de entrada e saída usando funções de associação da teoria de conjuntos difusos.
  • Criar uma interface que irá exibir as recomendações para alterar a posição da estratégia inicial com base em novas condições.
  • Criar configurações flexíveis das alterações das funções de associação, que permitirão, se necessário, ajustar este sistema de recomendações.

Para começar, vamos descrever a primeira variável de entrada, isto é, o valor de força de tendência.

1. Definimos 4 categorias de força de tendência: fraca (low), moderada (moderate), média (medium) e forte (high). Será parecido com isto:

Fig. 2. Separação visual de força da tendência em categorias

2. Para definir as categorias do sinal de saída, é necessário decidir como a categoria do ADX vai afetar na sua posição. Geralmente, quanto mais forte a tendência, maior tempo vai durar. Por isso, procedemos do seguinte modo: dependendo de onde se encontre o ADX no momento quando todos os três sinais de estratégia forem recebidos, vamos aumentar o TP em 10 - 50 pontos.

Por conseguinte, apresentamos as seguintes categorias, para o valor de alvos de lucro, que vão ser adicionados aos originais 50 pontos de nossa estratégia.

  • Categoria low_take: tendência fraca (Low), aos alvos adicionamos 10 - 20 pontos.
  • Categoria mod_take: tendência moderada (Moderate), aos alvos adicionamos 20 - 30 pontos.
  • Categoria med_take: tendência média (Medium), aos alvos adicionamos 30 - 40 pontos.
  • Categoria high_take: tendência média (High), aos alvos adicionamos 40 - 50 pontos.

3. No próximo passo, descrevemos as condições definidas acima usando a função de associação da teoria de conjuntos difusos. A descrição das quatro categorias de tendência é a seguinte:


Fig. 3. Descrição das quatro categorias de tendência de lógica difusa

Como mostrado na Fig.3, cada uma dessas categorias foi definida pela função de associação, nomeadamente: tendências low e high — duas funções trapezoidais, enquanto as categorias moderate e medium — duas triangulares.

Agora definimos o mesmo para RVI.

1. Definimos as categorias para o índice relativo vigor. Eles também serão quatro: fraca (low), média (medium), forte (high), supremo (higher). Terá a aparência a seguir: Será parecido com isto:

Fig. 4. Separação visual do índice relativo vigor em categorias

2. Definimos as categorias usando as funções de associação. Para descrever as categorias low e higher serão utilizadas as funções de associação trapezoidais, enquanto para medium e high, triangulares.


Fig. 5. Descrição de categorias do índice RVI

Da mesma forma, descrevemos as quatro categorias de valores de alvos de lucro: as primeiras e a quarta categorias (10-20 e 40-50 pontos) usando as funções trapezoidais, enquanto as duas restantes (20-30 e 30-40 pontos) implementando as funções triangulares. A descrição de nosso sinal de saída vai ficar assim.


Fig. 6. Descrição das categorias para valores de alvos de lucro

 

Implementação de interface de painel para exibição de recomendações para alterar a posição

Ao construir um painel de informações, nós selecionamos quatro parâmetros para observação:

  • Valor do ADX. Apenas sob condições especificadas, nomeadamente, 30 ou superior.
  • Valor do RVI. Só quando ele é superior a 0,1 (para o sinal de venda), ou inferior a -0,1 (para o sinal de compra).
  • O número recomendado de pontos que é preciso adicionar ao alvo original em 50.
  • Valor do Take Profit em formato de preço do instrumento de negociação (tendo em conta o preço inicial e recomendações para seu aumento).

Agora, na realização completa, a visão geral das configurações da estratégia de negociação será a seguinte (Fig.6).

Fig. 7. Realização completa e visão geral das configurações da estratégia de negociação

Agora, consideramos a implementação desse painel através do MQL4 e a biblioteca FuzzyNet.

Implementamos e examinamos os blocos lógicos chave desse painel de informações através do MQL4.

//+------------------------------------------------------------------+
//| FuzzyNet Panel                                                   |
//+------------------------------------------------------------------+
#property copyright "Alexander Fedosov"
#property version "1.0"
#property strict
#property link "https://www.mql5.com/pt/users/alex2356/"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Green
//+------------------------------------------------------------------+
//| Connecting libraries                                             |
//+------------------------------------------------------------------+
#include <Math\FuzzyNet\MamdaniFuzzySystem.mqh>

Definimos as propriedades iniciais e conectamos a biblioteca para trabalhar com lógica fuzzy. Definimos a localização do painel na janela do gráfico. Definimos o buffer de indicador e sua cor (verde) para o ponteiro-seta para a barra que estamos examinando.

//--- Input parameters
input string  p1="==== Parameters ====";
input int fontSize=15;
input int adx_period=10;
input int rvi_period=10;
input int num_bar=0;
input int Screen_corner=4;
input color label_clr=Red;
input color textColor=Black;

Vamos considerar mais detalhadamente o primeiro bloco de parâmetros de entrada Parameters. Ele contém os seguintes elementos:

  • fontSize — tamanho da fonte de informações de texto (intervalo recomendado 8 — 15).
  • adx_period — período do indicador ADX.
  • num_bar — número da barra na qual se calcula o sistema.
  • Screen_corner — ângulo de exibição do painel.
  • label_clr — cor do texto de cabeçalho.
  • textColor — cor do texto de valores.

O segundo bloco de parâmetros de entrada Fuzzy Logic Parameters contém a maioria dos parâmetros para ajuste flexível de todas as funções de associação, que descrevem os parâmetros de entrada (força da tendência ADX, índice RVI), bem como de saída (valor recomendado de pontos de alvo de lucro).

input string  p2="==== Fuzzy Logic Parameters ====";
//--- ADX
input double in_term1a = 20;
input double in_term1b = 30;
input double in_term1c = 40;
input double in_term1d = 45;
input double in_term2a = 40;
input double in_term2b = 50;
input double in_term2c = 60;
input double in_term3a = 50;
input double in_term3b = 60;
input double in_term3c = 70;
input double in_term4a = 60;
input double in_term4b = 70;
input double in_term4c = 100;
input double in_term4d = 120;
//--- RVI
input double in_term1a1 = -0.25;
input double in_term1b1 = 0.1;
input double in_term1c1 = 0.15;
input double in_term1d1 = 0.25;
input double in_term2a1 = 0.15;
input double in_term2b1 = 0.25;
input double in_term2c1 = 0.35;
input double in_term3a1 = 0.25;
input double in_term3b1 = 0.35;
input double in_term3c1 = 0.45;
input double in_term4a1 = 0.4;
input double in_term4b1 = 0.45;
input double in_term4c1 = 1;
input double in_term4d1 = 1.2;
//--- Output
input double out_term1a = 5;
input double out_term1b = 10;
input double out_term1c = 15;
input double out_term1d = 22.5;
input double out_term2a = 17.5;
input double out_term2b = 25;
input double out_term2c = 32.5;
input double out_term3a = 27.5;
input double out_term3b = 35;
input double out_term3c = 42.5;
input double out_term4a = 37.5;
input double out_term4b = 45;
input double out_term4c = 50;
input double out_term4d = 60;
input double min_tp = 10;
input double max_tp = 50;


No bloco seguinte, são declaradas as variáveis, nomes dos cabeçalhos, a escala do painel de informações (tamanho, localização, fonte e outros), e são definidos os parâmetros de exibição do elemento que indica a barra atual (no nosso caso é a seta).

int scaleX=55,scaleY=25,offsetX=35;
//--- 
string signalName[]={"ADX_val:","RVI_val:","TP_plus:","TP_prc:"};
double adx,adx_di_minus,adx_di_plus,rvi,rvi_sig,mdm;
double Buffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   if(fontSize>15 || fontSize<8)
     {
      Print("ERROR: Incorrect fontSize. Must be 8-15.");
      Alert("ERROR: Incorrect fontSize. Must be 8-15.");
      return(0);
     }
   if(Screen_corner>4 || Screen_corner<1)
     {
      Print("ERROR: Incorrect Screen_corner. Must be 1-4.");
      Alert("ERROR: Incorrect Screen_corner. Must be 1-4.");
      return(0);
     }
//---
   SetIndexStyle(0,DRAW_ARROW,EMPTY,1);
   SetIndexArrow(0,234);
   SetIndexBuffer(0,Buffer);
   ArrayInitialize(Buffer,0.0);
//---
   for(int y=0;y<4;y++)
     {
      ObjectCreate("lb_ind_nm"+string(y),OBJ_LABEL,0,0,0,0,0);
      //--- alteramos o ângulo de ancoragem    
      ObjectSet("lb_ind_nm"+string(y),OBJPROP_SELECTABLE,false);
      ObjectSet("lb_ind_nm"+string(y),OBJPROP_CORNER,Screen_corner);
      ObjectSet("lb_ind_nm"+string(y),OBJPROP_XDISTANCE,offsetX-30);
      ObjectSet("lb_ind_nm"+string(y),OBJPROP_YDISTANCE,y*scaleY+20);
      ObjectSetText("lb_ind_nm"+string(y),signalName[y],fontSize,"Tahoma",label_clr);
     }
//---
   for(int y=0;y<4;y++)
     {
      ObjectCreate("lb_ind0"+string(y),OBJ_LABEL,0,0,0,0,0);
      //--- alteramos o ângulo de ancoragem
      ObjectSet("lb_ind0"+string(y),OBJPROP_SELECTABLE,false);
      ObjectSet("lb_ind0"+string(y),OBJPROP_CORNER,Screen_corner);
      ObjectSet("lb_ind0"+string(y),OBJPROP_XDISTANCE,scaleX+offsetX);
      ObjectSet("lb_ind0"+string(y),OBJPROP_YDISTANCE,y*scaleY+20);
      ObjectSetText("lb_ind0"+string(y),"",fontSize,"Tahoma",textColor);
     }
   return(INIT_SUCCEEDED);
  }


Agora, consideramos o bloco principal de tratamento de sinais, a partir dos indicadores ADX e RVI.

São especificadas as condições sob as quais os valores dos indicadores satisfazem os sinais para compra e venda. Sua coincidência provoca que os valores sejam processados pela função mamdani(double t, double v) e apareçam no painel. Tudo isso é como segue: valores atuais dos indicadores indicando que o sinal buy (ou sell) foi obtido; recomendado TP (em pontos e em valor numérico).

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   Buffer[num_bar]=High[num_bar]+20*_Point;
   adx=NormalizeDouble(iADX(_Symbol,PERIOD_CURRENT,adx_period,PRICE_CLOSE,MODE_MAIN,num_bar),_Digits);
   adx_di_plus=NormalizeDouble(iADX(_Symbol,PERIOD_CURRENT,adx_period,PRICE_CLOSE,MODE_PLUSDI,num_bar),_Digits);
   adx_di_minus=NormalizeDouble(iADX(_Symbol,PERIOD_CURRENT,adx_period,PRICE_CLOSE,MODE_MINUSDI,num_bar),_Digits);
//---
   rvi=NormalizeDouble(iRVI(_Symbol,PERIOD_CURRENT,rvi_period,MODE_MAIN,num_bar),_Digits);
   rvi_sig=NormalizeDouble(iRVI(_Symbol,PERIOD_CURRENT,rvi_period,MODE_SIGNAL,num_bar),_Digits);
//---   
   if(adx>30 && adx_di_plus>adx_di_minus && rvi>rvi_sig && rvi<-0.1)
     {
      mdm=MathCeil(mamdani(adx,MathAbs(rvi)));
      ObjectSetText("lb_ind00","buy_signal: "+DoubleToString(adx,_Digits),fontSize,"Tahoma",textColor);
      ObjectSetText("lb_ind01","buy_signal: "+DoubleToString(rvi,_Digits),fontSize,"Tahoma",textColor);
      ObjectSetText("lb_ind02",DoubleToString(mdm,0),fontSize,"Tahoma",textColor);
      ObjectSetText("lb_ind03",DoubleToString(tp_prc(mdm),_Digits),fontSize,"Tahoma",textColor);
     }
   else if(adx>30 && adx_di_plus<adx_di_minus && rvi<rvi_sig && rvi>0.1)
     {
      mdm=MathCeil(mamdani(adx,rvi));
      ObjectSetText("lb_ind00","sell_signal: "+DoubleToString(adx,_Digits),fontSize,"Tahoma",textColor);
      ObjectSetText("lb_ind01","sell_signal: "+DoubleToString(rvi,_Digits),fontSize,"Tahoma",textColor);
      ObjectSetText("lb_ind02",DoubleToString(mdm,0),fontSize,"Tahoma",textColor);
      ObjectSetText("lb_ind03",DoubleToString(tp_prc(mdm),_Digits),fontSize,"Tahoma",textColor);
     }
   else
     {
      ObjectSetText("lb_ind00","no_signal",fontSize,"Tahoma",textColor);
      ObjectSetText("lb_ind01","no_signal",fontSize,"Tahoma",textColor);
      ObjectSetText("lb_ind02"," - ",fontSize,"Tahoma",textColor);
      ObjectSetText("lb_ind03"," - ",fontSize,"Tahoma",textColor);
     }
   return(rates_total);
  }

A função cria um sistema de lógica difusa. Ela contém dois sinais de entrada a partir dos indicadores trend e vigor (cada um dos quais consiste em quatro termos, descritos pela função de associação) e um de saída signal. O sistema também inclui quatro regras, que ligam os sinais de entrada e de saída.

//+------------------------------------------------------------------+
//| Função de criação e cálculo do sistema com base na lógica difusa     |
//+------------------------------------------------------------------+
double mamdani(double t,double v)
  {
   double res=0;
//--- Mamdani Fuzzy System  
   MamdaniFuzzySystem *fsSignal=new MamdaniFuzzySystem();
//--- Create input variables for the system
   FuzzyVariable *fsTrend=new FuzzyVariable("trend",30.0,100.0);
   FuzzyVariable *fsVigor=new FuzzyVariable("vigor",0.1,1.0);
//--- ADX
   fsTrend.Terms().Add(new FuzzyTerm("low", new TrapezoidMembershipFunction(in_term1a, in_term1b, in_term1c, in_term1d)));
   fsTrend.Terms().Add(new FuzzyTerm("moderate", new TriangularMembershipFunction(in_term2a, in_term2b, in_term2c)));
   fsTrend.Terms().Add(new FuzzyTerm("medium", new TriangularMembershipFunction(in_term3a, in_term3b, in_term3c)));
   fsTrend.Terms().Add(new FuzzyTerm("high",new TrapezoidMembershipFunction(in_term4a, in_term4b, in_term4c, in_term4d)));
   fsSignal.Input().Add(fsTrend);
//--- RVI
   fsVigor.Terms().Add(new FuzzyTerm("low", new TrapezoidMembershipFunction(in_term1a1, in_term1b1, in_term1c1, in_term1d1)));
   fsVigor.Terms().Add(new FuzzyTerm("medium", new TriangularMembershipFunction(in_term2a1, in_term2b1, in_term2c1)));
   fsVigor.Terms().Add(new FuzzyTerm("high", new TriangularMembershipFunction(in_term3a1, in_term3b1, in_term3c1)));
   fsVigor.Terms().Add(new FuzzyTerm("higher",new TrapezoidMembershipFunction(in_term4a1, in_term4b1, in_term4c1, in_term4d1)));
   fsSignal.Input().Add(fsVigor);
//--- Create Output
   FuzzyVariable *fvSignal=new FuzzyVariable("signal",min_tp,max_tp);
   fvSignal.Terms().Add(new FuzzyTerm("low_take", new TrapezoidMembershipFunction(out_term1a, out_term1b, out_term1c, out_term1d)));
   fvSignal.Terms().Add(new FuzzyTerm("mod_take", new TriangularMembershipFunction(out_term2a, out_term2b, out_term2c)));
   fvSignal.Terms().Add(new FuzzyTerm("med_take", new TriangularMembershipFunction(out_term3a, out_term3b, out_term3c)));
   fvSignal.Terms().Add(new FuzzyTerm("high_take", new TrapezoidMembershipFunction(out_term4a, out_term4b, out_term4c, out_term4d)));
   fsSignal.Output().Add(fvSignal);
//--- Create four Mamdani fuzzy rule
   MamdaniFuzzyRule *rule1 = fsSignal.ParseRule("if (trend is low) and (vigor is low) then signal is low_take");
   MamdaniFuzzyRule *rule2 = fsSignal.ParseRule("if (trend is moderate) and (vigor is medium) then signal is mod_take");
   MamdaniFuzzyRule *rule3 = fsSignal.ParseRule("if (trend is medium) and (vigor is high) then signal is med_take");
   MamdaniFuzzyRule *rule4 = fsSignal.ParseRule("if (trend is high) and (vigor is higher) then signal is high_take");
//--- Add four Mamdani fuzzy rule in system
   fsSignal.Rules().Add(rule1);
   fsSignal.Rules().Add(rule2);
   fsSignal.Rules().Add(rule3);
   fsSignal.Rules().Add(rule4);
//--- Set input value
   CList *in=new CList;
   Dictionary_Obj_Double *p_od_adx=new Dictionary_Obj_Double;
   Dictionary_Obj_Double *p_od_rvi=new Dictionary_Obj_Double;
   p_od_adx.SetAll(fsTrend,t);
   p_od_rvi.SetAll(fsVigor,v);
   in.Add(p_od_adx);
   in.Add(p_od_rvi);
//--- Get result
   CList *result;
   Dictionary_Obj_Double *p_od_out;
   result=fsSignal.Calculate(in);
   p_od_out=result.GetNodeAtIndex(0);
   res=NormalizeDouble(p_od_out.Value(),_Digits);
//---
   delete in;
   delete result;
   delete fsSignal;
   return res;
  }


Vamos para o último bloco, isto é, " Funções auxiliares ". A primeira delas, tp_prc(double take), converte o valor TP para pontos em valor numérico de preço do atual instrumento monetário. A segunda define o número de caracteres do atual instrumento monetário.

//+------------------------------------------------------------------+
//| Função de definição dos alvos de lucro                                |
//+------------------------------------------------------------------+
double tp_prc(double take)
  {
   int tip;
   double opr,tp;
   take+=50;
   adx_di_plus=NormalizeDouble(iADX(_Symbol,PERIOD_CURRENT,adx_period,PRICE_CLOSE,MODE_PLUSDI,num_bar),_Digits);
   adx_di_minus=NormalizeDouble(iADX(_Symbol,PERIOD_CURRENT,adx_period,PRICE_CLOSE,MODE_MINUSDI,num_bar),_Digits);
//---
   if(adx_di_plus>adx_di_minus)
      tip=0;
   else if(adx_di_plus<adx_di_minus)
      tip=1;
//---
   switch(tip)
     {
      case 0:
         opr=Ask;
         break;
      case 1:
         opr=Bid;
         break;
     }
   if(MathMod(tip,2.0)==0.0)
     {
      tp=opr+take*Dig()*_Point;
     }
   else
     {
      tp=opr-take*Dig()*_Point;
     }
   return(tp);
  }
//+------------------------------------------------------------------+
//| Função de retorno do número de dígitos após o ponto decimal      |
//+------------------------------------------------------------------+
int Dig()
  {
   return((_Digits==5 || _Digits==3 || _Digits==1)?10:1);
  }
//+------------------------------------------------------------------+

Também, gostaria de chamar a atenção para a validade das configurações e verificação repetida da validade dos parâmetros na seção Fuzzy Logic Parameters durante o teste. Recomendo apoiar-se nas suas representações gráficas originais, na fig. 3, 5, 6, já que valores incorretos podem levar a erros e um trabalho errado do sistema inteiro. Tenha cuidado!

 

Conclusão

Para concluir, resumimos e fazemos conclusões.

  • A primeira parte do trabalho na criação da estratégia de negociação manual usando lógica fuzzy consiste no desenvolvimento de umas regras claramente formalizadas desta estratégia. Isso se considerou nas fases № 1 — 3.
  • Logo, é necessário identificar lacunas de formalização clara naqueles lugares onde há uma categorização rigorosa de todos os blocos ou parâmetros de avaliação. No exemplo mostrado, foi encontrada parte da estratégia que não permitia determinar de maneira flexível quando entrar no mercado.
  • A seguir, todas as categorias claras são descritas usando a teoria de conjuntos difusos, assim, viram mais flexíveis. Agora, nos valores de fronteira, pode haver uma associação não apenas a uma determinada categoria, como costumavam ser, mas a dois de uma só vez, mas em diferentes níveis.
  • Esta estratégia é implementada como um indicador, paneis ou alerta. Neste artigo, foi escolhido um painel na linguagem MQL4.
Nós examinamos a possibilidade de melhorar a estratégia de negociação manual usando a teoria dos conjuntos difusos (fuzzy). Foi mostrado em detalhes, como a estratégia de negociação já formada é modificada e complementada graças à lógica difusa se livrando das deficiências encontradas.

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

Arquivos anexados |
fuzzy_panel.mq4 (23.67 KB)
Interfaces Gráficas V: O Controle Combobox (Capítulo 3) Interfaces Gráficas V: O Controle Combobox (Capítulo 3)
Nos dois primeiros capítulos da quinta parte da série, nós desenvolvemos as classes para criar uma barra de rolagem e uma lista. Neste capítulo, nós falaremos sobre a criação de uma classe para o controle combobox. Este é também um controle composto que contém, entre outros, os elementos considerados nos capítulos anteriores desta quinta parte.
Proteção contra falsos positivos do robô de negociação Proteção contra falsos positivos do robô de negociação
A rentabilidade dos sistemas de negociação é determinada não só pela lógica e precisão da dinâmica dos instrumentos financeiros, mas também pela qualidade do algoritmo de execução dessa lógica. Os falsos positivos são uma manifestação característica da má execução da lógica fundamental do robô de negociação. Neste artigo trataremos várias opções para resolver esse problema.
Como copiar sinais pelas suas regras usando um EA ? Como copiar sinais pelas suas regras usando um EA ?
Ao assinar um sinal, a seguinte situação pode ocorrer: sua conta de negociação tem uma alavancagem de 1:100, o provedor tem uma alavancagem de 1:500 e as negociações usam um lote mínimo, seus saldos são praticamente iguais - porém o coeficiente de cópia irá abranger somente de 10% a 15%. Este artigo descreve como aumentar a taxa de cópia em tais casos.
Interfaces Gráficas V: O Controle Lista (Capítulo 2) Interfaces Gráficas V: O Controle Lista (Capítulo 2)
No capítulo anterior, nós escrevemos as classes para criar a barra de rolagem vertical e horizontal. Neste capítulo, nós vamos implementá-las. Nós vamos escrever uma classe para criar o controle lista, sendo que a barra de rolagem vertical será sua parte integrante.