Algoritmos de média eficiente com lag mínimo: Usar em indicadores Expert Advisors
Nikolay Kositsin | 8 fevereiro, 2016
Introdução
Nos sistemas de negociação mecânica incorporados na base dos indicadores que são baseados em quaisquer algoritmos de média, seus desenvolvedores raramente usam mais que um algoritmo de média. Em muitos casos, se um algoritmo EA é baseado em indicadores e movimentos simples que são incluídos no conjunto padrão do terminal MetaTrader 4, somente quatro algoritmos padrão são usados: média de peso linear, simples, exponencial e suavizado. Tal abordagem limita muito as possibilidades de um Expert Advisor.
O mesmo sistema de negociação com o uso de diferentes algoritmos de média pode mostrar diferenças substanciais nos resultados de negociação. E é impossível dizer de antemão quais dos algoritmos disponíveis mostrarão a rentabilidade máxima de um sistema de negociação. Então, é mais razoável escrever um código usando algoritmos de média absolutamente diferentes que podem ser escolhidos alterando os valores de variáveis externa de um EA. Como resultado de tal abordagem, substituímos os indicadores usados pelo EA pelos nossos com uma configuração mais flexível de seleção de algoritmo de média. Assim, tal abordagem pode ser dividida em três estágios:
1. Escrevemos o código de um Expert Advisor com base nos movimentos padrão e indicadores incluídos no conjunto de indicadores técnicos no terminal do cliente MetaTrader 4.
2. Escrevemos indicadores personalizados de acordo com as descrições de indicadores padrão com a possibilidade de uma substituição mais flexível de algoritmos de suavização.
3. Substituímos as chamadas de indicadores técnicos pelas chamadas dos indicadores personalizados com a extração de parâmetros externos desses indicadores em variáveis externas do EA.
Nesse artigo, gostaria de tratar de indicadores mais universais com a possibilidade (se isso pode ser dito) de uma substituição quente de algoritmos de média que são usados nesses indicadores. O artigo é continuação de "Algoritmos de média eficiente com lag mínimo: Uso em indicadores", então, antes de ler este, é recomendado estudar com cuidado o artigo anterior.
A função universal de médias
No meu artigo anterior apresentei cinco funções de média. Gostaria de adicionar mais uma função à essa lista - MASeries() com algoritmos clássicos de médias:
double MASeries ( int number, int MA_Method, int MaxBar, int limit, int period, double series, int bar, int& reset )
Quanto ao seu uso, essa função é absolutamente análoga às cinco funções anteriores. O código da função está anexo ao arquivo - MASeries.mqh.
Agora, com base nessas seis funções, podemos construir uma função universal de média que chamei SmoothXSeries() e coloquei no arquivo SmoothXSeries.mqh. Como nas funções anteriores, essa é #include directive:
#include <SmoothXSeries.mqh>
Em termos de variáveis externas, essa função é análoga à JJMASeries(), mas há uma nova variável de identificador de algoritmo de suavização - SmoothMode:
double SmoothXSeries ( int number,int SmoothMode, int din, int MaxBar, int limit, int Phase, int Length, double Series, int bar, int& reset )
A seleção do algoritmo de média exigido é realizada pela variação do valor do parâmetro SmoothMode de zero a oito:
// 0 : JJMA // 1 : JurX // 2 : ParMA // 3 : LRMA // 4 : T3 // 5 : SMA // 6 : EMA // 7 : SSMA // 8 : LWMA
Naturalmente, as variáveis din e Phase são aplicadas para aqueles algoritmos para os quais são inicialmente definidas. Antes de usar essa função em um código do indicador, as variáveis dessa função devem ser inicializadas e a memória deve ser alocada para elas. Para isso, no bloco de inicialização do indicador, faça uma chamada para a função SmoothXSeriesResize(). Como o valor dessa variável Size externa, use o número das chamadas de função SmoothXSeries() no código do indicador.
//Ten calls of the SmoothXSeriesResize() function in the indicator code SmoothXSeriesResize(10);
Agora, tendo o algoritmo universal de média SmoothXSeries() podemos começar a escrever o código dos indicadores.
O movimento universal
Qualquer movimento obtido pela suavização de timeseries de preço. No artigo anterior escrevi sobre a função PriceSeries() para selecionar os valores de uma linha de preço de timeseries. A tarefa de construir um movimento é, na verdade, o processamento desses valores de séries de preço pela função SmoothXSeries() e a passagem deles para um buffer de indicador. Aqui está a variante da implementação de código:
/* For the operation of the indicator the files SmoothXSeries.mqh T3Series.mqh MASeries.mqh LRMASeries.mqh JurXSeries.mqh ParMASeries.mqh JJMASeries.mqh PriceSeries.mqh should be located in the directory: MetaTrader\experts\include\ Heiken Ashi#.mq4 should be located in the directory: MetaTrader\indicators\ */ //+X================================================================X+ //| X1MA.mq4 | //| Copyright © 2009, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+X================================================================X+ #property copyright "Copyright © 2009, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //---- drawing the indicator in the main window #property indicator_chart_window //---- number of indicator buffers #property indicator_buffers 1 //---- color of the indicator #property indicator_color1 Red //---- INPUT PARAMETERS OF THE INDICATOR +--------------------------------------------+ extern int Smooth_Mode = 0; // Choosing the smoothing algorithm 0 - JJMA, 1 - JurX, // 2 - ParMA, 3 - LRMA, 4 - T3, 5 - SMA, 6 - EMA, 7 - SSMA, 8 - LWMA extern int Length = 11; // depth of smoothing extern int Phase = 100; // parameter changing in limits -100 ... +100, //influences the quality of the transient process; extern int Shift = 0; // indicator shift along the time axis extern int Input_Price_Customs = 0; /* Selecting prices, upon which the calculation of the indicator is performed (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */ //---- +------------------------------------------------------------------------------+ //---- buffers double XMA[]; //---- variables bool INIT; int StartBar; //+X================================================================X+ //| SmoothXSeries() function | //+X================================================================X+ //----+ Declaring the function SmoothXSeries //----+ Declaring the function SmoothXSeriesResize //----+ Declaring the function SmoothXSeriesAlert #include <SmoothXSeries.mqh> //+X================================================================X+ //| PriceSeries() function | //+X================================================================X+ //----+ Declaring the function PriceSeries //----+ Declaring the function PriceSeriesAlert #include <PriceSeries.mqh> //+X================================================================X+ //| X1MA initialization function | //+X================================================================X+ int init() { //----+ //---- setting the style of the indicator presentation SetIndexStyle(0, DRAW_LINE); //---- defining a buffer for calculations SetIndexBuffer(0, XMA); //---- setting the values of the indicator that will not be visible on the chart SetIndexEmptyValue(0, 0.0); //---- setting alerts for not allowed values of external variables JJMASeriesAlert (0, "Length", Length); JJMASeriesAlert (1, "Phase", Phase); PriceSeriesAlert(Input_Price_Customs); //----+ Changing sizes of buffer variables of the function //SmoothXSeries, number = 1(One call of the SmoothXSeries function) if (SmoothXSeriesResize(1) != 1) { INIT = false; return(0); } //---- initialization of variables if (Smooth_Mode > 0 && Smooth_Mode < 9) StartBar = Length; else StartBar = 30; //---- setting the bar number, //starting from which the indicator will be drawn SetIndexDrawBegin(0, StartBar); //---- Setting the format of accuracy of the indicator drawing IndicatorDigits(Digits); //---- end of initialization INIT = true; return(0); //----+ } //+X================================================================X+ //| X1MA iteration function | //+X================================================================X+ int start() { //----+ //---- Getting the number of all bars int Bars_ = Bars - 1; //---- checking the initialization end and //checking if the number of bars is enough for calculation if (!INIT || Bars_ <= StartBar) return(-1); //---- Introducing variables with a floating point double Price, xma; //---- Introducing integer variables and obtaining the number //of already calculated bars int reset, MaxBar, limit, bar, counted_bars = IndicatorCounted(); //---- checking for possible errors if (counted_bars < 0) return(-1); //---- the last calculated bar must be recalculated if (counted_bars > 0) counted_bars--; //---- defining the number of the oldest bar, //starting from which new bars will be recalculated limit = Bars_ - counted_bars; //---- defining the number of the oldest bar, //starting from which all bars will be recalculated MaxBar = Bars_; //----+ the main cycle of the indicator calculation for(bar = limit; bar >= 0; bar--) { //---- Getting the initial value of the price series Price = PriceSeries(Input_Price_Customs, bar); //---- X1MA smoothing of the initial value of the price series //---- Call of the SmoothXSeries function number 0, //parameters Phase and Length are not changed at each bar (din = 0) xma = SmoothXSeries(0, Smooth_Mode, 0, MaxBar, limit, Phase, Length, Price, bar, reset); //---- checking that there are no errors in the previous operation if(reset != 0) return(-1); XMA[bar] = xma; //---- } //---- end of the indicator values calculation return(0); //----+ } //+X--------------------+ <<< The End >>> +--------------------X+
Nesse indicador, o algoritmo de média é escolhido alterando o valor da variável Smooth_Mode.
O movimento universal com o uso de uma média dupla
A eficiência do trabalho com tal movimento pode ser melhorada consideravelmente, se executarmos a média adicional do indicador obtido pela mesma função SmoothXSeries()
/* For the operation of the indicator the files SmoothXSeries.mqh T3Series.mqh MASeries.mqh LRMASeries.mqh JurXSeries.mqh ParMASeries.mqh JJMASeries.mqh PriceSeries.mqh should be located in the directory: MetaTrader\experts\include\ Heiken Ashi#.mq4 should be located in the directory: MetaTrader\indicators\ */ //+X================================================================X+ //| X2MA.mq4 | //| Copyright © 2009, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+X================================================================X+ #property copyright "Copyright © 2009, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //---- drawing the indicator in the main window #property indicator_chart_window //---- number of indicator buffers #property indicator_buffers 1 //---- color of the indicator #property indicator_color1 Lime //---- INPUT PARAMETERS OF THE INDICATOR +---------------------------------------------+ extern int Smooth_Mode1 = 0; // Choosing the 1st smoothing algorithm 0 - JJMA, 1 - JurX, // 2 - ParMA, 3 - LRMA, 4 - T3, 5 - SMA, 6 - EMA, 7 - SSMA, 8 - LWMA extern int Length1 = 9; // depth of smoothing extern int Phase1 = 100; // parameter changing in limits -100 ... +100, //influences the quality of the transient process; extern int Smooth_Mode2 = 0; // Choosing the 2nd smoothing algorithm 0 - JJMA, 1 - JurX, // 2 - ParMA, 3 - LRMA, 4 - T3, 5 - SMA, 6 - EMA, 7 - SSMA, 8 - LWMA extern int Length2 = 5; // depth of smoothing extern int Phase2 = 100; // parameter changing in limits -100 ... +100, //influences the quality of the transient process; extern int Shift = 0; // indicator shift along the time axis extern int Input_Price_Customs = 0; /* Selecting prices, upon which the calculation of the indicator is performed (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */ //---- +------------------------------------------------------------------------------+ //---- buffers double X2MA[]; //---- variables bool INIT; int StartBar, StartBar1, StartBar2; //+X================================================================X+ //| SmoothXSeries() function | //+X================================================================X+ //----+ Declaring the function SmoothXSeries //----+ Declaring the function SmoothXSeriesResize //----+ Declaring the function SmoothXSeriesAlert #include <SmoothXSeries.mqh> //+X================================================================X+ //| PriceSeries() function | //+X================================================================X+ //----+ Declaring the function PriceSeries //----+ Declaring the function PriceSeriesAlert #include <PriceSeries.mqh> //+X================================================================X+ //| X2MA initialization function | //+X================================================================X+ int init() { //----+ //---- setting the style of the indicator presentation SetIndexStyle(0, DRAW_LINE); //---- defining a buffer for calculations SetIndexBuffer(0, X2MA); //---- setting the values of the indicator that will not be visible on the chart SetIndexEmptyValue(0, 0.0); //---- setting alerts for not allowed values of external variables JJMASeriesAlert (0, "Length1", Length1); JJMASeriesAlert (1, "Phase1", Phase1); JJMASeriesAlert (0, "Length2", Length2); JJMASeriesAlert (1, "Phase2", Phase2); PriceSeriesAlert(Input_Price_Customs); //----+ Changing sizes of buffer variables of the function //SmoothXSeries, number = 2(Two calls of the SmoothXSeries function) if (SmoothXSeriesResize(2) != 2) { INIT = false; return(0); } //---- initialization of variables if (Smooth_Mode1 > 0 && Smooth_Mode1 < 9) StartBar1 = Length1; else StartBar1 = 30; if (Smooth_Mode2 > 0 && Smooth_Mode2 < 9) StartBar2 = Length2; else StartBar2 = 30; StartBar = StartBar1 + StartBar2; //---- setting the bar number, //starting from which the indicator will be drawn SetIndexDrawBegin(0, StartBar); //---- Setting the format of accuracy of the indicator drawing IndicatorDigits(Digits); //---- end of initialization INIT = true; return(0); //----+ } //+X================================================================X+ //| X2MA iteration function | //+X================================================================X+ int start() { //----+ //---- Getting the number of the last bar int Bars_ = Bars - 1; //---- checking the initialization end and //checking if the number of bars is enough for calculation if (!INIT || Bars_ <= StartBar) return(-1); //---- Introducing variables with a floating point double Price, x1ma, x2ma; //---- Introducing integer variables and obtaining the number //of already calculated bars int reset, MaxBar1, MaxBar2, limit, bar, counted_bars = IndicatorCounted(); //---- checking for possible errors if (counted_bars < 0) return(-1); //---- the last calculated bar must be recalculated if (counted_bars > 0) counted_bars--; //---- defining the number of the oldest bar, //starting from which new bars will be recalculated limit = Bars_ - counted_bars; //---- defining the number of the oldest bar, //starting from which all bars will be recalculated MaxBar1 = Bars_; MaxBar2 = MaxBar1 - StartBar1; //----+ the main cycle of the indicator calculation for(bar = limit; bar >= 0; bar--) { //---- Getting the initial value of the price series Price = PriceSeries(Input_Price_Customs, bar); //---- X1MA smoothing of the initial value of the price series, //---- Call of the SmoothXSeries function number 0, //parameters Phase and Length are not changed at each bar (din = 0) x1ma = SmoothXSeries(0, Smooth_Mode1, 0, MaxBar1, limit, Phase1, Length1, Price, bar, reset); //---- checking that there are no errors in the previous operation if(reset != 0) return(-1); //---- X2MA smoothing of the obtained indicator, //---- Call of the SmoothXSeries function number 1, //parameters Phase and Length are not changed at each bar (din = 0) x2ma = SmoothXSeries(1, Smooth_Mode2, 0, MaxBar2, limit, Phase2, Length2, x1ma, bar, reset); //---- checking that there are no errors in the previous operation if(reset != 0) return(-1); //---- X2MA[bar] = x2ma; //---- } //----+ end of the indicator values calculation return(0); //----+ } //+X--------------------+ <<< The End >>> +--------------------X+
Claro, o indicador final terá um pequeno atraso em comparação ao original, mas o número de alertas falsos recebido por tal movimento será muito menor, o que compensa o atraso.
Esse indicador pode ser melhorado se transformando na série contínua de valores que ele pode obter em um quantal (discreto). Um algoritmo simples é usado para esta finalidade:
//----+ normalizing the obtained value x2ma double Norma = Step * Point; //---- x2ma /= Norma; x2ma = NormalizeDouble(x2ma, 0); x2ma *= Norma;
A variável Step é um parâmetro externo do indicador, o que define a etapa de discrição de valores do movimento obtido em pontos. Não incluirei seu código no artigo - você pode vê-lo usando o indicador X2DigMa.mq4 anexado ao artigo.
Recomendações práticas na otimização de Expert Advisors que usando o indicador X2DigMa.mq4
Esse movimento tem um número grande de variáveis externas que é o motivo de qualquer Expert Advisor feito com base nesse indicador poder ser bem ajustado a qualquer mercado. No entanto, a adequação formal dos parâmetros de EA não é a melhor forma da sua programação para operações adicionais. Vamos tratar dos detalhes do trabalho com variáveis externas de tal movimento em um Expert Advisor. Suponhamos que temos um EA no qual todas as variáveis externas do movimento X2DigMA.mq4 são feitas variáveis externas do EA.
extern int Smooth_Mode1 = 0; extern int Length1 = 9; extern int Phase1 = 100; extern int Smooth_Mode2 = 0; extern int Length2 = 5; extern int Phase2 = 100; extern int Step = 10; extern int Input_Price_Customs = 0;
A variável Smooth_Mode1 aceita os valores de zero a oito, mas eu não recomendo otimizar o valor dessa variável em um testador usando um algoritmo genético. É melhor executar oito otimizações independentes para cada valor dessa variável. O valor da variável análoga de uma Smooth_Mode2 de suavidade repetida deve ser melhor fixado como igual a zero. Em tal caso, o algoritmo de média JMA será usado como uma suavização repetida. Esse algoritmo tem o lag mínimo e dá os melhores resultados como a média adicional em muitos casos.
Os parâmetros Phase1 e Phase2 que são usados somente nas médias das séries JMA e T3 devem ser melhor fixados como iguais a 100. O parâmetro Length2 pode tomar muito valores, mas em muitas situações e em EAs absolutamente diferentes, os mais ótimos são com frequência os mesmos valores das séries 3, 5, 7, 9, 11. O uso desses valores do parâmetro Length2 é suficiente como regra. O parâmetro Step depende muito do mercado, no qual o EA opera, e no período do gráfico; no entanto, com frequência ele é estabilizado nos mesmos valores. Os melhores valores do parâmetro nput_Price_Customs são normalmente zero e nove. Como resultado de uma investigação cuidadosa, somente um parâmetro, Length1, resta; seus valores podem ser diferentes.
O diagrama MACD universal
Usando a função SmoothXSeries() oferecida por mim, é possível construir qualquer indicador da análise técnica, por exemplo o diagrama MACD que é o gráfico de dois indicadores. O primeiro é um diagrama da diferença entre dois movimentos; o segundo é uma média de movimento dessa diferença.
/* For the operation of the indicator the files SmoothXSeries.mqh T3Series.mqh MASeries.mqh LRMASeries.mqh JurXSeries.mqh ParMASeries.mqh JJMASeries.mqh PriceSeries.mqh should be located in the directory: MetaTrader\experts\include\ Heiken Ashi#.mq4 should be located in the directory: MetaTrader\indicators\ */ //+X================================================================X+ //| XMACD.mq4 | //| Copyright © 2009, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+X================================================================X+ #property copyright "Copyright © 2009, Nikolay Kositsin" #property link "farria@mail.redcom.ru" //---- drawing the indicator in the main window #property indicator_separate_window //---- number of indicator buffers #property indicator_buffers 2 //---- colors of the indicator #property indicator_color1 Blue #property indicator_color2 Magenta //---- width of the diagram line #property indicator_width1 2 //---- INPUT PARAMETERS OF THE INDICATOR extern int MACD_Mode = 0; // Choosing the smoothing algorithm for MACD 0 - JJMA, 1 - JurX, // 2 - ParMA, 3 - LRMA, 4 - T3, 5 - SMA, 6 - EMA, 7 - SSMA, 8 - LWMA extern int MACD_Phase = 100; extern int FastXMA = 12; extern int SlowXMA = 26; extern int Signal_Mode = 0; // Choosing the smoothing algorithm for the signal line //0 - JJMA, 1 - JurX, 2 - ParMA, 3 - LRMA, 4 - T3, 5 - SMA, 6 - EMA, 7 - SSMA, 8 - LWMA extern int Signal_Phase = 100; extern int SignalXMA = 9; extern int Input_Price_Customs = 0; /* Selecting prices, upon which the calculation of the indicator is performed (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 14-Heiken Ashi Close.) */ //---- indicator buffers double XMacdBuffer[]; double XSignalBuffer[]; //---- variabless bool INIT; int StartBar, StartBar1, StartBar2; //+X================================================================X+ //| SmoothXSeries() function | //+X================================================================X+ //----+ Declaring the function SmoothXSeries //----+ Declaring the function SmoothXSeriesResize //----+ Declaring the function SmoothXSeriesAlert #include <SmoothXSeries.mqh> //+X================================================================X+ //| PriceSeries() function | //+X================================================================X+ //----+ Declaring the function PriceSeries //----+ Declaring the function PriceSeriesAlert #include <PriceSeries.mqh> //+X================================================================X+ //| XMACD indicator initialization function | //+X================================================================X+ int init() { //----+ //---- setting the style of the indicator presentation SetIndexStyle(0, DRAW_HISTOGRAM); SetIndexStyle(1, DRAW_LINE); //---- Setting the accuracy format (number of digits //after the decimal point) for the visualization of the indicator values IndicatorDigits(Digits + 1); //---- defining buffers for calculation SetIndexBuffer(0, XMacdBuffer); SetIndexBuffer(1, XSignalBuffer); //---- names for data windows and labels for subwindows IndicatorShortName(StringConcatenate ("XMACD(", FastXMA, ",", SlowXMA, ",", SignalXMA, ")")); SetIndexLabel(0, "XMACD"); SetIndexLabel(1, "XSignal"); //---- setting alerts for not allowed values of external variables JJMASeriesAlert (0, "FastXMA", FastXMA); JJMASeriesAlert (0, "SlowXMA", SlowXMA); JJMASeriesAlert (0, "SignalXMA", SignalXMA); //---- JJMASeriesAlert (1, "MACD_Phase", MACD_Phase); JJMASeriesAlert (1, "Signal_Phase", Signal_Phase); PriceSeriesAlert(Input_Price_Customs); //---- Changing sizes of buffer variables of the function //SmoothXSeries, number = 3(Three calls of the SmoothXSeries function) if (SmoothXSeriesResize(3) != 3) { INIT = false; return(0); } //---- initialization of variables if (MACD_Mode > 0 && MACD_Mode < 9) StartBar1 = MathMax( FastXMA, SlowXMA); else StartBar1 = 30; //---- if (Signal_Mode > 0 && Signal_Mode < 9) StartBar2 = SignalXMA; else StartBar2 = 30; //---- StartBar = StartBar1 + StartBar2; //---- SetIndexDrawBegin(0, StartBar1); SetIndexDrawBegin(1, StartBar); //---- end of initialization INIT = true; return(0); //----+ } //+X================================================================X+ //| XMACD indicator iteration function | //+X================================================================X+ int start() { //----+ //---- Getting the number of the last bat int Bars_ = Bars - 1; //---- checking the initialization end and //checking if the number of bars is enough for calculation if (!INIT || Bars_ <= StartBar) return(-1); //---- Introducing variables with a floating point double Price, FastXMA_, SlowXMA_, XMACD, SignalXMA_; //---- Introducing integer variables and obtaining the number //of already calculated bars int reset, MaxBar1, MaxBar2, limit, bar, counted_bars = IndicatorCounted(); //---- checking for possible errors if (counted_bars < 0) return(-1); //---- the last calculated bar must be recalculated if (counted_bars > 0) counted_bars--; //---- defining the number of the oldest bar, //starting from which new bars will be recalculated limit = Bars_ - counted_bars; //---- defining the number of the oldest bar, //starting from which all bars will be recalculated MaxBar1 = Bars_; MaxBar2 = MaxBar1 - StartBar1; //----+ the main cycle of the indicator calculation for(bar = limit; bar >= 0; bar--) { //---- Getting the initial value of the price series Price = PriceSeries(Input_Price_Customs, bar); //---- FastXMA smoothing of the initial value of the price series, //---- Call of the SmoothXSeries function number 0, //parameters Phase and Length are not changed at each bar (din = 0) FastXMA_ = SmoothXSeries(0, MACD_Mode, 0, MaxBar1, limit, MACD_Phase, FastXMA, Price, bar, reset); //---- checking that there are no errors in the previous operation if(reset != 0) return(-1); //---- SlowXMA smoothing of the initial value of the price series, //---- Call of the SmoothXSeries function number 1, //parameters Phase and Length are not changed at each bar (din = 0) SlowXMA_ = SmoothXSeries(1, MACD_Mode, 0, MaxBar1, limit, MACD_Phase, SlowXMA, Price, bar, reset); //---- checking that there are no errors in the previous operation if(reset != 0) return(-1); //---- if(bar < MaxBar2) XMACD = FastXMA_ - SlowXMA_; //---- SignalXMA smoothing of the obtained XMACD diagram, //---- Call of the SmoothXSeries function number 2, //parameters Phase and Length are not changed at each bar (din = 0) SignalXMA_ = SmoothXSeries(2, Signal_Mode, 0, MaxBar2, limit, Signal_Phase, SignalXMA, XMACD, bar, reset); //---- checking that there are no errors in the previous operation if(reset != 0) return(-1); //---- XMacdBuffer[bar] = XMACD; XSignalBuffer[bar] = SignalXMA_; } return(0); //----+ } //+X----------------------+ <<< The End >>> +-----------------------X+
A lógica de trabalho com tal indicador em um Expert Advisor é, em muitos aspectos, análoga ao que escrevi acima, mas nesse caso, o valor da variável Signal_Mode deve ser submetido a otimização genética.
Conclusão
Usando a chamada da função SmoothXSeries(), é possível construir qualquer indicador da análise técnica, as possibilidades da qual parecem ser mais altas que aquelas do seu clássico análogo. Claro, isso exige uma certa experiência na escrita de indicadores, mas o resultado final vale todos os esforços.