English Русский 中文 Español Deutsch 日本語
Teste visual da rentabilidade de indicadores e alertas

Teste visual da rentabilidade de indicadores e alertas

MetaTrader 4Exemplos | 8 fevereiro 2016, 13:14
667 0
Sergey Kravchuk
Sergey Kravchuk

Lembre-se quantas vezes, observando uma descoberta aleatória ou uma busca feita a muito tempo e encontrando finalmente o indicador, você queria saber imediatamente qual seria o resultado da negociação pelos alertas. A mesma situação ocorre quando oferecem a você um novo sistema de negociação para o qual não há EAs ou indicadores ainda. Antes de começar um trabalho sério e escrever um EA de trabalho, você gostaria de estimar se há um grão saudável entre os materiais oferecidos.

Ou você pode ter a seguinte situação: Há um indicador com bons alertas, mas você está com o pressentimento de que seus parâmetros não são ótimos, que você pode limpa-los e sabe até como pode fazer isso. Como você pode testar sua ideia sem ficar preso em um código longo e complicado?

Declaração do problema

Vamos pensar no que temos e no que queremos ter. Vamos pegar um ZigZag conhecido do padrão de entrega do MetaTrader 4 como exemplo. Anexe-o a qualquer gráfico de par de moeda em qualquer período de tempo: Você realmente quer negociá-lo? Tudo está claro: você deve vender na curva superior e fechar sua posição comprando o mais baixo.

Agora, a pergunta é: Quanto dinheiro você ganharia com essa negociação? É muito fácil ter uma resposta para essa pergunta: Resuma todos os altos dos segmentos e calcule novamente considerando o volume da posição nos lotes e o preço de um ponto na moeda de depósito. É possível acessar o buffer dos valores ZigZag chamando a função iCustom:

P=iCustom(NULL,0,"ZigZag",0,i);

em que i é o número da barra para a qual você obterá o valor.

Tudo o que você precisa fazer agora é pesquisar todos os valores de buffer e encontrar todos os pontos com valores que não sejam zero - esses são pontos para basear o ZigZag. Bem, você também precisa resumir as alturas dos segmentos. Por razões descritivas, é possível até desenhar essas linhas e colori-las de acordo com as cores das negociações e sua rentabilidade. Essa tarefa é bem fácil e pode ser atribuída a um indicador.

Uma solução universal

Para tal indicador poder testar qualquer outro indicador, você deve garantir sua universalidade. Como qualquer indicador ou sistema de negociação, em um caso geral, assume que apenas 4 operações são feitas: BUY, SELL, BUY CLOSE e SELL CLOSE, devemos ter uma série especial para cada uma delas. Deve ser possível preencher essa série a partir de qualquer fonte. É a única coisa que você precisa editar sozinho adicionando o código e preenchendo as séries de alertas (bem, você provavelmente deve colocar alguns parâmetros em variáveis externas também).

Funcionalmente, o indicador consiste dos seguintes blocos:

  • Inicialização - aqui, alocamos a memória para séries de alertas e redefinimos os contadores;
  • Como preencher as séries de alertas - aqui, vamos editar o código adicionando vários algoritmos de cálculo de alertas ou de recebimento deles a partir de outros indicadores;
  • Como limpar alertas repetidos - este bloco é necessário para "afinar" os alertas de indicadores que não funcionam em um modo discreto que gera um alerta, mas em modo em que o indicador fixa continuamente a disponibilidade de condições de abertura, não a primeira aparição do alerta pelo qual, na verdade, a ordem deve ser aberta. No bloco, o seguinte mecanismo é realizado: Se dois alertas idênticos estiverem localizados em barras vizinhas, a da direita é o reto, pois consideramos apenas uma ordem a ser usada, que já foi aberta na barra precedente (esquerda). Todos os alertas fora do conjunto de faixa de datas nos parâmetros são removidos aqui, também;
  • Como colocar marcas OPEN e CLOSE - neste bloco, o ZigZag é desenhado pelos alertas "finos" (discretos), linhas verticais são colocadas, se necessário, para rastrear a sincronização de alertas com os gráficos de outros indicadores incluindo aqueles que produzem alertas;
  • Como calcular os resultados pelas marcas colocadas -as quantidades de ordens abertas e seu lucro são calculadas no curso de marcas de colocação. Esse bloco faz alguns cálculos adicionais e mostra seus resultados como um comentário na janela do gráfico principal;
  • Funções de ajuda - duas funções estão localizadas aqui: a de colocação de linhas de marcação verticais e a de desenho de segmentos de ZigZag.

Realização

Abaixo está o código do próprio indicador, que contém um exemplo de fornecimento de dados do indicador ZigZag.

/*///———————————————————————————————————————————————————————————————————————————————————————————————————————
 
    IndicatorTester.mq4 
  
    Visual Testing the Profitability of Indicators and Alerts
    
    Copyright © 2006, Кравчук Сергей,  http://forextools.com.ua
 
/*///———————————————————————————————————————————————————————————————————————————————————————————————————————
#property copyright "Copyright © 2006-2008, Sergey Kravchuk. http://forextools.com.ua"
#property link      "http://forextools.com.ua"
 
#property indicator_chart_window
#property indicator_buffers 0
 
// parameters for displaying the elements of the chart
extern bool   ShowZZ          = true;           // should the ZZ be drawn?
extern bool   ShowMARKERS     = true;           // should the vertical marking lines be drawn?
 
//dates of drawing the chart
extern datetime DateStart     = D'1.01.1970';
extern datetime DateEnd       = D'31.12.2037';
 
//parameters of profit calculations
extern double LotForCalc      = 0.05;           // the amount of lots for profit calculations
extern int    Optimizm        = 0;              // -1 gives a pessimistic calculation; 0 gives the calculation on bar opening prices;  
                                                //+1 is optimistic
 
// BUY lines colors
extern color  ColorProfitBuy  = Blue;           // line color for profitable BUY trades
extern color  ColorLossBuy    = Red;            // line color for losing BUY trades
extern color  ColorZeroBuy    = Gray;           // line color for BUY trades with zero profits
 
// SELL lines colors
extern color  ColorProfitSell = Blue;           // line color for profitable SELL trades
extern color  ColorLossSell   = Red;            // line color for losing SELL trades
extern color  ColorZeroSell   = Gray;           // line color for SELL trades with zero profits
 
// alert lines colors
extern color  ColorBuy        = CornflowerBlue; // line color for BUY alerts
extern color  ColorSell       = HotPink;        // line color for SELL alerts
extern color  ColorClose      = Gainsboro;      // line color for closing alerts
 
//——————————————————————————————————————————————————————————————————————————————————————————————————————————
double sBuy[],sCloseBuy[],sSell[],sCloseSell[]; // arrays for alerts
int sBuyCnt,sSellCnt,sBuyCloseCnt,sSellCloseCnt;// alerts counters 
int i,DisplayBars;
//——————————————————————————————————————————————————————————————————————————————————————————————————————————
// service codes
#define MrakerPrefix "IT_"
#define OP_CLOSE_BUY  444
#define OP_CLOSE_SELL 555
//——————————————————————————————————————————————————————————————————————————————————————————————————————————
int init()   { ClearMarkers(); return(0); }
int deinit() { ClearMarkers(); return(0); }
//——————————————————————————————————————————————————————————————————————————————————————————————————————————
int start() 
{ 
  double Profit=0,P1,P2; int CntProfit=0,CntLoose=0,i1,i2;
 
  //————————————————————————————————————————————————————————————————————————————————————————————————————————
  // delete all marks, in case the indicator is going to be redrawn
  ClearMarkers(); 
  //————————————————————————————————————————————————————————————————————————————————————————————————————————
  // prepare alerts counters
  sBuyCnt=0; sSellCnt=0; sBuyCloseCnt=0; sSellCloseCnt=0; 
  //————————————————————————————————————————————————————————————————————————————————————————————————————————
  // allocate some memory for alerts arrays and zeroize their valuesя
  DisplayBars=Bars; // the amount of bars to be displayed
  ArrayResize(sBuy,DisplayBars);  ArrayInitialize(sBuy,0);
  ArrayResize(sSell,DisplayBars); ArrayInitialize(sSell,0);
  ArrayResize(sCloseBuy,DisplayBars);  ArrayInitialize(sCloseBuy,0);
  ArrayResize(sCloseSell,DisplayBars); ArrayInitialize(sCloseSell,0);
  //————————————————————————————————————————————————————————————————————————————————————————————————————————
  // find the first point and save its location and price
  for(i1=Bars-1;i1>=0;i1--) { P1=iCustom(NULL,0,"ZigZag",0,i1); if(P1!=0) break; }
  // process the ZigZag points
  for(i2=i1-1;i2>=0;i2--) 
  {
    // find the next point and save its location and price
    for(i2=i2;i2>=0;i2--) { P2=iCustom(NULL,0,"ZigZag",0,i2); if(P2!=0) break; }
    
    if(i2<0) break; // place the last point on the current price 
 
    // the opening conditions are at the same time the conditions of closing an opposite order
    if(P1>P2) { sSell[i1]=1; sBuy[i2]=1; sCloseSell[i2]=1; }
    if(P1<P2) { sBuy[i1]=1; sSell[i2]=1; sCloseBuy[i2]=1; }
 
    P1=P2; i1=i2; // save the bar in which the point has been found
  }
    //——————————————————————————————————————————————————————————————————————————————————————————————————————
  // delete the repeated alerts having saved only the very first ones located to the left on the chart
  for(i=0;i<DisplayBars;i++) 
  {
    if(sBuy[i]==sBuy[i+1]) sBuy[i]=0;
    if(sSell[i]==sSell[i+1]) sSell[i]=0;
    if(sCloseBuy[i]==sCloseBuy[i+1]) sCloseBuy[i]=0;
    if(sCloseSell[i]==sCloseSell[i+1]) sCloseSell[i]=0;
  }
  // delete the alerts outside the specified range of dates
  for(i=0;i<DisplayBars;i++) 
  {
    if(Time[i]<DateStart || DateEnd<Time[i]) { sBuy[i]=0; sSell[i]=0; sCloseBuy[i]=0; sCloseSell[i]=0; }
  }
  // add forcible closing marginal positions
  if(DateEnd<=Time[0]) { i=iBarShift(Symbol(),Period(),DateEnd); sBuy[i]=0; sSell[i]=0; 
                                                             sCloseBuy[i]=1; sCloseSell[i]=1; }
  if(DateEnd >Time[0]) { sCloseBuy[0]=1; sCloseSell[0]=1; }
  //————————————————————————————————————————————————————————————————————————————————————————————————————————
  // count the amount of alerts

  for(i=0;i<DisplayBars;i++) 
  {
    if(sBuy [i]!=0) sBuyCnt++;  if(sCloseBuy [i]!=0) sBuyCloseCnt++;
    if(sSell[i]!=0) sSellCnt++; if(sCloseSell[i]!=0) sSellCloseCnt++;
  }
  //————————————————————————————————————————————————————————————————————————————————————————————————————————
  // place the marks, draw a ZZ and calculate the profits
  //————————————————————————————————————————————————————————————————————————————————————————————————————————
  // process BUY trades
  for(i=DisplayBars-1;i>=0;i--) // go and collect the points
  {
    // find the next OPEN point and save its location and price
    for(i1=i;i1>=0;i1--) if(sBuy[i1]!=0) break; 
 
    // find the next CLOSE point of a BUY trade and save its location and price
    for(i2=i1-1;i2>=0;i2--) if(sCloseBuy[i2]!=0) break;
    if(i2<0) i2=0; // for the last unclosed position, calculate the CLOSE on the current price
    i=i2; // new bar to continue searching for OPEN points
 
    // define the prices for drawing according to the parameter of optimism, Optimizm
    if(Optimizm<0)  { P1=High[i1]; P2=Low[i2];  } 
    if(Optimizm==0) { P1=Open[i1]; P2=Open[i2]; } 
    if(Optimizm>0)  { P1=Low[i1];  P2=High[i2]; } 
    
    P1/=Point; P2/=Point; // express prices in points
    
    // find the profit and fill out the corresponding buffer
    if(i1>=0) 
    { 
      Profit=Profit+P2-P1; // collect the summed profit
      if(P2-P1>=0) CntProfit++; else CntLoose++; // count the number of orders
      DrawLine(i1,i2,OP_BUY,Optimizm); // draw the order line
      PlaceMarker(i1,OP_BUY); 
      PlaceMarker(i2,OP_CLOSE_BUY); 
    }
  }
  //————————————————————————————————————————————————————————————————————————————————————————————————————————
  // process the SELL trades
  for(i=DisplayBars-1;i>=0;i--) // go and collect the points
  {
    // find the next OPEN point and save its location and price
    for(i1=i;i1>=0;i1--) if(sSell[i1]!=0) break; 
 
    // find the next CLOSE point of a SELL trade and save its location and price
    for(i2=i1-1;i2>=0;i2--) if(sCloseSell[i2]!=0) break;
    if(i2<0) i2=0; // for the last unclosed position, calculate the CLOSE on the current price
    i=i2; // new bar to continue searching for OPEN points
 
    // define the prices for drawing according to the parameter of optimism, Optimizm
    if(Optimizm<0)  { P1=Low[i1];  P2=High[i2]; } 
    if(Optimizm==0) { P1=Open[i1]; P2=Open[i2]; } 
    if(Optimizm>0)  { P1=High[i1]; P2=Low[i2];  } 
    
    P1/=Point; P2/=Point; // express prices in points
    
    // if there are both points available, find the profit and fill the corresponding buffer
    if(i1>=0) 
    { 
      Profit=Profit+P1-P2; // collect the summed profit
      if(P1-P2>=0) CntProfit++; else CntLoose++; // count the number of orders
      DrawLine(i1,i2,OP_SELL,Optimizm); // draw the order line
      PlaceMarker(i1,OP_SELL); 
      PlaceMarker(i2,OP_CLOSE_SELL);
    }
  }
  //————————————————————————————————————————————————————————————————————————————————————————————————————————
  // calculating the totals for commenting  
  int Cnt=CntProfit+CntLoose; // total number of operations
  // coefficient to transfer points into the deposit currency
  double ToCurrency = MarketInfo(Symbol(),MODE_TICKVALUE)*LotForCalc;    
  string msg="Период: "+TimeToStr(MathMax(DateStart,Time[Bars-1]))+" - "
                                                      + TimeToStr(MathMin(DateEnd,Time[0]))+"\n\n";
  
  msg=msg+
  sBuyCnt+" BUY trades and "+sBuyCloseCnt+" their closings\n"+
  sSellCnt+" SELL trades and "+sSellCloseCnt+" their closings\n\n";
  
  // total time in days
  int TotalDays = (MathMin(DateEnd,Time[0])-MathMax(DateStart,Time[Bars-1]))/60/60/24; 
                                                                       //translate seconds into days
  if(TotalDays<=0) TotalDays=1; // to avoid zero divide for shorter days
  
  if(Cnt==0) msg=msg+("No operations");
  else msg=msg+
  (
    DoubleToStr(Profit,0)+" point on "+Cnt+" operations for "+TotalDays+" days\n"+
    DoubleToStr(Profit/Cnt,1)+" point for operation ("+
    DoubleToStr(Profit/TotalDays,1)+" within a day)\n\n"+
    "When trading with "+DoubleToStr(LotForCalc,2)+" obtain in "+AccountCurrency()+":\n"+
    DoubleToStr(Profit*ToCurrency,0)+" totally, by "+
    DoubleToStr(Profit/Cnt*ToCurrency,1)+" per trade ("+
    DoubleToStr(Profit/TotalDays*ToCurrency,1)+" within one day)\n\n"+
    CntProfit+" profitable ("+DoubleToStr(((CntProfit)*1.0/Cnt*1.0)*100.0,1)+"%)\n"+
    CntLoose+" losing ("+DoubleToStr(((CntLoose)*1.0/Cnt*1.0)*100.0,1)+"%)"
  );
  Comment(msg);
  
}
//——————————————————————————————————————————————————————————————————————————————————————————————————————————
 
 
 
//——————————————————————————————————————————————————————————————————————————————————————————————————————————
// deleting all objects from our chart
void ClearMarkers() 
{ 
  for(int i=0;i<ObjectsTotal();i++) 
  if(StringFind(ObjectName(i),MrakerPrefix)==0) { ObjectDelete(ObjectName(i)); i--; } 
}
//——————————————————————————————————————————————————————————————————————————————————————————————————————————
// placing a vertical line - marks of the operation of the op_type type
void PlaceMarker(int i, int op_type)
{
  if(!ShowMARKERS) return; // displaying markers disabled
 
  color MarkerColor; string MarkName; 
 
  // __ for the CLOSE line to be drawn below the OPEN line at sorting 
  if(op_type==OP_CLOSE_SELL) { MarkerColor=ColorClose; MarkName=MrakerPrefix+"__SELL_"+i; }
  if(op_type==OP_CLOSE_BUY)  { MarkerColor=ColorClose; MarkName=MrakerPrefix+"__BUY_"+i;  }  
  if(op_type==OP_SELL)       { MarkerColor=ColorSell;  MarkName=MrakerPrefix+"_SELL_"+i;  }
  if(op_type==OP_BUY)        { MarkerColor=ColorBuy;   MarkName=MrakerPrefix+"_BUY_"+i;   }
 
  ObjectCreate(MarkName,OBJ_VLINE,0,Time[i],0); 
  ObjectSet(MarkName,OBJPROP_WIDTH,1); 
  if(op_type==OP_CLOSE_BUY || op_type==OP_CLOSE_SELL) ObjectSet(MarkName,OBJPROP_STYLE,STYLE_SOLID); 
  else ObjectSet(MarkName,OBJPROP_STYLE,STYLE_DOT);
  ObjectSet(MarkName,OBJPROP_BACK,True);  
 
  ObjectSet(MarkName,OBJPROP_COLOR,MarkerColor);
}
//——————————————————————————————————————————————————————————————————————————————————————————————————————————
// placing a line on the chart for the operation of the op_type type at the prices of parameter Optimizm
void DrawLine(int i1,int i2, int op_type, int Optimizm)
{
  if(!ShowZZ) return; // ZZ displaying disabled
  
  color СurColor;
  string MarkName=MrakerPrefix+"_"+i1+"_"+i2;
  double P1,P2;
  
  // define prices for drawing, according to parameter Optimizm
  if(Optimizm<0 && op_type==OP_BUY)  { P1=High[i1]; P2=Low[i2];  } 
  if(Optimizm<0 && op_type==OP_SELL) { P1=Low[i1];  P2=High[i2]; } 
  if(Optimizm==0)                    { P1=Open[i1]; P2=Open[i2]; } 
  if(Optimizm>0 && op_type==OP_BUY)  { P1=Low[i1];  P2=High[i2]; } 
  if(Optimizm>0 && op_type==OP_SELL) { P1=High[i1]; P2=Low[i2];  } 
 
  ObjectCreate(MarkName,OBJ_TREND,0,Time[i1],P1,Time[i2],P2);
  
  ObjectSet(MarkName,OBJPROP_RAY,False); // draw segments, not lines
  ObjectSet(MarkName,OBJPROP_BACK,False);
  ObjectSet(MarkName,OBJPROP_STYLE,STYLE_SOLID);
  ObjectSet(MarkName,OBJPROP_WIDTH,2);
 
  // set line color depending on the profitability of the trade
  if(op_type==OP_BUY) 
  { 
    if(P1 <P2) СurColor = ColorProfitBuy;
    if(P1==P2) СurColor = ColorZeroBuy;
    if(P1 >P2) СurColor = ColorLossBuy;
  }
  if(op_type==OP_SELL) 
  { 
    if(P1 >P2) СurColor = ColorProfitSell;
    if(P1==P2) СurColor = ColorZeroSell;
    if(P1 <P2) СurColor = ColorLossSell;
  }
  ObjectSet(MarkName,OBJPROP_COLOR,СurColor);
}
//——————————————————————————————————————————————————————————————————————————————————————————————————————————
Os parâmetros de indicador contêm um parâmetro especial, Optimizm. Ele define o grau necessário de otimismo nos cálculos. Caso seu valor seja abaixo de zero, isso significa que os cálculos serão completamente pessimistas: para os preços BUY, ele escolherá High da barra de alerta, para os preços SELL - Low. É dessa forma que os piores resultados possíveis são modelados de forma que possamos obtê-los pelos alertas. Caso seu valor seja acima de zero, o cálculo mais otimista será modelado: comprar pelo mais baixo e vender pelo mais alto. Se o valor deste parâmetro for igual a zero, o comportamento neural será formado ao abrirmos e fecharmos as ordens nos preços de barras OPEN - é essa situação que é normalmente percebida ao negociar com EAs.

Como analisar resultados

Agora, vamos ver os resultados. Aqui está o resultado obtido na análise objetiva de zigzag.

Veja, o gráfico mostra oito partes de perda. Bem, o zigzag "trabalha" com os melhores preços e para reconstrui-lo devemos definir o parâmetro Optimizm = 1.

O resultado, se negociássemos da pior maneira possível, pode ser visto se definirmos o parâmetro Optimizm = -1


Uma pequena digressão

Prezados traders,

Não me culpem, mas esse indicador pode ser uma boa chicotada se ocorrer em mãos com gerenciamento habilidoso, que normalmente não se interessam por detalhes de táticas de negociação - elas se interessam apenas pelo resultado. Carregando o algoritmo de alertas ZigZag em um provador e definindo Optimizm = 1, eles obterão as figuras de lucro máximo que poderiam ser obtidas dessa parte do gráfico e que gostariam que você obtivesse. E se você sempre negocia menos da metade, isso os fará pensar que você pode ser muito indiferente às suas obrigações.

Por outro lado, essa ferramenta pode ser uma boa defesa contra demandas injustamente íngremes. Você terá argumentos base de que os planos que eles definiram para você são irreais e não podem ser obtidos mesmo nas condições mais favoráveis.

Veremos que, o uso do parâmetro Optimizm único permite o uso do indicador para a estimativa em potencial de um indicador de alertas testado nele. E mesmo se o cálculo mais otimista não tiver lucro, o indicador testado de alertas deve ser corrigido: você deve encontrar outros parâmetros para ele ou no pior caso, esquecê-lo pela economia de tempo desamparada do desenvolvimento de EA e do dinheiro do seu depósito que pode ser perdido para obter provas de que o indicador não funciona. Assim, nosso indicador de teste permite a economia não apenas de tempo, mas também de dinheiro.

Como analisar alertas de sistemas de negociação

Os buffers de outros indicadores não são a única fonte para preencher as séries de alertas, nas quais nosso indicador de teste opera. Em algum lugar nos livros ou nas profundezas da Internet, é possível encontrar a descrição de alertas de um sistema de negociação, para os qual não há indicadores ou Expert Advisors. Isso é somente um conjunto de regras que pode ser facilmente implementado no MQL4. Se você consegue escrever o cálculo de alertas para tal sistema e preencher os buffers de alerta com eles, o indicador de teste mostrará a você os resultados que você pode obter usando o sistema.

Se houver um código pronto para um sistema, é possível selecionar o cálculo de alertas, nos quais o EA opera, e construir os "resultados dessa operação" diretamente no gráfico. Claro que o mesmo pode ser obtido de forma ainda mais precisa no provador de estratégia MetaTrader 4, mas o indicador realizará as reconstruções mais rapidamente e as refletirá mais vividamente que as linhas estritas de um provador.

Um momento importante nesse caso e a possibilidade de unificar o gráfico dos resultados obtidos com outros indicadores. As linhas de marcas verticais cruzando os indicadores adicionais lhe dirão como podem ser usadas para alertas principais específicos ou irão detectar os lugares da sua operação inadequada. Por fim, apenas pelo método impreciso podemos escolher tais parâmetros de valores que provavelmente seriam mais adequados para nós que os resultados do otimizador.

Vamos pegar como exemplo o código pronto do padrão MACD. É assim que ele deve parecer. Bloco de preenchimento de séries de alerta, os conteúdos do qual são copiados e colocado do texto indicador:

// fill out alert arrays with values and count them
  for(i=DisplayBars;i>=0;i--) 
  {
    double MacdCurrent, MacdPrevious, SignalCurrent;
    double SignalPrevious, MaCurrent, MaPrevious;
  
    // to simplify the coding and speed up access
    // data are put into internal variables
    MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,i+0);
    MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,i+1);
    SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,i+0);
    SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,i+1);
    MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,i+0);
    MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,i+1);
    
    // check for long position (BUY) possibility
    if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious<SignalPrevious &&
       MathAbs(MacdCurrent)>(MACDOpenLevel*Point) && MaCurrent>MaPrevious) sBuy[i]=1;
       
    // check for short position (SELL) possibility
    if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious && 
       MathAbs(MacdCurrent)>(MACDOpenLevel*Point) && MaCurrent<MaPrevious) sSell[i]=1;
       
    if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious &&
       MathAbs(MacdCurrent)>(MACDCloseLevel*Point)) sCloseBuy[i]=1;
 
    if(MacdCurrent<0 && MacdCurrent>SignalCurrent &&  MacdPrevious<SignalPrevious && 
       MathAbs(MacdCurrent)>(MACDCloseLevel*Point)) sCloseSell[i]=1;
  }

E aqui está o resultado:

Observe que as linhas de marcas de alerta correspondem completamente aos pontos de cruzamento dos gráficos MACD. Talvez ao olhar para esses gráficos unidos você decida o que exatamente deveria ser alterado nos alertas. Por exemplo, que MaCurrent e MaPrevious não precisam de verificação. Um pequeno código corrigido:

  // fill out alert arrays with values and count them
  for(i=DisplayBars;i>=0;i--) 
  {
    double MacdCurrent, MacdPrevious, SignalCurrent;
    double SignalPrevious, MaCurrent, MaPrevious;
  
    // to simplify the coding and speed up access
    // data are put into internal variables
    MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,i+0);
    MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,i+1);
    SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,i+0);
    SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,i+1);
    MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,i+0);
    MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,i+1);
    
    // check for long position (BUY) possibility
    if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious<SignalPrevious &&
       MathAbs(MacdCurrent)>(MACDOpenLevel*Point)) sBuy[i]=1;
       
    // check for short position (SELL) possibility
    if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious && 
       MathAbs(MacdCurrent)>(MACDOpenLevel*Point)) sSell[i]=1;
       
    if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious &&
       MathAbs(MacdCurrent)>(MACDCloseLevel*Point)) sCloseBuy[i]=1;
 
    if(MacdCurrent<0 && MacdCurrent>SignalCurrent &&  MacdPrevious<SignalPrevious && 
       MathAbs(MacdCurrent)>(MACDCloseLevel*Point)) sCloseSell[i]=1;
  }

Veja qual é o resultado. O número de operações aumentou de 19 para 51. Embora o lucro total tenha virado perdas, o que mostra que não foi uma boa ideia melhorar a qualidade do alerta.

Fantasias de teste

Cada desenvolvedor com certeza tem algumas ideias intrusivas que nunca são consideradas. O provador de indicadores ajudará a visualizá-las e estimá-las rapidamente. Se as ideias parecem estar corretas e os resultados obtidos são positivos, um desenvolvedor pode pensar em escrever um indicador ou Expert Advisor. Nesse caso, os resultados do provador de indicador serão ao mesmo tempo uma ilustração das especificações exigidas para o desenvolvimento e um exemplo final, de acordo com o qual o produto pronto será verificado.

Veja aqui um exemplo de "sistema" primitivo: comprar usando um indicador MA simples. Condição da compra - crescimento de MA, condição da venda - MA cai. Veja como verificar rapidamente a rentabilidade dessa ideia. Aqui está o bloco de preenchimento de alerta:

 // fill out alert arrays with values and count them
  for(i=DisplayBars;i>=0;i--) 
  {
    double m1=iMA(NULL,0,MAPeriod,0,MAMode,MAPrice,i+1);
    double m2=iMA(NULL,0,MAPeriod,0,MAMode,MAPrice,i+2);
    
    // open conditions are at the same time close conditions of an opposite order
    if(m2<=m1 && MathAbs(m1-m2)>0.2*Point) { sBuy[i]=1; sCloseSell[i]=1; sBuyCnt++; sSellCloseCnt++; }
    if(m2>=m1 && MathAbs(m1-m2)>0.2*Point) { sSell[i]=1; sCloseBuy[i]=1; sSellCnt++; sBuyCloseCnt++; }
  }

E aqui estão os resultados:

Não são ruins, mas não são o melhor resultado - porque imaginamos lucros incríveis. Agora, vamos tentar diminuir o período de MA para aumentar a possibilidade de vencer em negociações de lucro. Diminuindo o período de 15 para 7 barras, conseguimos aumentar a média diária de lucro quase duas vezes:

O que resta é tornar a correlação de negociações rentáveis e com perda igual em pelo menos de 80% a 20%. Mas você terá de fazer isso sem minha ajuda.

Conclusão

Agora você tem mais uma ferramenta para expressar a análise de indicadores e alertas de negociação. Naturalmente, ela não substitui o provador ou a negociação real. Todos os dados obtidos usando essa ferramenta são de caráter descritivo e de estimativa. Entretanto, a conveniência de operação, visualização e velocidade dos dados obtidos me faz acreditar que essa ferramenta pode ser muito útil para qualquer desenvolvedor. Ela ajuda a verificar rapidamente ideias de negociação, sem perder muito tempo e esforço. Até certo ponto, ela pode ser a prova de uma ideia ser promissora ou fadada ao fracasso. E para um investigador racional ou experimentalista, essa pode ser a ferramenta de otimização delicada de parâmetros de indicador.


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

Arquivos anexados |
IndicatorTester.mq4 (15.96 KB)
Dormir ou não dormir? Dormir ou não dormir?
Uma alternativa à função Sleep() na realização de pausas entre as ações do EA é proposta. A abordagem em consideração permite o uso inteligente do tempo da máquina.
A ociosidade é o estímulo do progresso. Marcação semiautomática de um modelo A ociosidade é o estímulo do progresso. Marcação semiautomática de um modelo
Entre as dezenas de exemplos de como trabalhar com gráficos, há um método de marcação manual de um modelo. Linhas de tendência, canais, níveis de suporte/resistência etc. são impostos em um gráfico. Com certeza, há alguns programas especiais para esse tipo de trabalho. Todo mundo decide sobre qual método usar. Neste artigo, ofereço uma opção para você considerar de métodos de marcação manual com a automatização subsequente de alguns elementos das ações de rotina repetidas.
Pasta do programa do terminal do cliente MetaTrader 4 Pasta do programa do terminal do cliente MetaTrader 4
O artigo descreve os conteúdos da pasta do programa do terminal do cliente MetaTrader 4. Ele será útil para aqueles que já começaram a compreender os detalhes da operação do terminal do cliente.
Visão de Análise técnica no contexto de sistemas de controle automático (ACS) ou "Visão reversa" Visão de Análise técnica no contexto de sistemas de controle automático (ACS) ou "Visão reversa"
O artigo demonstra uma visão alternativa de análise técnica, que é baseada nos princípios da teoria de controle automático moderna e da própria teoria de análise técnica. O artigo é introdutório, representando a teoria com algumas aplicações práticas da mesma.