
Como Implementar Otimização Automática em Expert Advisors MQL5
Prepare-se para ser introduzido ao maravilhoso mundo dos algoritmos de negociação forex com auto-otimização. Isso pode permitir que seu Expert Advisor (EA) se ajuste automaticamente para a próxima iteração de negociação, com base nas condições de mercado após uma operação concluída.
Considere seu EA como um trader experiente que analisa tendências usando médias móveis. Funcionou, mas e se fosse uma “caixa preta” consciente do mercado, que ainda fosse capaz de aprender a ajustar sua estratégia com o tempo? Esse é o processo da auto-otimização.
Uma das principais vantagens de usar um Expert Advisor (EA) é que ele pode, em última análise, se ajustar às condições de mercado à medida que elas mudam continuamente. O EA se adapta automaticamente ao ambiente atual do mercado, reduzindo a necessidade de supervisão manual constante e alteração de parâmetros. Isso permite que os traders aproveitem de forma consistente as oportunidades de curto prazo, segundo a segundo, e executem suas estratégias sem interrupções. Além disso, o EA é capaz de ajustar as estratégias de negociação continuamente, o tempo todo.
No entanto, existem alguns pontos de atenção. Um desafio é o risco de overfitting com dados recentes, o que pode levar a um desempenho ruim em condições de mercado diferentes. Gerenciar os recursos computacionais de forma eficaz também é crucial, já que a complexidade do código pode aumentar com a automação das estratégias. A estabilidade durante mudanças de parâmetros pode ser difícil de manter, e atribuir corretamente o desempenho também pode se tornar um problema.
Neste guia, exploraremos o processo de construção de um EA com auto-otimização, incluindo a automação de estratégias com indicadores personalizados. Vamos abordar uma lógica de otimização robusta, boas práticas para seleção de parâmetros e como reconstruir estratégias com backtesting. Além disso, métodos mais avançados como a otimização walk-forward serão discutidos para aprimorar sua abordagem de trading.
Como alcançar seus objetivos, ser produtivo (e como não cair em armadilhas!)
Vamos basear nosso plano de negociação em uma estratégia de cruzamento de médias móveis, que é a mais básica de todas, mas que nunca falha em mercados com tendência.
1. Configurando Bibliotecas, Parâmetros de Entrada e Intervalos de Otimização para EA com Auto-Otimização
1.1 Importa as Bibliotecas Necessárias
Na linha inicial, incluímos as bibliotecas MQL5 necessárias:
#include <Trade\Trade.mqh> #include <Arrays\ArrayObj.mqh>
A biblioteca Trade fornece funções para execução de operações, enquanto a ArrayObj nos permite trabalhar com arrays dinâmicos de objetos, que usaremos para armazenar os resultados da otimização.
1.2 Definindo Parâmetros de Entrada
Em seguida, definimos os parâmetros de entrada para o nosso EA:
input int MA_Fast_Period = 10; // Fast Moving Average Period input int MA_Slow_Period = 20; // Slow Moving Average Period input ENUM_MA_METHOD MA_Method = MODE_SMA; // Moving Average Method input ENUM_APPLIED_PRICE Applied_Price = PRICE_CLOSE; // Applied Price input double LotSize = 0.1; // Lot Size input int StopLoss = 50; // Stop Loss in points input int TakeProfit = 100; // Take Profit in points // Optimization parameters input bool AutoOptimize = false; // Enable Auto Optimization input int OptimizationPeriod = 5000; // Number of ticks between optimizations input int MinDataPoints = 1000; // Minimum number of data points for optimization
Esses parâmetros permitem ao usuário configurar o comportamento do EA e os ajustes de otimização diretamente na interface do MetaTrader.
1.3 Variáveis Globais e Handles
Depois declaramos variáveis globais e handles que serão usados ao longo do EA:
CTrade trade; int fastMA_Handle, slowMA_Handle; double fastMA[], slowMA[]; int tickCount = 0; CArrayObj* optimizationResults; // Optimization ranges const int MA_Fast_Min = 5, MA_Fast_Max = 50, MA_Fast_Step = 1; const int MA_Slow_Min = 10, MA_Slow_Max = 100, MA_Slow_Step = 1;
O objeto CTrade gerencia operações de negociação, enquanto fastMA_Handle e slowMA_Handle são usados para controlar os indicadores de médias móveis. O array optimizationResults armazenará os resultados dos testes de otimização.
1.4 Configurações de Otimização
As configurações de otimização definem os intervalos de valores que serão testados para cada parâmetro:
- Período da MA Rápida: de 5 a 50, passo de 1 Período da MA Lenta: de 10 a 100, passo de 1
2. Implementando a Lógica Principal de Negociação
Com a estrutura do EA pronta, vamos implementar as funções principais que lidam com a inicialização, finalização e processamento dos ticks.
2.1 A Função OnInit()
A função OnInit() é chamada quando o EA é carregado pela primeira vez em um gráfico. Veja como a implementamos:
int OnInit() { // Initialize MA handles fastMA_Handle = iMA(_Symbol, PERIOD_CURRENT, MA_Fast_Period, 0, MA_Method, Applied_Price); slowMA_Handle = iMA(_Symbol, PERIOD_CURRENT, MA_Slow_Period, 0, MA_Method, Applied_Price); if(fastMA_Handle == INVALID_HANDLE || slowMA_Handle == INVALID_HANDLE) { Print("Failed to create MA indicators"); return INIT_FAILED; } // Initialize optimization results array optimizationResults = new CArrayObj(); return INIT_SUCCEEDED; }
Essa função cria os indicadores de médias móveis e inicializa o array de resultados da otimização. Se os indicadores não forem inicializados corretamente, o EA não será iniciado.
2.2 A Função OnDeinit()
A função OnDeinit() é chamada quando o EA é removido do gráfico ou quando o terminal é fechado:void OnDeinit(const int reason) { // Release MA handles IndicatorRelease(fastMA_Handle); IndicatorRelease(slowMA_Handle); // Clean up optimization results if(optimizationResults != NULL) { delete optimizationResults; optimizationResults = NULL; } }
Essa função garante que os handles dos indicadores sejam liberados corretamente e que a memória usada pelo array de resultados da otimização seja liberada.
2.3 A Função OnTick()
A função OnTick() é o coração do nosso EA, chamada a cada novo tick do símbolo selecionado:
void OnTick() { // Check if we have enough bars to calculate MAs if(Bars(_Symbol, PERIOD_CURRENT) < MA_Slow_Period) return; // Copy MA values if(CopyBuffer(fastMA_Handle, 0, 0, 2, fastMA) != 2) return; if(CopyBuffer(slowMA_Handle, 0, 0, 2, slowMA) != 2) return; // Auto Optimization if(AutoOptimize && ++tickCount >= OptimizationPeriod) { Optimize(); tickCount = 0; } // Trading logic if(fastMA[1] <= slowMA[1] && fastMA[0] > slowMA[0]) { // Open buy position double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); trade.Buy(LotSize, _Symbol, ask, ask - StopLoss * _Point, ask + TakeProfit * _Point); } else if(fastMA[1] >= slowMA[1] && fastMA[0] < slowMA[0]) { // Open sell position double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); trade.Sell(LotSize, _Symbol, bid, bid + StopLoss * _Point, bid - TakeProfit * _Point); } }
Essa função executa várias tarefas essenciais:
- Verifica se há dados históricos suficientes para calcular as médias móveis.
- Obtém os valores atuais das médias móveis.
- Se a auto-otimização estiver ativada e for o momento certo (baseado na contagem de ticks), chama a função Optimize().
- Implementa a lógica de negociação, abrindo posições de compra ou venda com base no cruzamento das médias móveis.
3. Implementando a Lógica de Otimização
O núcleo da funcionalidade de auto-otimização está na função Optimize(). Vamos detalhá-la e examinar seus componentes.
3.1 A Função Optimize()
Aqui está a estrutura geral da função Optimize():
void Optimize() { Print("Starting optimization..."); optimizationResults.Clear(); // Loop through all combinations of MA periods for(int fastPeriod = MA_Fast_Min; fastPeriod <= MA_Fast_Max; fastPeriod += MA_Fast_Step) { for(int slowPeriod = MA_Slow_Min; slowPeriod <= MA_Slow_Max; slowPeriod += MA_Slow_Step) { if(slowPeriod <= fastPeriod) continue; // Slow period should be greater than fast period double profit = TestParameters(fastPeriod, slowPeriod); OptimizationResult* result = new OptimizationResult; result.fastPeriod = fastPeriod; result.slowPeriod = slowPeriod; result.profit = profit; optimizationResults.Add(result); } } // Find the best result OptimizationResult* bestResult = NULL; for(int i = 0; i < optimizationResults.Total(); i++) { OptimizationResult* currentResult = optimizationResults.At(i); if(bestResult == NULL || currentResult.profit > bestResult.profit) { bestResult = currentResult; } } if(bestResult != NULL) { // Update the EA parameters MA_Fast_Period = bestResult.fastPeriod; MA_Slow_Period = bestResult.slowPeriod; // Update indicator handles IndicatorRelease(fastMA_Handle); IndicatorRelease(slowMA_Handle); fastMA_Handle = iMA(_Symbol, PERIOD_CURRENT, MA_Fast_Period, 0, MA_Method, Applied_Price); slowMA_Handle = iMA(_Symbol, PERIOD_CURRENT, MA_Slow_Period, 0, MA_Method, Applied_Price); Print("Optimization complete. New parameters: Fast MA = ", MA_Fast_Period, ", Slow MA = ", MA_Slow_Period); } else { Print("Optimization failed to find better parameters."); } }
3.2 Laços de Combinação de Parâmetros
Os laços for aninhados na função Optimize() permitem testar todas as combinações dos períodos das médias móveis rápidas e lentas dentro dos intervalos definidos. Isso é conhecido como abordagem "força bruta" de otimização.
for(int fastPeriod = MA_Fast_Min; fastPeriod <= MA_Fast_Max; fastPeriod += MA_Fast_Step) { for(int slowPeriod = MA_Slow_Min; slowPeriod <= MA_Slow_Max; slowPeriod += MA_Slow_Step) { if(slowPeriod <= fastPeriod) continue; // Slow period should be greater than fast period double profit = TestParameters(fastPeriod, slowPeriod); // Store results... } }
Ignoramos combinações onde o período lento é menor ou igual ao período rápido, pois isso não faz sentido para nossa estratégia.
3.3 Armazenando e Comparando Resultados
Para cada combinação válida, chamamos TestParameters() para avaliar seu desempenho. Os resultados são armazenados em um objeto OptimizationResult e adicionados ao array optimizationResults.
Após testar todas as combinações, percorremos os resultados para encontrar o conjunto de parâmetros com melhor desempenho:
OptimizationResult* bestResult = NULL; for(int i = 0; i < optimizationResults.Total(); i++) { OptimizationResult* currentResult = optimizationResults.At(i); if(bestResult == NULL || currentResult.profit > bestResult.profit) { bestResult = currentResult; } }
Se um melhor resultado for encontrado, atualizamos os parâmetros do EA e recriamos os handles dos indicadores com os novos períodos.
4. Testando os Parâmetros
A função TestParameters() é crucial para avaliar cada conjunto de parâmetros. Vamos examiná-la em detalhes.
4.1 A Função TestParameters()
double TestParameters(int fastPeriod, int slowPeriod) { int maFast = iMA(_Symbol, PERIOD_CURRENT, fastPeriod, 0, MA_Method, Applied_Price); int maSlow = iMA(_Symbol, PERIOD_CURRENT, slowPeriod, 0, MA_Method, Applied_Price); if(maFast == INVALID_HANDLE || maSlow == INVALID_HANDLE) { Print("Failed to create MA indicators for testing"); return -DBL_MAX; } double fastBuffer[], slowBuffer[]; ArraySetAsSeries(fastBuffer, true); ArraySetAsSeries(slowBuffer, true); int copied = CopyBuffer(maFast, 0, 0, MinDataPoints, fastBuffer); copied = MathMin(copied, CopyBuffer(maSlow, 0, 0, MinDataPoints, slowBuffer)); if(copied < MinDataPoints) { Print("Not enough data for testing"); return -DBL_MAX; } double profit = 0; for(int i = 1; i < copied; i++) { if(fastBuffer[i] > slowBuffer[i] && fastBuffer[i-1] <= slowBuffer[i-1]) { // Buy signal profit += Close[i-1] - Open[i]; } else if(fastBuffer[i] < slowBuffer[i] && fastBuffer[i-1] >= slowBuffer[i-1]) { // Sell signal profit += Open[i] - Close[i-1]; } } IndicatorRelease(maFast); IndicatorRelease(maSlow); return profit; }
4.2 Criando Indicadores Temporários
Para cada conjunto de parâmetros testado, criamos indicadores de média móvel temporários:
int maFast = iMA(_Symbol, PERIOD_CURRENT, fastPeriod, 0, MA_Method, Applied_Price); int maSlow = iMA(_Symbol, PERIOD_CURRENT, slowPeriod, 0, MA_Method, Applied_Price);
Esses indicadores temporários nos permitem calcular médias móveis com diferentes períodos sem afetar a lógica principal de negociação.
4.3 Simulando Operações
Em seguida, percorremos os dados históricos, simulando operações com base na lógica de cruzamento de médias móveis:
for(int i = 1; i < copied; i++) { if(fastBuffer[i] > slowBuffer[i] && fastBuffer[i-1] <= slowBuffer[i-1]) { // Buy signal profit += Close[i-1] - Open[i]; } else if(fastBuffer[i] < slowBuffer[i] && fastBuffer[i-1] >= slowBuffer[i-1]) { // Sell signal profit += Open[i] - Close[i-1]; } }
Essa simulação simplificada assume que podemos abrir uma operação no preço de abertura da barra após o cruzamento e fechá-la no preço de fechamento da mesma barra.
4.4 Calculando o Lucro
A função retorna o lucro total gerado pelas operações simuladas. Em uma implementação mais sofisticada, você pode considerar outros fatores como drawdown máximo, índice de Sharpe ou taxa de acerto.
5. Aplicando Parâmetros Otimizados
Uma vez que encontramos os parâmetros de melhor desempenho, precisamos aplicá-los ao nosso EA.
5.1 Atualizando os Parâmetros do EA
Atualizamos nossas variáveis globais com os novos valores ideais:
MA_Fast_Period = bestResult.fastPeriod; MA_Slow_Period = bestResult.slowPeriod;
5.2 Recriando os Handles dos Indicadores
Após atualizar os parâmetros, precisamos recriar os handles dos nossos indicadores:
IndicatorRelease(fastMA_Handle); IndicatorRelease(slowMA_Handle); fastMA_Handle = iMA(_Symbol, PERIOD_CURRENT, MA_Fast_Period, 0, MA_Method, Applied_Price); slowMA_Handle = iMA(_Symbol, PERIOD_CURRENT, MA_Slow_Period, 0, MA_Method, Applied_Price);
Isso garante que a lógica de negociação principal utilize os parâmetros recém-otimizados daqui para frente.
6. Técnicas Avançadas de Otimização
Embora nossa implementação atual forneça uma base sólida para otimização automática, existem várias técnicas avançadas que você pode considerar para melhorar ainda mais o desempenho do EA.
6.1 Otimização com Múltiplos Critérios
Em vez de otimizar apenas pelo lucro, você pode incorporar múltiplos critérios no seu processo de otimização. Por exemplo:
struct OptimizationResult { int fastPeriod; int slowPeriod; double profit; double drawdown; double sharpeRatio; }; double CalculateScore(const OptimizationResult &result) { return result.profit * 0.5 + result.sharpeRatio * 0.3 - result.drawdown * 0.2; }
Essa abordagem permite equilibrar múltiplos aspectos de desempenho, potencialmente levando a conjuntos de parâmetros mais robustos.
6.2 Otimização Walk-Forward
A otimização walk-forward envolve dividir seus dados históricos em vários segmentos, otimizando em um segmento e testando no próximo.
Isso pode ajudar a evitar overfitting:
void WalkForwardOptimization() { int totalBars = Bars(_Symbol, PERIOD_CURRENT); int segmentSize = 1000; // Adjust as needed for(int i = 0; i < totalBars - 2*segmentSize; i += segmentSize) { // Optimize on segment i to i+segmentSize OptimizeSegment(i, i+segmentSize); // Test on segment i+segmentSize to i+2*segmentSize TestSegment(i+segmentSize, i+2*segmentSize); } }
6.3 Ajuste Adaptativo de Parâmetros
Em vez de substituir completamente os parâmetros durante a otimização, você pode implementar um sistema que os ajuste gradualmente com base no desempenho recente:
void AdaptParameters() { double recentPerformance = CalculateRecentPerformance(); double adaptationRate = 0.1; // Adjust as needed MA_Fast_Period += (int)((bestResult.fastPeriod - MA_Fast_Period) * adaptationRate * recentPerformance); MA_Slow_Period += (int)((bestResult.slowPeriod - MA_Slow_Period) * adaptationRate * recentPerformance); }
Essa abordagem pode proporcionar uma transição mais suave entre conjuntos de parâmetros e potencialmente reduzir o impacto de ruídos de mercado de curto prazo no seu processo de otimização.
7. Boas Práticas e Considerações
Ao implementar e refinar seu EA com auto-otimização, mantenha estas boas práticas em mente:
7.1 Escolhendo a Frequência de Otimização
A frequência da otimização pode impactar significativamente o desempenho do EA. Otimizar com muita frequência pode causar reações exageradas a flutuações de curto prazo, enquanto otimizar raramente pode levar à perda de oportunidades.
Considere implementar uma frequência de otimização dinâmica com base na volatilidade do mercado ou no desempenho recente do EA:
bool ShouldOptimize() { double recentVolatility = CalculateRecentVolatility(); int dynamicPeriod = (int)(OptimizationPeriod * (1 + recentVolatility)); return tickCount >= dynamicPeriod; }
7.2 Equilibrando Adaptabilidade e Estabilidade
Embora a adaptabilidade seja uma vantagem importante dos EAs com auto-otimização, é essencial manter certo grau de estabilidade. Mudanças drásticas nos parâmetros podem gerar comportamentos de negociação inconsistentes.
Considere implementar limites sobre quanto os parâmetros podem mudar em uma única otimização:
void LimitParameterChange(int ¶meter, int newValue, int maxChange) { int change = newValue - parameter; change = MathMax(-maxChange, MathMin(change, maxChange)); parameter += change; }
7.3 Overfitting é um risco importante em qualquer processo de otimização. Um EA superajustado pode ter um desempenho excepcional com dados históricos, mas falhar em condições reais de mercado. Para mitigar esse risco, é importante usar uma quantidade suficiente de dados históricos para a otimização. Além disso, implementar testes fora da amostra ou otimização walk-forward pode ajudar a garantir robustez. A complexidade da sua estratégia também deve ser proporcional à quantidade de dados disponíveis. Monitorar de perto o desempenho em tempo real é essencial, e é preciso estar preparado para intervir se o comportamento do EA divergir significativamente dos resultados do backtest.
7.4 A otimização automática pode ser intensiva computacionalmente, então garantir eficiência computacional é fundamental. Para manter o EA responsivo, recomenda-se executar as otimizações fora do horário de negociação ou em uma thread separada. Estruturas de dados e algoritmos eficientes podem reduzir significativamente o tempo de processamento. Para tarefas de otimização mais intensas, soluções em nuvem podem ser uma boa opção a considerar.
8. Para tarefas de otimização mais intensas, soluções em nuvem podem ser uma boa opção a considerar.
8.1 Alguns problemas comuns podem surgir durante o desenvolvimento. Por exemplo, se seu EA apresentar resultados inconsistentes a cada execução, verifique se está usando dados consistentes e procure por elementos aleatórios no seu código. Desempenho fraco ao vivo, apesar de bons resultados no backtest, pode ser causado por fatores como slippage, spread ou mudanças nas condições de mercado. Se a otimização falhar ou produzir resultados inesperados, revise seus critérios de otimização e certifique-se de que a função TestParameters() esteja funcionando corretamente.
8.2 Para ajudar na depuração, é altamente recomendável implementar um sistema de logs abrangente. Isso permitirá que você acompanhe o comportamento do EA e o processo de otimização em detalhes, facilitando a identificação e resolução de problemas.
Implemente logging completo para acompanhar o comportamento do EA e o processo de otimização:void Log(string message) { Print(TimeToString(TimeCurrent()) + ": " + message); int handle = FileOpen("EA_Log.txt", FILE_WRITE|FILE_READ|FILE_TXT); if(handle != INVALID_HANDLE) { FileSeek(handle, 0, SEEK_END); FileWriteString(handle, TimeToString(TimeCurrent()) + ": " + message + "\n"); FileClose(handle); } }
Use essa função para registrar eventos importantes, mudanças de parâmetros e quaisquer erros que ocorram durante a operação ou otimização.
8.3 O Strategy Tester do MetaTrader é uma ferramenta valiosa para depurar seu EA. Você pode usar o modo visual para acompanhar o comportamento do EA barra por barra, o que fornece uma visão detalhada de como o EA está funcionando em tempo real. Além disso, comparar os resultados da otimização no Strategy Tester com aqueles da auto-otimização do EA pode ajudar a identificar discrepâncias. A função de otimização do Strategy Tester também serve para verificar o funcionamento da sua função TestParameters().
9. Desempenho e Desafios do EA com Média Móvel e Auto-Otimização
9.1 Para ilustrar os potenciais benefícios e desafios da auto-otimização, vejamos um estudo de caso hipotético.
Fizemos backtest do nosso EA com cruzamento de médias móveis com auto-otimização no gráfico H1 do EURUSD de 2010 a 2020. O EA foi configurado para otimizar seus parâmetros a cada 5000 ticks. Os resultados foram promissores: lucro líquido total de $15.420, fator de lucro de 1,65 e drawdown máximo de $2.105 em 1.247 operações.
Em seguida, comparamos esses resultados com o mesmo EA usando parâmetros estáticos (MA_Fast_Period = 10, MA_Slow_Period = 20). A versão estática obteve lucro líquido total de $8.750, fator de lucro de 1,38 e drawdown máximo maior de $3.210 em 1.562 operações. Essa comparação demonstrou que a versão com auto-otimização melhorou significativamente tanto a lucratividade geral quanto o retorno ajustado ao risco.
9.2 Embora os resultados do backtest sejam promissores, há vários fatores importantes a considerar ao avaliar o desempenho no mundo real. Mudanças de regime de mercado, como a crise financeira de 2008 ou a pandemia da COVID-19 em 2020, podem afetar a adaptabilidade do EA, exigindo avaliação cuidadosa. Além disso, os custos de transação devem ser considerados para garantir que o desempenho aprimorado compense o aumento da atividade de negociação. Os recursos computacionais necessários para executar otimização contínua em tempo real também são uma consideração, assim como a resiliência psicológica necessária para lidar com períodos de baixo desempenho enquanto o EA se adapta a novas condições.
10. Tendências Futuras em EAs com Auto-Otimização: Machine Learning, Dados Externos e Soluções em Nuvem
10.1 À medida que a tecnologia de negociação continua evoluindo, desenvolvimentos empolgantes estão surgindo para EAs com auto-otimização. Um desses avanços é a integração de algoritmos de machine learning no trading Forex, o que pode aprimorar o processo de otimização identificando padrões complexos nos dados de mercado. Isso abre oportunidades para estratégias de negociação ainda mais adaptativas e eficientes no futuro.
Algoritmos de machine learning podem potencialmente aprimorar o processo de otimização ao identificar padrões complexos nos dados de mercado:
from sklearn.ensemble import RandomForestRegressor def ml_optimize(data, labels): model = RandomForestRegressor(n_estimators=100) model.fit(data, labels) return model.feature_importances_
Embora este exemplo use Python, técnicas semelhantes de machine learning podem ser implementadas em MQL5 ou integradas via bibliotecas externas.
10.2 Integração com Fontes de Dados Externos
Incorporar dados externos (indicadores econômicos, análise de sentimento, etc.) no seu processo de otimização pode fornecer uma visão mais abrangente das condições de mercado:
string GetExternalData() { string cookie=NULL,headers; char post[],result[]; int res; string url="https://api.example.com/economic-data"; res=WebRequest("GET",url,cookie,NULL,500,post,0,result,headers); if(res==-1) { Print("Error in WebRequest. Error code =",GetLastError()); return ""; } string resultString=CharArrayToString(result); return resultString; }
Ao integrar dados externos, seu EA pode tomar decisões mais informadas sobre quando e como otimizar seus parâmetros.
10.3 Otimização Baseada em Nuvem
À medida que as tarefas de otimização se tornam mais complexas, soluções baseadas em nuvem oferecem potencial para processos de otimização mais poderosos e flexíveis:
void CloudOptimize() { string optimizationData = PrepareOptimizationData(); string url = "https://your-cloud-service.com/optimize"; string headers = "Content-Type: application/json\r\n"; char post[], result[]; string resultHeaders; StringToCharArray(optimizationData, post); int res = WebRequest("POST", url, headers, 30000, post, result, resultHeaders); if(res == -1) { Print("Error in WebRequest. Error code =", GetLastError()); return; } string optimizationResult = CharArrayToString(result); ApplyCloudOptimizationResult(optimizationResult); }
Essa abordagem permite aproveitar maior poder computacional e, potencialmente, algoritmos de otimização mais sofisticados do que seria viável em uma máquina local.
Desenvolver um EA com auto-otimização eficaz é um processo contínuo que exige melhorias e aprendizados constantes. Uma estratégia de melhoria é revisar regularmente o desempenho do EA. Essa prática ajudará a identificar pontos de refinamento e garantir que o EA continue operando de forma ideal mesmo com as mudanças nas condições de mercado.
void WeeklyPerformanceReview() { datetime startOfWeek = iTime(_Symbol, PERIOD_W1, 0); double weeklyProfit = 0; int totalTrades = 0; for(int i = 0; i < HistoryDealsTotal(); i++) { ulong ticket = HistoryDealGetTicket(i); if(HistoryDealGetInteger(ticket, DEAL_TIME) >= startOfWeek) { weeklyProfit += HistoryDealGetDouble(ticket, DEAL_PROFIT); totalTrades++; } } Print("Weekly Performance: Profit = ", weeklyProfit, ", Trades = ", totalTrades); }
Use essas revisões para identificar oportunidades de melhoria e possíveis problemas no processo de otimização.
Manter-se informado sobre tecnologia de negociação, dinâmicas de mercado e regulamentações é essencial. Testes rigorosos, incluindo testes fora da amostra (out-of-sample) e testes futuros (forward testing), são fundamentais Aprendizado e monitoramento contínuos são a chave para o sucesso no longo prazo. Embora poderosa, a auto-otimização deve complementar princípios sólidos de negociação e gestão de risco. Mantenha-se curioso e cauteloso, priorizando sempre a proteção do seu capital.
Bons trades!
Para quem deseja aprofundar o entendimento sobre auto-otimização e negociação algorítmica, aqui estão alguns recursos adicionais:
- Building Reliable Trading Systems, de Keith Fitschen
- Algorithmic Trading: Winning Strategies and Their Rationale, de Ernie Chan
- Machine Learning for Algorithmic Trading, de Stefan Jansen
- Documentação MQL5: Documentação MQL5
- Fórum Forex Factory - Fórum de Código: Fórum Forex Factory
- Cursos Quantopian: Cursos Quantopian
11. Código de Exemplo do EA
Abaixo está o código completo do EA com auto-otimização. Copie esse código para o MetaEditor e compile-o para usar no MetaTrader 5.
//+------------------------------------------------------------------+ //| Auto-Optimizing Moving Average Crossover EA | //| Copyright 2024, Javier Santiago Gaston de Iriarte Cabrera | //| https://www.mql5.com/en/users/jsgaston/news | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, Javier Santiago Gaston de Iriarte Cabrera" #property link "https://www.mql5.com/en/users/jsgaston/news" #property version "1.00" #property strict // Include necessary libraries #include <Trade\Trade.mqh> #include <Arrays\ArrayObj.mqh> // Input parameters input ENUM_MA_METHOD MA_Method = MODE_SMA; // Moving Average Method input ENUM_APPLIED_PRICE Applied_Price = PRICE_CLOSE; // Applied Price input double LotSize = 0.01; // Lot Size input int StopLoss = 100; // Stop Loss in points input int TakeProfit = 200; // Take Profit in points input int Initial_MA_Fast_Period = 10; // Initial Fast Moving Average Period input int Initial_MA_Slow_Period = 20; // Initial Slow Moving Average Period // Optimization parameters input bool AutoOptimize = true; // Enable Auto Optimization input int OptimizationPeriod = 5000; // Number of ticks between optimizations input int MinDataPoints = 1000; // Minimum number of data points for optimization // Global variables CTrade trade; int fastMA_Handle, slowMA_Handle; double fastMA[], slowMA[]; int tickCount = 0; CArrayObj optimizationResults; int MA_Fast_Period, MA_Slow_Period; // Optimization ranges const int MA_Fast_Min = 5, MA_Fast_Max = 50, MA_Fast_Step = 1; const int MA_Slow_Min = 10, MA_Slow_Max = 100, MA_Slow_Step = 1; // Class to hold optimization results class OptimizationResult : public CObject { public: int fastPeriod; int slowPeriod; double profit; }; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { MA_Fast_Period = Initial_MA_Fast_Period; MA_Slow_Period = Initial_MA_Slow_Period; // Initialize MA handles fastMA_Handle = iMA(_Symbol, PERIOD_CURRENT, MA_Fast_Period, 0, MA_Method, Applied_Price); slowMA_Handle = iMA(_Symbol, PERIOD_CURRENT, MA_Slow_Period, 0, MA_Method, Applied_Price); if(fastMA_Handle == INVALID_HANDLE || slowMA_Handle == INVALID_HANDLE) { Print("Failed to create MA indicators"); return INIT_FAILED; } return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // Release MA handles IndicatorRelease(fastMA_Handle); IndicatorRelease(slowMA_Handle); // Clean up optimization results optimizationResults.Clear(); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // Check if we have enough bars to calculate MAs if(Bars(_Symbol, PERIOD_CURRENT) < MA_Slow_Period) return; // Copy MA values if(CopyBuffer(fastMA_Handle, 0, 0, 2, fastMA) != 2) return; if(CopyBuffer(slowMA_Handle, 0, 0, 2, slowMA) != 2) return; // Auto Optimization if(AutoOptimize && ++tickCount >= OptimizationPeriod) { Optimize(); tickCount = 0; } // Trading logic if(fastMA[1] <= slowMA[1] && fastMA[0] > slowMA[0]) { // Open buy position double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); trade.Buy(LotSize, _Symbol, ask, ask - StopLoss * _Point, ask + TakeProfit * _Point); } else if(fastMA[1] >= slowMA[1] && fastMA[0] < slowMA[0]) { // Open sell position double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); trade.Sell(LotSize, _Symbol, bid, bid + StopLoss * _Point, bid - TakeProfit * _Point); } } //+------------------------------------------------------------------+ //| Optimization function | //+------------------------------------------------------------------+ void Optimize() { Print("Starting optimization..."); optimizationResults.Clear(); // Loop through all combinations of MA periods for(int fastPeriod = MA_Fast_Min; fastPeriod <= MA_Fast_Max; fastPeriod += MA_Fast_Step) { for(int slowPeriod = MA_Slow_Min; slowPeriod <= MA_Slow_Max; slowPeriod += MA_Slow_Step) { if(slowPeriod <= fastPeriod) continue; // Slow period should be greater than fast period double profit = TestParameters(fastPeriod, slowPeriod); OptimizationResult* result = new OptimizationResult(); result.fastPeriod = fastPeriod; result.slowPeriod = slowPeriod; result.profit = profit; optimizationResults.Add(result); } } // Find the best result OptimizationResult* bestResult = NULL; for(int i = 0; i < optimizationResults.Total(); i++) { OptimizationResult* currentResult = optimizationResults.At(i); if(bestResult == NULL || currentResult.profit > bestResult.profit) { bestResult = currentResult; } } if(bestResult != NULL) { // Update the EA parameters MA_Fast_Period = bestResult.fastPeriod; MA_Slow_Period = bestResult.slowPeriod; // Update indicator handles IndicatorRelease(fastMA_Handle); IndicatorRelease(slowMA_Handle); fastMA_Handle = iMA(_Symbol, PERIOD_CURRENT, MA_Fast_Period, 0, MA_Method, Applied_Price); slowMA_Handle = iMA(_Symbol, PERIOD_CURRENT, MA_Slow_Period, 0, MA_Method, Applied_Price); Print("Optimization complete. New parameters: Fast MA = ", MA_Fast_Period, ", Slow MA = ", MA_Slow_Period); } else { Print("Optimization failed to find better parameters."); } } //+------------------------------------------------------------------+ //| Test a set of parameters | //+------------------------------------------------------------------+ double TestParameters(int fastPeriod, int slowPeriod) { int maFast = iMA(_Symbol, PERIOD_CURRENT, fastPeriod, 0, MA_Method, Applied_Price); int maSlow = iMA(_Symbol, PERIOD_CURRENT, slowPeriod, 0, MA_Method, Applied_Price); if(maFast == INVALID_HANDLE || maSlow == INVALID_HANDLE) { Print("Failed to create MA indicators for testing"); return -DBL_MAX; } double fastBuffer[], slowBuffer[]; ArraySetAsSeries(fastBuffer, true); ArraySetAsSeries(slowBuffer, true); int copied = CopyBuffer(maFast, 0, 0, MinDataPoints, fastBuffer); copied = MathMin(copied, CopyBuffer(maSlow, 0, 0, MinDataPoints, slowBuffer)); if(copied < MinDataPoints) { Print("Not enough data for testing"); return -DBL_MAX; } double Close[], Open[]; ArraySetAsSeries(Close, true); ArraySetAsSeries(Open, true); copied = CopyClose(_Symbol, PERIOD_CURRENT, 0, copied, Close); copied = MathMin(copied, CopyOpen(_Symbol, PERIOD_CURRENT, 0, copied, Open)); double profit = 0; for(int i = 1; i < copied; i++) { if(fastBuffer[i] > slowBuffer[i] && fastBuffer[i-1] <= slowBuffer[i-1]) { // Buy signal profit += Close[i-1] - Open[i]; } else if(fastBuffer[i] < slowBuffer[i] && fastBuffer[i-1] >= slowBuffer[i-1]) { // Sell signal profit += Open[i] - Close[i-1]; } } IndicatorRelease(maFast); IndicatorRelease(maSlow); return profit; } //+------------------------------------------------------------------+ //| Custom function to log important events | //+------------------------------------------------------------------+ void Log(string message) { Print(TimeToString(TimeCurrent()) + ": " + message); int handle = FileOpen("EA_Log.txt", FILE_WRITE|FILE_READ|FILE_TXT); if(handle != INVALID_HANDLE) { FileSeek(handle, 0, SEEK_END); FileWriteString(handle, TimeToString(TimeCurrent()) + ": " + message + "\n"); FileClose(handle); } }
Como Usar Este Expert Advisor
- Copie todo o código para um novo arquivo no MetaEditor.
- Salve o arquivo com a extensão .mq5 (ex.: "AutoOptimizingMA.mq5").
- Compile o EA clicando no botão “Compile” ou pressionando F7.
- No MetaTrader 5, arraste o EA compilado para um gráfico.
- Ajuste os parâmetros de entrada conforme necessário na janela de configurações do EA.
- Habilite o AutoTrading e deixe o EA rodar.
Recursos Principais deste EA
- Estratégia de Cruzamento de Médias Móveis: o EA usa uma estratégia básica de cruzamento de médias móveis para decisões de negociação.
- Auto-Otimização: o EA pode otimizar automaticamente seus parâmetros (períodos das MAs rápida e lenta) com base em dados recentes de mercado.
- Entradas Personalizáveis: o usuário pode ajustar diversos parâmetros, incluindo tamanho de lote, stop loss, take profit e configurações de otimização.
- Registro de Desempenho: o EA inclui uma função de log para registrar eventos importantes e alterações de parâmetros.
Notas Importantes
- Este EA é fornecido como um exemplo educacional e não deve ser usado em negociação real sem testes e personalizações completos.-Auto-otimização pode ser intensiva em termos de processamento. Fique atento ao uso de recursos do sistema, especialmente se estiver usando em VPS ou máquina local.
- Sempre teste o EA extensivamente em uma conta demo antes de considerar uso em conta real.
- Desempenho passado não garante resultados futuros. As condições de mercado podem mudar, afetando o desempenho do EA.
Ao usar este EA, você pode explorar como a auto-otimização funciona na prática e potencialmente melhorar a adaptabilidade da sua estratégia de negociação às mudanças no mercado. Lembre-se de monitorar continuamente o desempenho e ajustar conforme necessário.
Você pode obter resultados melhores adicionando mais condições às ordens, como incluir Deep Learning, RSI ou qualquer outro critério que fizer sentido.
Lembre-se, o mundo do trading algorítmico é vasto e está em constante evolução. Este guia serve como ponto de partida para sua jornada com Expert Advisors auto-otimizáveis. À medida que você ganha experiência e aprofunda seu conhecimento, certamente descobrirá novas técnicas e abordagens para refinar e melhorar seus sistemas de negociação.
Boa sorte, e que seus trades sejam lucrativos!
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/15837
Aviso: Todos os direitos sobre esses materiais pertencem à MetaQuotes Ltd. É proibida a reimpressão total ou parcial.
Esse artigo foi escrito por um usuário do site e reflete seu ponto de vista pessoal. A MetaQuotes Ltd. não se responsabiliza pela precisão das informações apresentadas nem pelas possíveis consequências decorrentes do uso das soluções, estratégias ou recomendações descritas.






- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso