English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
Indicador para representação de gráfico Kagi

Indicador para representação de gráfico Kagi

MetaTrader 5Exemplos | 28 março 2014, 15:15
4 201 0
Dmitriy Zabudskiy
Dmitriy Zabudskiy

Introdução

O artigo "Indicador para traçar ponto e figura" descreveu uma da formas de programação de criação de Gráfico de ponto e figura. Este gráfico é conhecido desde o século 19. No entanto, este não é o único gráfico do passado distante. Outro representante notável dos primeiros tipos de representação do mercado financeiro é o Gráfico Kagi. Este gráfico será discutido no presente artigo.

A bolsa de valores - instituição financeira desconhecida para o século 19 no Japão - foi fundada em maio de 1878. É conhecida como a Bolsa de valores de Tokyo hoje em dia. Este evento teve um papel vital na criação e no posterior desenvolvimento de gráficos Kagi. A Europa e os EUA foram saber de gráficos Kagi após a publicação de Steve Nison "Beyond Candlesticks: New Japanese Charting Techniques Revealed" em 1994.

As palavras japonesas "Kagi" significam uma chave em forma de L que estava em uso no momento do desenvolvimento do gráfico. Além disso, há uma versão modificada do nome - "gráfico chave". Na publicação de Steve Nison de "Beyond Candlesticks", você também pode encontrar os nomes alternativos do gráfico: gráfico faixa de preço, gráfico gancho, gráfico delta ou cadeia.

O que é tão especial sobre este gráfico? Sua principal característica é que ele ignora a escala de tempo, deixando apenas a escala de preço (ao contrário dos gráficos de castiçais japoneses, barras e linhas). Assim, o gráfico esconde flutuações de preços insignificantes, deixando apenas os mais significativos.

O gráfico representa um conjunto de linhas espessas Yan e linhas finas Yin substituindo umas as outras, dependendo da situação do mercado. No caso do mercado se mover na mesma direção, a linha é estendida atingindo uma nova faixa de preço. No entanto, se o mercado girar para trás e atingir uma quantia predefinida, a linha Kagi é desenhada na direção oposta na coluna nova. A quantia predefinida é estabelecida tanto em pontos (geralmente usados para pares de moedas), ou em valor percentual do preço atual (normalmente usado para ações). A espessura da linha varia dependendo do avanço mais próximo de alta ou de baixa.


1. Exemplo de gráfico

Vamos usar dados do histórico no EURUSD, H1 de 8 a 11 de outubro.

Um exemplo de imagens padrão com limiar inversa de 15 pontos é exibida na fig. 1:

Gráfico Kagi, EURUSD H1

Fig. 1. Gráfico Kagi, EURUSD H1

Como podemos ver, o preço começou a cair as 17:00 horas. O movimento de queda continuou até as 21:00 horas. As 22:00 horas, o preço subiu de 1.3566 e é fechado em 1.3574. Em outras palavras, o preço passa de 11 pontos. Isso não é suficiente para uma inversão, mas a nova baixa não foi atingida também. As próximas duas horas, o preço vai ficar invariável e finalmente, a 01:00 hora (09 de outubro), vemos um forte movimento ascendente, que se fechou em 1.3591 englobando 25 pontos (1.3591-1.3566). Isto significa que o preço inverteu-se.

A tendência de alta continua na hora seguinte. O preço chega a 1.3599 reforçando a linha espessa Yang. As 03:00 horas, o preço cai drasticamente fechando em 1.3578, que é 21 pontos da alta anterior (1.3599-1.3578). Isso é mais do que suficiente para a inversão. A linha se move para baixo, mas mantém a sua forma (linha espessa Yang).

Até as 16:00 horas, o preço cai e, finalmente, rompe o mínimo mais próximo e muda da linha espessa de Yang para a linha fina de Yin. O baixo valor mencionado anteriormente de 1.3566 serviu como um preço imbatível aqui. O preço continua movendo-se como uma linha de Yin e é alterado para Yang as 14:00 horas em 10 de outubro, rompendo a alta mais próxima de 1.3524 formada as 23:00 horas (9 de outubro). Este pequeno exemplo mostra como o gráfico Kagi é formado.


2. Princípio de gráfico indicador Kagi

A fim de tornar o indicador independente do período de tempo atual, foi decidido copiar os dados do período de tempo, em que o indicador foi supostamente formado de forma separada e depois criar o indicador usando os dados obtidos.

Isso permite examinar vários prazos de tempo simultaneamente em um único gráfico expandindo os limites da análise técnica sobre gráficos Kagi. O indicador em si está localizado numa janela separada, mas também é possível visualizar os dados do gráfico principal. Em outras palavras, a formação de base (padrão ou modificado) é realizada na janela indicadora. O indicador é copiado para o gráfico principal, assim como os preços e as marcas de tempo (dependendo das configurações) são desenhados.

Como mencionado anteriormente, o indicador desenha o gráfico tanto na versão padrão como na modificada. A versão padrão foi descrita acima. Agora, vamos considerar a versão modificada.

Eu não sei se é uma ideia nova, mas eu não ouvi falar de tal versão. A ideia do filtro adicional é que não só reverte pontos, mas cada movimento do gráfico é agora filtrado. Em outras palavras, o preço deve mover uma certa distância especificada para que a nova alta ou baixa (não confundir com o ombro/cintura) seja formada. Em geral, sempre que o preço se move, ele deve primeiro cobrir uma distância especificada. Depois disso, ele é definido como se fosse uma continuação de tendência ou uma inversão.

A fig. 2 mostra como os princípios funcionam. O visual do gráfico modificado é mostrado em azul, enquanto o padrão - em vermelho. Como podemos ver, o visual modificado responde às alterações do movimento de preço, filtrando lentamente a maioria dos sinais menores.

As versões padrão e modificadas de criar o gráfico Kagi

Fig. 2. As versões modificada (linha azul) e padrão (linha vermelha) de criação de gráfico Kagi

Além do gráfico Kagi, o indicador fornece alguns elementos adicionais, tanto na janela do indicador como no gráfico principal.

Dependendo das configurações, as marcas podem ser definidas na janela do indicador. Estas marcas fornecem dados sobre preços de inversão. A mesma função é realizada através de níveis de preços, o que (dependendo das configurações) pode distribuir uniformemente ao longo da janela em toda a faixa de preço utilizado para a formação do indicador ou a cada inversão do gráfico. As cores podem ser definidas em três versões: de acordo com o tipo de inversão (para cima - para baixo), tipo de linha (Yin - Yang) ou sem mudança de cor.

As marcas de preço de inversão, incluindo as temporárias, são fornecidas no gráfico principal. Estas marcas (dependendo das configurações) podem ser de uma única cor ou mudar a cor de acordo com as cores das linhas de Yin ou Yang.

O código indicador inteiro é implementado usando as funções de comunicação umas com as outras através de variáveis globais.

O código pode ser dividido em três funções principais e outras onze adicionais. A principal dificuldade dos cálculos e preenchimentos de buffer de construções gráficas básicas e de matrizes adicionais é apoiar-se na função da formação do gráfico Kagi na janela indicadora. As outras duas funções são responsáveis por fornecer os dados: a primeira copia os dados de tempo, enquanto a outra - os dados sobre os preços de cada barra do período de tempo selecionado.

As funções auxiliares restantes são responsáveis por executar todas as construções, excluir os objetos, descarregar o indicador acompanhado pela exclusão de todos os objetos do indicador, cálculo de parâmetros de inversão, desenhar marcas no gráfico principal e na janela indicadora, criar objetos gráficos do tipo "linha de tendência", desenhar Kagi no gráfico principal, bem como definir a chegada da nova barra para iniciar a formação do indicador.


3. Código e algoritmo indicador

Agora, vamos examinar o código e o algoritmo indicador da sua formação em detalhes. O código é muito grande e pode ser bem difícil para programadores iniciantes compreendê-lo. As funções se comunicam umas com as outras através de variáveis ​globais tornando o código um pouco confuso. Nesta parte do artigo, explicarei cada função e parte do código separadamente. Primeiro, descreverei as configurações do indicador e, em seguida, haverá esclarecimentos sobre funções iniciais de cópia de dados, cálculo de parâmetros de inversão, função principal da formação e cálculo de gráfico Kagi e outras funções auxiliares.

3.1. Parâmetros de entrada do indicador

O código começa com a declaração do indicador em uma janela separada, bem como de 12 buffers e de 8 construções gráficas de indicador. Primeiro de tudo, vamos definir o porquê de construções gráficas, incluindo dois "histogramas" e seis "linhas", terem sido usadas. Cada "histograma" constrói sua própria linha vertical. Uma das linhas é responsável pela linha Yin, enquanto que a outra para linha Yang.

O caso é um pouco mais complicado com as "linhas", uma vez que existem três delas para cada linha. Isto é feito devido ao fato de que a linha é desenhada caso haja um outro ponto desenhado perto do primeiro. Em outras palavras, precisamos de apenas duas construções de gráfico do tipo "linha"a serem rodados para desenhar duas linhas adjacentes umas às outras. No entanto, se vamos precisar omitir pontos necessários, temos a terceira construção a ser rodada com mais outras duas.

Isso é explicado na Figura 3, onde você pode ver o que acontece, se apenas duas construções de gráfico do tipo "linha" forem usadas:


 Fig. 3. Exemplo do uso de duas construções de gráfico do tipo "linha"para exibir linhas de ombro e cintura.

Em seguida, o menu de configurações é criado. Há cinco enumerações aqui (vamos examiná-las nos parâmetros de entrada).

A primeira entrada de parâmetro "período" é um período em que a construção é realizada, ela é seguida por "period_to_redraw" - período de atualização da construção de gráfico e o último parâmetro é "start_data" - o início da construção do tempo.

Esses parâmetros são seguidos por construção de gráfico e por parâmetros de etiquetagem adicional:

  • kagi_type - tipo de construção de gráfico definido pelo usuário, padrão ou modificado;
  • price_type - tipo do preço usado para a construção: Fechado, aberto, alta e baixa;
  • type_doorstep - tipo inversão usado: ponto e porcentagem;
  • doorstep - valor de inversão (especificado em pontos ou valor em porcentagem, dependendo do parâmetro acima);
  • color_yin - cor da linha Yin na janela indicadora;
  • color_yang - cor da linha Yang na janela indicadora;
  • width_yin - largura da linha Yin na janela indicadora;
  • width_yang - largura da linha Yang na janela indicadora;
  • levels_on_off - caso níveis de preço devam ser desenhados na janela indicadora;
  • levels_type - tipos de níveis de preços na janela indicadora. Existem dois valores para escolher: a cada inversão ou através da taxa de preço de forma uniforme;
  • levels_number - número de níveis de preço na janela indicadora;
  • levels_change_color - permite alterar a cor das linhas do nível de preços, as opções são reversões superiores e inferiores, linhas Yin e Yang ou nenhuma alteração;
  • levels_first_color - a primeira cor de um nível de preço;
  • levels_second_color - a segunda cor de um nível de preço;
  • label_1 - etiquetas de preço de inversão de gráfico de desenho na janela indicadora;
  • label_1_number - número de etiquetas exibido na janela indicadora;
  • label_1_color – cor das etiquetas de preço na janela indicadora;
  • label_2 - etiquetas de preço de desenho no gráfico principal;
  • label_2_color - cor da etiqueta no gráfico principal;
  • time_line_draw - linhas de tempo de inversão de desenho no gráfico principal;
  • time_separate_windows - continuação de desenho de linhas de tempo de inversão a partir do gráfico principal;
  • time_line_change_color - mudança de cor da linha do tempo de acordo com a etiqueta de inversão na linha Yin ou Yang;
  • time_first_color - a primeira cor da linha do tempo no gráfico principal;
  • time_second_color - a segunda cor da linha do tempo no gráfico principal;
  • kagi_main_chart - se Kagi deve ser desenhado no gráfico principal;
  • color_yin_main - cor da linha Yin no gráfico principal;
  • color_yang_main - cor da linha Yang no gráfico principal;
  • width_yin_main - largura da linha Yin no gráfico principal;
  • width_yang_main - largura da linha Yang no gráfico principal;
  • magic_numb - número mágico utilizado para a construção de objetos e sua exclusão, bem como no nome indicador, a fim de iniciar vários indicadores em um único gráfico.

Estes parâmetros são, por sua vez seguidos por declarações dos buffers indicadores, buffers auxiliares para armazenar preços e valores de tempo, variáveis auxiliares (stop_data, bars_copied, bars_copied_time, copy_history, copy_time), matrizes de armazenamento de dados nas quais as linha Yin ou Yang marcam a mudança do movimento de gráfico que ocorreu, o tempo e o preço dessa mudança, o preço central (se Yin é substituído por Yang na barra ou vice- versa). Finalmente, uma das variáveis​ globais mais utilizadas que contenham dados sobre o número de alterações de movimento do gráfico "а" é declarada.

//+------------------------------------------------------------------+
//|                                                         BKCV.mq5 |
//|                                   Azotskiy Aktiniy ICQ:695710750 |
//|                          https://www.mql5.com/pt/users/Aktiniy |
//+------------------------------------------------------------------+
//--- Build Kagi Chart Variable
#property copyright "Azotskiy Aktiniy ICQ:695710750"
#property link      "https://www.mql5.com/pt/users/Aktiniy"
#property version   "1.00"
#property description "Build Kagi Chart Variable"
#property description " "
#property description "This indicator makes drawing a chart Kagi as a matter of indicator window, and in the main chart window"
#property indicator_separate_window
#property indicator_buffers 12
#property indicator_plots   8
//--- plot Yin
#property indicator_label1  "Yin"
#property indicator_type1   DRAW_HISTOGRAM2
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot Yin1
#property indicator_label2  "Yin1"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- plot Yin2
#property indicator_label3  "Yin2"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrRed
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1
//--- plot Yin3
#property indicator_label4  "Yin3"
#property indicator_type4   DRAW_LINE
#property indicator_color4  clrRed
#property indicator_style4  STYLE_SOLID
#property indicator_width4  1
//--- plot Yang
#property indicator_label5  "Yang"
#property indicator_type5   DRAW_HISTOGRAM2
#property indicator_color5  clrRed
#property indicator_style5  STYLE_SOLID
#property indicator_width5  2
//--- plot Yang1
#property indicator_label6  "Yang1"
#property indicator_type6   DRAW_LINE
#property indicator_color6  clrRed
#property indicator_style6  STYLE_SOLID
#property indicator_width6  2
//--- plot Yang2
#property indicator_label7  "Yang2"
#property indicator_type7   DRAW_LINE
#property indicator_color7  clrRed
#property indicator_style7  STYLE_SOLID
#property indicator_width7  2
//--- plot Yang3
#property indicator_label8  "Yang3"
#property indicator_type8   DRAW_LINE
#property indicator_color8  clrRed
#property indicator_style8  STYLE_SOLID
#property indicator_width8  2
//--- Enumerations as input data (for more attractive setting)
//--- Kagi charting type
enum kagi_type_enum
  {
   classic=0,  // Classic
   modified=1, // Modified
  };
//--- Type of the price used for construction
enum price_type_enum
  {
   c=0, // Close
   o=1, // Open
   h=2, // High
   l=3, // Low
  };
//--- Type of the used reversal
enum type_doorstep_enum
  {
   point=0,   // Point
   procent=1, // Percent
  };
//--- Type of levels location
enum levels_type_enum
  {
   cor=0, // Cornering
   equ=1, // Equal distance
  };
//--- Level colors change type (works when "Type of levels location"="Cornering")
enum levels_change_color_enum
  {
   up_down=0,  // Up & Down
   yin_yang=1, // Yin & Yang
   no=2,       // Don't change
  };
//--- input parameters
input ENUM_TIMEFRAMES period=PERIOD_CURRENT;                // Calculation period to build the chart
input ENUM_TIMEFRAMES period_to_redraw=PERIOD_M1;           // Refresh period chart
input datetime start_data=D'2013.07.10 00:00:00';           // Start time to build the chart
input kagi_type_enum kagi_type=classic;                     // The type to build Kagi chart
input price_type_enum price_type=c;                         // Price used to build chart
input type_doorstep_enum type_doorstep=point;               // Type calculate doorstep
input double   doorstep=25;                                 // Doorstep reversal
input color    color_yin=clrRed;                            // Color Yin line (indicator window)
input color    color_yang=clrRed;                           // Color Yang line (indicator window)
input char     width_yin=1;                                 // Width Yin line (indicator window)
input char     width_yang=2;                                // Width Yang line (indicator window)
input bool     levels_on_off=false;                         // Draw level (indicator window)
input levels_type_enum levels_type=cor;                     // Type of drawing levels (indicator window)
input uint     levels_number=6;                             // Number of levels  (indicator window)
input levels_change_color_enum levels_change_color=up_down; // Type change color of levels (indicator window)
input color    levels_first_color=clrBeige;                 // The first color of level (indicator window)
input color    levels_second_color=clrCoral;                // The second color of level (indicator window)
input bool     label_1=true;                                // Draw price label on (indicator window)
input uint     label_1_number=10;                           // The number of labels (indicator window)
input color    label_1_color=clrGreenYellow;                // The color of labels (indicator window)
input bool     label_2=true;                                // Draw price label on (main chart)
input color    label_2_color=clrGreenYellow;                // The color of labels (main chart)
input bool     time_line_draw=true;                         // Draw a timeline reversal (main chart)
input bool     time_separate_windows=false;                 // Draw a timeline reversal on indicator window
input bool     time_line_change_color=true;                 // Different color timeline on the Yin and Yang lines (main chart)
input color    time_first_color=clrRed;                     // The first color of timeline (main chart)
input color    time_second_color=clrGreenYellow;            // The second color of timeline (main chart)
input bool     kagi_main_chart=true;                        // Draw Kagi on main chart (main chart)
input color    color_yin_main=clrRed;                       // Color Yin line (main chart)
input color    color_yang_main=clrRed;                      // Color Yang line (main chart)
input char     width_yin_main=1;                            // Width Yin line (main chart)
input char     width_yang_main=2;                           // Width Yang line (main chart)
input long     magic_numb=65758473787389;                   // The magic number for drawing objects
//--- indicator buffers
double         YinBuffer1[];
double         YinBuffer2[];
double         Yin1Buffer[];
double         Yin2Buffer[];
double         Yin3Buffer[];
double         YangBuffer1[];
double         YangBuffer2[];
double         Yang1Buffer[];
double         Yang2Buffer[];
double         Yang3Buffer[];
//--- additional variables
double Price[]; // Buffer for storing the copied price data
double Time[];  // Buffer for storing the copied time data
//---
datetime stop_data;      // Current time
int bars_copied=0;       // Number of the already copied bars from the initial date
int bars_copied_time;    // Number of the already copied bars having the initial date
bool copy_history=false; // Price history copying result
bool copy_time=false;    // Time history copying result
//---
datetime time_change[];      // Array for writing the time when the chart movement started changing (up or down)
char time_line[];            // Array for storing the data on what line (Yin=0 or Yang=1) direction has changed
double time_change_price[];  // Array for writing the chart movement change price
double time_central_price[]; // Array for writing the average price during the chart movement change

uint a=0; // Variable for building the chart, number of chart reversals is fixed

  

3.2. Função de inicialização do indicador

A próxima é a função de inicialização do indicador. Os buffers indicadores e a sua correção de índice (principalmente como períodos de tempo, pois o gráfico Kagi é menor do que a principal, é melhor desenhá-lo de trás para frente) são especificados lá. Além disso, os valores que não devem ser exibidos na tela são definidos (EMPTY_VALUE=-1).

Agora, atribuímos o nome de indicador e precisão da tela. Como mencionado anteriormente, o número mágico é adicionado ao nome. Isto é feito para proporcionar a correta operação da função ChartWindowFind(). Caso contrário, o objeto gráfico desenhado na janela indicadora é exibido apenas no primeiro indicador iniciado (se vários indicadores em um único gráfico são usados).

Em seguida, atribuímos nomes às linhas de construção, proibimos a exibição dos valores numéricos atuais na janela indicadora, definimos a cor e a largura das linhas Yin e Yang, definimos o número de níveis de preço exibidos na janela do indicador.

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,YinBuffer1,INDICATOR_DATA);
   ArraySetAsSeries(YinBuffer1,true);
   SetIndexBuffer(1,YinBuffer2,INDICATOR_DATA);
   ArraySetAsSeries(YinBuffer2,true);
   SetIndexBuffer(2,Yin1Buffer,INDICATOR_DATA);
   ArraySetAsSeries(Yin1Buffer,true);
   SetIndexBuffer(3,Yin2Buffer,INDICATOR_DATA);
   ArraySetAsSeries(Yin2Buffer,true);
   SetIndexBuffer(4,Yin3Buffer,INDICATOR_DATA);
   ArraySetAsSeries(Yin3Buffer,true);
//---
   SetIndexBuffer(5,YangBuffer1,INDICATOR_DATA);
   ArraySetAsSeries(YangBuffer1,true);
   SetIndexBuffer(6,YangBuffer2,INDICATOR_DATA);
   ArraySetAsSeries(YangBuffer2,true);
   SetIndexBuffer(7,Yang1Buffer,INDICATOR_DATA);
   ArraySetAsSeries(Yang1Buffer,true);
   SetIndexBuffer(8,Yang2Buffer,INDICATOR_DATA);
   ArraySetAsSeries(Yang2Buffer,true);
   SetIndexBuffer(9,Yang3Buffer,INDICATOR_DATA);
   ArraySetAsSeries(Yang3Buffer,true);
//--- add the buffer for copying data on prices for calculation
   SetIndexBuffer(10,Price,INDICATOR_CALCULATIONS);
//--- add the buffer for copying data on bar open time for construction
   SetIndexBuffer(11,Time,INDICATOR_CALCULATIONS);

//--- set what values are not to be drawn
   for(char x=0; x<8; x++)
     {
      PlotIndexSetDouble(x,PLOT_EMPTY_VALUE,-1);
     }
//--- set the indicator's look
   IndicatorSetString(INDICATOR_SHORTNAME,"BKCV "+IntegerToString(magic_numb)); // Indicator name
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits); // Display accuracy
//--- assign names to graphical constructions
   PlotIndexSetString(0,PLOT_LABEL,"Yin");
   PlotIndexSetString(1,PLOT_LABEL,"Yin");
   PlotIndexSetString(2,PLOT_LABEL,"Yin");
   PlotIndexSetString(3,PLOT_LABEL,"Yin");
   PlotIndexSetString(4,PLOT_LABEL,"Yang");
   PlotIndexSetString(5,PLOT_LABEL,"Yang");
   PlotIndexSetString(6,PLOT_LABEL,"Yang");
   PlotIndexSetString(7,PLOT_LABEL,"Yang");
//--- prohibit display of the results of the current values for graphical constructions
   PlotIndexSetInteger(0,PLOT_SHOW_DATA,false);
   PlotIndexSetInteger(1,PLOT_SHOW_DATA,false);
   PlotIndexSetInteger(2,PLOT_SHOW_DATA,false);
   PlotIndexSetInteger(3,PLOT_SHOW_DATA,false);
   PlotIndexSetInteger(4,PLOT_SHOW_DATA,false);
   PlotIndexSetInteger(5,PLOT_SHOW_DATA,false);
   PlotIndexSetInteger(6,PLOT_SHOW_DATA,false);
   PlotIndexSetInteger(7,PLOT_SHOW_DATA,false);
//--- set color for Yin line
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,color_yin);
   PlotIndexSetInteger(1,PLOT_LINE_COLOR,color_yin);
   PlotIndexSetInteger(2,PLOT_LINE_COLOR,color_yin);
   PlotIndexSetInteger(3,PLOT_LINE_COLOR,color_yin);
//--- set color for Yang line
   PlotIndexSetInteger(4,PLOT_LINE_COLOR,color_yang);
   PlotIndexSetInteger(5,PLOT_LINE_COLOR,color_yang);
   PlotIndexSetInteger(6,PLOT_LINE_COLOR,color_yang);
   PlotIndexSetInteger(7,PLOT_LINE_COLOR,color_yang);
//--- set Yin line width
   PlotIndexSetInteger(0,PLOT_LINE_WIDTH,width_yin);
   PlotIndexSetInteger(1,PLOT_LINE_WIDTH,width_yin);
   PlotIndexSetInteger(2,PLOT_LINE_WIDTH,width_yin);
   PlotIndexSetInteger(3,PLOT_LINE_WIDTH,width_yin);
//--- set Yang line width
   PlotIndexSetInteger(4,PLOT_LINE_WIDTH,width_yang);
   PlotIndexSetInteger(5,PLOT_LINE_WIDTH,width_yang);
   PlotIndexSetInteger(6,PLOT_LINE_WIDTH,width_yang);
   PlotIndexSetInteger(7,PLOT_LINE_WIDTH,width_yang);
//--- set the number of levels in the indicator window
   IndicatorSetInteger(INDICATOR_LEVELS,levels_number);
//---
   return(INIT_SUCCEEDED);
  }


3.3. Função de cópia de dados

Agora vamos examinar as funções de cópia de dados.

Há duas delas aqui. A primeira é para copiar os preços, enquanto que a segunda é para copiar tempo aberto de cada barra. Ambas as funções mantêm seus valores em buffers de cálculo do indicador previamente declarado.

Primeiro, vamos considerar a função de cópia de preço. Parâmetros de entrada de função: a matriz para armazenamento de dados, início de término da cópia de dados (tempo atual). O corpo da função contém as variáveis de resposta para a função, o número de dados (barras) copiados à matriz intermediária, a própria matriz dinâmica intermediária e o número de barras que devem ser copiadas à matriz intermediária. O número de barras é calculado com base no número total de barras no período de tempo determinado e no número de barras (variável global) copiadas na chamada da função anterior.

Se não for a primeira vez que os dados foram copiados, os dados sobre a última barra copiada devem ser atualizados. Para fazer isso, reduzimos o número de barras copiadas por um e aumentamos o número de barras recém copiadas por um. Mudamos também o tamanho da matriz intermediária preparando-a para copiar as barras.

Dependendo das configurações, copiamos os preços para a matriz intermediária. Se a cópia for bem sucedida, os dados são copiados da matriz intermediária para o fim da matriz de buffer (matriz de resposta da função), atribuímos a resposta positiva à função e atualizamos a variável global armazenando os dados sobre o número de barras copiadas. Este tipo de cópia permite copiar apenas algumas últimas barras reduzindo o tempo de cópia.

//+------------------------------------------------------------------+
//| Func Copy History                                                |
//+------------------------------------------------------------------+
bool func_copy_history(double &result_array[],
                       datetime data_start,
                       datetime data_stop)
  {
//---
   int x=false; // Variable for answer

   int result_copy=-1; // Number of copied data

   static double price_interim[]; // Temporary dynamic array for storing copied data
   static int bars_to_copy;       // Number of bars for copying

   bars_to_copy=Bars(_Symbol,period,data_start,data_stop); // Find out the current number of bars on the time interval
   bars_to_copy-=bars_copied; // Calculate the number of bars to be copied

   if(bars_copied!=0) // If it is not the first time the data has been copied
     {
      bars_copied--;
      bars_to_copy++;
     }

   ArrayResize(price_interim,bars_to_copy); // Change the size of the receiving array

   switch(price_type)
     {
      case 0:
         result_copy=CopyClose(_Symbol,period,0,bars_to_copy,price_interim);
         break;
      case 1:
         result_copy=CopyOpen(_Symbol,period,0,bars_to_copy,price_interim);
         break;
      case 2:
         result_copy=CopyHigh(_Symbol,period,0,bars_to_copy,price_interim);
         break;
      case 3:
         result_copy=CopyLow(_Symbol,period,0,bars_to_copy,price_interim);
         break;
     }

   if(result_copy!=-1) // If copying to the intermediate array is successful
     {
      ArrayCopy(result_array,price_interim,bars_copied,0,WHOLE_ARRAY); // Copy the data from the temporary array to the main one
      x=true; // assign the positive answer to the function
      bars_copied+=result_copy; // Increase the value of the processed data
     }
//---
   return(x);
  }

A próxima função é que é a correta para copiar os dados de tempo. É diferente da anterior em que se trata de um outro tipo de variável - datetime (que é convertida ao dobro quando copiadas para matriz de buffer de tempo - matriz de resposta de função). Uma outra diferença é que a declaração switch() não é utilizada, como não há necessidade alguma de selecionar os dados copiados.

//+------------------------------------------------------------------+
//| Func Copy Time                                                   |
//+------------------------------------------------------------------+
bool func_copy_time(double &result_array[],
                    datetime data_start,
                    datetime data_stop)
  {
//---
   int x=false; // Variable for answer
   int result_copy=-1; // Number of copied data

   static datetime time_interim[]; // Temporary dynamic array for storing copied data
   static int bars_to_copy_time; // Number of bars for copying

   bars_to_copy_time=Bars(_Symbol,period,data_start,data_stop); // Find out the current number of bars on the time interval
   bars_to_copy_time-=bars_copied_time; // Calculate the number of bars to be copied

   if(bars_copied_time!=0) // If it is not the first time the data has been copied
     {
      bars_copied_time--;
      bars_to_copy_time++;
     }
   ArrayResize(time_interim,bars_to_copy_time); // Change the size of the receiving array
   result_copy=CopyTime(_Symbol,period,0,bars_to_copy_time,time_interim);

   if(result_copy!=-1) // If copying to the intermediate array is successful
     {
      ArrayCopy(result_array,time_interim,bars_copied_time,0,WHOLE_ARRAY); // Copy the data from the temporary array to the main one
      x=true; // assign the positive answer to the function
      bars_copied_time+=result_copy; // Increase the value of the processed data
     }
//---
   return(x);
  }

3.4. Função de cálculo de parâmetro de inversão

Uma vez que o parâmetro de inversão pode ser um ponto ou uma porcentagem um, precisamos da função que calculará o parâmetro de inversão, dependendo das definições de indicadores. A função tem apenas um parâmetro - o preço para o cálculo do percentual de inversão A variável para a resposta é primeiro inicializada pelo tipo duplo e após os cálculos, é convertida indiretamente para o tipo int para resposta.

Isso é feito porque os números de ponto flutuante são usados ​nos cálculos, enquanto a resposta deve ser apresentada como números inteiros. A seleção é implementada na função pela declaração condicional if-else. A comparação é desempenhada diretamente com a variável externa input (parâmetros indicadores). O cálculo dos pontos é realizado usando uma equação simples. Em primeiro lugar, é definido o número total de pontos que o preço passou. Em seguida, a porcentagem indicada é calculada com base nesse número e atribuída à variável devolvida.

//+------------------------------------------------------------------+
//| Func Calculate Doorstep                                          |
//+------------------------------------------------------------------+
int func_calc_dorstep(double price)
  {
   double x=0; // Variable for answer
   if(type_doorstep==0) // If the calculation is to be performed in points
     {
      x=doorstep;
     }
   if(type_doorstep==1) // If the calculation is to be performed in percentage
     {
      x=price/_Point*doorstep/100;
     }
   return((int)x);
  }

3.5. A função principal - Desenho de gráfico Kagi

Já examinamos todas as funções que são necessárias para a operação da função principal - desenho de gráfico Kagi na janela indicadora (ou seja, o preenchimento dos buffers indicadores). Os parâmetros de entrada da função consistem de matrizes de dados. Duas delas são os buffers de cálculo descritos acima (preço e tempo previamente copiados), todo o resto são as matrizes dos buffers de construção gráfica de indicador.

As variáveis necessárias para armazenar os dados sobre a construção do gráfico são declaradas dentro da função. Uma vez que o gráfico é construído utilizando a declaração for loop, devemos ter os dados no estágio que terminou a etapa anterior. Isto pode ser conseguido por seis variáveis: line_move - onde o preço moveu-se na etapa anterior, line_gauge - line calibre (espessura da linha) - Yin ou Yang, price_1 e price_2 - preço anterior e atual que está sendo considerado, price_down e price_up - preço anterior de um ombro e cintura. Como podemos ver, price_1 é imediatamente equiparado ao primeiro elemento da matriz de preços copiados devido ao fato de que esta variável está envolvida em cálculos antes de comparação desde o início do ciclo.

Uma vez que matrizes de buffers da construção gráfica do indicador tenham a bandeira de correção de índice AS_SERIES elas devem ser preenchidas na ordem inversa. Para conseguir isso, as matrizes que têm o tempo e o tamanho apropriados são implementadas. As variáveis globais para armazenar os dados em tempo, tipos de linhas, "ombro" e "cintura", bem como os preços de inversão são então convertidas da mesma maneira.

Em seguida, todas as matrizes devem ser preenchidas com valores "vazios" (-1). Isso é feito utilizando dois ciclos pequenos. É possível juntar tudo em um único ciclo. Mas o uso de dois torna todas as ações executadas muito mais claras, enquanto que o tempo de execução não é muito alterado. Em outras palavras, as matrizes de tempo de cálculo e buffers gráficos são preenchidos separadamente.

Agora, todas as variáveis são declaradas, convertidas e preenchidas, para que o ciclo principal possa ser iniciado. É muito grande (apesar de que o cálculo é realizado com bastante rapidez) e inclui digitalização de todas as barras previamente copiadas.

O ciclo passa por todas as barras copiadas e preenche as matrizes previamente declaradas necessárias para trabalhar com elas ainda mais. Primeiro, vamos definir todas as matrizes usadas no ciclo:

  • yin_int_1 - valor principal de preço da linha Yin vertical (se linha Yin vertical é desenhada e o gráfico se move para baixo, este é o valor superior do preço, se o gráfico se move para cima, temos o caso oposto);
  • yin_int_2 - valor secundário de preço de linha Yin vertical, (se a linha ascendente é desenhada, este é o valor superior, se a linha for para baixo, temos o caso oposto);
  • yang_int_1 - valor principal do preço da linha Yang vertical;
  • yang_int_2 - valor secundário de preço de linha Yang vertical;
  • lin_yin - valor de linha Yin horizontal (preço de inversão na linha Yin);
  • lin_yang - valor da linha Yang horizontal (preço de inversão na linha Yang);
  • time_change - tempo de inversão do gráfico (construção de um ombro ou uma cintura);
  • time_line - a linha durante inversão Yin = 0 ou Yang = 1;
  • time_central_price - o valor do preço central, o preço no momento em que a linha Yin torna-se Yang, ou vice-versa;
  • time_change_price - o valor de preço de inversão (ombro ou cintura), a variável é a comum não dependendo de tipos de linha Yin ou Yang.

O valor do preço atual analisado atual​a partir do buffer de preço é atribuído à variável price_2 antes de cada passagem de ciclo para posterior comparação em declarações condicionais if-else. Depois disso, a matriz de buffer de dados copiados será analisada passo a passo e as matrizes acima referidas são preenchidas. Cada declaração condicional if-else executa certas ações, dependendo das condições: direção anterior de linhas de gráfico (para cima ou para baixo) e visual anterior das linhas (Yin ou Yang). Em seguida, as condições de movimento (se o preço passou um certo número de pontos) são verificadas em função do tipo de construção (padrão ou modificada).

Se tudo estiver bem, as novas variáveis (elementos da matriz) são reinstaladas ou definidas. O tipo de linha (Yin ou Yang) é definida no início. Dependendo do movimento e das ações anteriores, a distribuição posterior é realizada.

Há dois possíveis movimentos de preço:

  1. Preço sobe;
  2. Preço cai.

Há também quatro tipos de ações anteriores em cada direção:

  1. A linha anterior era Yin e subiu;
  2. A linha anterior era Yan e subiu;
  3. A linha anterior era Yin e caiu;
  4. A linha anterior era Yan e caiu.

Assim, temos oito casos além das duas primeiras definições de movimento inicial do gráfico (aparência primeira linha).

Depois disso, o ciclo principal termina. A reinstalação (inversa) e o preenchimento dos buffers são realizados para construir o gráfico em um pequeno ciclo consiste no número de inversões de gráfico Kagi previamente definidas no ciclo principal e escritas em variável "a". Quanto à distribuição dos valores de preços superiores e inferiores e linhas verticais, é tudo muito simples: uma inversão simples é executada. Em outras palavras, os valores primários obtidos anteriormente (matrizes tendo índices 0,1,2,3...) são atribuídos aos valores finais dos buffers (elemento com índice "а", por exemplo, а, а-1, а-2, а-3 ... é utilizado como um valor final). Para prevenir linhas (horizontais) de inversão de grudarem umas nas outras, o giro usando a declaração switch é executado como mencionado acima.

Fora isso, o trabalho da função principal da construção do gráfico Kagi está completo.

//+------------------------------------------------------------------+
//| Func Draw Kagi                                                   |
//+------------------------------------------------------------------+
void func_draw_kagi(double &array_input[],
                    double &arr_yin_1[],
                    double &arr_yin_2[],
                    double &arr_yin_lin1[],
                    double &arr_yin_lin2[],
                    double &arr_yin_lin3[],
                    double &arr_yang_1[],
                    double &arr_yang_2[],
                    double &arr_yang_lin1[],
                    double &arr_yang_lin2[],
                    double &arr_yang_lin3[],
                    double &arr_time[])
  {
//---
   a=0; // Variable for the chart construction fixing the number of chart reversals
   char line_move=0; // Previous price direction 1-up, -1-down
   char line_gauge=0; // Previous look of the line 1-thick yang, -1-thin yin
   double price_1=0,price_2=0; // Auxiliary variables for defining the price movement
   double price_down=-99999,price_up=99999; // Auxiliary variables for storing the reversal price values
   price_1=array_input[0];
//--- auxiliary arrays for the initial data storing before the reversal (transferring to the buffers)
   double yin_int_1[];
   double yin_int_2[];
   double lin_yin[];
   double yang_int_1[];
   double yang_int_2[];
   double lin_yang[];
//--- change the sizes of dynamic arrays
   ArrayResize(yin_int_1,bars_copied);
   ArrayResize(yin_int_2,bars_copied);
   ArrayResize(yang_int_1,bars_copied);
   ArrayResize(yang_int_2,bars_copied);
   ArrayResize(lin_yin,bars_copied);
   ArrayResize(lin_yang,bars_copied);
//--- time data storing arrays
   ArrayResize(time_change,bars_copied_time);
   ArrayResize(time_line,bars_copied_time); // Look of the line Yin = 0 or Yang = 1
   ArrayResize(time_change_price,bars_copied_time);
   ArrayResize(time_central_price,bars_copied_time);
//--- assign -1 (not displayed) value to the transferred buffers
   for(int z=0; z<bars_copied; z++)
     {
      arr_yin_1[z]=-1;
      arr_yin_2[z]=-1;
      arr_yin_lin1[z]=-1;
      arr_yin_lin2[z]=-1;
      arr_yin_lin3[z]=-1;
      arr_yang_1[z]=-1;
      arr_yang_2[z]=-1;
      arr_yang_lin1[z]=-1;
      arr_yang_lin2[z]=-1;
      arr_yang_lin3[z]=-1;
     }
//--- equate -1 (not displayed) value to the arrays
   for(int z=0; z<bars_copied; z++)
     {
      yin_int_1[z]=-1;
      yin_int_2[z]=-1;
      lin_yin[z]=-1;
      yang_int_1[z]=-1;
      yang_int_2[z]=-1;
      lin_yang[z]=-1;
      time_change[z]=-1;
      time_line[z]=-1;
      time_change_price[z]=-1;
      time_central_price[z]=-1;
     }
//--- function's main loop
   for(int z=0; z<bars_copied; z++)
     {
      price_2=array_input[z];
      //--- first, let's define the initial market direction
      //--- first THIN DESCENDING line
      if(((price_1-price_2)/_Point>func_calc_dorstep(price_2)) && line_move==0)
        {
         yin_int_1[a]=price_1;
         yin_int_2[a]=price_2;

         line_move=-1;
         line_gauge=-1;

         price_1=price_2;

         time_change[a]=(datetime)arr_time[z];
         time_line[a]=0;
        }
      //--- first THICK ASCENDING line
      if(((price_1-price_2)/_Point<-func_calc_dorstep(price_2)) && line_move==0)
        {
         yang_int_1[a]=price_1;
         yang_int_2[a]=price_2;

         line_move=1;
         line_gauge=1;

         price_1=price_2;

         time_change[a]=(datetime)arr_time[z];
         time_line[a]=1;
        }
      //--- price moves DOWN
      //--- if the price moved DOWN before that, the line is THIN
      if(line_move==-1 && line_gauge==-1)
        {
         if(((price_1-price_2)/_Point>func_calc_dorstep(price_2)) || (kagi_type==0 && (price_1-price_2)/_Point>0))
           {
            yin_int_2[a]=price_2;

            line_move=-1;
            line_gauge=-1;

            price_1=price_2;

            time_change[a]=(datetime)arr_time[z];
            time_line[a]=0;
           }
        }
      //--- if the price moved DOWN before that, the line is THICK
      if(line_move==-1 && line_gauge==1)
        {
         if(((price_1-price_2)/_Point>func_calc_dorstep(price_2)) || (kagi_type==0 && (price_1-price_2)/_Point>0))
           {
            if(price_2<price_down) // If the thick line crossed the lower shoulder when moving downwards
              {
               yin_int_1[a]=price_down;
               yin_int_2[a]=price_2;

               yang_int_2[a]=price_down;

               line_move=-1;
               line_gauge=-1;

               price_1=price_2;

               time_change[a]=(datetime)arr_time[z];
               time_central_price[a]=price_down;
               time_line[a]=0;
              }
            else //if(price_2>=price_down) // If the thick line has not crossed the lower shoulder when moving downwards
              {
               yang_int_2[a]=price_2;

               line_move=-1;
               line_gauge=1;

               price_1=price_2;

               time_change[a]=(datetime)arr_time[z];
               time_line[a]=1;
              }
           }
        }
      //--- if the price has moved UPWARDS before that, the line is THIN
      if(line_move==1 && line_gauge==-1)
        {
         if((price_1-price_2)/_Point>func_calc_dorstep(price_2))
           {
            a++;
            yin_int_1[a]=price_1;
            yin_int_2[a]=price_2;

            lin_yin[a]=price_1;

            line_move=-1;
            line_gauge=-1;

            price_up=price_1;

            price_1=price_2;

            time_change[a]=(datetime)arr_time[z];
            time_line[a]=0;
            time_change_price[a]=lin_yin[a];
           }
        }
      //--- if the price has moved UPWARDS before that, the line is THICK
      if(line_move==1 && line_gauge==1)
        {
         if((price_1-price_2)/_Point>func_calc_dorstep(price_2))
           {
            a++;
            if(price_2<price_down) // If the thick line has crossed the lower shoulder when moving downwards
              {
               yin_int_1[a]=price_down;
               yin_int_2[a]=price_2;

               yang_int_1[a]=price_1;
               yang_int_2[a]=price_down;

               lin_yang[a]=price_1;

               line_move=-1;
               line_gauge=-1;

               price_up=price_1;

               price_1=price_2;

               time_change[a]=(datetime)arr_time[z];
               time_line[a]=0;
               time_change_price[a]=lin_yang[a];
               time_central_price[a]=price_down;
              }
            else//if(price_2>=price_down) // If the thick line has not crossed the lower shoulder when moving downwards
              {
               yang_int_1[a]=price_1;
               yang_int_2[a]=price_2;

               lin_yang[a]=price_1;

               line_move=-1;
               line_gauge=1;

               price_up=price_1;

               price_1=price_2;

               time_change[a]=(datetime)arr_time[z];
               time_line[a]=1;
               time_change_price[a]=lin_yang[a];
              }
           }
        }
      //--- the price moves UP
      //--- if the price has moved UPWARDS before that, the line is THICK
      if(line_move==1 && line_gauge==1)
        {
         if(((price_1-price_2)/_Point<-func_calc_dorstep(price_2)) || (kagi_type==0 && (price_1-price_2)/_Point<0))
           {
            yang_int_2[a]=price_2;

            line_move=1;
            line_gauge=1;

            price_1=price_2;

            time_change[a]=(datetime)arr_time[z];
            time_line[a]=1;
           }
        }

      //--- if the price has moved UPWARDS before that, the line is THIN
      if(line_move==1 && line_gauge==-1)
        {
         if(((price_1-price_2)/_Point<-func_calc_dorstep(price_2)) || (kagi_type==0 && (price_1-price_2)/_Point<0))
           {
            if(price_2>price_up) // If the thin line has not crossed the upper shoulder when moving upwards
              {
               yin_int_2[a]=price_up;

               yang_int_1[a]=price_up;
               yang_int_2[a]=price_2;

               line_move=1;
               line_gauge=1;

               price_1=price_2;

               time_change[a]=(datetime)arr_time[z];
               time_central_price[a]=price_up;
               time_line[a]=1;
              }
            else//if(price_2<=price_up) // If the thin line has not crossed the upper shoulder when moving upwards
              {
               yin_int_2[a]=price_2;

               line_move=1;
               line_gauge=-1;

               price_1=price_2;

               time_change[a]=(datetime)arr_time[z];
               time_line[a]=0;
              }
           }
        }

      //--- if the price has moved DOWNWARDS before that, the line is THICK
      if(line_move==-1 && line_gauge==1)
        {
         if((price_1-price_2)/_Point<-func_calc_dorstep(price_2))
           {
            a++;

            yang_int_1[a]=price_1;
            yang_int_2[a]=price_2;

            lin_yang[a]=price_1;

            line_move=1;
            line_gauge=1;

            price_down=price_1;
            price_1=price_2;

            time_change[a]=(datetime)arr_time[z];
            time_line[a]=1;
            time_change_price[a]=lin_yang[a];
           }
        }

      //--- if the price has moved DOWNWARDS before that, the line is THIN
      if(line_move==-1 && line_gauge==-1)
        {
         if((price_1-price_2)/_Point<-func_calc_dorstep(price_2))
           {
            a++;
            if(price_2>price_up) // If the thin line has crossed the upper shoulder when moving upwards
              {
               yin_int_1[a]=price_1;
               yin_int_2[a]=price_up;

               yang_int_1[a]=price_up;
               yang_int_2[a]=price_2;

               lin_yin[a]=price_1;

               line_move=1;
               line_gauge=1;

               price_down=price_1;
               price_1=price_2;

               time_change[a]=(datetime)arr_time[z];
               time_line[a]=1;
               time_change_price[a]=lin_yin[a];
               time_central_price[a]=price_up;
              }
            else //if(price_2<=price_up) // If the thin line has not crossed the upper shoulder when moving upwards
              {
               yin_int_1[a]=price_1;
               yin_int_2[a]=price_2;

               lin_yin[a]=price_1;

               line_move=1;
               line_gauge=-1;

               price_down=price_1;
               price_1=price_2;

               time_change[a]=(datetime)arr_time[z];
               time_line[a]=0;
               time_change_price[a]=lin_yin[a];
              }
           }
        }

     }
//--- function's main loop
//--- assign actual values to drawing buffers
   uint y=a;
//--- auxiliary variables for storing data on filling the current buffer
   char yin=1;
   char yang=1;
   for(uint z=0; z<=a; z++)
     {
      arr_yin_1[z]=yin_int_1[y];
      arr_yin_2[z]=yin_int_2[y];

      switch(yin)
        {
         case 1:
           {
            arr_yin_lin1[z]=lin_yin[y];
            arr_yin_lin1[z+1]=lin_yin[y];
            yin++;
           }
         break;
         case 2:
           {
            arr_yin_lin2[z]=lin_yin[y];
            arr_yin_lin2[z+1]=lin_yin[y];
            yin++;
           }
         break;
         case 3:
           {
            arr_yin_lin3[z]=lin_yin[y];
            arr_yin_lin3[z+1]=lin_yin[y];
            yin=1;
           }
         break;
        }

      arr_yang_1[z]=yang_int_1[y];
      arr_yang_2[z]=yang_int_2[y];

      switch(yang)
        {
         case 1:
           {
            arr_yang_lin1[z]=lin_yang[y];
            arr_yang_lin1[z+1]=lin_yang[y];
            yang++;
           }
         break;
         case 2:
           {
            arr_yang_lin2[z]=lin_yang[y];
            arr_yang_lin2[z+1]=lin_yang[y];
            yang++;
           }
         break;
         case 3:
           {
            arr_yang_lin3[z]=lin_yang[y];
            arr_yang_lin3[z+1]=lin_yang[y];
            yang=1;
           }
         break;
        }
      y--;
     }
//---
  }


3.6. Função para criação do objeto gráfico da "Linha de tendência"

Agora, vamos examinar a função para a criação de "linha de tendência" do objeto gráfico. Esta função é necessária, a fim de chamar no gráfico Kagi principal.

A função é muito simples. Ela contém os parâmetros de entrada necessários para a criação de objeto gráfico "linha de tendência": nome do objeto, preços e horários primeiro e segundo preços e pontos de tempo, assim como a largura da linha e a cor. O corpo da função contém a função de criação do objeto gráfico e seis funções de mudar as propriedades do objeto gráfico.

//+------------------------------------------------------------------+
//| Func Object Create Trend Line                                    |
//+------------------------------------------------------------------+
void func_create_trend_line(string name,
                            double price1,
                            double price2,
                            datetime time1,
                            datetime time2,
                            int width,
                            color color_line)
  {
   ObjectCreate(0,name,OBJ_TREND,0,time1,price1,time2,price2);
//--- set the line color
   ObjectSetInteger(0,name,OBJPROP_COLOR,color_line);
//--- set the line display style
   ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID);
//--- set the line width
   ObjectSetInteger(0,name,OBJPROP_WIDTH,width);
//--- display in the foreground (false) or background (true)
   ObjectSetInteger(0,name,OBJPROP_BACK,false);
//--- enable (true) or disable (false) the mode of continuing the line display to the left
   ObjectSetInteger(0,name,OBJPROP_RAY_LEFT,false);
//--- enable (true) or disable (false) the mode of continuing the line display to the right
   ObjectSetInteger(0,name,OBJPROP_RAY_RIGHT,false);
  }

3.7. Desenho no gráfico Kagi principal

A próxima função que se aplica, várias vezes, é a função Kagi em construção anteriores ao gráfico. As variáveis ​globais preenchidas na função principal previamente examinada da construção do gráfico Kagi são utilizadas como variáveis de entrada: a matriz de preços de inversão ("ombros" e "cinturas"), a matriz de mudança e preços centrais (o preço, em que a linha Yin transforma-se em Yang, ou vice-versa), a matriz de tempo de inversão (localizada em tempo real, [z-1] índice de matriz é usada para marcar o início de inversão), a matriz do tipo de linha, em que a inversão ocorreu (é também um elemento para a frente, como a matriz de tempo).

O corpo da função consiste em um ciclo. O ciclo é dividido em duas partes: desenhar linhas verticais e horizontais. O primeiro também é dividido em dois: desenhar as verticais, considerando a mudança de linha (preço central de mudança) e ausência de mudança. Observe os parâmetros da "linha de tendência" transferidos da função de criação do objeto.

A nomenclatura é executada repetidamente. O nome do objeto começa com um número mágico (necessário para a exclusão de objetos de um determinado indicador), em seguida, o seu tipo é fixo e, finalmente, o índice é atribuído. O índice é atualizado a cada passagem do ciclo.

//+------------------------------------------------------------------+
//| Func Kagi Main Chart                                             |
//+------------------------------------------------------------------+
void func_kagi_main_chart(double &price[],         // Shoulder prices array
                          double &central_price[], // Array of the prices of passing through the shoulders
                          datetime &time[],        // Current location time array ([-1] - start of shoulder)
                          char &type_line_end[])   // Line type by the start of shoulder formation
  {
//--- start of the loop
   for(uint z=1; z<=a; z++)
     {
      //--- check for the pass conditions (no pass)
      if(central_price[z]==-1)
        {
         if(type_line_end[z-1]==0 && price[z+1]!=-1)
           {
            func_create_trend_line(IntegerToString(magic_numb)+"_trend_yin_v"+IntegerToString(z),
                                   price[z],price[z+1],time[z],time[z],width_yin_main,color_yin_main);
           }
         if(type_line_end[z-1]==1 && price[z+1]!=-1)
           {
            func_create_trend_line(IntegerToString(magic_numb)+"_trend_yang_v"+IntegerToString(z),
                                   price[z],price[z+1],time[z],time[z],width_yang_main,color_yang_main);
           }
        }
      else //--- check for the pass conditions (pass is present)
        {
         if(type_line_end[z-1]==0 && price[z+1]!=-1)
           {
            func_create_trend_line(IntegerToString(magic_numb)+"_trend_yin_v"+IntegerToString(z),
                                   central_price[z],price[z],time[z],time[z],width_yin_main,color_yin_main);
            func_create_trend_line(IntegerToString(magic_numb)+"_trend_yang_v"+IntegerToString(z),
                                   central_price[z],price[z+1],time[z],time[z],width_yang_main,color_yang_main);
           }
         if(type_line_end[z-1]==1 && price[z+1]!=-1)
           {
            func_create_trend_line(IntegerToString(magic_numb)+"_trend_yin_v"+IntegerToString(z),
                                   central_price[z],price[z+1],time[z],time[z],width_yin_main,color_yin_main);
            func_create_trend_line(IntegerToString(magic_numb)+"_trend_yang_v"+IntegerToString(z),
                                   central_price[z],price[z],time[z],time[z],width_yang_main,color_yang_main);
           }
        }
      //--- check for the pass conditions (pass is present)
      //--- draw the horizontals
      if(type_line_end[z-1]==0)
        {
         func_create_trend_line(IntegerToString(magic_numb)+"_trend_h"+IntegerToString(z),
                                price[z],price[z],time[z-1],time[z],width_yin_main,color_yin_main);
        }
      if(type_line_end[z-1]==1)
        {
         func_create_trend_line(IntegerToString(magic_numb)+"_trend_h"+IntegerToString(z),
                                price[z],price[z],time[z-1],time[z],width_yang_main,color_yang_main);
        }
      //--- draw the horizontals
     }
  }

3.8. Implementação de etiquetas adicionais

Como já mencionado acima, o indicador implementa etiquetas adicionais. Vamos examinar a função de fornecer essas etiquetas no gráfico principal. Existem apenas dois tipos de etiquetas de preços aqui: etiquetas de inversão e etiquetas de tempo mostradas via "etiqueta de preço" e "etiqueta vertical". Os seguintes parâmetros são passados como os de entrada: atributo do desenho da etiqueta de preço de inversão e cor da etiqueta, atributos do desenho de etiqueta de tempo de inversão e de mudança de cor da etiqueta, a primeira e a segunda cor do tempo de inversão.

A função inteira é dividida em duas partes: a primeira parte é responsável por etiquetas de tempo, enquanto que a segunda - para etiquetas de preços. Ambas as partes da função consistem em ciclos limitados pelo número de gráficos de inversões (variável "a"). A declaração condicional é definida antes do cicloif-else. A declaração verifica a necessidade de seu desenho de acordo com as definições do indicador.

O primeiro ciclo cria etiquetas de tempo, a definição de nome do objeto é executada no início do ciclo (princípio de geração de nome foi descrito acima). Em seguida, a cor é selecionada, dependendo da linha do tipo a partir da matriz de tipo de linha globalmente declarada (se o parâmetro é definido) e outros parâmetros são aplicados para à linha.

O segundo ciclo é responsável pela criação de etiquetas de preços de inversão. Em primeiro lugar, o nome do objeto é gerado. Em seguida, a seleção do índice da matriz de tempo é definida dependendo se Kagi está sendo construído no gráfico principal ou não. Se isso não for feito, as etiquetas serão localizadas "no ar" e não ficará suficientemente claro do lugar que ocorreu a inversão. Em seguida, o objeto tipo "etiqueta de preço" é criado e configurado.

//+------------------------------------------------------------------+
//| Func Label Main Chart                                            |
//+------------------------------------------------------------------+
void func_label_main_chart(bool label_print,
                           color label_color,
                           bool time_change_print,
                           bool time_change_color,
                           color time_color_first,
                           color time_color_second)
  {
   if(time_change_print==true)
     {
      for(uint z=1; z<=a; z++)
        {
         string name=IntegerToString(magic_numb)+"_time_2_"+IntegerToString(z);
         //--- create an object of a vertical line type
         ObjectCreate(0,name,OBJ_VLINE,0,time_change[z],0);
         //--- set the line color
         color color_line=clrBlack;
         if(time_change_color==true)
           {
            if(time_line[z]==0)color_line=time_color_first;
            if(time_line[z]==1)color_line=time_color_second;
           }
         else color_line=time_color_first;
         ObjectSetInteger(0,name,OBJPROP_COLOR,color_line);
         //--- set the line display style
         ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID);
         //--- set the line width
         ObjectSetInteger(0,name,OBJPROP_WIDTH,1);
         //--- display on the foreground (false) or background (true)
         ObjectSetInteger(0,name,OBJPROP_BACK,false);
         //--- enable (true) or disable (false) the line display mode in the chart subwindows
         ObjectSetInteger(0,name,OBJPROP_RAY,time_separate_windows);
        }
     }
   if(label_print==true)
     {
      for(uint z=1; z<=a; z++)
        {
         string name=IntegerToString(magic_numb)+"_label_2_"+IntegerToString(z);
         uint numb_time;
         if(kagi_main_chart==true)numb_time=z;
         else numb_time=z-1;
         //--- create a label type object
         ObjectCreate(0,name,OBJ_ARROW_RIGHT_PRICE,0,time_change[numb_time],time_change_price[z]);
         //--- set the label color
         ObjectSetInteger(0,name,OBJPROP_COLOR,label_color);
         //--- set the edging line style
         ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID);
         //--- set the label size
         ObjectSetInteger(0,name,OBJPROP_WIDTH,1);
         //--- display on the foreground (false) or background (true)
         ObjectSetInteger(0,name,OBJPROP_BACK,false);
        }
     }
  }

Agora, vamos ver como podemos definir as etiquetas na janela do indicador.

Todas as etiquetas na janela do indicador são principalmente de preços e só há dois tipos delas: etiquetas de preços de inversão e níveis de preços. Existem dois tipos de desenhos dos níveis de preço: nas inversões de gráfico e em uma distância igual de toda a faixa de preço gráfico. O primeiro tipo pode mudar a cor dos níveis de duas maneiras: dependendo do tipo de linha (Yin Yang ou) e de acordo com reversão (para cima ou para baixo).

Assim, a própria função é dividida em dois ciclos: o primeiro é responsável pela criação de etiquetas de preços de inversão, o segundo trata da designação dos níveis de preços. Este último é dividido em dois tipos: de etiquetas em cada inversão ou etiquetas em todo o intervalo de preços em um nível igual.

Esta função é diferente da anterior na medida em que ela tem limitações sobre o número de etiquetas de preço e níveis, devido ao fato de que, em grandes números elas sobrecarregam o gráfico, que complica a sua compreensão.

Devido a esta característica, ambos os ciclos são limitados pelo número de passagens especificadas nas configurações do indicador (número de etiquetas de preço e níveis). Tal abordagem é perigosa, pois o número de inversões pode vir a ser muito menor do que o número de etiquetas de preços fixadas nas configurações. Devido a esta razão, a presença de inversão durante cada passagem do ciclo é verificada para desenhar uma etiqueta de preço ou nível.

A única exceção é o desenho de níveis de preço ao longo de toda a faixa de preço em uma distância igual. A geração de objetos gráficos do tipo "Etiqueta de preço" é realizada nas coordenadas em ordem inversa, ou seja, as etiquetas são colocadas a partir da data atual para o passado. O mesmo se aplica aos níveis de preços: os níveis de preços atuais são gerados primeiro, seguido por anteriores. As exceções são os níveis de preços que não dependam das inversões de gráfico.

Mudanças de cor do nível de preços são realizadas usando declarações condicionais if-else de acordo com as configurações.

//+------------------------------------------------------------------+
//| Func Label Indicator Window                                      |
//+------------------------------------------------------------------+
void func_label_indicator_window(bool label_print,         // Draw price labels
                                 bool levels_print,        // Draw levels
                                 char levels_type_draw,    // Type of drawing the levels by reversals or at an equal distance of the entire price range
                                 char levels_color_change) // Change line color
  {
   uint number=a;
   if(label_print==true)
     {
      for(uint z=0; z<=label_1_number; z++)
        {
         if(z<number)
           {
            string name=IntegerToString(magic_numb)+"_label_1_"+IntegerToString(z);
            //--- create label type object
            ObjectCreate(0,name,OBJ_ARROW_RIGHT_PRICE,ChartWindowFind(),(datetime)Time[(bars_copied_time-z-2)],time_change_price[number-z]);
            //--- set the label color
            ObjectSetInteger(0,name,OBJPROP_COLOR,label_1_color);
            //--- set the style of the edging line
            ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID);
            //--- set the label size
            ObjectSetInteger(0,name,OBJPROP_WIDTH,1);
            //--- display on the foreground (false) or background (true)
            ObjectSetInteger(0,name,OBJPROP_BACK,false);
           }
        }
     }
   if(levels_print==true)
     {
      if(levels_type_draw==0)
        {
         for(uint z=0; z<=levels_number; z++)
           {
            if(z<number)
              {
               IndicatorSetDouble(INDICATOR_LEVELVALUE,z,time_change_price[number-z]);
               if(levels_change_color==0)
                 {
                  double numb_even=z;
                  if(MathMod(numb_even,2)==0)
                    {
                     IndicatorSetInteger(INDICATOR_LEVELCOLOR,z,levels_first_color);
                    }
                  if(MathMod(numb_even,2)!=0)
                    {
                     IndicatorSetInteger(INDICATOR_LEVELCOLOR,z,levels_second_color);
                    }
                 }
               if(levels_change_color==1)
                 {
                  if(time_line[number-z]==0)IndicatorSetInteger(INDICATOR_LEVELCOLOR,z,levels_first_color);
                  if(time_line[number-z]==1)IndicatorSetInteger(INDICATOR_LEVELCOLOR,z,levels_second_color);
                 }
               if(levels_change_color==2)
                 {
                  IndicatorSetInteger(INDICATOR_LEVELCOLOR,z,levels_first_color);
                 }
              }
           }
        }
      if(levels_type_draw==1)
        {
         double max_price=Price[ArrayMaximum(Price)];
         double min_price=Price[ArrayMinimum(Price,1,ArrayMinimum(Price)-1)];
         double number_difference=(max_price-min_price)/levels_number;
         NormalizeDouble(number_difference,_Digits);
         for(uint z=0; z<=levels_number; z++)
           {
            IndicatorSetDouble(INDICATOR_LEVELVALUE,z,(min_price+(z*number_difference)));
            IndicatorSetInteger(INDICATOR_LEVELCOLOR,z,levels_first_color);
           }
        }
     }
  }

3.9. Exclusão de objetos gráficos criados anteriormente

Nós já sabemos que este indicador é rico em objetos gráficos. É hora de pensar em como podemos excluí-los de forma rápida e eficiente.

Esta tarefa é executada pela função, para excluir os objetos gráficos. O nome e o número inicial de objetos, são utilizados como parâmetros de função. Como durante a criação, o nome do objeto deve conter o número mágico e o nome de um tipo de objeto. A chamada de função no programa é limitada pelo número de objetos que excedam à sua possível existência. No entanto, isto não afeta a funcionalidade do indicador.

//+------------------------------------------------------------------+
//| Func Delete Objects                                              |
//+------------------------------------------------------------------+
void func_delete_objects(string name,
                         int number)
  {
   string name_del;
   for(int x=0; x<=number; x++)
     {
      name_del=name+IntegerToString(x);
      ObjectDelete(0,name_del);
     }
  }

3.10. Função para o início da construção do gráfico

Agora, depois de ter examinado todas as funções para cálculo e construção do gráfico Kagi, bem como para criação e exclusão de objetos, devemos considerar uma outra pequena função para verificação do recebimento da nova barra. A função é bastante simples e tem um parâmetro de entrada - período analisado. A resposta da função também é muito simples. Ela tem tipo bool e contém a resposta sobre se uma nova barra está presente ou não. A base do corpo da função é mudar a declaração que passa o controle para suas declarações diferentes dependendo do período.

No exemplo, a função cobre toda a faixa do período, embora apenas um período possa também ser usado.

O algoritmo de função foi pego do código IsNewBar: o tempo de abertura da última barra é comparado com o valor de tempo anteriormente definido. Se os valores forem diferentes, há uma nova barra. O novo valor é designado como o definido anteriormente e uma resposta da função é considerada positiva. Se o tempo de abertura da última barra coincide com o valor de tempo anteriormente determinado, então a nova barra ainda não apareceu e a resposta da função é negativa.

//+------------------------------------------------------------------+
//| Func New Bar                                                     |
//+------------------------------------------------------------------+
bool func_new_bar(ENUM_TIMEFRAMES period_time)
  {
//----
   static datetime old_Times[22];// array for storing old values
   bool res=false;               // analysis result variable  
   int  i=0;                     // old_Times[] array cell index    
   datetime new_Time[1];         // new bar time

   switch(period_time)
     {
      case PERIOD_M1:  i= 0; break;
      case PERIOD_M2:  i= 1; break;
      case PERIOD_M3:  i= 2; break;
      case PERIOD_M4:  i= 3; break;
      case PERIOD_M5:  i= 4; break;
      case PERIOD_M6:  i= 5; break;
      case PERIOD_M10: i= 6; break;
      case PERIOD_M12: i= 7; break;
      case PERIOD_M15: i= 8; break;
      case PERIOD_M20: i= 9; break;
      case PERIOD_M30: i=10; break;
      case PERIOD_H1:  i=11; break;
      case PERIOD_H2:  i=12; break;
      case PERIOD_H3:  i=13; break;
      case PERIOD_H4:  i=14; break;
      case PERIOD_H6:  i=15; break;
      case PERIOD_H8:  i=16; break;
      case PERIOD_H12: i=17; break;
      case PERIOD_D1:  i=18; break;
      case PERIOD_W1:  i=19; break;
      case PERIOD_MN1: i=20; break;
      case PERIOD_CURRENT: i=21; break;
     }
   // copy the time of the last bar to new_Time[0] cell  
   int copied=CopyTime(_Symbol,period_time,0,1,new_Time);
  
   if(copied>0) // all is well. Data has been copied
      {
      if(old_Times[i]!=new_Time[0])       // if the bar's old time is not equal to new one
         {
         if(old_Times[i]!=0) res=true;    // if it is not the first launch, true = new bar
         old_Times[i]=new_Time[0];        // store the bar's time
         }
      }
//----
   return(res);
  }

 

3.11. Funções OnCalculate() e OnChartEvent()

Todas as funções descritas acima são consolidadas na função que levam o mesmo nome - Func Consolidation. Esta função é iniciada cada vez que uma nova barra aparece na função OnCalculate() e quando a tecla "R" é pressionada a partir função OnChartEvent(). 

Antes que o gráfico seja gerado ou atualizado, a função de exclusão de todos os objetos gráficos é chamado na função de consolidação (Func Consolidation). Uma vez que existem vários objetos e eles são divididos em etiquetas de preço da janela indicadora e do gráfico principal, as linhas verticais indicando o tempo de inversão, bem como linhas de tendência vertical e horizontal Yin e Yang, o número geral de chamadas da função será 7.

Em seguida, os dados históricos são copiados por preço e tempo. A função principal para a construção do gráfico Kagi é, então, iniciada. Depois disso, a função de colocar todas as etiquetas de preço no gráfico principal e na janela indicadora é chamada. Finalmente, o Kagi é gerado no gráfico principal e a função para redesenhar os objetos é iniciada.

//+------------------------------------------------------------------+
//| Func Consolidation                                               |
//+------------------------------------------------------------------+
void func_consolidation()
  {
//--- date of construction end
   stop_data=TimeCurrent();

//--- deleting all graphical objects belonging to the indicator
   func_delete_objects(IntegerToString(magic_numb)+"_label_2_",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_label_1_",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_time_2_",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_trend_yin_v",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_trend_yang_v",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_trend_h",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_trend_h",ObjectsTotal(0,-1,-1));

//--- copy price data to the main buffer
   copy_history=func_copy_history(Price,start_data,stop_data);

//--- display information about the error when copying price data
   if(copy_history==false)Alert("Error of copy history Price");

//--- copy time data to the main buffer
   copy_time=func_copy_time(Time,start_data,stop_data);

//--- display a notification of the error occurred while copying time data
   if(copy_time==false)Alert("Error of copy history Time");

//--- construct Kagi chart in the indicator window
   func_draw_kagi(Price,YinBuffer1,YinBuffer2,Yin1Buffer,Yin2Buffer,Yin3Buffer,
                  YangBuffer1,YangBuffer2,Yang1Buffer,Yang2Buffer,Yang3Buffer,Time);

//--- draw labels on the main chart
   func_label_main_chart(label_2,label_2_color,time_line_draw,time_line_change_color,time_first_color,time_second_color);

//--- draw labels on the indicator chart
   func_label_indicator_window(label_1,levels_on_off,levels_type,levels_change_color);

//--- construct Kagi chart in the main window
   if(kagi_main_chart==true)func_kagi_main_chart(time_change_price,time_central_price,time_change,time_line);

//--- redraw the chart
   ChartRedraw(0);
//---
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
//---
   if(func_new_bar(period_to_redraw)==true)
     {
      func_consolidation();
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| OnChartEvent                                                     |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,         // event ID  
                  const long& lparam,   // long type event parameter
                  const double& dparam, // double type event parameter
                  const string& sparam) // string type event parameter
  {
   if(id==CHARTEVENT_KEYDOWN) // Keyboard button pressing event
     {
      if(lparam==82) // "R" key has been pressed
        {
         func_consolidation();
        }
     }
  }

 

3.12. Função OnDeinit()

A exclusão de todos os objetos é realizada na função de deinicialização do indicador.

//+------------------------------------------------------------------+
//| OnDeinit                                                         |
//+------------------------------------------------------------------+ 
void OnDeinit(const int reason)
  {
//--- delete all graphical objects belonging to the indicator
   func_delete_objects(IntegerToString(magic_numb)+"_label_2_",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_label_1_",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_time_2_",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_trend_yin_v",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_trend_yang_v",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_trend_h",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_trend_h",ObjectsTotal(0,-1,-1));
//--- redraw the chart
   ChartRedraw(0);
  }

Agora, vamos passar a usar o indicador na prática.


4. Uso do gráfico Kagi na prática

Há muitas estratégias de negociação baseadas no gráfico Kagi. Vamos examinar algumas delas.

Vamos começar com a estratégia mais popular: vender quando Yang muda para Yin e comprar, no caso oposto. Isto é mostrado na fig. 4:

A estratégia de compra e venda durante as mudanças de linha

Fig. 4. Vender quando Yang muda para Yin e comprar no caso contrário 

Como pode ser visto na fig. 4 (EURUSD M30, 5 pontos), esta estratégia mostra bons resultados. A figura mostra 8 pontos para 4 sinais, o primeiro (1) mostra que a posição longa deve ser aberta em 1.3518, o que parece ser correto, pois o preço, em seguida, atinge cerca de 1.3560, que abrange 42 pontos por dia. Este é um bom resultado.

O próximo ponto (2) recomenda vender a 1.3519. Como podemos ver, o preço realmente se move para baixo cruzando o nível de 1.3485 (e cobrindo 34 pontos), aproximadamente por duas horas.

Vamos ao ponto (3). A posição longa é aberta em 1.3538 e o preço sobe atingindo 1.3695. Assim, o lucro abrange 157 pontos já por um dia e meio. Claro, estes são os maiores lucros possíveis, mas o resultado ainda é bom o suficiente.

A próxima estratégia de negociação está rolando para trás da linha de tendência mostrada na fig. 5 (EURUSD M30, 5 pontos), de 07 a 18 de outubro:

Redução a partir da linha de tendência

Fig. 5. Redução a partir da linha de tendência

Podemos seguir em frente e negociar seguindo os canais. Um exemplo de busca de um canal pode ser analisado na figura 6 (EURUSD H1, 5 pontos), aproximadamente o mesmo período:

Negociação por canais

Fig. 6. Negociação por canais

A estratégia menos popular baseada no fato de que, depois de 7-10 "ombros" de aumento sucessivo ou de "cinturas" de diminuição, certamente haverá uma inversão (ascensão e queda).

Isto é apresentado na Figura 7 (GBPUSD H4, 25 pontos), de 10 de julho - 18 outubro:

7-10 sucessivos

Fig. 7. 7-10 sucessivos "ombros" de aumento ou "cinturas" de diminuição

Como pode ser visto na imagem, sete ombros ascendentes são seguidos por uma queda bastante considerável igual a aproximadamente metade da elevação anterior (cerca de 300 pontos).

Vamos examinar a estratégia de "Negociação por meio de uma etiqueta de preço" para mostrar a necessidade do uso de parâmetros indicadores adicionais. A ideia é entrar no mercado quando o preço exceder (compra) ou mover para abaixo (vender) a etiqueta de preço anterior.

A estratégia é mostrada na fig. 8 (GBPUSD H4, 30 pontos, construção modificada):

Negociação através de uma etiqueta de preço

Fig. 8. Negociação através de uma etiqueta de preço 

Setas de exibição vermelhas na figura 8 ao comprar ou vender. As setas estão se movendo a partir da etiqueta de preço anterior, exibindo os locais das etiquetas de preços anteriores que foram quebradas completamente.

Etiquetas de tempo servem principalmente como indicadoras de direção e tendência. Visto que a cor das etiquetas de tempo podem ser alteradas em relação ao tipo de linha, e o tipo de linha Yin ou Yang mostra a direção de tendência ou inversão, a cor pode nos ajudar a definir a atmosfera do mercado atual.

Por exemplo, vamos pegar o gráfico de ações de #IBM (H4, 1%, construção padrão) mostrado na figura 9:

Definição da direção de tendência utilizando etiquetas de tempo

Fig. 9. Definição de direção de tendência utilizando etiquetas de tempo

O gráfico mostra que as linhas azuis estão localizadas principalmente nos topos do gráfico, enquanto as vermelhas - nas partes inferiores.


Conclusão

O gráfico Kagi pode ser usado com sucesso para negociação no mercado como base de estratégia ou como uma ferramenta auxiliar para a análise mais precisa.

Neste artigo, examinei o código em si e algumas especificações da construção do indicador. O objetivo principal foi a criação do indicador multi-funcional que contém todos os elementos necessários com alguns recursos extras que podem ser desativados.

Terei todo o prazer de considerar novas ideias e melhorias para o indicador e, talvez, implementá-las no futuro. Além disso, por favor, me forneça o seu feedback. Ficarei feliz em responder suas perguntas sobre o indicador.

Este artigo continua a série dedicada ao desenvolvimento de indicadores para a construção dos gráficos do passado. O artigo anterior pode ser encontrado aqui. A série deve ser continuada e espero encontrá-lo novamente em breve. Obrigado pelo seu interesse! Desejo-lhe negociações de sucesso, assim como códigos estáveis e otimizados.

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

Arquivos anexados |
bkcv.mq5 (44.19 KB)
Vídeo tutorial: serviço de sinais do MetaTrader Vídeo tutorial: serviço de sinais do MetaTrader
Em apenas 15 minutos, este vídeo tutorial explica do que se trata o serviço de sinais do MetaTrader e demonstra com riqueza de detalhes como se inscrever para sinais de negociação e como se tornar um provedor de sinal em nosso serviço. Ao observar este tutorial, você será capaz de se inscrever para qualquer sinal de negociação ou publicar e promover seus próprios sinais em nosso serviço.
Criando um Expert Advisor multissistema e multimoeda Criando um Expert Advisor multissistema e multimoeda
O artigo apresenta uma estrutura para um Expert Advisor que negocia múltiplos símbolos e utiliza vários sistemas de negociação simultaneamente. Se você já identificou os parâmetros de entrada ideais para todos os seus EAs e obteve bons resultados de simulação para cada um deles separadamente, pergunte-se quais os resultados que você obteria se testasse todos os EAs simultaneamente, com todas as suas estratégias juntas.
Como desenvolver um Expert Advisor usando ferramentas de UML Como desenvolver um Expert Advisor usando ferramentas de UML
Este artigo discute a criação de Expert Advisors usando a linguagem gráfica UML, que é usada para modelagem visual de sistemas de software orientados a objeto. A principal vantagem dessa abordagem é a visualização do processo de modelagem. O artigo contém um exemplo que mostra a modelagem da estrutura e propriedades de um Expert Advisor usando o Software Ideas Modeler.
Guia prático do MQL5: Desenvolvimento de um indicador de símbolos múltiplos no MQL5 Guia prático do MQL5: Desenvolvimento de um indicador de símbolos múltiplos no MQL5
Neste artigo, vamos considerar o desenvolvimento de um indicador de volatilidade de símbolos múltiplos. O desenvolvimento de indicadores de símbolos múltiplos pode apresentar algumas dificuldades para os desenvolvedores novatos do MQL5, as quais este artigo ajuda a esclarecer. As principais questões que surgem no curso do desenvolvimento de um indicador de símbolos múltiplos têm a ver com sincronização de dados de outros símbolos em relação ao símbolo atual, a falta de alguns dados de indicadores e a identificação de início de barras 'reais' de um determinado período de tempo. Todas essas questões serão atentamente consideradas no artigo.