![Sistema de negociação simples com o uso de indicadores semáforo](https://c.mql5.com/i/articles/overlay.png)
Sistema de negociação simples com o uso de indicadores semáforo
Introdução
Indicadores semáforo ou sinal são detectores simples que indicam o momento para entrar ou sair do mercado. Caso houver um sinal de entrada na barra atual, uma etiqueta apropriada aparece em um gráfico de símbolo. Esta etiqueta pode então ser usada como condição para realização de uma negociação.
Há muitos indicadores desse tipo, mas a essência do sistema de negociação original com base nesses indicadores não foi modificada. Dessa forma, é uma boa ideia implementá-lo da forma mais simples e universal. Isto permitirá o uso posterior dos resultados obtidos ao trabalhar com quaisquer indicadores similares sem alterações significativas.
Figura 1. Indicador de sinal semáforo ASCtrend
Figura 2. Sinal de negociação para realização de um acordo usando o indicador de sinal de semáforo ASCtrend
Exemplos de indicadores de sinal de semáforo típicos
Atualmente, há muitos desses indicadores na Base de códigos. Neste artigo, apenas forneceremos alguns links para as páginas adequadas:
- BykovTrend;
- ASCtrend;
- BrainTrend1Sig;
- BrainTrend2Sig;
- SilverTrend_Signal;
- Stalin;
- WPRSI signal;
- StepMA_NRTR;
- LeManSignal;
- 3Parabolic System;
- PriceChannel_Stop;
- Arrows&Curves;
- Karacatica;
- Sidus.
Além dos indicadores de sinal de semáforo, há um grupo de indicadores de tendência de semáforo:
Figura 3. Indicador de tendência de semáforo
Figura 4. Sinal de negociação para realização de um acordo usando o indicador de tendência de semáforo Heiken Ashi Smoothed
Sistemas de negociação que usam esses indicadores têm códigos um pouco diferentes para a obtenção de sinais de negociação, enquanto o código do Expert Advisor permanece quase inalterado.
Exemplos de indicadores de tendência de semáforo típicos
A base de códigos contém diversos indicadores desse tipo. Neste artigo, apenas forneceremos alguns links para as páginas adequadas:
- FiboCandles;
- Parabolic SAR;
- X2MA;
- Candles_Smoothed;
- SuperTrend;
- Go;
- 3LineBreak;
- Laguerre;
- Heiken Ashi Smoothed;
- NonLagDot.
Dados básicos para criação de um sistema de negociação:
- O indicador de semáforo com os parâmetros de entrada que devem ser apresentados no Expert Advisor.
- A lista de parâmetros adicionais de entrada de negociação do Expert Advisor:
- um compartilhamento de recursos financeiros de depósito utilizados em uma negociação;
- um tamanho de Stop Loss e Take Profit (os pedidos pendentes não devem ser utilizados em caso de valores nulos);
- deslize (diferença máxima permitida entre preços de negociação estabelecidos e atuais);
- índice da barra, a partir do qual os sinais de negociação serão recebidos;
- permissões para abertura de posições curtas e longas;
- permissões para fechamento forçado de posições curtas e longas de acordo com os sinais do indicador.
É evidente que seria muito mais conveniente dar ordens para a realização de negociações usando funções universais de negociação. Essas funções são muito complexas e deveriam ser agrupadas em um arquivo de biblioteca distinto para tonar o código do aplicativo o mais fácil possível.
O código do Expert Advisor que implementa o sistema de negociação de semáforo:
//+------------------------------------------------------------------+ //| Exp_ASCtrend.mq5 | //| Copyright © 2011, Nikolay Kositsin | //| Khabarovsk, farria@mail.redcom.ru | //+------------------------------------------------------------------+ #property copyright "Copyright © 2011, Nikolay Kositsin" #property link "farria@mail.redcom.ru" #property version "1.00" //+----------------------------------------------+ //| Expert Advisor indicator input parameters | //+----------------------------------------------+ input double MM=-0.1; // Share of a deposit in a deal, negative values - lot size input int StopLoss_=1000; // Stop loss in points input int TakeProfit_=2000; // Take profit in points input int Deviation_=10; // Max. price deviation in points input bool BuyPosOpen=true; // Permission to buy input bool SellPosOpen=true; // Permission to sell input bool BuyPosClose=true; // Permission to exit long positions input bool SellPosClose=true; // Permission to exit short positions //+----------------------------------------------+ //| ASCtrend indicator input parameters | //+----------------------------------------------+ input ENUM_TIMEFRAMES InpInd_Timeframe=PERIOD_H1; // ASCtrend indicator time frame input int RISK=4; // Risk level input uint SignalBar=1; // Bar index for getting an entry signal //+----------------------------------------------+ int TimeShiftSec; //---- declaration of integer variables for the indicators handles int InpInd_Handle; //---- declaration of integer variables of the start of data calculation int min_rates_total; //+------------------------------------------------------------------+ //| Trading algorithms | //+------------------------------------------------------------------+ #include <TradeAlgorithms.mqh> //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //---- getting ASCtrend indicator handle InpInd_Handle=iCustom(Symbol(),InpInd_Timeframe,"ASCtrend",RISK); if(InpInd_Handle==INVALID_HANDLE) Print(" Failed to get handle of ASCtrend indicator"); //---- initialization of a variable for storing a chart period in seconds TimeShiftSec=PeriodSeconds(InpInd_Timeframe); //---- initialization of variables of the start of data calculation min_rates_total=int(3+RISK*2+SignalBar); //---- return(0); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //---- GlobalVariableDel_(Symbol()); //---- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //---- checking the number of bars to be enough for calculation if(BarsCalculated(InpInd_Handle)<min_rates_total) return; //---- uploading history for IsNewBar() and SeriesInfoInteger() functions normal operation LoadHistory(TimeCurrent()-PeriodSeconds(InpInd_Timeframe)-1,Symbol(),InpInd_Timeframe); //---- declaration of local variables double DnVelue[1],UpVelue[1]; //---- declaration of static variables static bool Recount=true; static bool BUY_Open=false,BUY_Close=false; static bool SELL_Open=false,SELL_Close=false; static datetime UpSignalTime,DnSignalTime; static CIsNewBar NB; //+----------------------------------------------+ //| Searching for deals performing signals | //+----------------------------------------------+ if(!SignalBar || NB.IsNewBar(Symbol(),InpInd_Timeframe) || Recount) // checking for a new bar { //---- zeroing out trading signals BUY_Open=false; SELL_Open=false; BUY_Close=false; SELL_Close=false; Recount=false; //---- copy newly appeared data into the arrays if(CopyBuffer(InpInd_Handle,1,SignalBar,1,UpVelue)<=0) {Recount=true; return;} if(CopyBuffer(InpInd_Handle,0,SignalBar,1,DnVelue)<=0) {Recount=true; return;} //---- getting buy signals if(UpVelue[0] && UpVelue[0]!=EMPTY_VALUE) { if(BuyPosOpen) BUY_Open=true; if(SellPosClose) SELL_Close=true; UpSignalTime=datetime(SeriesInfoInteger(Symbol(),InpInd_Timeframe,SERIES_LASTBAR_DATE))+TimeShiftSec; } //---- getting sell signals if(DnVelue[0] && DnVelue[0]!=EMPTY_VALUE) { if(SellPosOpen) SELL_Open=true; if(BuyPosClose) BUY_Close=true; DnSignalTime=datetime(SeriesInfoInteger(Symbol(),InpInd_Timeframe,SERIES_LASTBAR_DATE))+TimeShiftSec; } //---- searching for the last trading direction for getting positions closing signals //if(!MQL5InfoInteger(MQL5_TESTING) && !MQL5InfoInteger(MQL5_OPTIMIZATION)) //if execution is set to "Random delay" in the Strategy Tester if((BuyPosOpen && BuyPosClose || SellPosOpen && SellPosClose) && (!BUY_Close && !SELL_Close)) { int Bars_=Bars(Symbol(),InpInd_Timeframe); for(int bar=int(SignalBar+1); bar<Bars_; bar++) { if(SellPosClose) { if(CopyBuffer(InpInd_Handle,1,bar,1,UpVelue)<=0) {Recount=true; return;} if(UpVelue[0]!=0 && UpVelue[0]!=EMPTY_VALUE) { SELL_Close=true; break; } } if(BuyPosClose) { if(CopyBuffer(InpInd_Handle,0,bar,1,DnVelue)<=0) {Recount=true; return;} if(DnVelue[0]!=0 && DnVelue[0]!=EMPTY_VALUE) { BUY_Close=true; break; } } } } } //+----------------------------------------------+ //| Performing deals | //+----------------------------------------------+ //---- Closing a long position BuyPositionClose(BUY_Close,Symbol(),Deviation_); //---- Closing a short position SellPositionClose(SELL_Close,Symbol(),Deviation_); //---- Buying BuyPositionOpen(BUY_Open,Symbol(),UpSignalTime,MM,0,Deviation_,StopLoss_,TakeProfit_); //---- Selling SellPositionOpen(SELL_Open,Symbol(),DnSignalTime,MM,0,Deviation_,StopLoss_,TakeProfit_); //---- } //+------------------------------------------------------------------+
O código para a realização desta ideia é muito simples e claro. Entretanto, alguns detalhes devem ser esclarecidos.
O período do gráfico utilizado por um indicador de sinal e por um Expert Advisor é fixado à variável de entrada InpInd_Timeframe do Expert Advisor. Assim, a mudança em um gráfico, no qual um Expert Advisor está localizado, não altera este parâmetro para o Expert Advisor.
A função IsNewBar() necessária para determinar o momento de chegada de uma nova barra é implementada como uma classe posicionada no arquivo TradeAlgorithms.mqh. Isso permite usar facilmente qualquer número dessas funções no código através do estabelecimento de uma variável CIsNewBar individual estática para cada uma delas.
As variáveis UpSignalTime e DnSignalTime são usadas para armazenar e transferir o tempo, após o qual é possível realizar a próxima negociação depois da anterior, às funções de negociação. Em nosso caso, este recurso é utilizado para evitar a realização de diversos acordos em uma mesma direção da mesma barra (ao realizar um acordo, a função de negociação armazena o tempo do fim da barra atual e não realiza novos acordos na mesma direção até aquele momento).
O bloco "Buscando a última direção de negociação para obter sinais para fechamento de posições" na função OnTick() é necessário para o recebimento de sinais de fechamento de posições nas barras sem sinais de negociação. Em caso de operação normal de um Expert Advisor, isso não é necessário. Mas em caso de falha na conexão com a Internet, é muito possível que um novo sinal de negociação seja perdido. Não é muito boa ideia entrar no mercado post factum, mas fechar as posições abertas seria uma jogada inteligente.
Utilizar o sistema de negociação com outros indicadores de sinal de semáforo
Agora, se houver necessidade de usar este código com outro indicador de sinal de semáforo, as seguintes ações devem ser realizadas:
- Substituir os dados do indicador anterior pelos parâmetros necessários do novo indicador nos parâmetros de entrada de um Expert Advisor.
- Alterar o código de obtenção do handle do indicador no bloco OnInit().
- Determinar os índices dos buffers do indicador, utilizados para armazenar sinais de negociação de compra e venda a partir do código do indicador, e inseri-los adequadamente nas chamadas da função CopyBuffer() no bloco OnTick(). Neste caso, são usados os buffers zero e primeiro do indicador.
- Alterar a inicialização da variável de ponto de início da inicialização do cálculo de dados (min_rates_total) em um Expert Advisor de acordo com o código do indicador.
- Alterar o bloco "Buscando a última direção de negociação para obter sinais para fechamento de posições" na função OnTick() de acordo com o código do indicador.
Utilizar o sistema de negociação com outros indicadores de tendência de semáforo
Ao utilizar este sistema de negociação com o indicador de tendência de semáforo, o código do Expert Advisor foi alterado um pouco no bloco para determinação de sinais para negociações da função OnTick(). Por exemplo, o código terá o aspecto abaixo para o Expert Advisor baseado no indicador FiboCandles:
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //---- checking the number of bars to be enough for calculation if(BarsCalculated(InpInd_Handle)<min_rates_total) return; //---- uploading history for IsNewBar() and SeriesInfoInteger() functions LoadHistory(TimeCurrent()-PeriodSeconds(InpInd_Timeframe)-1,Symbol(),InpInd_Timeframe); //---- declaration of local variables double TrendVelue[2]; //---- declaration of static variables static bool Recount=true; static bool BUY_Open=false,BUY_Close=false; static bool SELL_Open=false,SELL_Close=false; static datetime UpSignalTime,DnSignalTime; static CIsNewBar NB; //+----------------------------------------------+ //| Searching for deals performing signals | //+----------------------------------------------+ if(!SignalBar || NB.IsNewBar(Symbol(),InpInd_Timeframe) || Recount) // checking for a new bar { //---- zeroing out trading signals BUY_Open=false; SELL_Open=false; BUY_Close=false; SELL_Close=false; Recount=false; //---- copy the newly obtained data into the arrays if(CopyBuffer(InpInd_Handle,4,SignalBar,2,TrendVelue)<=0) {Recount=true; return;} //---- getting buy signals if(TrendVelue[0]==1 && TrendVelue[1]==0) { if(BuyPosOpen) BUY_Open=true; if(SellPosClose)SELL_Close=true; UpSignalTime=datetime(SeriesInfoInteger(Symbol(),InpInd_Timeframe,SERIES_LASTBAR_DATE))+TimeShiftSec; } //---- getting sell signals if(TrendVelue[0]==0 && TrendVelue[1]==1) { if(SellPosOpen) SELL_Open=true; if(BuyPosClose) BUY_Close=true; DnSignalTime=datetime(SeriesInfoInteger(Symbol(),InpInd_Timeframe,SERIES_LASTBAR_DATE))+TimeShiftSec; } //---- searching for the last trading direction for getting positions closing signals //if(!MQL5InfoInteger(MQL5_TESTING) && !MQL5InfoInteger(MQL5_OPTIMIZATION)) //if execution is set to "Random delay" in the Strategy Tester { if(SellPosOpen && SellPosClose && TrendVelue[1]==0) SELL_Close=true; if(BuyPosOpen && BuyPosClose && TrendVelue[1]==1) BUY_Close=true; } } //+----------------------------------------------+ //| Performing deals | //+----------------------------------------------+ //---- Closing a long position BuyPositionClose(BUY_Close,Symbol(),Deviation_); //---- Closing a short position SellPositionClose(SELL_Close,Symbol(),Deviation_); //---- Buying BuyPositionOpen(BUY_Open,Symbol(),UpSignalTime,MM,0,Deviation_,StopLoss_,TakeProfit_); //---- Selling SellPositionOpen(SELL_Open,Symbol(),DnSignalTime,MM,0,Deviation_,StopLoss_,TakeProfit_); //---- }
Neste caso, os sinais de negociação são recebidos a partir de um único buffer de indicador de cor (que contém índices de cor). Os dados deste buffer podem ter somente dois valores: 0 - para mercado crescente e 1 - para decrescente. O código do bloco "Buscando a última direção de negociação para obter sinais para fechamento de posições" tornou-se o mais simples possível visto que a direção de tendência em qualquer barra pode ser recebida diretamente a partir da célula adequada do buffer do indicador.
No bloco "realizando negociações" as funções de fechamento de posições vão primeiro, seguidas pelas funções de abertura. Em caso de sequência oposta, será possível fechar apenas as negociações em uma barra. Você não poderá abri-las simultaneamente ao realizar testes no modo "apenas preços Open"! Dessa forma, os resultados de negociação serão seriamente interrompidos.
Teste do sistema de negociação
Antes de passarmos ao teste do sistema de negociação, um detalhe importante deve ser esclarecido. Caso a variável de entrada SignalBar seja igual a zero, o Expert Advisor obterá negociações realizando sinais da barra atual. Mas o sinal da barra atual não é confiável para indicar a mudança da tendência que se moveu na direção oposta a este sinal na barra anterior. Os sinais da barra atual podem aparecer e desaparecer, enquanto que uma tendência pode se mover na direção contrária a esses sinais por muito tempo. Isto pode ser facilmente percebido caso um Expert Advisor seja testado em todos os ticks com visualização habilitada e a variável SignalBar seja igual a zero. A visualização da operação do indicador ASCtrend apresenta uma evidência muito clara desse fato no caso em análise.
Novamente, apenas o modo "Cada tick" é adequado para uma otimização de Expert Advisor com um sinal recebido da barra atual. Caso ele seja recebido de qualquer barra que já tenha sido fechada, o modo "apenas preços Open" já é suficiente. Isso acelera muito a análise de comportamento do sistema de negociação sem qualquer perda considerável de qualidade.
Assim, é melhor não usar sinais da barra atual para testar e otimizar esses sistemas de negociação!
Então, vamos testar o Expert Advisor com parâmetros padrão em EUR/USD desde o início do ano até o início de dezembro:
Figura 5. Resultados de teste do Expert Advisor Exp_ASCtrend com parâmetros padrão em EUR/USD H1
Após alterar um pouco as configurações do Expert Advisor no Provador de Estratégia, podemos encontrar a combinação mais adequada de parâmetros de Expert Advisor para dados históricos existentes muito facilmente:
Figura 6. Resultados de teste do Expert AdvisorExp_ASCtrend após a otimização com melhores parâmetros em EUR/USD H1
O processo de otimização do sistema de negociação não possui quaisquer peculiaridades. Esta é a razão pela qual apresentaremos um único link para o artigo que descreve este processo em detalhes: "MQL5: Guia de teste e otimização de Expert Advisors em MQL5".
É claro que seria ingênuo esperar lucros expressivos com um sistema de negociação tão simples. Mas, é bastante possível conseguir bons resultados no caso deste sistema semi-automático ser habilmente manuseado e ser regularmente sintonizado de acordo com o comportamento atual do mercado.
Por exemplo, havia uma tendência crescente no gráfico EUR/USD H12 em 2011, de janeiro a maio. E isso era facilmente detectável nas primeiras etapas:
Figura 7. Gráfico EUR/USD H12 (janeiro/maio de 2011)
Seria interessante testar o Expert Advisor neste intervalo de tempo com as configurações padrão, somente a possibilidade de comprar e o uso de apenas 5% de um depósito (MM=0.05). Aqui estão os resultados do Expert Advisor com esses parâmetros testado no gráfico H1:
Figura 8. Resultados de teste do Expert Advisor Exp_ASCtrend com parâmetros padrão em EUR/USD H1 para janeiro-maio de 2011 (apenas posições longas, MM=0.05)
É claro que, neste caso, um negociador é totalmente responsável pela seleção de uma direção de negociação. Mas se lembrarmos que isso deve ser feito com o uso de grandes gráficos de período de tempo, dificilmente encontraremos qualquer dificuldade.
Modificação do módulo de negociação para utilizá-lo com outro indicador
Este artigo poderia terminar aqui, mas o MetaEditor implementou a possibilidade de gerar Expert Advisors com base em módulos de negociação prontos para uso. O processo de criação desses módulos, considerando todo o material apresentado aqui, é muito complexo e requer um estudo separado. Por essa razão, o nosso foco será os módulos de criação já criados que são completamente análogos aos sistemas de negociação que foram sugeridos. E apenas após isso é que passaremos aos detalhes da modificação desses módulos de acordo com os indicadores de sinal específicos, evitando detalhamento desnecessário.
Vamos supor que já tenhamos a coleção de módulos de negociação para sistemas de sinal de semáforo (MySignals.zip) e desejamos criar o módulo análogo para qualquer indicador específico. Como exemplo, vamos usar o indicador BykovTrendSignal.mq5, que é um indicador de sinal de semáforo típico. Primeiramente, devemos encontrar o mais análogo ao indicador nesta coleção (indicators.zip). Visualmente, determinamos que o primeiro indicador deste artigo (ASCtrend) é o mais similar a ele. Assim, utilizaremos o módulo de negociação deste indicador para a modificação.
Considerando o uso dele no código de programa requerido, o próprio indicador (BykovTrend) possui um conjunto de parâmetros de entrada:
//+----------------------------------------------+ //| Indicator input parameters | //+----------------------------------------------+ input int RISK=3; input int SSP=9; //+----------------------------------------------+
E nós precisamos dos índices dos buffers de indicador utilizados para armazenar os sinais para realização de negociações. Em nosso caso, ele são: 0 - para sinais de venda e 1 - para sinais de compra.
Agora que sabemos qual módulo deve ser usado para a modificação, copiamos ele na pasta \MQL5\Include\Expert\Signal\MySignals\ com o nome de arquivo BykovTrendSignal.mqh e o abrimos no MetaEditor. Há uma expressão "ASCtrend" (o nome do indicador anterior) regularmente encontrada no código utilizado. Ela deve ser substituída pelo nome do novo indicador - "BykovTrend". Para fazer isso, pressione as teclas "Ctrl" e "H" simultaneamente e faça a modificação necessária:
Figura 9. Substituir o nome do indicador no código do módulo de negociação
A próxima etapa do nosso trabalho é a mais meticulosa. Temos que substituir tudo o que diz respeito aos parâmetros de entrada do indicador no código do módulo de negociação. O processo é muito similar ao que foi apresentado no artigo "MQL5 Wizard: Como criar um módulo de sinais de negociação".
Primeiramente, devemos fazer algumas mudanças no bloco comentado da descrição de classe de sinais de negociação do MQL5 Wizard:
//+----------------------------------------------------------------------+ //| Description of the class | //| Title=The signals based on BykovTrend indicator | //| Type=SignalAdvanced | //| Name=BykovTrend | //| Class=CBykovTrendSignal | //| Page= | //| Parameter=BuyPosOpen,bool,true,Permission to buy | //| Parameter=SellPosOpen,bool,true,Permission to sell | //| Parameter=BuyPosClose,bool,true,Permission to exit a long position | //| Parameter=SellPosClose,bool,true,Permission to exit a short position | //| Parameter=Ind_Timeframe,ENUM_TIMEFRAMES,PERIOD_H1,Timeframe | //| Parameter=RISK,int,4,Risk level | //| Parameter=SSP,int,9,SSP | //| Parameter=SignalBar,uint,1,Bar index for entry signal | //+----------------------------------------------------------------------+ //--- wizard description end //+----------------------------------------------------------------------+ //| CBykovTrendSignal class. | //| Purpose: Class of generator of trade signals based on | //| BykovTrend indicator https://www.mql5.com/ru/code/497/. | //| Is derived from the CExpertSignal class. | //+----------------------------------------------------------------------+
Ambos os indicadores contém a mesma variável de entrada RISK (risco). Dessa forma, ela pode ser mantida. Mas o valor padrão é diferente para esses indicadores. Na realidade, esta diferença não é expressiva e ele pode permanecer inalterado. A linha de comentário da variável SSP foi adicionada:
//| Parameter=SSP,int,9,SSP |
E o link para o indicador Base de códigos foi substituído:
//| Purpose: Class of generator of trade signals based on | //| BykovTrend values https://www.mql5.com/ru/code/497/. |
Agora, tudo o que se relaciona às mudanças dos parâmetros de entrada deve ser refletido na descrição da classe de sinais de negociação CBykovTrendSignal. Nós temos a linha da nova declaração de variável de classe global m_SSP nos parâmetros de configuração:
uint m_SSP; // SSP
E a linha da nova declaração de parâmetros de configuração de método de instalação SSP():
void SSP(uint value) { m_SSP=value; }
Tudo que se relaciona à variável de entrada RISK no módulo de sinais de negociação que criarmos é equivalente ao módulo de entrada e, dessa forma, não há mudanças nos blocos de módulo de negociação atuais ou em quaisquer outros.
Agora, passamos ao construtor de classe CBykovTrendSignal::CBykovTrendSignal(). A inicialização de uma nova variável deve ser adicionada a este bloco:
m_SSP=4;
O processo de verificação de funcionamento correto da nova variável deve ser realizado no bloco de verificação de parâmetros de configuração BykovTrendSignal::ValidationSettings():
if(m_SSP<=0) { printf(__FUNCTION__+": SSP must be above zero"); return(false); }
Após isso, podemos passar ao bloco de inicialização do indicador BykovTrend - BykovTrendSignal::InitBykovTrend(). O novo indicador tem um número diferente de variáveis de entrada e, assim, a dimensão da série declarada de parâmetros de entrada também será diferente:
//--- setting the indicator parameters MqlParam parameters[3];
Em nosso caso, precisamos de uma dimensão para o nome da string do indicador e mais duas para os seus parâmetros de entrada.
Agora temos que inicializar uma nova célula das séries de parâmetros de entrada, indicando o tipo de variável que será armazenado nela:
parameters[2].type=TYPE_INT; parameters[2].integer_value=m_SSP;
Após isso, mude o número de variáveis de entrada para 3 neste bloco na chamada para a inicialização do indicador:
//--- object initialization if(!m_indicator.Create(m_symbol.Name(),m_Ind_Timeframe,IND_CUSTOM,3,parameters))
O número de buffers no indicador permanece o mesmo e igual a dois. Assim, em nosso caso, não há necessidade de alterar nada na linha de inicialização de número de buffers do indicador:
//--- number of buffers if(!m_indicator.NumBuffers(2)) return(false);
Cada um dos indicadores ASCtrend e BykovTrend têm dois buffers. As funções dos buffers são completamente similares. O buffer zero é usado para armazenar sinais de venda, enquanto que o buffer que tem índica 1 é usado para armazenar sinais de compra. Assim, não há necessidade de alterar nada nos blocos de funções para entrada de sinais de negociação CBykovTrendSignal::LongCondition() e CBykovTrendSignal::ShortCondition() e o trabalho de modificação do módulo de sinais de negociação pode ser considerado completo.
Mas, em geral, todos os indicadores de semáforo são diferentes e, assim, esses blocos para indicadores de semáforo diferentes podem ser consideravelmente diferentes uns dos outros. O arquivo de módulo de negociação MySignals.zip e o arquivo Indicators.zip adequado contêm quantidades suficientes de exemplos para a criação de vários indicadores. Após um exame, é possível encontrar os detalhes do processo de substituição e possíveis versões de código para isso.
Agora, vamos focar na variável de entrada Ind_Timeframe do módulo de sinais de negociação. Esta variável permite baixar um período de tempo apropriado no indicador. Entretanto, o Expert Advisor que foi gerado opera no período de tempo para o qual foi designado. Isso significa que, para proporcionar uma operação normal de módulo, o período de tempo da variável de entrada Ind_Timeframe nunca deve exceder um período do gráfico em que o Expert Advisor opera.
Finalmente, vamos revelar outra peculiaridade da criação de módulos de sinais de negociação. Às vezes, enumerações personalizadas são implementadas no código de indicador básico como os tipos para as variável de entrada do módulo. Por exemplo, a enumeração personalizada Smooth_Method é utilizada como um tipo de variável MA_SMethod para o indicador Candles_Smoothed:
//+-----------------------------------+ //| Declaration of enumerations | //+-----------------------------------+ enum Smooth_Method { MODE_SMA_, // SMA MODE_EMA_, // EMA MODE_SMMA_, // SMMA MODE_LWMA_, // LWMA MODE_JJMA, // JJMA MODE_JurX, // JurX MODE_ParMA, // ParMA MODE_T3, // T3 MODE_VIDYA, // VIDYA MODE_AMA, // AMA }; */ //+----------------------------------------------+ //| Indicator input parameters | //+----------------------------------------------+ input Smooth_Method MA_SMethod=MODE_LWMA; // Smoothing method input int MA_Length=30; // Smoothing depth input int MA_Phase=100; // Smoothing parameter // for JJMA varying within the range -100 ... +100, // for VIDIA it is a CMO period, for AMA it is a slow average period //+----------------------------------------------+
Neste caso, variáveis de entrada desse tipo e todos os elementos associados no módulo de sinais de negociação (Candles_SmoothedSignal.mqh) devem ser modificados para as variáveis do tipo int ou uint. Além disso, o procedimento inverso de enumerações personalizadas até os parâmetros de entrada do Expert Advisor e substituição dos tipos de variável de entrada necessários (ExpM_Candles_Smoothed Expert Advisor) devem ser realizados para facilitar o uso dessas variáveis de entrada no código que já foi gerado do Expert Advisor pronto:
//+------------------------------------------------------------------+ //| Declaration of enumerations | //+------------------------------------------------------------------+ enum Smooth_Method { MODE_SMA_, // SMA MODE_EMA_, // EMA MODE_SMMA_, // SMMA MODE_LWMA_, // LWMA MODE_JJMA, // JJMA MODE_JurX, // JurX MODE_ParMA, // ParMA MODE_T3, // T3 MODE_VIDYA, // VIDYA MODE_AMA, // AMA }; //+------------------------------------------------------------------+ //| Inputs | //+------------------------------------------------------------------+ //--- inputs for expert input string Expert_Title ="Candles_Smoothed"; // Document name ulong Expert_MagicNumber =29976; // bool Expert_EveryTick =false; // //--- inputs for main signal input int Signal_ThresholdOpen =40; // Signal threshold value to open [0...100] input int Signal_ThresholdClose=20; // Signal threshold value to close [0...100] input double Signal_PriceLevel =0.0; // Price level to execute a deal input double Signal_StopLevel =50.0; // Stop Loss level (in points) input double Signal_TakeLevel =50.0; // Take Profit level (in points) input int Signal_Expiration =1; // Expiration of pending orders (in bars) input bool Signal__BuyPosOpen =true; // Candles_Smoothed() Permission to buy input bool Signal__SellPosOpen =true; // Candles_Smoothed() Permission to sell input bool Signal__BuyPosClose =true; // Candles_Smoothed() Permission to exit a long position input bool Signal__SellPosClose =true; // Candles_Smoothed() Permission to exit a short position input ENUM_TIMEFRAMES Signal__Ind_Timeframe=PERIOD_H1; // Candles_Smoothed() Timeframe input Smooth_Method Signal__MA_SMethod =4; // Candles_Smoothed() Smoothing method (1 - 10) input uint Signal__MA_Length =30; // Candles_Smoothed() Smoothing depth input uint Signal__MA_Phase =100; // Candles_Smoothed() Smoothing parameter input uint Signal__SignalBar =1; // Candles_Smoothed() Bar index for the entry signal input double Signal__Weight =1.0; // Candles_Smoothed() Weight [0...1.0] //--- inputs for money input double Money_FixLot_Percent =10.0; // Percent input double Money_FixLot_Lots =0.1; // Fixed volume
Em nosso caso, isso foi feito com a variável de entrada Signal__MA_SMethod.
Você pode acelerar significativamente a modificação se você abrir as duas versões de código (ASCtrendSignal.mqh e BykovTrendSignal.mqh) simultaneamente no editor (posicionando uma delas ao lado esquerdo e a outra ao lado direito) e compará-las cuidadosamente.
Conclusão
Incluímos uma quantidade suficiente de Expert Advisors baseados no sistema de negociação de semáforo no arquivo Experts.zip, anexo a este artigo, para permitir que criadores iniciantes de Expert Advisors possam compreender facilmente todas as características da escrita desse código ou, pelo menos, trabalhar com Expert Advisors pronto para uso, os quais utilizam indicadores muito populares.
Todos os Expert Advisors anexos são adicionalmente apresentados como módulos de treinamento para aqueles que desejam usar o gerador de estratégias de negociação como base para os seus próprios sistemas de negociação. Esses módulos estão localizados em MySignals.zip, enquanto que os sistemas de negociação baseados neles podem ser encontrados em Expertsez.zip. Os indicadores utilizados nos Expert Advisors estão em Indicators.zip. Os caminhos para extração dos arquivos são os seguintes:
- Experts.zip: "\MQL5\Experts\";
- Expertsez.zip: "\MQL5\Experts\";
- MySignals.zip: "\MQL5\Include\Expert\Signal\MySignals\";
- Indicators.zip: "\MQL5\Indicators\";
- SmoothAlgorithms.mqh: "\Include\";
- TradeAlgorithms.mqh: "\Include\".
Reinicie o MetaEditor, abra a janela do navegador, clique com o botão direito do mouse na etiqueta MQL5 e selecione "Compilar" no menu pop-up.
O arquivo SmoothAlgorithms.mqh é necessário para a compilação de alguns indicadores do arquivo Indicators.zip, enquanto que o arquivo TradeAlgorithms.mqh é necessário para a compilação de todos os Expert Advisors do arquivo Experts.zip.
Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/358
![Crie o seu próprio robô de negociação em 6 passos!](https://c.mql5.com/2/0/make_trade_signals.png)
![Abordagem orientada a objetos para construção de painéis de múltiplos períodos de tempo e múltiplas moedas](https://c.mql5.com/2/0/Multi-Currency-Panels_MQL5.png)
![Visualizar uma estratégia no Tester do MetaTrader 5](https://c.mql5.com/2/0/trade_robot_in_Backtester.png)
![Os Fundamentos da programação orientada a objetos](https://c.mql5.com/2/0/OOP_avatar.png)
![MQL5 - Linguagem para estratégias de negociação inseridas no terminal do cliente MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- 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