Kaique Mitsuo Silva Yamamoto
Mercado financeiroAutomação de EstratégiasMetaTrader 5 / MQL5

MQL5 — Indicadores Customizados

Como criar indicadores personalizados em MQL5: SetIndexBuffer, estilos de plotagem (DRAW_LINE, DRAW_HISTOGRAM, DRAW_ARROW, DRAW_FILLING, DRAW_CANDLES), buffers, propriedades e exemplos completos.

MQL5 — Indicadores Customizados

Os indicadores customizados em MQL5 analisam preços e exibem informações visuais no gráfico — linhas, histogramas, setas, velas e outros estilos. Eles não executam ordens, mas são usados por Expert Advisors via iCustom() e CopyBuffer().

Event handlers: MQL5 — Event Handlers | Indicadores prontos: Indicadores Técnicos


Estrutura Básica de um Indicador

// 1. Propriedades do indicador
#property indicator_chart_window   // ou indicator_separate_window
#property indicator_buffers 1      // número total de buffers
#property indicator_plots   1      // número de séries plotadas
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrDodgerBlue
#property indicator_width1  2

// 2. Buffer global
double LineBuffer[];

// 3. OnInit: vincular buffers
int OnInit()
{
    SetIndexBuffer(0, LineBuffer, INDICATOR_DATA);
    PlotIndexSetString(0, PLOT_LABEL, "Meu Indicador");
    IndicatorSetString(INDICATOR_SHORTNAME, "MeuInd");
    return(INIT_SUCCEEDED);
}

// 4. OnCalculate: preencher buffers
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
    int start = (prev_calculated == 0) ? 1 : prev_calculated;

    for(int i = start; i < rates_total; i++)
        LineBuffer[i] = (high[i] + low[i]) / 2.0;

    return(rates_total);
}

Propriedades do Indicador (#property)

Posicionamento

PropriedadeDescrição
indicator_chart_windowPlota na janela principal do gráfico
indicator_separate_windowPlota em janela separada (sub-janela)
indicator_minimum / indicator_maximumEscala mínima/máxima da sub-janela

Configuração de buffers e plots

PropriedadeDescrição
indicator_buffers NTotal de buffers alocados (máximo: 512)
indicator_plots NTotal de séries visíveis no gráfico
indicator_typeN DRAW_*Estilo de plotagem da série N
indicator_colorN clrXxxCor da série N
indicator_widthN NEspessura da linha N (pixels)
indicator_styleN STYLE_*Estilo de linha (SOLID, DASH, DOT, DASHDOT)
indicator_labelN "nome"Rótulo exibido no tooltip da série N
// Exemplo: duas linhas + histograma
#property indicator_separate_window
#property indicator_minimum -100
#property indicator_maximum  100
#property indicator_buffers 3
#property indicator_plots   3

#property indicator_type1   DRAW_LINE
#property indicator_color1  clrGreen
#property indicator_width1  2
#property indicator_label1  "Linha Rápida"

#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed
#property indicator_width2  1
#property indicator_label2  "Linha Lenta"

#property indicator_type3   DRAW_HISTOGRAM
#property indicator_color3  clrGray
#property indicator_label3  "Diferença"

SetIndexBuffer — Vincular Buffers

bool SetIndexBuffer(int               index,
                    double            &buffer[],
                    ENUM_INDEXBUFFER_TYPE usage)
usageDescrição
INDICATOR_DATADados visíveis no gráfico (plotados)
INDICATOR_CALCULATIONSBuffer interno (não plotado) — para cálculos intermediários
INDICATOR_COLOR_INDEXBuffer de índice de cor (para estilos COLOR)
double FastLine[], SlowLine[], DiffHist[], CalcBuffer[];

int OnInit()
{
    // Buffers visíveis
    SetIndexBuffer(0, FastLine,   INDICATOR_DATA);
    SetIndexBuffer(1, SlowLine,   INDICATOR_DATA);
    SetIndexBuffer(2, DiffHist,   INDICATOR_DATA);

    // Buffer de cálculo interno (não aparece no gráfico)
    SetIndexBuffer(3, CalcBuffer, INDICATOR_CALCULATIONS);

    return(INIT_SUCCEEDED);
}

Estilos de Plotagem (DRAW_*)

DRAW_LINE — Linha contínua

#property indicator_type1 DRAW_LINE
// Buffers necessários: 1 (valores)

DRAW_SECTION — Linha com segmentos (com gaps quando EMPTY_VALUE)

#property indicator_type1 DRAW_SECTION
// Buffers necessários: 1
// Define EMPTY_VALUE onde não deve plotar
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);

DRAW_HISTOGRAM — Histograma a partir do zero

#property indicator_type1 DRAW_HISTOGRAM
// Buffers necessários: 1 (altura da barra)
// Útil para OBV, volume, MACD histogram

DRAW_HISTOGRAM2 — Histograma entre dois valores

#property indicator_type1 DRAW_HISTOGRAM2
// Buffers necessários: 2 (valor superior, valor inferior)
// Útil para plotar faixas

DRAW_ARROW — Setas/símbolos nos pontos

#property indicator_type1  DRAW_ARROW
#property indicator_color1 clrGold

// Buffers necessários: 1 (posição vertical da seta)
// Código Wingdings da seta:
PlotIndexSetInteger(0, PLOT_ARROW, 233); // símbolo de seta para cima

Códigos comuns de setas (Wingdings):

CódigoSímbolo
233▲ seta para cima
234▼ seta para baixo
159● círculo
108◆ diamante

DRAW_ZIGZAG — Linha zigzag entre pares de pontos

#property indicator_type1 DRAW_ZIGZAG
// Buffers necessários: 2 (pontos altos, pontos baixos)
// Buffer 1: valores de máximas (ou EMPTY_VALUE)
// Buffer 2: valores de mínimas (ou EMPTY_VALUE)

DRAW_FILLING — Preenchimento entre duas linhas

#property indicator_type1  DRAW_FILLING
#property indicator_color1 clrLightBlue  // cor quando linha1 > linha2
#property indicator_color2 clrLightPink  // cor quando linha1 < linha2

// Buffers necessários: 2 (linha superior, linha inferior)
// Usado em Bollinger Bands, Ichimoku Cloud, Envelopes

DRAW_BARS — Barras OHLC

#property indicator_type1 DRAW_BARS
// Buffers necessários: 4 (open[], high[], low[], close[])

DRAW_CANDLES — Velas japonesas

#property indicator_type1  DRAW_CANDLES
#property indicator_color1 clrWhite  // corpo de alta
#property indicator_color2 clrRed    // corpo de baixa

// Buffers necessários: 4 (open[], high[], low[], close[])

Estilos com cor dinâmica (DRAW_COLOR_*)

Versões com buffer de índice de cor — permite cores diferentes por barra:

EstiloBuffersUso
DRAW_COLOR_LINE2 (valor + índice cor)Linha com cor variável
DRAW_COLOR_SECTION2Segmentos coloridos
DRAW_COLOR_HISTOGRAM2Histograma colorido
DRAW_COLOR_HISTOGRAM23Histograma 2 colorido
DRAW_COLOR_ARROW2Setas coloridas
DRAW_COLOR_ZIGZAG3Zigzag colorido
DRAW_COLOR_BARS5Barras coloridas
DRAW_COLOR_CANDLES5Velas coloridas
// Exemplo: histograma com cor dinâmica (verde se positivo, vermelho se negativo)
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   1
#property indicator_type1   DRAW_COLOR_HISTOGRAM
#property indicator_color1  clrGreen, clrRed  // índice 0=verde, 1=vermelho

double HistBuffer[], ColorBuffer[];

int OnInit()
{
    SetIndexBuffer(0, HistBuffer,  INDICATOR_DATA);
    SetIndexBuffer(1, ColorBuffer, INDICATOR_COLOR_INDEX);
    return(INIT_SUCCEEDED);
}

int OnCalculate(const int rates_total, const int prev_calculated,
                const datetime &time[], const double &open[],
                const double &high[], const double &low[],
                const double &close[], const long &tick_volume[],
                const long &volume[], const int &spread[])
{
    for(int i = MathMax(prev_calculated, 1); i < rates_total; i++)
    {
        HistBuffer[i]  = close[i] - close[i-1];  // variação
        ColorBuffer[i] = (HistBuffer[i] >= 0) ? 0 : 1; // 0=verde, 1=vermelho
    }
    return(rates_total);
}

PlotIndexSetInteger/Double/String — Configurar Plots

// Configurar após SetIndexBuffer
PlotIndexSetInteger(int plot_index, ENUM_PLOT_PROPERTY_INTEGER prop_id, int value);
PlotIndexSetDouble (int plot_index, ENUM_PLOT_PROPERTY_DOUBLE  prop_id, double value);
PlotIndexSetString (int plot_index, ENUM_PLOT_PROPERTY_STRING  prop_id, string value);
PropriedadeTipoDescrição
PLOT_DRAW_TYPEIntegerEstilo (DRAW_LINE, etc.)
PLOT_COLOR_INDEXESIntegerNúmero de cores para estilos COLOR
PLOT_LINE_COLORIntegerCor da linha (índice de cor)
PLOT_LINE_WIDTHIntegerEspessura
PLOT_LINE_STYLEIntegerSTYLE_SOLID, STYLE_DASH, etc.
PLOT_ARROWIntegerCódigo Wingdings da seta
PLOT_EMPTY_VALUEDoubleValor a ignorar na plotagem
PLOT_LABELStringNome no tooltip
PLOT_DRAW_BEGINIntegerÍndice a partir do qual plotar
// Exemplo de configuração via código (alternativa ao #property)
PlotIndexSetInteger(0, PLOT_DRAW_TYPE,  DRAW_LINE);
PlotIndexSetInteger(0, PLOT_LINE_COLOR, clrDodgerBlue);
PlotIndexSetInteger(0, PLOT_LINE_WIDTH, 2);
PlotIndexSetDouble (0, PLOT_EMPTY_VALUE, 0.0);
PlotIndexSetString (0, PLOT_LABEL, "Minha Linha");
PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, 20); // começar após 20 barras

IndicatorSetInteger/Double/String — Configurar o Indicador

IndicatorSetString(INDICATOR_SHORTNAME, "Nome no gráfico");
IndicatorSetInteger(INDICATOR_DIGITS, 4); // casas decimais no tooltip
IndicatorSetDouble(INDICATOR_MINIMUM, -100.0); // escala da sub-janela
IndicatorSetDouble(INDICATOR_MAXIMUM,  100.0);

Exemplo Completo: Bollinger Bands com Filling

#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots   3

#property indicator_type1   DRAW_LINE
#property indicator_color1  clrSilver
#property indicator_width1  1
#property indicator_label1  "BB Superior"

#property indicator_type2   DRAW_FILLING
#property indicator_color2  clrLightBlue, clrLightBlue
#property indicator_label2  "BB Filling"

#property indicator_type3   DRAW_LINE
#property indicator_color3  clrSilver
#property indicator_width3  1
#property indicator_label3  "BB Inferior"

input int    BBPeriod = 20;
input double BBDev    = 2.0;

double UpperBand[], FillUpper[], LowerBand[];

int OnInit()
{
    SetIndexBuffer(0, UpperBand, INDICATOR_DATA);
    SetIndexBuffer(1, FillUpper, INDICATOR_DATA); // topo do filling
    SetIndexBuffer(2, LowerBand, INDICATOR_DATA); // fundo do filling (plot 2)

    // plot 1 (índice 1) é o DRAW_FILLING entre buffer 1 e buffer 2
    PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, BBPeriod);
    PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, BBPeriod);
    PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, BBPeriod);

    IndicatorSetString(INDICATOR_SHORTNAME,
                       StringFormat("BB(%d, %.1f)", BBPeriod, BBDev));
    return(INIT_SUCCEEDED);
}

int OnCalculate(const int rates_total, const int prev_calculated,
                const datetime &time[], const double &open[],
                const double &high[], const double &low[],
                const double &close[], const long &tick_volume[],
                const long &volume[], const int &spread[])
{
    int start = MathMax(prev_calculated, BBPeriod);

    for(int i = start; i < rates_total; i++)
    {
        // Calcular média
        double sum = 0;
        for(int j = 0; j < BBPeriod; j++) sum += close[i - j];
        double ma = sum / BBPeriod;

        // Calcular desvio padrão
        double variance = 0;
        for(int j = 0; j < BBPeriod; j++)
            variance += MathPow(close[i - j] - ma, 2);
        double stddev = MathSqrt(variance / BBPeriod);

        UpperBand[i] = ma + BBDev * stddev;
        FillUpper[i] = ma + BBDev * stddev; // mesmo que UpperBand
        LowerBand[i] = ma - BBDev * stddev;
    }

    return(rates_total);
}

Usando o Indicador Customizado em um EA

// Via iCustom()
int handle = iCustom(_Symbol, PERIOD_CURRENT, "MeuIndicador",
                     param1, param2, param3);

if(handle == INVALID_HANDLE)
{
    Print("Erro ao criar handle: ", GetLastError());
    return(INIT_FAILED);
}

// Ler valores do buffer 0 (3 últimos valores)
double buffer[];
ArraySetAsSeries(buffer, true);
if(CopyBuffer(handle, 0, 0, 3, buffer) < 3) return;

double valorAtual    = buffer[0];
double valorAnterior = buffer[1];

// Liberar ao finalizar
IndicatorRelease(handle);

Limitações e Boas Práticas

LimiteValor
Máximo de buffers por indicador512
Máximo de plots visíveis64
Extensão do arquivo compilado.ex5

Boas práticas:

  • Use INDICATOR_CALCULATIONS para buffers intermediários — reduz memória consumida
  • Defina PLOT_DRAW_BEGIN para não plotar nas primeiras barras onde o cálculo é inválido
  • Defina PLOT_EMPTY_VALUE para omitir pontos específicos sem criar gaps visuais indesejados
  • Use ArraySetAsSeries(buffer, false) para acessar buffers em ordem cronológica (índice 0 = mais antigo) dentro de OnCalculate

Referências

Referências externas

On this page