
Estratégia de Trading Cascade Order Baseada em Cruzamentos de EMA para MetaTrader 5
Introdução
Neste artigo, estamos demonstrando a Estratégia de Trading Cascade Order do Expert Advisor de Forex (EA) em MetaQuotes Language 5 (MQL5) para MetaTrader 5. Neste artigo do Expert Advisor MQL5 usando cruzamentos de médias móveis como base para a estratégia de trading, este artigo MQL5 automatiza as escolhas de trading na plataforma MetaTrader 5. Este artigo incorpora recursos essenciais para inicialização, ajuste e monitoramento de posições, utilizando a biblioteca Trade.mqh para administração eficiente de ordens.
Primeiro, duas médias móveis exponenciais (EMA) com períodos predeterminados são usadas inicialmente como parte da técnica. Dependendo da direção do cruzamento, um sinal de compra ou venda é produzido quando essas médias móveis se cruzam. As ordens são configuradas com take profit e stop loss especificados, que são ajustados dinamicamente à medida que o mercado avança.
Além disso, o script possui uma rotina para identificar novas barras, que são essenciais para garantir que as decisões de trading sejam tomadas com base nas formações de velas concluídas. Além disso, é oferecido um recurso para ajustar a posição atual ao atingir as metas de lucro.
Esta recomendação de expert, quando considerada como um todo, demonstra como o MQL5 pode ser utilizado para colocar em prática uma estratégia de trading sistemática, utilizando execução automatizada e indicadores técnicos para realizar negociações com base em regras predeterminadas.
Neste artigo, estamos discutindo os seguintes tópicos:
Explicação da Estratégia de Trading Cascade Order
A Estratégia de Trading Cascade Order descreve uma técnica na qual os resultados ou termos de ordens anteriores são usados para determinar o posicionamento de ordens subsequentes. Para gerenciar e otimizar entradas, saídas e tamanhos de posição com base nos movimentos do mercado e regras predeterminadas, essa estratégia é frequentemente utilizada no trading. Aqui está uma descrição detalhada de como uma estratégia de trading usando ordens em cascata poderia operar.
Componentes essenciais da Estratégia de Trading Cascade Order:
- Colocação de Ordens Consecutivas: - Uma estratégia de ordens em cascata envolve a iniciação consecutiva de transações em resposta a eventos ou condições predeterminadas. Uma ordem inicial pode ser colocada por um trader, por exemplo, em resposta a um sinal de um indicador técnico específico.
- Ordem Contingente: - As ordens futuras são colocadas com base nos resultados das transações anteriores ou no estado do mercado. Se o mercado avançar a seu favor, isso pode significar a colocação de mais ordens para ampliar a posição.
- Escalonamento para Dentro e para Fora: - Para controlar o risco e otimizar o potencial de lucro, a estratégia de cascata frequentemente implica entrar progressivamente em uma posição. Por outro lado, escalonar para fora implica diminuir o tamanho da posição quando as metas de lucro são atingidas ou quando o mercado se move negativamente.
- Gerenciamento de Risco: - Para minimizar as perdas, o gerenciamento de risco eficaz é essencial nas técnicas em cascata. Isso implica estabelecer limites de stop loss para cada ordem ou modificá-los dinamicamente conforme a posição muda.
Tomada de Lucros: quando certos requisitos são atendidos, ações são tomadas para garantir os ganhos. As metas de lucro são definidas para cada ordem em todas as etapas da transação. Isso garante que os traders obtenham lucro, permitindo mais valorização caso as circunstâncias de mercado exijam.
Aqui está o gráfico resumindo a estratégia de trading em cascata:
Implementação do EA em MQL5
Primeiramente, a biblioteca Trade.mqh do MQL5 é uma biblioteca robusta e prática que facilita as atividades de trading. Ela oferece uma interface de alto nível para abrir, modificar e excluir posições e ordens. Quando incluímos a Trade.mqh, obtemos acesso à classe CTrade, que simplifica e encapsula muitos dos detalhes intrincados das atividades de trading, melhorando a legibilidade e manutenção do código.
#include <Trade/Trade.mqh>
CTrade obj_Trade;
Após incluir a Trade.mqh, podemos acessar a classe CTrade, que é instantaneamente instanciada como obj_Trade. Observamos que as várias funcionalidades para trading estão encapsuladas na classe CTrade. A seguir, estão algumas das principais técnicas que a classe CTrade oferece:
- Colocação de uma Ordem
- Modificação de Ordem
- Terminação de Ordem
A seguir, passamos para as variáveis globais, que são muito cruciais para o funcionamento da estratégia de trading e desempenham várias funções no Expert Advisor (EA). Vamos falar sobre cada variável global e o que ela significa:
- Variáveis inteiras
int handleMAFast; int handleMASlow;
Os manipuladores, ou IDs, dos indicadores de média móvel rápida e lenta, calculados pela função OnInit, são armazenados nessas variáveis. Para recuperar os valores atuais desses indicadores, os manipuladores são necessários para acessar seus buffers.
- Arrays de Double para Médias Móveis
double maSlow[],maFast[];
Os valores das médias móveis rápidas e lentas derivadas dos buffers de indicadores são mantidos nesses arrays. Eles são utilizados para armazenar os valores atuais e passados dos indicadores para análise e decisões de trading.
- Variáveis de Take Profit e Stop Losse
double takeProfit = 0; double stopLoss = 0;
Os níveis de take profit (TP) e stop loss (SL) para as operações de trading estão atualmente armazenados nesta variável. Eles são utilizados para inserir ou modificar ordens de trading, sendo atualizados conforme as condições de mercado.
- Variáveis do Estado do Sistema Reservado
bool isBuySystemInitiated = false; bool isSellSystemInitiated = false;
Essas flags de sistema reservado monitoram o estado inicial dos sistemas de compra e venda. Elas ajudam a evitar ordens desnecessárias ou duplicadas, garantindo que as ordens sejam colocadas apenas quando critérios específicos (como cruzamentos de médias móveis) forem atendidos.
- Parâmetros de entrada
input int slPts = 300; input int tpPts = 300; input double lot = 0.01; input int slPts_Min = 100; input int fastPeriods = 10; input int slowPeriods = 20;
Essas variáveis são parâmetros de entrada que, sem alterar o próprio código, permitem a configuração externa do comportamento do EA. Os traders podem modificar esses parâmetros através das configurações de EA na interface do MetaTrader. Eles gerenciam variáveis como take-profit, stop-loss, tamanho do lote e períodos de média móvel rápida.
Após explicar o significado das variáveis, percebemos que os dados que precisam ser acessados entre os ticks e funções são armazenados em variáveis globais no MQL5. Isso ocorre porque elas servem para armazenar dados vitais, incluindo parâmetros de ordens, status de trading, valores de indicadores e configurações definidas pelo usuário. Elas são usadas para realizar a estratégia de trading, manter posições e responder às condições de mercado, diferentes funções do EA acessam e alteram essas variáveis.
Certamente! Vamos detalhar a parte de inicialização do código. A função OnInit é responsável por configurar o estado inicial do expert advisor. O que acontece primeiro é a criação dos manipuladores para as médias móveis rápida e lenta usando a função iMA. Verifique se esses manipuladores são válidos. Se algum manipulador for inválido, a inicialização falha. Em seguida, configure os arrays maFast e maSlow para serem arrays de séries temporais usando ArraySetAsSeries. Por fim, retorne sucesso.
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit(){ handleMAFast = iMA(_Symbol,_Period,fastPeriods,0,MODE_EMA,PRICE_CLOSE); if (handleMAFast == INVALID_HANDLE){ Print("UNABLE TO LOAD FAST MA, REVERTING NOW"); return (INIT_FAILED); } handleMASlow = iMA(_Symbol,_Period,slowPeriods,0,MODE_EMA,PRICE_CLOSE); if (handleMASlow == INVALID_HANDLE){ Print("UNABLE TO LOAD SLOW MA, REVERTING NOW"); return (INIT_FAILED); } ArraySetAsSeries(maFast,true); ArraySetAsSeries(maSlow,true); return(INIT_SUCCEEDED); }
Depois, analisamos a função de desinicialização. Dentro do sistema do expert advisor MQL5, a função é invocada quando o expert advisor é fechado ou removido do gráfico. É aqui que ocorre a limpeza das tarefas.
//+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- }
Neste caso, a função está vazia, indicando que nenhuma ação específica é tomada ao desinicializar o EA.
Um parâmetro inteiro, reason, que especifica a causa da desinicialização, é passado para a função. Isso pode ocorrer porque o terminal foi fechado, o EA foi retirado do gráfico, ou por outros motivos.
Agora, passamos para a função OnTick, que é acionada toda vez que um novo tick (mudança de preço) é recebido. A lógica de trading é aplicada nesta função. A função OnTick no código fornecido executa a estratégia de trading baseada em cruzamentos de médias móveis.
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick(){ double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); if (CopyBuffer(handleMAFast,0,1,3,maFast) < 3){ Print("NO ENOUGH DATA FROM FAST MA FOR ANALYSIS, REVERTING NOW"); return; } if (CopyBuffer(handleMASlow,0,1,3,maSlow) < 3){ Print("NO ENOUGH DATA FROM SLOW MA FOR ANALYSIS, REVERTING NOW"); return; } //if (IsNewBar()){Print("FAST MA DATA:");ArrayPrint(maFast,6);} if (PositionsTotal()==0){ isBuySystemInitiated=false;isSellSystemInitiated=false; } if (PositionsTotal()==0 && IsNewBar()){ if (maFast[0] > maSlow[0] && maFast[1] < maSlow[1]){ Print("BUY SIGNAL"); takeProfit = Ask+tpPts*_Point; stopLoss = Ask-slPts*_Point; obj_Trade.Buy(lot,_Symbol,Ask,stopLoss,0); isBuySystemInitiated = true; } else if (maFast[0] < maSlow[0] && maFast[1] > maSlow[1]){ Print("SELL SIGNAL"); takeProfit = Bid-tpPts*_Point; stopLoss = Bid+slPts*_Point; obj_Trade.Sell(lot,_Symbol,Bid,stopLoss,0); isSellSystemInitiated = true; } } else { if (isBuySystemInitiated && Ask >= takeProfit){ takeProfit = takeProfit+tpPts*_Point; stopLoss = Ask-slPts_Min*_Point; obj_Trade.Buy(lot,_Symbol,Ask,0); ModifyTrades(POSITION_TYPE_BUY,stopLoss); } else if (isSellSystemInitiated && Bid <= takeProfit){ takeProfit = takeProfit-tpPts*_Point; stopLoss = Bid+slPts_Min*_Point; obj_Trade.Sell(lot,_Symbol,Bid,0); ModifyTrades(POSITION_TYPE_SELL,stopLoss); } } }
Aqui está o detalhamento da função OnTick para facilitar o entendimento:
Obter os preços Ask e Bid: A função obtém os preços Ask e Bid no momento e os arredonda para o número adequado de casas decimais. A recuperação e normalização dos preços atuais são essenciais para que uma estratégia de trading de ordens em cascata tome decisões bem-informadas sobre a colocação de ordens em diferentes pontos de preço. Manter um olhar atento sobre os preços atuais do mercado é necessário ao colocar a estratégia de trading de ordens em cascata em prática. Isso implica obter os preços Ask e Bid para o símbolo em que você está negociando no MetaTrader. O preço atual Ask para o símbolo designado (_Symbol) é obtido chamando a função. O preço ao qual você pode comprar este ativo é conhecido como preço ask. O preço atual Bid para o símbolo é recuperado por esta chamada de função. O preço ao qual você pode vender este ativo é conhecido como preço bid.
double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
A normalização garante que os preços recuperados atendam aos requisitos de precisão dos símbolos de negociação. Isso também depende de evitar problemas com a matemática de ponto flutuante. O valor é arredondado para o número designado de casas decimais (_Digits) por esta chamada de função. _Digits, que denota o número de casas decimais que o símbolo suporta, geralmente é predefinido para o símbolo.
Duplicar os Buffers de Média Móvel: A função obtém os valores mais recentes para as médias móveis, tanto lentas quanto rápidas. A função termina e uma mensagem de erro é impressa se houver dados insuficientes. As médias móveis são usadas em uma estratégia de ordens em cascata para identificar negociações e determinar os melhores momentos para colocar ordens. Para que a estratégia seja confiável, é imprescindível que antes de iniciar o estudo, haja dados suficientes das médias móveis.
if (CopyBuffer(handleMAFast,0,1,3,maFast) < 3){ Print("NO ENOUGH DATA FROM FAST MA FOR ANALYSIS, REVERTING NOW"); return; } if (CopyBuffer(handleMASlow,0,1,3,maSlow) < 3){ Print("NO ENOUGH DATA FROM SLOW MA FOR ANALYSIS, REVERTING NOW"); return; }
Esta função transfere informações para o array maFast a partir do buffer do indicador de média móvel rápida. Os manipuladores dos indicadores de média móvel rápida, o número do buffer, que normalmente é 0 para a linha principal de um indicador, o ponto de início a partir do qual os dados devem ser copiados, a quantidade de itens a serem duplicados e o array no qual a cópia dos dados será armazenada. O número de elementos copiados com sucesso é retornado pela função. Enquanto verificamos a viabilidade dos dados, determinamos se o maFast teve menos de três elementos copiados. Menos de três componentes transferidos indica dados insuficientes da média móvel rápida para suportar uma análise sólida. A função termina a execução imprimindo uma mensagem e retornando antecipadamente. A média móvel lenta com o manipulador MASlow e o maSlow segue o mesmo raciocínio.
Aqui está o gráfico das médias móveis plotadas contra os dados de preço. O gráfico inclui a série de preços, a média móvel rápida (EMA de 10 dias) e as médias móveis lentas (EMA de 20 dias).
Antes de tomarmos qualquer decisão de trading, a estratégia garante que há uma quantidade mínima de dados históricos das médias móveis. Isso ajuda a fazer escolhas mais confiáveis e bem-informadas. A estratégia evita informações inadequadas, o que poderia resultar em sinais falsos e negociações perdedoras, verificando se há dados suficientes. Este trecho serve como uma etapa de validação antes do trading. Se a condição não for atendida, a estratégia irá reverter e não executará negociações ou análises para aquele tick.
As médias móveis são usadas para determinar a direção e a força de uma tendência em uma estratégia de ordens em cascata. Se a média móvel rápida cruzar acima ou abaixo da média móvel lenta, por exemplo, você pode colocar ordens em diferentes níveis.
Verificar Posições Abertas: As flags de início do sistema de compra e venda são redefinidas se não houver posições abertas. Para evitar sobreposição de transações e gerenciar eficientemente o status do sistema de trading, é imprescindível, ao usar uma estratégia de ordens em cascata, verificar se há posições abertas. Um dos mecanismos que realizamos nesta função é redefinir flags específicas se não houver posições abertas.
//if (IsNewBar()){Print("FAST MA DATA:");ArrayPrint(maFast,6);} if (PositionsTotal()==0){ isBuySystemInitiated=false;isSellSystemInitiated=false; }
A função retorna o número total de posições abertas para a conta de trading atual. Descobrir se há negociações ativas é útil. Quando assumimos que PositionasTotal() == 0, essa condição determina se há 0 posições abertas no total, o que indica que não há negociações abertas no momento. As flags isBuySytemInitiated e isSellSystemInitiated são definidas como falsas quando não há posições abertas. Redefine a flag indicando se o sistema de compra foi iniciado (_isBuySystemInitiated = false;). Redefine a flag indicando se o sistema de venda foi iniciado (_isSellSystemInitiated = false;).
A abordagem garante que novas negociações sejam iniciadas apenas quando não houver posições abertas, verificando periodicamente as posições abertas e redefinindo as flags de início. Dessa forma, as negociações sobrepostas, que podem resultar em sobreexposição ao risco ou ações de trading contraditórias, são evitadas. Gerenciamos o sistema de trading iniciando as flags, isBuySystemInitiated e isSellSystemInitiated. Essas flags garantem que, até que as posições atuais sejam fechadas, o sistema não inicie ordens de compra ou venda idênticas dentro de uma tendência particular mais de uma vez. Também obtemos ajuda para manter o fluxo lógico da estratégia intacto nessa verificação. A abordagem pode reagir com precisão às condições do mercado e às tendências, garantindo que novas ordens sejam colocadas de forma forte quando apropriado, ou seja, quando não houver posições abertas. Alcançamos uma melhor gestão de risco evitando que várias posições sejam abertas ao mesmo tempo. Dessa forma, a estratégia pode limitar a exposição ao mercado e evitar possível sobre alavancagem.
Detecção de Nova Barra: Com base nos cruzamentos das médias móveis, ela procura sinais de compra ou venda se uma nova barra (vela) se formou e não há posições abertas. Para evitar a execução múltipla da estratégia de trading, é importante detectar o surgimento de uma nova barra. Usar os dados da barra finalizada como base para as escolhas de trading, em vez de mudanças de preço instáveis dentro da barra, melhora a precisão do trading.
if (PositionsTotal()==0 && IsNewBar()){ if (maFast[0] > maSlow[0] && maFast[1] < maSlow[1]){ Print("BUY SIGNAL"); takeProfit = Ask+tpPts*_Point; stopLoss = Ask-slPts*_Point; obj_Trade.Buy(lot,_Symbol,Ask,stopLoss,0); isBuySystemInitiated = true; } else if (maFast[0] < maSlow[0] && maFast[1] > maSlow[1]){ Print("SELL SIGNAL"); takeProfit = Bid-tpPts*_Point; stopLoss = Bid+slPts*_Point; obj_Trade.Sell(lot,_Symbol,Bid,stopLoss,0); isSellSystemInitiated = true; } }
Quando PositionsTotal == 0, essa condição garante que a função do bloco if seja executada apenas se não houver posições abertas. Dessa forma, evita-se que as negociações se sobreponham e novas ordens só serão abertas após o fechamento das ordens mais antigas. A função IsNewBar() determina se uma nova barra foi formada desde a última execução. Essencialmente, quando o tempo de abertura foi registrado anteriormente, esse método deve retornar verdadeiro.
No Sinal de Compra, aqui determinamos se a barra recente apresentou um cruzamento de alta ou se a média móvel rápida (MA) cruzou acima da média móvel lenta. Se for o caso, ele calcula os níveis de take profit e stop loss e publica uma mensagem "BUY SIGNAL". Após isso, ele define a flag isBuySystemInitiated como verdadeira e envia uma ordem de compra usando obj_Trade.Buy(). Abaixo está um Sinal de Compra do Cruzamento de EMA da Estratégia de Trading de Ordens em Cascata:
No Sinal de Venda, aqui determinamos se a barra recente representa um cruzamento de baixa, ou seja, se a média móvel rápida (MA) cruzou abaixo da média móvel lenta. Se for o caso, ele calcula os níveis de take profit e stop loss e exibe uma mensagem "SELL SIGNAL". Após isso, ele usa obj_Trade para enviar uma ordem de venda. A flag isSellSystemInitiated é definida como verdadeira por Sell(). Abaixo está um Sinal de Venda do Cruzamento de EMA da Estratégia de Trading de Ordens em Cascata:
A estratégia garante que a lógica de trading seja executada apenas uma vez por barra, identificando quando uma nova barra é detectada. Dessa forma, o problema de várias ordens serem colocadas dentro da mesma barra é evitado, o que pode resultar em sobretrading e taxas de transação mais altas. Quando usamos dados de barras concluídas para informar as decisões de trading, garantimos que as escolhas sejam baseadas em informações confiáveis. Mudanças de preço dentro das barras podem ser ruidosas e gerar indicações errôneas. O estado do sistema de trading é gerenciado de forma eficaz, combinando a verificação de que não há posições abertas com a detecção de uma nova barra. Isso garante que novas ordens sejam feitas apenas quando necessário, preservando o fluxo lógico da estratégia.
Executar Ordens de Compra ou Venda: - Uma ordem de compra é colocada se a média móvel rápida cruzar acima da média móvel lenta. Uma ordem de venda é iniciada se a média móvel rápida cruzar abaixo da média móvel lenta. Ela também modifica as flags de início e define os níveis de take profit e stop loss (SL). Esse "cascateamento" das ordens ajuda a estabelecer gradualmente uma posição à medida que o preço se move a favor do primeiro negócio.
else { if (isBuySystemInitiated && Ask >= takeProfit){ takeProfit = takeProfit+tpPts*_Point; stopLoss = Ask-slPts_Min*_Point; obj_Trade.Buy(lot,_Symbol,Ask,0); ModifyTrades(POSITION_TYPE_BUY,stopLoss); }
Nas Cascatas de Ordem de Compra, a estratégia determina se o nível de take profit foi atingido e se o preço ask atual é maior ou igual a ele. Esta circunstância significa que uma ordem de compra extra foi acionada, já que o preço se moveu a favor da posição de compra atual. O nível de take profit é aumentado por uma quantidade predeterminada de pontos, estabelecendo um novo valor global para o próximo incremento na cascata. A modificação de Stop Loss garante que o risco seja controlado para a nova ordem de compra e o nível de stop loss seja alterado para um novo nível abaixo do preço ask. A adição de uma Ordem de Compra coloca uma segunda ordem de compra com o tamanho de lote especificado, efetiva ao preço Ask atual. A modificação das Trades atuais gerencia o risco para a posição geral, o stop loss para as posições de compra atuais é alterado para o novo nível de stop loss.
A Ordem de Venda Sequencial, a estratégia determina se o preço Bid atual é menor ou igual ao nível de takeProfit e se o sistema de venda foi iniciado. Esta situação significa que uma ordem de venda extra foi acionada, já que o preço se moveu a favor da posição de venda atual. O nível de take profit é diminuído por uma quantidade predeterminada de pontos, estabelecendo uma nova meta para o próximo incremento na cascata. A atualização do stop loss garante que o risco seja controlado para a nova ordem de venda, o nível de stop loss é alterado para um novo nível acima do preço Bid existente. Uma ordem de venda adicional com o tamanho de lote especificado é executada no preço Bid atual. A modificação das Trades atuais controla o risco de forma abrangente, o stop loss para as posições de venda atuais é alterado para o novo nível de stop loss.
Ajustar posições atuais: Se houver posições abertas e o preço atingir o limite de take-profit, mais ordens são colocadas e os valores de stop loss são atualizados adequadamente. Isso ajuda na maximização incremental dos lucros e no gerenciamento de risco.
else if (isSellSystemInitiated && Bid <= takeProfit){ takeProfit = takeProfit-tpPts*_Point; stopLoss = Bid+slPts_Min*_Point; obj_Trade.Sell(lot,_Symbol,Bid,0); ModifyTrades(POSITION_TYPE_SELL,stopLoss); } } }
Uma flag booleana chamada isBuySystemInitiated indica se o sistema de compra foi iniciado ou não. Uma flag booleana chamada isSellSystemInitiated indica se o sistema de venda foi iniciado ou não. O preço ask atual, o preço bid, a quantidade de take profit, o número de pontos necessários para modificar o limite de take-profit, o nível de stop loss, o ponto mínimo de ajuste de stop loss, o tamanho do lote da negociação, a capacidade de colocar uma ordem de compra, a capacidade de enviar uma ordem de venda e o recurso que permite modificar o stop loss de uma posição existente.
Agora verificamos se o sistema UT foi iniciado e se o preço ask atual atingiu ou superou o limite de take-profit. Aumentando o nível de Take Profit por uma quantidade predeterminada de pontos. Isso permite que a estratégia capture ganhos adicionais possíveis, estabelecendo uma nova meta de take profit mais alta do que a existente. Definindo o stop loss em um novo preço, mais baixo que o preço ask. Travar uma parte dos ganhos anteriores ajuda no gerenciamento de risco. Completando ordens de compra adicionais ao preço Ask executa a segunda ordem de compra com o tamanho de lote designado ao preço ask. À medida que o preço se move a favor das negociações iniciais, isso aumenta gradualmente a posição. Atualiza todos os stop losses das posições de compra atuais para refletir o novo valor do stop loss. Isso ajuda a controlar o risco total associado à posição de compra.
Em seguida, verificamos se o mecanismo de venda foi iniciado e se o preço bid subiu ou caiu abaixo do limite de take-profit. Reduzindo o nível de Take Profit por um número fixo de pontos. Como resultado, a nova meta de take profit será menor que o nível existente. Após atualizar o stop loss, isso moverá o stop loss para um novo nível acima do preço bid. Travar uma parte dos ganhos anteriores ajuda no gerenciamento de risco. Completa uma ordem de venda adicional com o tamanho de lote designado ao preço bid atual. À medida que o preço se move a favor da negociação inicial, isso aumenta gradualmente a posição. Atualiza todos os stop losses das posições de venda atuais para refletir o novo valor do stop loss. Isso ajuda a controlar o risco total associado à posição de venda.
À medida que o mercado se move a favor da primeira transação, a estratégia aumenta gradualmente a posição de trading. Dessa forma, o trader pode aumentar sua posição sem assumir risco excessivo no início e lucrar com tendências significativas. A estratégia gerencia eficazmente o risco variando os níveis de stop loss para tanto as novas ordens quanto as posições abertas. Se o mercado cair, isso ajuda a preservar os ganhos e reduzir as perdas. Sempre que o mercado avança na direção da preferência da estratégia de cascata, novos níveis de take profit são progressivamente definidos para maximizar os lucros. Isso permite crescimento futuro enquanto garante um bloqueio progressivo dos lucros.
Agora vamos dar uma olhada nas duas funções auxiliares no código do nosso Expert Advisor (EA) MQL5. IsNewBar and ModifyTrades. Essas rotinas fornecem operações auxiliares necessárias para apoiar a lógica central de trading que é fornecida na função OnTick.
Começamos com a função IsNewBar. Esta função examina o gráfico para ver se uma nova barra ou vela foi formada. Isso é necessário para garantir que ações específicas, como abrir novas negociações, sejam realizadas apenas uma vez por barra.
//+------------------------------------------------------------------+ bool IsNewBar(){ static int prevBars = 0; int currBars = iBars(_Symbol,_Period); if (prevBars==currBars) return (false); prevBars = currBars; return (true); }
O número de barras do tick anterior é armazenado na variável estática prevBars. O valor da variável é preservado entre as chamadas de função graças à palavra-chave estática. Contagem atual de Barras: currBars recupera a contagem atual de barras no gráfico. Comparação: A função retorna falso se nenhuma nova barra foi gerada e prevBars e currBars forem iguais. Uma nova barra surgiu se eles discordarem. A função retorna verdadeiro após atualizar prevBars para currBars.
Agora vamos para a função ModifyTrades. Com base no tipo de posição especificado, a função ModifyTrades ajusta os níveis de stop loss (SL) das posições ativas.
void ModifyTrades(ENUM_POSITION_TYPE posType, double sl){ for (int i=0; i<=PositionsTotal(); i++){ ulong ticket = PositionGetTicket(i); if (ticket > 0){ if (PositionSelectByTicket(ticket)){ ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); if (type==posType){ obj_Trade.PositionModify(ticket,sl,0); } } } } }
Nesta função:
- Loop sobre as posições: usa PositionTotal() para percorrer todas as posições abertas.
- Obter Ticket: Retorna o número do ticket da posição no índice {i}.
- Verificar Ticket: Verifica se o número do ticket é válido (maior que 0).
- Selecionar Posição: Usa PositionSelectByTicket para escolher a posição.
- **Verificar Tipo de Posição**: Verifica se o tipo de posição especificado corresponde ao tipo da posição.
- **Modificar Posição**: Usa PositionModify para alterar o tipo da posição.
O código completo da Estratégia de Trading de Ordens em Cascata é o seguinte:
//| CASCADE ORDERING.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include <Trade/Trade.mqh> CTrade obj_Trade; int handleMAFast; int handleMASlow; double maSlow[], maFast[]; double takeProfit = 0; double stopLoss = 0; bool isBuySystemInitiated = false; bool isSellSystemInitiated = false; input int slPts = 300; input int tpPts = 300; input double lot = 0.01; input int slPts_Min = 100; input int fastPeriods = 10; input int slowPeriods = 20; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { handleMAFast = iMA(_Symbol, _Period, fastPeriods, 0, MODE_EMA, PRICE_CLOSE); if (handleMAFast == INVALID_HANDLE) { Print("UNABLE TO LOAD FAST MA, REVERTING NOW"); return (INIT_FAILED); } handleMASlow = iMA(_Symbol, _Period, slowPeriods, 0, MODE_EMA, PRICE_CLOSE); if (handleMASlow == INVALID_HANDLE) { Print("UNABLE TO LOAD SLOW MA, REVERTING NOW"); return (INIT_FAILED); } ArraySetAsSeries(maFast, true); ArraySetAsSeries(maSlow, true); return (INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // Cleanup code if necessary } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits); if (CopyBuffer(handleMAFast, 0, 1, 3, maFast) < 3) { Print("NO ENOUGH DATA FROM FAST MA FOR ANALYSIS, REVERTING NOW"); return; } if (CopyBuffer(handleMASlow, 0, 1, 3, maSlow) < 3) { Print("NO ENOUGH DATA FROM SLOW MA FOR ANALYSIS, REVERTING NOW"); return; } if (PositionsTotal() == 0) { isBuySystemInitiated = false; isSellSystemInitiated = false; } if (PositionsTotal() == 0 && IsNewBar()) { if (maFast[0] > maSlow[0] && maFast[1] < maSlow[1]) { Print("BUY SIGNAL"); takeProfit = Ask + tpPts * _Point; stopLoss = Ask - slPts * _Point; obj_Trade.Buy(lot, _Symbol, Ask, stopLoss, 0); isBuySystemInitiated = true; } else if (maFast[0] < maSlow[0] && maFast[1] > maSlow[1]) { Print("SELL SIGNAL"); takeProfit = Bid - tpPts * _Point; stopLoss = Bid + slPts * _Point; obj_Trade.Sell(lot, _Symbol, Bid, stopLoss, 0); isSellSystemInitiated = true; } } else { if (isBuySystemInitiated && Ask >= takeProfit) { takeProfit = takeProfit + tpPts * _Point; stopLoss = Ask - slPts_Min * _Point; obj_Trade.Buy(lot, _Symbol, Ask, 0); ModifyTrades(POSITION_TYPE_BUY, stopLoss); } else if (isSellSystemInitiated && Bid <= takeProfit) { takeProfit = takeProfit - tpPts * _Point; stopLoss = Bid + slPts_Min * _Point; obj_Trade.Sell(lot, _Symbol, Bid, 0); ModifyTrades(POSITION_TYPE_SELL, stopLoss); } } } static int prevBars = 0; int currBars = iBars(_Symbol, _Period); if (prevBars == currBars) return (false); prevBars = currBars; return (true); } //+------------------------------------------------------------------+ //| ModifyTrades Function | //+------------------------------------------------------------------+ void ModifyTrades(ENUM_POSITION_TYPE posType, double sl) { for (int i = 0; i <= PositionsTotal(); i++) { ulong ticket = PositionGetTicket(i); if (ticket > 0) { if (PositionSelectByTicket(ticket)) { ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE) PositionGetInteger(POSITION_TYPE); if (type == posType) { obj_Trade.PositionModify(ticket, sl, 0); } } } } }
Conclusão
Finalmente, este expert advisor MQL5 é um ótimo exemplo de uma estratégia de trading baseada em cruzamento de médias móveis bem executada. O artigo exibe uma automação eficiente das escolhas de trading, utilizando a biblioteca Trade.mqh para simplificar a gestão de ordens e incluir níveis dinâmicos para take profit e stop loss.
Entre as características salientes deste expert advisor estão:
- Inicialização e Gestão: Sinais de compra e venda baseados em cruzamentos são gerenciados sistematicamente, e as médias móveis são inicializadas de forma eficiente.
- Gerenciamento de Risco: Uso de procedimentos de take-profit e stop-loss para reduzir riscos e garantir recompensas dentro dos limites configuráveis pelo usuário.
- Modularidade e Flexibilidade: Uso de parâmetros de entrada e variáveis globais para personalizar e se adaptar a diferentes situações de mercado e preferências de trading.
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/15250





- 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