English Русский 中文 Español Deutsch 日本語
preview
Desenvolvendo um EA de negociação do zero (Parte 29): Plataforma falante

Desenvolvendo um EA de negociação do zero (Parte 29): Plataforma falante

MetaTrader 5Exemplos | 2 setembro 2022, 14:55
892 0
Daniel Jose
Daniel Jose

1.0 - Introdução

Que tal deixar o EA mais divertido ? Operar mercados financeiros costuma ser uma atividade extremamente chata e monótona, mas podemos deixar as coisas um pouco menos monótonas, apesar de que isto pode ser perigoso caso você tenha algum problema que lhe faça ficar viciado, pode ser que a coisa fique um pouco menos chata.

Então fica o alerta: NÃO utilize as modificações presentes neste artigo caso você esteja vendo o mercado como um jogo, pois existe risco real de perdas muito grandes.

Apesar do aviso acima parecer uma piada, ou brincadeira, a verdade é que algumas modificações no EA, fazem com que ele se torne perigoso para algumas pessoas que tem propensão ao vicio de jogos em geral.

Algumas das mudanças que serão feitas aqui, visam um aumento na estabilidade e no desempenho geral do EA, mas caso você queira manter elas, tudo bem. Mas com o sistema de ordens que foi criado e que esta presente no EA, algumas coisas podem ser retiradas sem nenhum tipo de prejuízo para um operador mais experiente, então sinta-se a vontade em retirar ou manter as coisas, ou até mesmo modificá-las.


2.0 - Removendo o Chart Trade

O Chart Trade é algo que em um sistema de ordens menos complexo do que o existente no nosso EA ainda faz sentido, mas no caso do EA que esta sendo desenvolvido, e na atual estagio de desenvolvimento, já não faz sentido ter um Chart Trade no gráfico, podemos retira-lo, mas caso você deseje poderá manter o mesmo, isto com a edição de apenas 1 único comando. Sim isto mesmo, eu gosto de deixar as coisas bastante simples, para ser possível mudá-las ou não de forma bastante rápida e sem gerar nenhum tipo de stress durante estas mudanças, como problemas no código ou falhas catastróficas feitas em pontos críticos.

Bem para controlar de forma o mais rápida possível e ao mesmo tempo de forma segura, dentro do código do EA, adicionamos a seguinte definição:

#define def_INTEGRATION_CHART_TRADER            // Integra o chart trader ao EA ...

caso esta definição não exista, ou seja transformada em um comentário, o CHART TRADE não será compilado junto com o EA, mas vamos ver quais são os pontos afetados por esta definição, o primeiro e mais obvio, as includes:

#ifdef def_INTEGRATION_CHART_TRADER
        #include <NanoEA-SIMD\SubWindow\C_TemplateChart.mqh>
#endif 

O código acima não esta dentro do arquivo do EA, e sim do arquivo C_IndicatorTradeView.mqh, mas para o compilador a definição será vista em todos os pontos do código a serem compilados, então não precisamos nos preocupar em reajustar o código, apenas criamos a definição em um ponto fácil de encontrar, no caso dentro do código do EA e utilizamos ela onde for preciso.

Mas vamos continuar por um tempo dentro do arquivo C_IndicatorTradeView.mqh. Já que poderemos compilar um EA sem o Chart Trade, temos que nos organizar de forma a acessar os dados definidos na caixa de mensagem de inicialização do EA, estes podem ser visto na imagem abaixo:

Lembre-se temos que acessar estes dados, antes transferimos estes para dentro do Chart Trade e quando houve-se necessidade de saber deles, íamos no Chart Trade e os buscávamos, mas agora sem o Chart Trade teremos que seguir um outro caminho para acessar estes mesmos dados.

No arquivo C_IndicatorTradeView.mqh estes valores são necessários em apenas e somente em um único local, é este é no momento em que iremos criar o indicador 0 que é usado para mostrar onde a ordem pendente será posicionada, este ponto esta dentro da rotina DispatchMessage, e pode ser visto no fragmento baixo:

// ... Código anterior ...

                                        case CHARTEVENT_MOUSE_MOVE:
                                                Mouse.GetPositionDP(dt, price);
                                                mKeys   = Mouse.GetButtonStatus();
                                                bEClick  = (mKeys & 0x01) == 0x01;    //Clique esquerdo
                                                bKeyBuy  = (mKeys & 0x04) == 0x04;    //SHIFT Pressionada
                                                bKeySell = (mKeys & 0x08) == 0x08;    //CTRL Pressionada
                                                if (bKeyBuy != bKeySell)
                                                {
                                                        if (!bMounting)
                                                        {
#ifdef def_INTEGRATION_CHART_TRADER
                                                                m_Selection.bIsDayTrade = Chart.GetBaseFinance(m_Selection.vol, valueTp, valueSl);
#else 
                                                                m_Selection.vol = EA_user20 * Terminal.GetVolumeMinimal();
                                                                valueTp = EA_user21;
                                                                valueSl = EA_user22;
                                                                m_Selection.bIsDayTrade = EA_user23;
#endif 
                                                                valueTp = Terminal.AdjustPrice(valueTp * Terminal.GetAdjustToTrade() / m_Selection.vol);
                                                                valueSl = Terminal.AdjustPrice(valueSl * Terminal.GetAdjustToTrade() / m_Selection.vol);
                                                                m_Selection.it = IT_PENDING;
                                                                m_Selection.pr = price;
                                                        }

// ... Restante do código ...

Observem as linhas em destaque, não adianta procurar estes valores EA_userXX dentro deste arquivo, eles não estão aqui, eles vem do código do EA, e podem ser visto no fragmento abaixo:

#ifdef def_INTEGRATION_CHART_TRADER
        input group "Chart Trader"
#else 
        input group "Base Operacional do EA"
#endif 
input int       EA_user20   = 1;     //Fator de alavancagem
input double    EA_user21   = 100;   //Take Profit ( FINANCEIRO )
input double    EA_user22   = 81.74; //Stop Loss ( FINANCEIRO )
input bool      EA_user23   = true;  //Day Trade ?

Com isto já temos um controle da forma como seria feito caso o Chart Trade estivesse no gráfico, notem que praticamente não mudamos em nada o código, apenas levamos os dados necessários que são definidos pelo usuário para dentro do local correto, algumas pessoas podem achar desnecessário esta configuração por parte do operador durante o carregamento do EA, e isto de certa forma é verdade, já que o sistema de ordens permite que ajustemos todos as variáveis sem nenhuma dificuldade, então você poderia definir um valor mínimo como fator de alavancagem e manter tanto o STOP quanto o TAKE em 0, e as operações iniciais como sendo Day Trade, e isto lá na função DispatchMessage da classe C_IndicatorTradeView, pois isto não iria afetar em nada o sistema, pois o operador pode modificar a ordem que esta no gráfico e depois enviar ela para o servidor, este tipo de modificação fica ao seu critério, já que isto é algo bastante pessoal.


2.0.1 - Ajustando algumas coisas

Antes de voltarmos a parte que retiramos o Chart Trade, existe um outra coisa que precisamos fazer, e isto irá melhorar a estabilidade do EA de forma geral.

Vamos fazer o seguinte, na classe C_IndicatorTradeView, definiremos uma estrutura de dados privativa, que pode ser vista abaixo:

struct st01
{
        bool    ExistOpenPosition,
                SystemInitilized;
}m_InfoSystem;

esta será inicializada no código abaixo:

void Initilize(void)
{
        static int ot = 0, pt = 0;
                                
        m_InfoSystem.ExistOpenPosition = false;
        m_InfoSystem.SystemInitilized = false;
        ChartSetInteger(Terminal.Get_ID(), CHART_SHOW_TRADE_LEVELS, false);
        ChartSetInteger(Terminal.Get_ID(), CHART_DRAG_TRADE_LEVELS, false);                             
        if ((ot != OrdersTotal()) || (pt != PositionsTotal()))
        {
                ObjectsDeleteAll(Terminal.Get_ID(), def_NameObjectsTrade);
                ChartRedraw();
                for (int c0 = ot = OrdersTotal(); c0 >= 0; c0--)  IndicatorAdd(OrderGetTicket(c0));
                for (int c0 = pt = PositionsTotal(); c0 >= 0; c0--) IndicatorAdd(PositionGetTicket(c0));
        }
        m_InfoSystem.SystemInitilized = true;
}

Por que estamos criando e inicializando estes dados aqui ?!?! Calma, lembre-se que o MetaTrader 5 envia EVENTOS para dentro do EA, e um destes eventos é o OnTick, de certa forma em sistemas mais simples não existe muitos problemas, mas conforme o sistema vai ficando cada vez mais complexo, temos que cuidar para que as coisas funcionem de forma adequada, e pode acontecer do MetaTrader 5 enviar eventos para dentro do EA antes mesmo do EA esta realmente preparado pra tratar tais eventos, então garantimos que o EA esteja preparado ao criar certas variáveis que podem indicar em que nível de funcionamento o EA se encontra, e caso este não esteja completamente pronto os eventos disparados pelo MetaTrader 5 deverão ser ignorados até que o EA de fato possa responder de forma adequada a tais eventos.

O ponto mais critico de todos é visto no código logo a seguir:

inline double SecureChannelPosition(void)
                        {
                                static int nPositions = 0;
                                double Res = 0;
                                ulong ticket;
                                int iPos = PositionsTotal();
                                
                                if (!m_InfoSystem.SystemInitilized) return 0;
                                if ((iPos != nPositions) || (m_InfoSystem.ExistOpenPosition))
                                {
                                        m_InfoSystem.ExistOpenPosition = false;
                                        for (int i0 = iPos - 1; i0 >= 0; i0--) if (PositionGetSymbol(i0) == Terminal.GetSymbol())
                                        {
                                                m_InfoSystem.ExistOpenPosition = true;
                                                ticket = PositionGetInteger(POSITION_TICKET);
                                                if (iPos != nPositions) IndicatorAdd(ticket);
                                                SetTextValue(ticket, IT_RESULT, PositionGetDouble(POSITION_VOLUME), Res += PositionGetDouble(POSITION_PROFIT), PositionGetDouble(POSITION_PRICE_OPEN));
                                        }
                                        nPositions = iPos;
                                }
                                return Res;
                        };

Os pontos em destaque não existiam antes, então em alguns momentos coisas estranhas poderiam acontecer, mas agora temos os testes necessários para garantir que nada de anormal passe desapercebido.

Esta questão de testar tudo e cada possibilidade é algo bastante complicado, já que muitos testes ajuda a garantir que o sistema fique bastante estável, mas também pode complica seja no momento de se fazer manutenção ou mudanças no código, já que alguns testes tem que ser feitos em uma determinada sequência lógica para de fato serem efetivos, e isto é algo bastante custoso de ser feito.

Mas observem que ao fazermos o teste de que se existe ou não uma posição no ativo que o EA esta acompanhando, nos permite dar uma certa agilidade para ele, ainda mais quando o MetaTrader 5 esta com diversos ativos abertos e cada um tendo uma quantidade de posições que irão aparecer para o EA, mas filtrando isto aqui, eliminamos o laço de forma que o EA somente irá executar o código dentro do laço se isto realmente for necessário, caso contrário iremos reduzir um pouco o tempo de processamento que o EA irá consumir, é pouco, mas já faz alguma diferença em casos bastante extremos.


2.0.2 - Extirpando o Chart Trade do EA

Bem, agora que fizemos a modificação na classe C_IndicatorTradeView, podemos voltar a focar no código do EA, e retirar o Chart Trade do código. A primeira coisa a ser feita é remover ele do código OnInit, vamos ver como fazer isto:

int OnInit()
{       
        Terminal.Init();

#ifdef def_INTEGRATION_WITH_EA
        WallPaper.Init(user10, user12, user11);
        VolumeAtPrice.Init(user32, user33, user30, user31);
        TimesAndTrade.Init(user41);
        EventSetTimer(1);
#endif 

        Mouse.Init(user50, user51, user52);
        
#ifdef def_INTEGRATION_CHART_TRADER
        static string   memSzUser01 = "";
        if (memSzUser01 != user01)
        {
                Chart.ClearTemplateChart();
                Chart.AddThese(memSzUser01 = user01);
        }
        Chart.InitilizeChartTrade(EA_user20 * Terminal.GetVolumeMinimal(), EA_user21, EA_user22, EA_user23);
        TradeView.Initilize();
        OnTrade();
#else 
        TradeView.Initilize();
#endif 
   
        return INIT_SUCCEEDED;
}

Todo o código em Verde será substituído pelo código em Azul, caso não usemos o Chart Trade, pode parecer que não faz muita diferença, que foi apenas uma mudança no tamanho do executável, mas não é somente isto, observem que junto com o código do Chart Trade removemos também um evento OnTrade, agora este evento não será mais necessário para o EA e ele não irá tratar deste evento.

Mas você é louco ?!?! Como pode retirar o evento OnTrade do EA ?!?! E agora como iremos tratar os eventos de negociação ?!?! Estes eventos serão tratados pelo evento OnTradeTransaction, e este tratado de uma forma mais eficiente que o evento OnTrade, ou seja o EA ficará mais simples e consequentemente mais robusto.

Um outro ponto que também sofre mudanças é a rotina que pode ser vista logo abaixo:

void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
        Mouse.DispatchMessage(id, lparam, dparam, sparam);
#ifdef def_INTEGRATION_WITH_EA
        switch (id)
        {
                case CHARTEVENT_CHART_CHANGE:
                        Terminal.Resize();
                        WallPaper.Resize();
                        TimesAndTrade.Resize();
        break;
        }
        VolumeAtPrice.DispatchMessage(id, sparam);
#endif 

#ifdef def_INTEGRATION_CHART_TRADER
        Chart.DispatchMessage(id, lparam, dparam, sparam);
#endif 

        TradeView.DispatchMessage(id, lparam, dparam, sparam);  
}

Caso não exista nenhuma integração dentro do EA, as únicas linhas que realmente será compiladas estão em destaque, já que estes eventos costumam ser bastante constantes, quanto mais eficiente for o tratamento destes eventos melhor, muitas vezes eles irão concorrer com um outro evento que o MetaTrader 5 irá disparar para o EA tratar, e este outro é visto logo abaixo:

void OnTick()
{
#ifdef def_INTEGRATION_CHART_TRADER
        Chart.DispatchMessage(CHARTEVENT_CHART_CHANGE, 0, TradeView.SecureChannelPosition(), C_Chart_IDE::szMsgIDE[C_Chart_IDE::eRESULT]);
#else 
        TradeView.SecureChannelPosition();
#endif 

#ifdef def_INTEGRATION_WITH_EA
        TimesAndTrade.Update();
#endif 
}

Este evento é um verdadeiro PESADELO, ele costuma ser chamado diversas vezes, e em alguns casos várias vezes em menos de 1 segundo. Mas com as mudanças feitas no código da classe C_IndicatorTradeView, o tratamento deste evento é ligeiramente mais eficiente, mas no futuro iremos melhorar um pouco mais esta eficiência, mas por enquanto isto já será suficiente.

Pois bem, depois de todas estas mudanças o Chart Trade não será integrado ao EA, você pode tornar o Chart Trade um indicador, e isto terá alguns benefícios, ao mesmo tempo que mantemos o sistema do EA voltado apenas para o seu trabalho principal. tratar, posicionar e manter o sistema de ordens dentro de um gerenciamento adequado. Mas como o transporte do Chart Trade para dentro de um indicador envolve algumas mudanças extras, não irei mostrar agora como fazer isto, esta transferência será vista em outro momento. Mas sim temos como levar o Chart Trade para dentro de um indicador e ainda assim conseguir enviar ordens por ele.


3.0 - Adicionando Sons

Muitas vezes não ficamos de fato olhando o gráfico, mas queremos saber o que esta acontecendo, uma das forma de sermos alertados sobre algo é via sonora, e este é um dos melhores tipos de alerta pois realmente nos chama a atenção de forma imediata e mutas vezes já saberemos como agir apenas ouvindo o alerta, sem precisar de nenhuma outra mensagem.

Então vamos aprender a colocar, apenas alguns e bem básicos, alertas sonoros, e em alguns casos uma frase nos dizendo algo especifico, mas apesar do que irei mostrar aqui e disponibilizar no anexo ser algo bastante básico, talvez isto lhe motive a aumentar a quantidade deste mesmos alertas e avisos, a ponto de não ter que ficar perdendo tempo lendo mensagens, já que um som muitas vezes pode lhe indicar algum evento especifico, e isto irá lhe dar um ganho em agilidade em momentos específicos de negociação, acreditem isto faz muita diferença.

A primeira coisa a ser feita é criar um novo arquivo que irá conter uma nova classe, e esta irá dar suporte e isolar o nosso sistema de som. Feito isto podemos começar a produzir a coisas de forma bastante sustentável. A classe a ser criada pode ser vista na integra no código logo abaixo:

class C_Sounds
{
        protected:
                enum eTypeSound {TRADE_ALLOWED, OPERATION_BEGIN, OPERATION_END};
        public  :
//+------------------------------------------------------------------+
inline bool PlayAlert(const int arg)
                {
                        return PlaySound(StringFormat("NanoEA-SIMD\\RET_CODE\\%d.wav", arg));
                }
//+------------------------------------------------------------------+
inline bool PlayAlert(const eTypeSound arg)
                {
                        string str1;
        
                        switch (arg)
                        {
                                case TRADE_ALLOWED   : str1 = def_Sound00; break;
                                case OPERATION_BEGIN : str1 = def_Sound01; break;
                                case OPERATION_END   : str1 = def_Sound02; break;
                                defaultreturn false;
                        }
                        PlaySound("::" + str1);
                        
                        return true;
                }
//+------------------------------------------------------------------+
};

Apesar da extrema simplicidade deste código, temos algo bastante interessante aqui. Vejam que estamos sobrescrevendo a função PlayAlert, de forma a termos 2 versões da mesma função. E por que disto ?!?! O motivo é por conta da forma como nosso sistema de som irá funcionar devemos ter estas duas variações. No caso da primeira versão da função, iremos reproduzir um som que esta em arquivo, e na segunda versão iremos reproduzir o som que faz parte do EA, sendo um recurso do mesmo. Agora tem uma coisa que muitos talvez não saibam como fazer, que é reproduzir sons diretamente dos arquivos de áudio, mas não se preocupem, irei mostrar como você deve proceder para conseguir fazer isto. O motivo da primeira versão é que algumas pessoas podem querer colocar a sua própria voz, ou algum outro som como alerta, e trocá-lo a qualquer momento, e para fazer isto não será preciso recompilar o EA, na verdade você pode trocar estes sons mesmo com o EA estando em execução dentro do MetaTrader 5, que a partir do momento em que o som tiver que ser executado, o EA irá utilizar a versão mais recente que você colocou, então bastará trocar o arquivo de áudio por um outro que você desejar, que o EA nem irá notar a diferença ou a mudança, e isto ajuda bastante. Mas existe um outro motivo, que será visto ao olhar o código do EA.

De fato, a primeira versão é usada em um local bastante especifico, e este pode ser visto no fragmento da classe abaixo em destaque:

class C_Router
{
        protected:
        private  :
                MqlTradeRequest TradeRequest;
                MqlTradeResult  TradeResult;
//+------------------------------------------------------------------+
inline bool Send(void)
        {
                if (!OrderSend(TradeRequest, TradeResult))
                {
                        if (!Sound.PlayAlert(TradeResult.retcode))Terminal.MsgError(C_Terminal::FAILED_ORDER, StringFormat("Error Number: %d", TradeResult.retcode));
                        
                        return false;
                }
                return true;
        }

// ... Restante da classe ....

Pensem só na quantidade de trabalho que seria necessário para tratar todos os erros possíveis de retorno do servidor de negociação, seria quase uma insanidade, mas ao gravar um arquivo de áudio, e ao colocar o nome dele de forma a refletir o valor que esta sendo retornado pelo servidor de negociação, o EA saberá qual arquivo deverá ter seu áudio executado, isto facilita em muito a nossa vida, pois iremos apenas indicar qual é o arquivo com base no valor de retorno do servidor, e o EA iria procurar e reproduzir estes mesmo arquivo, nos dando um alerta sonoro, ou uma mensagem em voz para que possamos saber exatamente o que aconteceu. Maravilhoso não é mesmo ?!?! Pois agora a plataforma irá nos informar de forma bastante clara o que aconteceu, ou o que esta errado fazendo com que as ordens sejam rejeitadas, e isto de forma bastante adequada e que lhe represente algo especifico, algo que pode ser exclusivo e único a sua forma de operar e agir no mercado. Vejam o quanto de agilidade você estará ganhando, pois no mesmo arquivo de áudio você pode deixar claro como resolver o problema.

Mas temos também um segundo modo de funcionamento da função, que é aquele que os sons são armazenados dentro do executável do EA, esta é a segunda versão da mesma função, e será usada neste atual estágio, em 3 locais diferentes, para indicar 3 tipos de eventos diferentes. O primeiro local pode ser visto no fragmento de código logo abaixo:

int OnInit()
{
        if (!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
        {
                Sound.PlayAlert(C_Sounds::TRADE_ALLOWED);
                return INIT_FAILED;
        }
        
        Terminal.Init();

// ... Restante do código ...

o que este código faz é verificar se o AlgoTrading esta ou não habilitado na plataforma, caso você esqueça de habilitar ele o EA irá lhe informar isto, não irá ficar disponível para nenhuma operação. Para verificar se ele estau ou não habilitado, basta observar o indicador presente na plataforma, e este é visto no ponto mostrado na imagem abaixo:


o segundo ponto em que iremos usar um som de recurso, é visto no fragmento abaixo:

void CreateIndicator(ulong ticket, eIndicatorTrade it)
{
        string sz0;
                                
        switch (it)
        {
                case IT_TAKE    : macroCreateIndicator(it, clrForestGreen, clrDarkGreen, clrNONE); break;
                case IT_STOP    : macroCreateIndicator(it, clrFireBrick, clrMaroon, clrNONE); break;
                case IT_PENDING:
                        macroCreateIndicator(it, clrCornflowerBlue, clrDarkGoldenrod, def_ColorVolumeEdit);
                        m_BtnCheck.Create(ticket, sz0 = macroMountName(ticket, it, EV_CHECK), def_BtnCheckEnabled, def_BtnCheckDisabled);
                        m_BtnCheck.SetStateButton(sz0, true);
                        macroInfoBase(IT_PENDING);
                        break;
                case IT_RESULT  :
                        macroCreateIndicator(it, clrSlateBlue, clrSlateBlue, def_ColorVolumeResult);
                        macroInfoBase(IT_RESULT);
                        Sound.PlayAlert(C_Sounds::OPERATION_BEGIN);
                        m_InfoSystem.ExistOpenPosition = true;
                        break;
        }
        m_BtnClose.Create(ticket, macroMountName(ticket, it, EV_CLOSE), def_BtnClose);
}

Toda a vez que um indicador de posição for criado, um som indicando isto será reproduzido, isto facilita muito a nossa vida, já que saberemos que uma ordem pendente passou a ser uma posição, e que devemos começar a presta atenção a ela.

O terceiro e último ponto onde temos um som de recurso, é quando uma posição esta sendo fechada por qualquer motivo, isto é feito em um ponto bastante especifico que é o código abaixo:

inline void RemoveIndicator(ulong ticket, eIndicatorTrade it = IT_NULL)
{
        ChartSetInteger(Terminal.Get_ID(), CHART_EVENT_OBJECT_DELETE, false);
        if ((it == IT_NULL) || (it == IT_PENDING) || (it == IT_RESULT))
        {
                if (macroGetPrice(ticket, IT_RESULT, EV_LINE) > 0) Sound.PlayAlert(C_Sounds::OPERATION_END);
                ObjectsDeleteAll(Terminal.Get_ID(), StringFormat("%s%c%llu%c", def_NameObjectsTrade, def_SeparatorInfo, ticket, (ticket > 1 ? '*' : def_SeparatorInfo)));
        } else ObjectsDeleteAll(Terminal.Get_ID(), StringFormat("%s%c%llu%c%c", def_NameObjectsTrade, def_SeparatorInfo, ticket, def_SeparatorInfo, (char)it));
        ChartSetInteger(Terminal.Get_ID(), CHART_EVENT_OBJECT_DELETE, true);
        m_Selection.ticket = 0;
        Mouse.Show();
        ChartRedraw();
}

Você pode pensar que ao remover o EA este irá emitir o som de fechamento de posição, mas não, isto não irá acontecer, pois a linha de preço ainda estará presente no sistema, mas quando a posição é fechada irá acontecer algo diferente, e a linha do preço da posição estará na posição de preço 0, neste momento teremos o som sendo emitido, nos indicando que a posição foi fechada.

Lembrando que estes sons que são recursos do EA irão com ele para onde o executável for, não podendo ser modificados sem que o código seja recompilado, por conta disto são mais limitados, mas ao mesmo tempo ajudam a portar o EA para outros locais sem que precisemos levar arquivos de áudio junto.

Mas nos caso dos sons usados para nos alertar sobre falhas ou erros, estes são diferentes, devendo ser transportados a parte, e colocados em um local predeterminado para que possam funcionar quando for preciso.

No código em anexo, você terá uma pasta chamada SOUNDS. Não adianta deixar esta pasta na mesma pasta onde estará os códigos, pois os sons contidos nesta pasta não serão reproduzidos, você tem que transportá-la para uma outra localização, esta localização pode ser facilmente encontrada, caso você não saiba onde ela esta, executando o seguinte script, não se preocupem, ele estará junto com o restante do código:

#property copyright "Daniel Jose"
//+------------------------------------------------------------------+
void OnStart()
{
        Print(TerminalInfoString(TERMINAL_PATH));
}
//+------------------------------------------------------------------+

Quando você executar este script irá ter uma informação na caixa de ferramentas, esta indica a localização que iremos usar, um exemplo de resultado da execução pode ser visto na imagem abaixo:

O que você irá fazer é o seguinte:

  1. Abra o anexo do Artigo;
  2. Abra o Explorador de arquivos;
  3. Navegue de forma a ir até a pasta indicada na imagem acima;
  4. Copie o conteúdo da pasta SOUNDS presente no anexo para a pasta acima;
  5. Caso deseje elimine os 3 arquivos ( WARRING, BEGIN, END ) pois eles serão compilados junto com o EA;
  6. Troque o conteúdo dos arquivos .WAV se desejar por algo que lhe seja mais agradável, mas tomando o cuidado de deixar ele com o mesmo nome;
  7. Use o EA no Terminal MetaTrader 5 e seja feliz ...
Mas lembre-se de que para os sons ( WARRING, BEGIN, END ) sejam compilados para dentro do EA, você deverá ter no diretório MQL5 de códigos, a pasta SOUNDS com estes mesmos sons, caso contrário, eles não irão ser integrados ao código do EA.


4.0 - Conclusão

Neste artigo você aprendeu como adicionar sons personalizados no sistema de EA.  É bem verdade que aqui fizemos o uso de um sistema bastante simples a fim de conseguir demonstrar como fazer isto de fato, mas não ficamos limitados apenas ao EA podemos usar isto também em indicadores ou mesmo scripts.

O grande detalhe é que se você usar os mesmos conceitos e ideias propostas aqui, poderá gravar mensagens de voz dizendo, ou alertando sobre algo. E quando o EA, ou qualquer outro processo que estiver sendo executado pelo MetaTrader 5 e que utilize o sistema de som, vier a disparar por meio de gatilhos mostrados no artigo, você ou outro operador irá receber a tal mensagem sonora lhe dizendo ou alertando sobre algum tipo de medida que você já havia previsto e deverá ser adotada.

E isto não como texto, mas sim uma mensagem de voz, o que torna a coisa bem mais eficaz, já que você pode explicar rapidamente a quem esta usado o sistema o que deverá ser feito, ou qual foi a causa que gerou tal mensagem.

Mas este sistema de fato não fica somente neste esquema, podemos ir além do que foi demonstrado aqui, mas a ideia é justamente esta, permitir que tenhamos na plataforma uma aliada, já que quanto temos uma interação vocal com o operador podemos passar uma mensagem que pode ser melhor compreendida do que apenas um texto. Ou seja o que irá te limitar é apenas a sua criatividade ...
   


Arquivos anexados |
EA_-_h_Parte_29_6.zip (14465.62 KB)
Metamodelos em aprendizado de máquina e negociação: Tempo original das ordens de negociação Metamodelos em aprendizado de máquina e negociação: Tempo original das ordens de negociação
Metamodelos em aprendizado de máquina: Criação automática de sistemas de negociação com quase nenhum envolvimento humano, o próprio modelo decide como operar e quando operar.
DoEasy. Controles (Parte 8): Objetos básicos do WinForms por categoria, controles GroupBox e CheckBox DoEasy. Controles (Parte 8): Objetos básicos do WinForms por categoria, controles GroupBox e CheckBox
Neste artigo, veremos como criar dois objetos WinForms, especificamente GroupBox e CheckBox, e também geraremos objetos básicos para categorias de objetos WinForms. Todos os objetos criados ainda são estáticos, ou seja, não possuem a funcionalidade de interação com o mouse.
Experiências com redes neurais (Parte 1): Lembrando a geometria Experiências com redes neurais (Parte 1): Lembrando a geometria
As redes neurais são tudo para nós. Vamos ver se isso é verdade na prática. Para tal, vamos fazer experiências e adotar abordagens não-convencionais. Vamos escrever também um sistema de negociação lucrativo. A explicação vai ser simples.
Redes neurais de maneira fácil (Parte 17): Redução de dimensionalidade Redes neurais de maneira fácil (Parte 17): Redução de dimensionalidade
Continuamos a estudar modelos de inteligência artificial, em particular, algoritmos de aprendizado não supervisionados. Já nos encontramos com um dos algoritmos de agrupamento. E neste artigo quero compartilhar com vocês outra maneira de resolver os problemas de redução de dimensionalidade.