Español
preview
Desenvolvendo um sistema de Replay (Parte 77): Um novo Chart Trade (IV)

Desenvolvendo um sistema de Replay (Parte 77): Um novo Chart Trade (IV)

MetaTrader 5Exemplos | 4 dezembro 2024, 09:29
199 0
Daniel Jose
Daniel Jose

Introdução

No artigo anterior Desenvolvendo um sistema de Replay (Parte 76): Um novo Chart Trade (III), expliquei a parte realmente importante do código DispatchMessage. E comecei a explicar como o processo de comunicação, ou protocolo de comunicação deverá ser criado.

Porém, antes de realmente começar este artigo, vamos fazer primeiramente uma pequena mudança, naquele mesmo código visto no artigo anterior. Tudo que foi explicado lá continua valendo. Então vamos ao tópico da mudança a ser feita. Já que o real interesse neste artigo será explorar uma outra coisa.


Estabilizando ainda mais o código DispatchMessage

Por conta de alguma falha na interação, entre o indicador de mouse e o Chart Trade, temos que mudar uma coisa aqui. De fato não consigo entender o verdadeiro motivo da interação as vezes falhar. Mas usando o fragmento logo abaixo, a falha desaparece.

259. //+------------------------------------------------------------------+
260.       void DispatchMessage(const int id, const long &lparam, const double &dparam, const string &sparam)
261.          {
262. #define macro_AdjustMinX(A, B)    {                          \
263.             B = (A + m_Info.Regions[MSG_TITLE_IDE].w) > x;   \
264.             mx = x - m_Info.Regions[MSG_TITLE_IDE].w;        \
265.             A = (B ? (mx > 0 ? mx : 0) : A);                 \
266.                                  }
267. #define macro_AdjustMinY(A, B)   {                           \
268.             B = (A + m_Info.Regions[MSG_TITLE_IDE].h) > y;   \
269.             my = y - m_Info.Regions[MSG_TITLE_IDE].h;        \
270.             A = (B ? (my > 0 ? my : 0) : A);                 \
271.                                  }
272.                               
273.             static short sx = -1, sy = -1, sz = -1;
274.             static eObjectsIDE obj = MSG_NULL;
275.             short   x, y, mx, my;
276.             double dvalue;
277.             bool b1, b2, b3, b4;
278.             ushort ev = evChartTradeCloseAll;
279.    
280.             switch (id)
281.             {
282.                case CHARTEVENT_CHART_CHANGE:
283.                   x = (short)ChartGetInteger(GetInfoTerminal().ID, CHART_WIDTH_IN_PIXELS);
284.                   y = (short)ChartGetInteger(GetInfoTerminal().ID, CHART_HEIGHT_IN_PIXELS);
285.                   macro_AdjustMinX(m_Info.x, b1);
286.                   macro_AdjustMinY(m_Info.y, b2);
287.                   macro_AdjustMinX(m_Info.minx, b3);
288.                   macro_AdjustMinY(m_Info.miny, b4);
289.                   if (b1 || b2 || b3 || b4) AdjustTemplate();
290.                   break;
291.                case CHARTEVENT_MOUSE_MOVE:
292.                   if ((*m_Mouse).CheckClick(C_Mouse::eClickLeft))
293.                   {                  
294.                      switch (CheckMousePosition(x = (short)lparam, y = (short)dparam))
295.                      {
296.                         case MSG_MAX_MIN:
297.                            if (sz < 0) m_Info.IsMaximized = (m_Info.IsMaximized ? false : true);
298.                            break;
299.                         case MSG_DAY_TRADE:
300.                            if ((m_Info.IsMaximized) && (sz < 0)) m_Info.IsDayTrade = (m_Info.IsDayTrade ? false : true);
301.                            break;
302.                         case MSG_LEVERAGE_VALUE:
303.                            if ((m_Info.IsMaximized) && (sz < 0)) CreateObjectEditable(obj = MSG_LEVERAGE_VALUE, m_Info.Leverage);
304.                            break;
305.                         case MSG_TAKE_VALUE:
306.                            if ((m_Info.IsMaximized) && (sz < 0)) CreateObjectEditable(obj = MSG_TAKE_VALUE, m_Info.FinanceTake);
307.                            break;
308.                         case MSG_STOP_VALUE:
309.                            if ((m_Info.IsMaximized) && (sz < 0)) CreateObjectEditable(obj = MSG_STOP_VALUE, m_Info.FinanceStop);
310.                            break;
311.                         case MSG_TITLE_IDE:
312.                            if (sx < 0)
313.                            {
314.                               DeleteObjectEdit();
315.                               ChartSetInteger(GetInfoTerminal().ID, CHART_MOUSE_SCROLL, false);
316.                               sx = x - (m_Info.IsMaximized ? m_Info.x : m_Info.minx);
317.                               sy = y - (m_Info.IsMaximized ? m_Info.y : m_Info.miny);
318.                            }
319.                            if ((mx = x - sx) > 0) ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_XDISTANCE, mx);
320.                            if ((my = y - sy) > 0) ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_YDISTANCE, my);
321.                            if (m_Info.IsMaximized)
322.                            {
323.                               m_Info.x = (mx > 0 ? mx : m_Info.x);
324.                               m_Info.y = (my > 0 ? my : m_Info.y);
325.                            }else
326.                            {
327.                               m_Info.minx = (mx > 0 ? mx : m_Info.minx);
328.                               m_Info.miny = (my > 0 ? my : m_Info.miny);
329.                            }
330.                            break;
331.                         case MSG_BUY_MARKET:
332.                            ev = evChartTradeBuy;
333.                         case MSG_SELL_MARKET:
334.                            ev = (ev != evChartTradeBuy ? evChartTradeSell : ev);
335.                         case MSG_CLOSE_POSITION:
336.                            if ((m_Info.IsMaximized) && (sz < 0))
337.                            {
338.                               string szTmp = StringFormat("%d?%s?%c?%d?%.2f?%.2f", ev, _Symbol, (m_Info.IsDayTrade ? 'D' : 'S'), m_Info.Leverage, 
339.                                                          FinanceToPoints(m_Info.FinanceTake, m_Info.Leverage), FinanceToPoints(m_Info.FinanceStop, m_Info.Leverage));                           
340.                               PrintFormat("Send %s - Args ( %s )", EnumToString((EnumEvents) ev), szTmp);
341.                               sz = x;
342.                               EventChartCustom(GetInfoTerminal().ID, ev, 0, 0, szTmp);
343.                            }
344.                            break;
345.                      }
346.                      if (sz < 0)
347.                      {
348.                         sz = x;
349.                         AdjustTemplate();
350.                         if (obj == MSG_NULL) DeleteObjectEdit();
351.                      }
352.                   }else
353.                   {
354.                      sz = -1;
355.                      if (sx > 0)
356.                      {
357.                         ChartSetInteger(GetInfoTerminal().ID, CHART_MOUSE_SCROLL, true);                  
358.                         sx = sy = -1;
359.                      }
360.                   }
361.                   break;
362.                case CHARTEVENT_OBJECT_ENDEDIT:
363.                   switch (obj)
364.                   {
365.                      case MSG_LEVERAGE_VALUE:
366.                      case MSG_TAKE_VALUE:
367.                      case MSG_STOP_VALUE:
368.                         dvalue = StringToDouble(ObjectGetString(GetInfoTerminal().ID, m_Info.szObj_Editable, OBJPROP_TEXT));
369.                         if (obj == MSG_TAKE_VALUE)
370.                            m_Info.FinanceTake = (dvalue <= 0 ? m_Info.FinanceTake : dvalue);
371.                         else if (obj == MSG_STOP_VALUE)
372.                            m_Info.FinanceStop = (dvalue <= 0 ? m_Info.FinanceStop : dvalue);
373.                         else
374.                            m_Info.Leverage = (dvalue <= 0 ? m_Info.Leverage : (short)MathFloor(dvalue));
375.                         AdjustTemplate();
376.                         obj = MSG_NULL;
377.                         ObjectDelete(GetInfoTerminal().ID, m_Info.szObj_Editable);
378.                         break;
379.                   }
380.                   break;
381.                case CHARTEVENT_OBJECT_CLICK:
382.                   if (sparam == m_Info.szObj_Chart) if ((*m_Mouse).CheckClick(C_Mouse::eClickLeft)) switch (obj = CheckMousePosition(x = (short)lparam, y = (short)dparam))
383.                   {
384.                      case MSG_DAY_TRADE:
385.                         m_Info.IsDayTrade = (m_Info.IsDayTrade ? false : true);
386.                         DeleteObjectEdit();
387.                         break;
388.                      case MSG_MAX_MIN:
389.                         m_Info.IsMaximized = (m_Info.IsMaximized ? false : true);
390.                         DeleteObjectEdit();
391.                         break;
392.                      case MSG_LEVERAGE_VALUE:
393.                         CreateObjectEditable(obj, m_Info.Leverage);
394.                         break;
395.                      case MSG_TAKE_VALUE:
396.                         CreateObjectEditable(obj, m_Info.FinanceTake);
397.                         break;
398.                      case MSG_STOP_VALUE:
399.                         CreateObjectEditable(obj, m_Info.FinanceStop);
400.                         break;
401.                   }
402.                   if (obj != MSG_NULL) AdjustTemplate();
403.                   break;
404.                case CHARTEVENT_OBJECT_DELETE:
405.                   if (sparam == m_Info.szObj_Chart) macro_CloseIndicator(C_Terminal::ERR_Unknown);
406.                   break;
407.             }
408.             ChartRedraw();
409.          }
410. //+------------------------------------------------------------------+

Fragmento do arquivo C_ChartFloatingRAD.mqh

Note que existem algumas linhas riscadas. Como por exemplo a linha 314 e 341. Tanto uma como a outra, foram movimentadas para dentro do teste presente na linha 346. Este visa estabilizar um problema que acontecia, quando se clicava em alguns dos controles. Observe que a variável sz, é usada em cada um dos objetos. Você nota isto ao observar as linhas 297, 300, 303, 306 e 309. Além dos testes que já existiam, nas linhas 312 e 336.

Comparando este código com o anterior, este visa de fato estabilizar a interação entre o indicador de mouse e o Chart Trade. Já que quando o indicador de mouse, era carregado primeiro. Alguns controles do Chart Trade, não respondiam de forma adequada. Sendo preciso, remover o indicador de mouse do gráfico, e logo em seguida, o recolocar no gráfico. Somente assim, os controles no Chart Trade, passavam a responder de forma correta. Algo estranho, diga-se de passagem.

Por conta disto, o evento CHARTEVENT_OBJECT_CLICK, deverá ser removido do código de processamento. Assim todas as linhas entre 381 e 403 deverão ser retiradas do código visto no artigo anterior. E já que tais mudanças, não trouxeram nenhuma real diferenciação, ao que foi explicado a respeito do código, visto no artigo anterior. Poderemos passar para o próximo tópico. Que de fato é o tema principal deste artigo.


Entendendo o planejamento sobre o protocolo de mensagens

Como não sei, o que você caro leitor, de fato sabe sobre sistemas de comunicação, onde fazemos uso de computadores. Vou assumir que você não conhece absolutamente nada sobre o assunto. Caso este não seja o seu caso. Muito provavelmente o que irei de fato explicar, não irá de maneira alguma agregar algum conhecimento a você, podendo desta forma passar para o próximo tópico.

No artigo anterior, explique o motivo de você precisar converter valores números, em seu correspondente literal. Ou seja, se você precisa transferir o valor binário: 0001 0011 você deverá transformar isto, em uma string que represente o valor 19, ou seja você precisará transferir 2 bytes em vez de 1 byte. Apesar de parecer pouco eficiente, a ideia aqui, não é ser eficiente. Mas sim, garantir que a informação seja realmente passada, de maneira que seja corretamente compreendida. Se for possível fazer com eficiência, melhor. Mas a prioridade é que a correta informação seja de fato entendida do outro lado.

Como foi explicado no artigo anterior, iremos de fato usar o campo sparam. Agora temos que pensar o seguinte: Se a informação deverá ser passada dentro de uma única string. Como podemos fazer para reconhecer, quando uma informação termina e uma outra começa? Esta que é a verdadeira questão aqui.

Bolar ou planejar uma forma de se fazer isto. Você precisa colocar as informações de uma forma que depois, consiga recuperar elas. Existem diversas formas, diferentes e ao mesmo tempo, complementares de se fazer isto. Uma delas é colocando cada informação dentro de um array de tamanho fixo. Estes array, depois seriam concatenados formando assim uma string, que seria de fato transmitida. Esta abordagem tem vantagens e desvantagens.

A vantagem é que qualquer informação, poderia ser obtida a partir de um índex. Já que o array teria sempre um tamanho fixo. O que facilita indexar as informações. Mas da mesma forma que o uso de um array de tamanho fixo, facilita o acesso a qualquer informação dentro da string. Isto torna a string algo bastante ineficiente, se cada informação não fizer uso de todo o bloco do array. Posições vazias, iriam de fato ocupar banda, ou no nosso caso memória.

Para que você possa entender melhor, veja a imagem logo abaixo:

Image 1

Nesta imagem, o bloco em azul, corresponde ao carácter NULO, que sempre estará presente no final da string. Mostrando onde ela termina. Note que existe dois array de tamanho quatro. E que em um deles, temos blocos, ou melhor, posições, que se encontram vagas. É este tipo de coisa que dificulta o uso de um array de tamanho fixo.

Mas podemos fazer uma outra abordagem. E se em vez de colocar um array de tamanho fixo, colocássemos um array que daria o tamanho da informação esperada? Isto iria de fato, deixar a string bem mais adequada, facilitando muito a pesquisa e encontrar as informações que precisamos. Porém apesar deste tipo de abordagem ser muito boa. Ela tem um problema. Precisamos codificar mais. E ao criar mais códigos, precisamos testar os mesmos. E muitas das vezes, se a informação ultrapassar o limite que estabelecemos na implementação, teremos perda de informação durante a montagem da string. Na hipótese perfeita, podemos ver o que é mostrado na imagem logo abaixo:

Image 2

Igual ao que foi visto na primeira imagem. O bloco em azul, indica onde o carácter que marca o final da string se encontra. Note que aqui temos uma condição perfeita, onde cada uma das cores representa alguma informação que estará compactada dentro da string. Apesar de isto dificultar em alguns casos a descompactação da string, a fim de conseguir recuperar integralmente e de forma correta a informação original. Este caso parece bastante adequado. Porém, aqui especificamente. Cada um dos conjuntos terá um tamanho fixo. Então teríamos uma abordagem, que seria melhor do que a mostrada na primeira imagem. Porém, temos um problema. E este é: O que acontece se por exemplo a informação que deveria estar no conjunto verde, em vez de usar dois bytes, tivesse que usar três bytes?

Esta seria a pior das situações. Isto por que um dos bytes seria perdido durante a montagem do conjunto verde. Mas você pode pensar assim: E se o conjunto verde pudesse crescer para conter este byte extra. Poderíamos fazer isto? NÃO. Se você fizer isto, toda a informação que vier depois do conjunto verde ficaria comprometida. E o receptor não conseguiria de fato compreender que o conjunto verde, agora tem três e não dois bytes, que seria o esperado por ele.

Percebe agora, que esta parte da criação do protocolo de comunicação, não é assim algo tão banal. Se quem terá de decodificar a mensagem estiver esperando que cada conjunto tenha um dado tamanho. E durante a criação do conjunto, mudemos as regras, o receptor não conseguirá entender o que estamos tentando dizer. Precisamos então de uma abordagem um pouco diferente.

Então vamos pensar um pouco. E se ao invés de criar um bloco de tamanho fixo, criamos um de tamanho variável. Onde a informação poderia ter qualquer tamanho. Isto seria bem melhor não é mesmo? De certa forma sim. Mas temos um problema. Como dizer ao receptor da mensagem, quando um conjunto termina e outro começa? Agora temos um outro problema para resolver. E é neste ponto que você precisa pensar bem mais. Pois se você não pensar com bastante calma, sobre como está fazendo as coisas. Irá de fato transmitir uma mensagem que o receptor não conseguirá entender. Mesmo que ela esteja, na sua visão correta. Mas para o receptor, ela não está tão clara. Mas como assim?

Pense no seguinte: Cada seção da mensagem, poderá ter qualquer tamanho. O que nos permite, virtualmente, transferir qualquer tipo de informação. As informações precisam estar em uma determinada sequência. Seja ela qual for. Mas a sequência deverá ser sempre mantida. Até neste ponto tudo, ok. Não temos nenhum problema. A não ser o seguinte problema: Como dizer que uma seção terminou, e outra está começando?

Bem, como eu falei acima, esta é a parte complicada. Isto por que tudo dependerá do tipo de dados que estamos colocando na string. Se você colocar os dados, de forma a usar todos os 255 valores possíveis, em um byte. Claro que devemos evitar o carácter NULO, por isto 255 e não 256. Teremos um grande problema, que é como dizer que estamos dando uma outra informação dentro do bloco da string. Porém se reduzimos os valores a caracteres presentes entre os valores 32 e 127, teremos mais trabalho, com relação a montagem. Porém isto, nos permite usar qualquer valor entre 128 e 255 como um carácter de marcação.

Contudo, para nos aqui, podemos limitar as coisas ainda mais. Podemos usar apenas e somente os caracteres alfanuméricos, a fim de transmitir a informação desejada. Isto abre as portas para que possamos usar, sinais de pontuação, ou caracteres delimitadores, como forma de dizer quando uma informação, presente dentro da string completa, se inicia ou termina. E por que podemos fazer isto aqui? O motivo é que os dados que precisamos repassar, são basicamente informações sobre o nome do ativo, e alguns valores numéricos. Seja eles, o nível de alavancagem, seja os valores de take profit ou stop loss. Estes são configurados no Chart Trade, mas precisam ser repassados para o Expert Advisor.

Mas além destes valores, que são bastante simples, precisamos passar um outro. Sem bem que o MetaTrader 5 faz isto para nos. Mas como quero, garantir firmemente de que as coisas nunca sairão de fato do controle, vamos repassar no meio da string, a operação que estaremos de fato fazendo. Este tipo de coisa não seria de fato necessária.

Mas quero que você entenda o seguinte: Você não precisa, realmente usar todas as aplicações, em um único terminal. Você pode criar meios de comunicar, via protocolo de rede, as coisas. Assim em um computador, teríamos o terminal e em outra estação de trabalho, poderíamos ter todo um sistema de gerenciamento de posições e ordens. Desta forma, mesmo um computador modesto, daria conta de trabalhar como se fosse uma máquina bem mais moderna.

Mas não vou entrar nestas questões, neste momento. A ideia aqui é promover e entender como a comunicação irá de fato funcionar.


Unindo o melhor de cada mundo

O que vamos de fato fazer aqui, é a união, do que existe de melhor em cada uma das abordagens explicadas acima. Porém de um forma a poder usar os conceitos explicados no final do tópico anterior. Ou seja, vamos usar caracteres alfanuméricos, para transmitir a informação que precisamos, ao mesmo tempo, vamos deixar as coisas de forma que a informação poderá ser buscada via índex. Mas com um detalhe: A informação, poderá usar tantos caracteres, quantos forem necessários, para que ela, a informação, seja realmente repassada integralmente.

Para entender isto, observe a linha 338, no fragmento mostrado no começo deste artigo. Para deixar ainda mais claro, vamos ver um exemplo de envio pratico.

Image 3

Nesta imagem imediatamente acima, você pode ser um exemplo REAL de envio, via Chart Trade. Mas o que esta mensagem maluca, está de fato informando? Bem para entender, precisamos olhar o que está acontecendo na linha 338 do fragmento. Apesar de parecer confusa e bastante dispersa. Esta mensagem está seguindo um protocolo de envio. Aqui estamos de fato usando o melhor de dois mundos. Estamos permitindo que os blocos dentro da string tenham qualquer tamanho, ao mesmo tempo que conseguimos indexar de alguma forma as informações presentes na string.

Muito provavelmente, você não esteja entendendo, como esta indexação esteja ocorrendo. Ela realmente não é muito evidente. Mas ela existe. Observe o carácter D dentro da mensagem. Note que ele está sendo antecedido e precedido pelo mesmo carácter. E que temos apenas e somente um bloco neste ponto, que está sendo preenchido pelo carácter D. Este tipo de coisa, não acontece em nenhum outro ponto da mensagem. Isto então indica que este único carácter pode ser indexado de alguma forma. Mas isto ficará mais claro depois. No momento vamos entender o que está acontecendo aqui.

O primeiro bloco, que nesta mensagem em especial, contém um único carácter, indica qual o tipo de operação que deverá ser feita. Novamente, o MetaTrader 5, informará isto ao nosso programa Expert Advisor, como será visto depois. Mas aqui estou considerando o fato, de que o Chart Trade irá realmente se comunicar com o Expert Advisor, de qualquer maneira, seja via rede, via E-mail ou qualquer outra coisa. Por conta disto, estou informando o tipo de operação que deverá ser executada.

Um detalhe, este valor nove corresponde ao evento de compra a mercado. Mas ele poderá ser diferente, por exemplo, se neste bloco, tivéssemos o valor onze, isto iria de fato indicar um fechamento de todas as posições. E neste caso, o bloco teria dois caracteres, e não um como vemos neste exemplo acima. Mas por que o valor é nove, para compra e onze para fechamento das posições? De onde vem este valor? Este tipo de pergunta, é algo bastante válido. Veja que na linha 338, o primeiro valor a ser colocado na string é um valor ushort. Mas isto não explica o por que, de nove indicar compra e onze indicar fechamento? Sim, de fato isto não explica.

Mаs olhe a linha 278. De onde vem este valor? Este valor vem do arquivo de cabeçalho Defines.mqh. Agora preste atenção. No arquivo Defines.mqh, existe uma enumeração: EnumEvents. Tal enumeração se inicia no valor zero, e a cada novo elemento, o compilador incrementa um. Então contando a partir do primeiro evento que é evHideMouse. Temos o evento nove sendo evChartTradeBuy e o evento onze sendo evChartTradeCloseAll. Agora você, já sabe de onde vem estes valores que serão visto no começo da string. Eles derivam da enumeração EnumEvents.

Então vamos continuar. Note que todos os caracteres de interrogação estão marcados em violeta. O carácter NULO, que encerra a string está marcado em azul. Já que cada bloco, é de fato delimitado pelo carácter de interrogação. Podemos colocar quantos caracteres alfanuméricos forem necessários para enviar a mensagem. Só que alguns detalhes. Esta mensagem, precisa ser construída em uma dada sequência. Lembre-se: O receptor espera receber os dados em uma determinada ordem. Mesmo que possamos colocar as informações em uma ordem aleatória, o receptor, pelo menos nesta versão que irei de fato mostrar, não espera isto.

Então o próximo bloco de carácteres, informará o novo do ativo, em que estamos executando o pedido. Novamente, isto não seria necessário, se o Expert Advisor e o Chart Trade estiverem em um mesmo gráfico. Mas estou considerando que isto não estaria de fato ocorrendo.

Além do mais, futuramente, você verá que dá para usar estas informações da mensagem para fazer outras coisas. No caso do exemplo, o ativo em questão é BOVA11, que se trata de um ETF. Esta parte do nome do ativo é algo realmente que complicaria as coisas, caso não usássemos um delimitador. Isto por que, existem mercados que o nome do ativo é composto de quatro símbolos alfanuméricos, já em outros casos podemos ter cinco símbolos. No caso em questão temos 5 símbolos. Mas mesmo na B3 ( Bolsa do Brasil ), existem diversos ativos que fazem uso de quatro símbolos.

E tem mais uma coisa. Lembre-se que a ideia aqui, é gerar um Chart Trade que também poderá ser utilizado no replay/simulador. E neste caso o nome do símbolo pode ter qualquer número de caracteres alfanuméricos. Então por este motivo, um bloco de tamanho dinâmico seria muito bem-aceito.

Agora chegamos novamente no nosso carácter D. Neste ponto, quero lhe chamar a atenção para que olhe novamente a linha 338. Note que se a operação a ser feita, não for do tipo que se encerra no mesmo dia, o conhecido day trade. O carácter que estará neste bloco, irá de fato ser diferente. Sendo substituído por um S. Você pode usar qualquer outro carácter que desejar. Mas lembre-se de mudar isto no receptor também, caso contrário, a comunicação ficará mais difícil de ser feita. Pois o receptor pode não entender o que a letra, ou conjunto de caracteres de fato representa.

Logo depois disto, temos um valor literal. No caso 250. O que este valor representa? Novamente, olhe o código na linha 338, para entender que este valor é o nível de alavancagem desejada. Aqui mora uma questão interessante. No caso estamos usando três símbolos numéricos, para representar o valor que desejamos usar de alavancagem.

Mas será que poderíamos usar um valor binário para isto? De fato, isto parece ser bastante adequado, já que não é possível usar um nível de alavancagem zero. Porém existe uma condição que impede que isto seja feito. E não estou falando, da condição de que não podemos formatar a string, com um carácter correspondente ao valor 250, ou qualquer outro. E sim do problema do símbolo, ou carácter usado como delimitador. Pegue uma tabela ASCII e veja qual o valor que o símbolo de interrogação tem. Você verá que o valor é o 63.

Para facilitar a sua vida, caro leitor. Na imagem abaixo, estou disponibilizando a tabela ASCII, do carácter 0 até o carácter 128.

Image 4

E por que este valor 63 é importante para nos? O motivo é que qualquer valor de alavancagem que você vier a utilizar, que venha a fazer uso do valor 63, irá ser visto pelo receptor que irei em breve mostrar, como sendo um carácter delimitador. Ou seja, o receptor que mostrarei, não conseguirá entender, que o quarto bloco, se trata do valor a ser usado como nível de alavancagem.

Mas ai você pode pensar: E se eu modificar esta condição indo para um outro valor? Por exemplo: Se eu somar ao nível de alavancagem este valor 63, sabendo que o valor de alavancagem, nunca será igual a zero. Assim o primeiro valor a ser de fato montado será o 64. Problema resolvido? Eu até gostaria que as coisas fossem simples assim. Mas não, você ao fazer isto, de somar 63 ao valor de alavancagem, apenas estará de fato adiando o problema, para um outro momento.

Agora complicou. Pois não entendi nada. Como assim. Se eu somar 63, ao valor de alavancagem, todos os valores serão sempre maiores que 63. Sim de fato todos os valores serão maiores que 63. E é ai que mora a piada. Em programação, nenhum e repito nenhum valor é de fato infinito. Todo e qualquer valor é limitado a um número. O número máximo depende do tamanho da palavra que estamos usando. Mesmo em um processador de 64 bits, que é onde o MetaTrader 5, roda atualmente, o sistema de gerenciamento é baseado em conceitos de 8 bits.

Ou seja, você mesmo usando um processador de 64 bits, não poderá de fato contar, isto em termos de caracteres um valor de 2 elevado a 64, que seria: 18.446.744.073.709.551.615. Na verdade você contaria no máximo até 255 que é o equivalente a 2 elevado a 8. Mas por que? Será que não teria como contornar isto? Sim, existem formas de contornar isto. Uma delas é usando uma tabela diferente da ASCII. Um exemplo seria usando tabelas unicode.

Mas existe um outro problema. A chamada StringFormat não faz uso da tabela unicode. Pelo menos não neste momento, em que escrevo este artigo. As funções de string do MQL5, basicamente, seguem os princípios do C / C++, ou seja, ela de fato faz uso da tabela ASCII. Apesar do C / C++, ter funções para trabalhar com a tabela unicode. Originalmente isto não acontecia.

Então, mesmo que você adicione 63 ao valor de alavancagem, a cada 255 posições, irá ser gerado de fato um valor composto. Este valor será a combinação de um fator mais o valor 63. Este fator indica quantas vezes o ciclo de contagem até 255 aconteceu. Então para que você entenda, o valor 319 é a combinação de 1 que seria o fator mais 63 que é o valor da contagem atual. O valor 575 é a combinação de 2 que é o fator somado a 63 que é o valor da contagem atual. E assim sucessivamente.

Então para representar as coisas você precisaria de 2 bytes, sendo que o segundo byte sempre seria o valor 63, em algum momento da contagem. Já o primeiro byte seria o valor do fator. Ou seja, quantas vezes a contagem alcançou o limite máximo permitido. Sendo que este seria sempre 2 elevado a 8, por conta do que expliquei acima. Este tipo de coisa, trás diversas implicações matemáticas, mas não explicarei isto aqui e agora. Pois envolve coisa que fogem do conteúdo atual dos artigos.

Para encerrar a explicação de como o protocolo das mensagens está sendo criado. Veja que temos dois valores, que poderiam ser representados como um double ou float. Mas pelos mesmos motivos que foram vistos sobre o nível de alavancagem. Precisamos usar de forma literal os valores. Por isto eles tem a aparência que você pode ver na imagem.

Mas agora vem uma pergunta, que você muito provavelmente deve está se fazendo: Por que estes valores, tem esta aparência? O que eles na verdade representam? Estes valores pode lhe parecer estranhos, pelo fato de que você esteja se esquecendo em olhar o que está na linha 338 do fragmento de código. Observe que ali, estamos transformando um valor financeiro em um valor de pontos. Então o valor 3.60 representa um financeiro de $ 900 e o valor 3.02 um financeiro de $ 755.

Mas por que não usar valores financeiros, no lugar de valores em pontos? O motivo é simplicidade. É bem mais simples implementar um Expert Advisor que venha a usar valores, já convertidos do que ter que converter estes valores internamente no Expert Advisor. Isto talvez não seja tão claro agora. Mas você verá que poderemos fazer uso disto de diversas formas diferentes. Mas isto ficará de fato para o futuro. Já que existem coisas que serão necessárias serem explicadas, para que você realmente consiga entender a profundidade em se enviar a mensagem, já ajustada para dentro do Expert Advisor. Mas como eu disse isto irá de fato ficar para o futuro.


Conclusão

Neste artigo tentei explicar, com o máximo de detalhes possíveis, como você faz para criar um protocolo de comunicação. Este assunto ainda não terminou, já que ainda falta ver a parte responsável pela recepção destas mensagens. Porém, acredito que o intuito deste artigo, foi alcançado. já que expliquei por que você deve tomar cuidados ao projetar o seu protocolo de comunicação. Isto caso você deseje fazer uso de algo diferente do que estarei usando.

Tudo isto deve ser pensado agora. Pois se você for fazer isto depois, irá se enrolar todinho, tentando fazer com que o protocolo de comunicação consiga de fato transferir as informações. Tais informações serão primordiais para que o Expert Advisor, saiba o que e como fazer as coisas. Então não deixe para depois. Estude agora e comece a fazer o ajuste, que você por ventura ache necessário ser feito. No próximo artigo iremos de fato ver a parte relacionada ao receptor, ou seja, o Expert Advisor.

Arquivos anexados |
Anexo.zip (420.65 KB)
Do básico ao intermediário: Definições (II) Do básico ao intermediário: Definições (II)
Neste artigo iremos ver e explorar um pouco mais sobre a diretiva #define. Só que agora com o foco voltado para a segunda forma de utilização desta diretiva. Ou seja, a criação de macros. Como sei que este material pode vir a ser um pouco complicado no começo. Procurei utilizar uma aplicação que já vem sendo explorada a algum tempo. Então espero que se divirtam com o conteúdo deste artigo.
Técnicas do MQL5 Wizard que você deve conhecer (Parte 27): Médias Móveis e o Ângulo de Ataque Técnicas do MQL5 Wizard que você deve conhecer (Parte 27): Médias Móveis e o Ângulo de Ataque
O Ângulo de Ataque é uma métrica frequentemente citada, cuja inclinação é entendida como tendo uma forte correlação com a força de uma tendência predominante. Vamos analisar como ele é comumente usado e compreendido e examinar se há mudanças que poderiam ser introduzidas na forma como é medido, para benefício de um sistema de negociação que o utilize.
Criando um Limitador de Drawdown Diário EA em MQL5 Criando um Limitador de Drawdown Diário EA em MQL5
O artigo discute, de forma detalhada, como implementar a criação de um Expert Advisor (EA) baseado no algoritmo de negociação. Isso ajuda a automatizar o sistema em MQL5 e a controlar o Drawdown Diário.
Desenvolvendo um EA multimoeda (Parte 18): Automação da seleção de grupos considerando o período forward Desenvolvendo um EA multimoeda (Parte 18): Automação da seleção de grupos considerando o período forward
Continuaremos automatizando etapas que anteriormente realizávamos manualmente. Desta vez, voltaremos à automação da segunda etapa, ou seja, a escolha do grupo ideal de instâncias individuais de estratégias de negociação, complementada pela capacidade de considerar os resultados dessas instâncias no período forward.