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

MQL5 — Integração Externa e Recursos Avançados

WebRequest, integração com Python via sockets, ONNX (machine learning), banco de dados SQLite, OnTimer e serviços em MQL5.

MQL5 — Integração Externa e Recursos Avançados

O MQL5 vai muito além de indicadores e EAs simples. É possível consumir APIs REST, integrar modelos de machine learning via ONNX, rodar Python em paralelo, armazenar dados em SQLite e criar serviços que rodam continuamente em background.

Fundamentos: MQL5 — Fundamentos


WebRequest — Consumir APIs REST

O WebRequest permite fazer chamadas HTTP/HTTPS diretamente do MQL5.

Pré-requisito: adicionar o domínio em Tools > Options > Expert Advisors > Allow WebRequest for listed URL.

#include <JAson.mqh>  // biblioteca JSON da MQL5 Community

string GetEconomicCalendar()
{
    string url     = "https://api.tradingeconomics.com/calendar?c=YOUR_KEY&f=json";
    string headers = "Content-Type: application/json\r\n";
    char   postData[];
    char   result[];
    string resultHeaders;

    int code = WebRequest("GET", url, headers, 5000, postData, result, resultHeaders);

    if(code == 200)
        return CharArrayToString(result);
    else
    {
        Print("WebRequest erro: ", code, " | ", GetLastError());
        return "";
    }
}

// POST com JSON body
bool SendWebhookAlert(string message)
{
    string url  = "https://hooks.slack.com/services/YOUR/WEBHOOK/URL";
    string body = "{\"text\":\"" + message + "\"}";

    char postData[];
    StringToCharArray(body, postData, 0, StringLen(body));

    char result[];
    string headers = "Content-Type: application/json\r\n";
    string resHeaders;

    int code = WebRequest("POST", url, headers, 5000, postData, result, resHeaders);
    return (code == 200 || code == 204);
}

OnTimer — Execução Periódica

Útil para tarefas que não dependem de ticks: verificar calendário econômico, enviar relatórios, monitorar equity.

int OnInit()
{
    EventSetTimer(60);  // dispara OnTimer() a cada 60 segundos
    return(INIT_SUCCEEDED);
}

void OnTimer()
{
    double equity   = AccountInfoDouble(ACCOUNT_EQUITY);
    double balance  = AccountInfoDouble(ACCOUNT_BALANCE);
    double drawdown = (balance - equity) / balance * 100;

    if(drawdown > 5.0)
        SendWebhookAlert("ALERTA: Drawdown de " + DoubleToString(drawdown, 2) + "%");
}

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

Serviços (Services) — Background Contínuo

Serviços rodam independentemente de qualquer gráfico, sem precisar de um EA anexado. Ideais para coleta de dados e monitoramento.

// Arquivo: MQL5/Services/DataCollector.mq5
void OnStart()
{
    Print("Serviço iniciado");

    while(!IsStopped())
    {
        MqlTick tick;
        if(SymbolInfoTick("EURUSD", tick))
        {
            int file = FileOpen("eurusd_ticks.csv",
                                FILE_WRITE | FILE_READ | FILE_CSV | FILE_ANSI);
            FileSeek(file, 0, SEEK_END);
            FileWrite(file,
                TimeToString(tick.time, TIME_DATE | TIME_SECONDS),
                DoubleToString(tick.bid, 5),
                DoubleToString(tick.ask, 5),
                (long)tick.volume);
            FileClose(file);
        }
        Sleep(1000);  // em Services, Sleep() é permitido
    }

    Print("Serviço encerrado");
}

SQLite — Banco de Dados Embutido

MQL5 inclui suporte nativo ao SQLite desde a build 2455.

#include <sqlite3.mqh>  // disponível no CodeBase MQL5

int db;

int OnInit()
{
    db = DatabaseOpen("trades.db", DATABASE_OPEN_READWRITE | DATABASE_OPEN_CREATE);

    DatabaseExecute(db,
        "CREATE TABLE IF NOT EXISTS trades ("
        "id INTEGER PRIMARY KEY AUTOINCREMENT,"
        "symbol TEXT,"
        "openTime DATETIME,"
        "closeTime DATETIME,"
        "lots REAL,"
        "profit REAL"
        ")");

    return INIT_SUCCEEDED;
}

void SaveTrade(string symbol, datetime openTime, datetime closeTime,
               double lots, double profit)
{
    string sql = StringFormat(
        "INSERT INTO trades (symbol, openTime, closeTime, lots, profit) "
        "VALUES ('%s', %d, %d, %.2f, %.2f)",
        symbol, openTime, closeTime, lots, profit);

    DatabaseExecute(db, sql);
}

void OnDeinit(const int reason)
{
    DatabaseClose(db);
}

ONNX — Machine Learning no MetaTrader 5

O MT5 suporta modelos ONNX (Open Neural Network Exchange) nativamente desde a build 3325. É possível treinar modelos em Python (scikit-learn, TensorFlow, PyTorch) e executar diretamente no EA.

Fluxo completo

Python (treino)                      MQL5 (inferência)
────────────────                     ───────────────────
1. Coleta dados históricos           4. Carrega modelo .onnx
2. Feature engineering               5. Prepara input (normalizado)
3. Treina e exporta para .onnx  →    6. OnnxRun() para previsão
                                     7. Usa output como sinal

Exemplo de inferência em MQL5

#include <ONNX/OnnxModel.mqh>

long g_model;
float g_input[1][10];   // 1 amostra, 10 features
float g_output[1][1];   // 1 amostra, 1 saída

int OnInit()
{
    // Carregar modelo treinado em Python
    g_model = OnnxCreate("model.onnx", ONNX_DEFAULT);
    if(g_model == INVALID_HANDLE)
    {
        Print("Falha ao carregar ONNX: ", GetLastError());
        return INIT_FAILED;
    }

    // Configurar shapes
    ulong inputShape[]  = {1, 10};
    ulong outputShape[] = {1, 1};
    OnnxSetInputShape(g_model,  0, inputShape);
    OnnxSetOutputShape(g_model, 0, outputShape);

    return INIT_SUCCEEDED;
}

double PredictDirection()
{
    // Preencher features (ex: retornos normalizados)
    MqlRates rates[];
    ArraySetAsSeries(rates, true);
    CopyRates(_Symbol, PERIOD_H1, 1, 11, rates);

    for(int i = 0; i < 10; i++)
        g_input[0][i] = (float)((rates[i].close - rates[i+1].close) / rates[i+1].close);

    // Inferência
    if(!OnnxRun(g_model, ONNX_DEFAULT, g_input, g_output))
    {
        Print("Erro na inferência ONNX: ", GetLastError());
        return 0;
    }

    return g_output[0][0];  // probabilidade de subida (0 a 1)
}

void OnDeinit(const int reason)
{
    OnnxRelease(g_model);
}

Treinamento em Python (exemplo com scikit-learn)

import MetaTrader5 as mt5
import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestClassifier
import skl2onnx
from skl2onnx import convert_sklearn
from skl2onnx.common.data_types import FloatTensorType

# Conectar ao MT5
mt5.initialize()

# Baixar dados
rates = mt5.copy_rates_from_pos("EURUSD", mt5.TIMEFRAME_H1, 0, 5000)
df = pd.DataFrame(rates)

# Feature engineering
for i in range(1, 11):
    df[f'ret_{i}'] = df['close'].pct_change(i)

df['target'] = (df['close'].shift(-1) > df['close']).astype(int)
df.dropna(inplace=True)

features = [f'ret_{i}' for i in range(1, 11)]
X, y = df[features].values.astype(np.float32), df['target'].values

# Treinar
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X, y)

# Exportar para ONNX
initial_type = [('float_input', FloatTensorType([None, 10]))]
onnx_model = convert_sklearn(model, initial_types=initial_type,
                              target_opset=12)

with open("model.onnx", "wb") as f:
    f.write(onnx_model.SerializeToString())

print("Modelo exportado: model.onnx")
mt5.shutdown()

Python + MetaTrader 5 via biblioteca oficial

A MetaQuotes mantém a biblioteca MetaTrader5 para Python, que permite controle total do terminal.

import MetaTrader5 as mt5

# Inicializar
mt5.initialize()

# Informações da conta
info = mt5.account_info()
print(f"Balance: {info.balance} | Equity: {info.equity}")

# Dados históricos
import pandas as pd
rates = mt5.copy_rates_from_pos("EURUSD", mt5.TIMEFRAME_M15, 0, 1000)
df = pd.DataFrame(rates)
df['time'] = pd.to_datetime(df['time'], unit='s')

# Enviar ordem
request = {
    "action":   mt5.TRADE_ACTION_DEAL,
    "symbol":   "EURUSD",
    "volume":   0.1,
    "type":     mt5.ORDER_TYPE_BUY,
    "price":    mt5.symbol_info_tick("EURUSD").ask,
    "sl":       mt5.symbol_info_tick("EURUSD").ask - 0.0050,
    "tp":       mt5.symbol_info_tick("EURUSD").ask + 0.0100,
    "comment":  "Python order",
    "magic":    12345,
}
result = mt5.order_send(request)
print(f"Retcode: {result.retcode} | Deal: {result.deal}")

mt5.shutdown()

OnChartEvent — Interface interativa

Permite criar painéis com botões e inputs diretamente no gráfico.

void OnChartEvent(const int id, const long &lparam,
                  const double &dparam, const string &sparam)
{
    // Clique em objeto gráfico (botão)
    if(id == CHARTEVENT_OBJECT_CLICK)
    {
        if(sparam == "btn_buy")
        {
            CTrade trade;
            double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
            trade.Buy(0.1, _Symbol, ask, ask - 50*_Point, ask + 100*_Point);
        }
        if(sparam == "btn_close_all")
            CloseAllPositions();
    }

    // Clique no gráfico (coordenadas de preço)
    if(id == CHARTEVENT_CLICK)
    {
        double price = ChartGetDouble(0, CHART_PRICE_MIN) + dparam;
        Print("Clique no preço: ", price);
    }
}

// Criar botão no gráfico
void CreateButton(string name, string text, int x, int y)
{
    ObjectCreate(0, name, OBJ_BUTTON, 0, 0, 0);
    ObjectSetString(0, name, OBJPROP_TEXT, text);
    ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
    ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
    ObjectSetInteger(0, name, OBJPROP_XSIZE, 100);
    ObjectSetInteger(0, name, OBJPROP_YSIZE, 30);
}

Referências

On this page