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

MQL5 — Event Handlers: Estrutura de Execução

Guia completo dos 14 event handlers do MQL5: OnInit, OnDeinit, OnTick, OnCalculate, OnTimer, OnTrade, OnTradeTransaction, OnChartEvent, OnTester e outros — com assinaturas, códigos de retorno e exemplos práticos.

MQL5 — Event Handlers: Estrutura de Execução

O MQL5 é orientado a eventos. Em vez de um loop infinito, cada programa reage a eventos gerados pelo terminal. Os event handlers são as funções que você implementa para processar esses eventos.

Fundamentos da linguagem: MQL5 — Fundamentos | Indicadores técnicos: Indicadores Técnicos


Visão Geral dos 14 Handlers

HandlerTipo de programaQuando é chamado
OnStart()Scripts, ServiçosUma vez ao iniciar
OnInit()EA, IndicadorUma vez ao carregar
OnDeinit()EA, IndicadorUma vez ao remover
OnTick()EAA cada novo tick
OnCalculate()IndicadorA cada novo tick / nova barra
OnTimer()EA, IndicadorA cada N segundos (EventSetTimer)
OnTrade()EAAo mudar estado de ordens/posições
OnTradeTransaction()EAPara cada transação de trading
OnBookEvent()EAMudança no Book (DOM)
OnChartEvent()EA, IndicadorClick, teclado, objeto gráfico
OnTester()EAAo finalizar um pass no Tester
OnTesterInit()EAInício do processo de otimização
OnTesterDeinit()EAFim do processo de otimização
OnTesterPass()EAFim de cada pass na otimização

OnStart — Scripts e Serviços

int OnStart(void)

Função principal de scripts e serviços. Executa uma vez e depois encerra (scripts) ou em loop (serviços).

// Script: executa uma ação e encerra
void OnStart()
{
    // Fechar todas as posições abertas
    for(int i = PositionsTotal() - 1; i >= 0; i--)
    {
        ulong ticket = PositionGetTicket(i);
        trade.PositionClose(ticket);
    }
    Print("Todas as posições fechadas.");
}
// Serviço: loop contínuo
void OnStart()
{
    while(!IsStopped())
    {
        // Verificar condições e agir
        Sleep(1000); // esperar 1 segundo
    }
}

OnInit — Inicialização

int OnInit(void)

Executado uma vez ao carregar o EA ou indicador no gráfico. Use para:

  • Criar handles de indicadores com iMA(), iRSI(), etc.
  • Validar parâmetros de entrada
  • Inicializar variáveis e objetos

Códigos de retorno

ConstanteValorDescrição
INIT_SUCCEEDED0Inicialização bem-sucedida
INIT_FAILED1Falha — programa é removido
INIT_PARAMETERS_INCORRECT-1Parâmetros inválidos
INIT_AGENT_NOT_SUITABLE-2Agente incompatível (otimização)
input int FastPeriod = 10;
input int SlowPeriod = 20;

int handleFast, handleSlow;

int OnInit()
{
    // Validar parâmetros
    if(FastPeriod >= SlowPeriod)
    {
        Print("Erro: FastPeriod deve ser menor que SlowPeriod");
        return(INIT_PARAMETERS_INCORRECT);
    }

    // Criar handles de indicadores
    handleFast = iMA(_Symbol, PERIOD_CURRENT, FastPeriod, 0, MODE_EMA, PRICE_CLOSE);
    handleSlow = iMA(_Symbol, PERIOD_CURRENT, SlowPeriod, 0, MODE_EMA, PRICE_CLOSE);

    if(handleFast == INVALID_HANDLE || handleSlow == INVALID_HANDLE)
    {
        Print("Erro ao criar handles de indicadores: ", GetLastError());
        return(INIT_FAILED);
    }

    // Configurar timer (opcional)
    EventSetTimer(60); // dispara OnTimer a cada 60s

    return(INIT_SUCCEEDED);
}

OnDeinit — Limpeza

void OnDeinit(const int reason)

Executado ao remover o programa. Libere recursos criados em OnInit().

Códigos de razão (reason)

ConstanteValorDescrição
REASON_PROGRAM0Encerrado pelo próprio programa
REASON_REMOVE1Removido do gráfico manualmente
REASON_RECOMPILE2Recompilado no MetaEditor
REASON_CHARTCHANGE3Símbolo ou timeframe mudou
REASON_CHARTCLOSE4Gráfico foi fechado
REASON_PARAMETERS5Parâmetros de input foram alterados
REASON_ACCOUNT6Conta alterada
REASON_TEMPLATE7Template aplicado
REASON_INITFAILED8OnInit() retornou erro
REASON_CLOSE9Terminal sendo fechado
void OnDeinit(const int reason)
{
    // Liberar handles de indicadores
    IndicatorRelease(handleFast);
    IndicatorRelease(handleSlow);

    // Cancelar timer
    EventKillTimer();

    // Remover objetos gráficos criados
    ObjectsDeleteAll(0, "EA_");

    // Log da razão
    Print("OnDeinit: razão = ", reason);
}

OnTick — Lógica Principal do EA

void OnTick(void)

Chamado a cada tick (atualização de preço). É onde fica a lógica central do Expert Advisor.

Não disponível em indicadores — use OnCalculate().

#include <Trade/Trade.mqh>
CTrade trade;

void OnTick()
{
    // 1. Verificar se há uma nova barra (evitar execução redundante)
    static datetime lastBar = 0;
    datetime currentBar = iTime(_Symbol, PERIOD_CURRENT, 0);
    if(currentBar == lastBar) return;
    lastBar = currentBar;

    // 2. Ler valores dos indicadores
    double fast[], slow[];
    ArraySetAsSeries(fast, true);
    ArraySetAsSeries(slow, true);

    if(CopyBuffer(handleFast, 0, 0, 3, fast) < 3) return;
    if(CopyBuffer(handleSlow, 0, 0, 3, slow) < 3) return;

    // 3. Detectar cruzamento
    bool crossUp   = (fast[1] > slow[1]) && (fast[2] <= slow[2]);
    bool crossDown = (fast[1] < slow[1]) && (fast[2] >= slow[2]);

    // 4. Executar
    if(crossUp  && PositionsTotal() == 0) trade.Buy(0.1);
    if(crossDown && PositionsTotal() == 0) trade.Sell(0.1);
}

Padrão: executar apenas na abertura de nova barra

bool IsNewBar()
{
    static datetime prevTime = 0;
    datetime curTime = iTime(_Symbol, PERIOD_CURRENT, 0);
    if(curTime != prevTime)
    {
        prevTime = curTime;
        return true;
    }
    return false;
}

void OnTick()
{
    if(!IsNewBar()) return;
    // lógica aqui...
}

OnCalculate — Lógica Principal do Indicador

Dois overloads disponíveis:

Overload simples (uma série de preço)

int OnCalculate(const int    rates_total,
                const int    prev_calculated,
                const int    begin,
                const double &price[])

Usado quando o indicador é aplicado sobre outro indicador ou série de preço.

Overload completo (OHLCV)

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[])

Lógica de prev_calculated

  • prev_calculated = número de barras já calculadas na chamada anterior
  • Permite calcular apenas as barras novas, sem recalcular o histórico inteiro
double Buffer[];

int OnInit()
{
    SetIndexBuffer(0, Buffer, INDICATOR_DATA);
    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[])
{
    // Calcular apenas barras novas (eficiência)
    int start = (prev_calculated == 0) ? 1 : prev_calculated;

    for(int i = start; i < rates_total; i++)
    {
        Buffer[i] = (high[i] + low[i] + close[i]) / 3.0; // Typical Price
    }

    return(rates_total); // retorna o total calculado
}

OnTimer — Eventos Periódicos

void OnTimer(void)

Disparado a cada N segundos após EventSetTimer(N) em OnInit().

int OnInit()
{
    EventSetTimer(3600); // a cada 1 hora
    return(INIT_SUCCEEDED);
}

void OnTimer()
{
    // Enviar relatório, verificar notícias, atualizar parâmetros...
    string msg = StringFormat("Posições abertas: %d | P&L: %.2f",
                              PositionsTotal(),
                              AccountInfoDouble(ACCOUNT_PROFIT));
    Print(msg);
}

void OnDeinit(const int reason)
{
    EventKillTimer();
}

OnTrade — Mudança de Estado de Trading

void OnTrade(void)

Chamado quando o estado de ordens ou posições muda (abertura, fechamento, modificação). Não inclui detalhes da transação — use OnTradeTransaction() para isso.

void OnTrade()
{
    // Verificar se posição foi fechada
    if(PositionsTotal() == 0)
    {
        Print("Todas as posições foram fechadas.");
        // Reset de variáveis, log, etc.
    }
}

OnTradeTransaction — Detalhes de Cada Transação

void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest     &request,
                        const MqlTradeResult      &result)

Chamado para cada transação processada — mais granular que OnTrade().

void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest     &request,
                        const MqlTradeResult      &result)
{
    // Filtrar apenas transações de deal executado
    if(trans.type == TRADE_TRANSACTION_DEAL_ADD)
    {
        if(trans.deal_type == DEAL_TYPE_BUY)
            Print("Compra executada: ", trans.volume, " @ ", trans.price);
        else if(trans.deal_type == DEAL_TYPE_SELL)
            Print("Venda executada: ", trans.volume, " @ ", trans.price);
    }
}

Tipos de transação relevantes

ConstanteDescrição
TRADE_TRANSACTION_ORDER_ADDNova ordem adicionada
TRADE_TRANSACTION_ORDER_UPDATEOrdem modificada
TRADE_TRANSACTION_ORDER_DELETEOrdem removida (executada/cancelada)
TRADE_TRANSACTION_DEAL_ADDNovo deal executado
TRADE_TRANSACTION_POSITIONPosição atualizada
TRADE_TRANSACTION_HISTORY_ADDDeal adicionado ao histórico

OnChartEvent — Interação com o Gráfico

void OnChartEvent(const int     id,
                  const long    &lparam,
                  const double  &dparam,
                  const string  &sparam)

Processa eventos de interface: mouse, teclado, objetos gráficos.

idEventolparamdparamsparam
CHARTEVENT_CLICKClick no gráficox (pixels)y (pixels)
CHARTEVENT_KEYDOWNTecla pressionadacódigo da tecla
CHARTEVENT_OBJECT_CLICKClick em objetoxynome do objeto
CHARTEVENT_OBJECT_DRAGObjeto arrastadonome do objeto
CHARTEVENT_CUSTOMEvento customizado (0..65535)
CHARTEVENT_MOUSE_MOVEMouse movidoxyflags
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
    if(id == CHARTEVENT_KEYDOWN)
    {
        if(lparam == 66) // tecla 'B'
        {
            trade.Buy(0.1);
            Print("Compra manual via teclado");
        }
        if(lparam == 83) // tecla 'S'
        {
            trade.Sell(0.1);
            Print("Venda manual via teclado");
        }
    }

    if(id == CHARTEVENT_OBJECT_DRAG && sparam == "StopLine")
    {
        // Atualizar stop loss ao arrastar linha
        double newStop = ObjectGetDouble(0, "StopLine", OBJPROP_PRICE);
        Print("Novo Stop Loss: ", newStop);
    }
}

OnTester, OnTesterInit, OnTesterDeinit, OnTesterPass

Handlers usados para personalizar o processo de otimização no Strategy Tester.

// Retorna a métrica customizada para o otimizador
double OnTester()
{
    double profit     = TesterStatistics(STAT_PROFIT);
    double drawdown   = TesterStatistics(STAT_EQUITY_DD_RELATIVE);
    double trades     = TesterStatistics(STAT_TRADES);

    if(trades < 50 || drawdown > 20) return 0; // penalizar

    return profit / MathMax(drawdown, 0.01); // maximizar ratio
}

// Chamado antes do início da otimização (no agente coordenador)
void OnTesterInit()
{
    Print("Iniciando otimização...");
}

// Chamado ao final da otimização completa
void OnTesterDeinit()
{
    Print("Otimização concluída.");
}

// Chamado após cada pass individual ser concluído
void OnTesterPass()
{
    // Coletar resultados de cada pass para análise customizada
}

Estatísticas disponíveis em TesterStatistics()

ConstanteDescrição
STAT_PROFITLucro líquido
STAT_TRADESTotal de trades
STAT_PROFIT_FACTORProfit Factor
STAT_EXPECTED_PAYOFFPayoff esperado
STAT_EQUITY_DDDrawdown absoluto
STAT_EQUITY_DD_RELATIVEDrawdown relativo (%)
STAT_SHARPE_RATIOSharpe Ratio
STAT_RECOVERY_FACTORRecovery Factor

OnBookEvent — Profundidade de Mercado (DOM)

void OnBookEvent(const string &symbol)

Chamado quando o book de ofertas muda. Requer MarketBookAdd(symbol) em OnInit().

int OnInit()
{
    MarketBookAdd(_Symbol);
    return(INIT_SUCCEEDED);
}

void OnBookEvent(const string &symbol)
{
    if(symbol != _Symbol) return;

    MqlBookInfo book[];
    MarketBookGet(_Symbol, book);

    // book[0] = melhor oferta de venda (ask)
    // Analisar pressão compradora vs vendedora
    int bids = 0, asks = 0;
    for(int i = 0; i < ArraySize(book); i++)
    {
        if(book[i].type == BOOK_TYPE_BUY)  bids++;
        if(book[i].type == BOOK_TYPE_SELL) asks++;
    }
    Print("Bids: ", bids, " | Asks: ", asks);
}

void OnDeinit(const int reason)
{
    MarketBookRelease(_Symbol);
}

Ordem de Chamada dos Handlers

Ao carregar o EA/indicador:
  OnInit()
    ↓ (se INIT_SUCCEEDED)
  OnTick() / OnCalculate()    ← loop principal
  OnTimer()                   ← em paralelo (se EventSetTimer ativo)
  OnTrade()                   ← ao mudar posições
  OnTradeTransaction()        ← para cada transação
  OnChartEvent()              ← interação do usuário
    ↓ (ao remover)
  OnDeinit(reason)

Referências

Referências externas

On this page