Resultado do mês de junho (2019)

O mês de junho surpreendeu de diferentes maneiras. Aliás, alguns acontecimentos são dignos de filme. Provavelmente, o vazamento ilegal de uma possível conversa entre o então Juiz Sergio Moro e procurador Deltan Dalla­gnol foi o assunto mais discutido. No entanto, muitos acontecimentos marcaram o mês. Felizmente, não precisei lidar com imprevistos. Sem muitas delongas, vamos aos resultados.

Conforme exposto, o vazamento ilegal de uma possível conversa entre Sergio Moro e procuradores da Lava Jato foi a desculpa que a defesa do ex-presidente (Lula) precisava para tentar desqualificar (indevidamente) todo o processo de condenação. Porém, na justiça brasileira, qualquer “documento” obtido de forma ilegal (como no ataque hacker) não pode ser incluído como prova – vale lembrar, também, que não há como comprovar a autenticidade do diálogo, visto que o hacker pode facilmente produzir diálogos em nome dos participantes.

Certamente, o ocorrido causou desconforto, mas não tem base suficiente para se manter. Tanto é verdade que, logo em seguida, o Mercado Financeiro praticamente ignorou o momento turbulento. E, sejamos sensatos, a defesa do ex-presidente não conseguiu refutar nenhuma das acusações até então (todas com provas contundentes).

O mercado continua otimista…

Ibov encerra o mês acima dos 100 mil pontos!

Já a discussão em torno a Reforma de Previdência parece não ter fim. Ao contrário do que a oposição prega, o maior prejudicado não é o mais pobre (pelo contrário) – aliás, acredito (opinião pessoal) que o maior embate acontece porque a reforma propõe o fim de privilégios em cargos públicos de alta renda (igualando ao teto do INSS).

Por mais incrível que possa parecer, ainda há quem questione o déficit…

Se você ainda tem dúvidas, sugiro assistir o seguinte vídeo:

O portal G1 publicou um estudo sobre o déficit nos principais Estados brasileiros e os números são assustadores. A pior situação ficou com o Estado de Minas Gerais com déficit de R$ 5.4 bi – fiquei surpreso em saber que a situação de Minas é mais delicada que do Rio Grande do Sul (déficit de R$ 3.8 bi).

Pois é, os números não mentem! 😉

Mas, a confusão (ou desinformação) tem sido tanta que alguns movimentos sociais convocaram uma greve geral *contra* a Reforma de Previdência e o Contingenciamento na Educação, embora tenhamos presenciado claramente oportunistas brigando por outras pautas (não é preciso dizer quais… risos)!

Confiram o compilado da greve produzido pelo canal Mamaefalei:

Em alguns aspectos entendo que o governo vem acertando, mas não acho que esteja lidando muito bem com conflitos internos, principalmente por permitir conflitos ideológicos. No mesmo mês, tivemos mais duas baixas – a demissão do general Santos Cruz da Secretaria de Governo e do presidente do BNDS, Joaquim Levy.

Na sexta-feira (28/06/2019), a MP 873, que proíbe o desconto em folha do imposto sindical, perderia a validade – particularmente, não concordo com a “contribuição” obrigatória! Mas, felizmente, o Ministro Barroso cassou a decisão que autorizava desconto em folha de contribuição sindical.

Apesar das turbulências internas, estamos cada vez mais próximos de ingressar na OCDE (Organização para a Cooperação e o Desenvolvimento Econômico). Além do apoio Norte Americano, o Reino Unido também manifestou apoio para o ingresso do Brasil na OCDE.

Por sorte, as notícias boas não param por aí. A semana encerrou com mais uma grande aliança. Segundo o Ministério da Economia, o acordo firmado entre o Mercosul e União Europeia pode aumentar o PIB brasileiro em até U$ 125 bi em 15 anos.

Como de costume, confiram os principais números e acontecimentos que sacudiram o país e o mundo (do redator chefe da Modal):

O mês está encerrando com forte valorização das principais criptomoedas (de certa forma indexadas pela criptomoeda Bitcoin). Para os simpatizantes deste mercado, o Facebook lançou mais uma criptomoeda conhecida como Libra e com grande potencial de crescimento, pois já conta com parcerias como Mastercard, Paypal, Ebay, Spotify e Uber, por exemplo.

De maneira geral, ainda é cedo para tecer conclusões sobre as criptomoedas. Acredito que, no caso da Libra, haverá algum tipo de regulação. Mas, o Bitcoin, por exemplo, cedo ou tarde, causará reação mais enérgica no mundo inteiro. A Receita Federal Brasileira já permite declarar a posição em Bitcoin, mas a verdade é que boa parte dos investidores não o fazem. E, tudo isto, sem considerar que muitos estão fazendo remessa não declarada para o exterior. Hoje, é impossível ter controle sobre todas operações envolvendo as criptomoedas – se o governo acredita que pode, é muita ingenuidade (não creio que sejam tão ingênuos assim… risos). Seja qual for sua visão, não ignore este fato.

Neste mês, finalmente, a Petrobras conseguiu concluir a venda da TAG (Transportadora Associada de Gás S.A.), com o pagamento de R$ 33,5 bi pela Engie.

O interesse claro na privatização dos Correios – reforçado com a demissão do presidente Juarez Aparecido – vem despertando a atenção de gigantes internacionais. Há rumores de que empresas como Amazon e Alibaba estão interessadas em comprar.

A Odebrecht também fez barulho com o maior pedido de recuperação judicial da história brasileira – de acordo com a Infomoney, a companhia divulgou R$ 51 bi de dívidas passíveis de reestruturação.

Finalmente, a “briga” pela Netshoes chegou ao fim. Segundo o portal Terra, “depois de passar semanas disputando a aquisição da Netshoes com a Centauro, a Magazine Luiza ganhou o deal, e concluiu o processo de aquisição“.

O balanço dos ativos que mantenho em carteira foram divulgado nos dois meses anteriores e, de maneira geral, o resultado foi positivo, tornando a situação da carteira de renda variável confortável e promissora.

Para ter acesso ou acompanhar os balanços, recomendo o seguinte link:
https://www.acionista.com.br/agenda/resultados-das-cias.html

Quanto aos investimentos…

Recebi proventos de BBAS3, CRFB3, ITUB3, BRCR11 (0,488), FCFL11 (0,511%), PQDP11 (0,481%), KNRI11 (0,477%), RNGO11 (0,578%), SAAG11 (0,722%), GGRC11 (0,536%), MXRF11 (0,599%), KNCR11 (0,620%), HGRE11 (0,470%), FLMA11 (0,420%), HGBS11 (0,538%) e FIGS11 (0,574%). O resultado foi modesto, mas o desempenho da carteira continua excelente. Devido a forte valorização dos últimos meses (e apenas por esta razão), o pior rendimento foi do fundo FLMA11 – o fundo continua excelente, porém, no atual momento, entendo que existam opções mais interessantes para direcionar novos aportes. Com o fim da RMG, é preciso ficar atento com o FIGS11, pois o fundo já divulgou rendimento de apenas 0,202% para o mês de julho – deixarei em quarentena (reduzi minha exposição no ano passado). Já o fundo BRCR11, com a nova ocupação do CENESP pelo Banco do Brasil, conseguiu reduzir a taxa de vacância do imóvel de 62,2% para 33,9%a vacância física do fundo passará a ser de 15% (o desempenho do fundo tende aumentar). De maneira geral, o rendimento da carteira permanece excelente, sendo reforçado com o pagamento de dividendos e JCP de BBAS3, CRFB3 e ITUB3 (pouco expressivo).

Conforme exposto inúmeras vezes, o posicionamento como holder é praticamente uma conduta obrigatória. E, para auxiliar na identificação de empresas sólidas e lucrativas, recomendo assistir o seguinte vídeo (Canal do Holder):

Com o rendimento da própria carteira, somado ao capital que me prontifico separar para investir mensalmente, comprei mais ações (ou cotas) de WEGE3, SAAG11 e BRCR11. O maior aporte foi para SAAG11 e o menor foi para BRCR11. Destinei o menor aporte ao fundo BRCR11 porque, apesar de gostar do fundo, já tenho uma exposição alta.

Confiram a distribuição dos ativos, segundo o portal CEI (NÃO inclui o Fundo DI):

A proporção em ações aumentou em decorrência da forte valorização do índice Ibov

A composição atual ficou assim (gráfico do IrpfBolsa):

Vale lembrar que o gráfico acima representa uma distribuição baseada no custo de aquisição, não no valor de mercado

Quanto ao meu projeto APFTrend-v2.0 (robô trades)…

Desta vez, o resultado do robô foi negativo, em aproximadamente R$ 400 (prejuízo). Ainda assim, tenho consciência que o objetivo é buscar assimetrias que ofereçam prejuízo pequeno e lucro maior, logo é importante avaliar o comportamento do robô ao longo do ano.

Não nego que fiquei um pouco preocupado e já até pensei em abandonar as operações de trade, mas não me dou por vencido facilmente. Decidi revisar o código e incluir alguns controles adicionais!

Precisei melhorar os pontos de entrada e buscar controles para limitar entradas tardias. Aproveitei o feriado de Corpus Christi e trabalhei arduamente nos ajustes do robô.

Comecei incluindo suporte ao algoritmo do indicador Trend Direction and Force (TDF). A grande vantagem do TDF é a possibilidade de mensurar a intensidade do movimento dentro da tendência através da “vetor val“. Em paralelo, inclui mais controles baseados no desvio padrão. Depois da alteração, consegui melhorar a eficiência do robô em 4x (infelizmente, apenas no final do mês).

A versão demo do robô (apenas binários) está disponível para download através do link:
http://aprendizfinanceiro.com.br/APFTrend-v2.0-demo.zip

Aos interessados em testar o robô, recomendo começar pelas simulações – o projeto ainda está em fase experimental. É importante ressaltar que operações especulativas envolvem perdas esporádicas. Não há garantias de lucro. Portanto, mantenham cautela e jamais coloquem dinheiro que não possam perder (a única garantia é que pequenas perdas acontecerão inevitavelmente)!

De maneira geral, continuo bastante satisfeito com o resultado da carteira e também com a evolução do robô de trades (apesar do resultado negativo neste mês). Ainda assim, o ganho da capital da carteira continua superando minhas expectativas – tem sido expressivo. Vale lembrar que, no curto prazo, oscilações são naturais e esperadas (com movimentos de repique, por exemplo). Dentro de qualquer tendência, os papeis não se movimentam em linha reta.

Estou apenas demonstrando o potencial de crescimento, isto não é recomendação de investimento!

Expert Advisor-parte1: Programação de robôs de trade (videoaula)

Finalmente, trataremos a codificação do Expert Advisor (robô ou assistente especializado). As etapas tratadas anteriormente foram fundamentais para melhor compreensão e aprendizado da linguagem MQL5. Neste artigo, veremos como codificar um EA e integrá-lo com o indicador implementado anteriormente.

Vale lembrar que o segredo deste EA está no indicador, não no EA. Logo, é preciso melhorar a eficiência do indicador APF-Color-Base!”

O download do projeto pode ser feito pelo link:
http://aprendizfinanceiro.com.br/APF-Color-Base-EA.zip

Para agilizar o processo de codificação e reduzir a margem de erros, incluímos as bibliotecas internas CPositionInfo (controle de posição), CTrade (operações de trade) e CSymbolInfo (informações de mercado, referentes ao ativo analisado).

#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>

CPositionInfo  m_position;                 // trade position object
CTrade         m_trade;                    // trading object
CSymbolInfo    m_symbol;                   // symbol info object

Como o robô se orienta pelo indicador APF-Color-Base, precisamos obter a cor da barra através de uma chamada iCustom, no bloco OnInit:

hAPF=iCustom(_Symbol,PERIOD_CURRENT,"\\Indicators\\APF-Color-base-1.1.ex5");
if(hAPF==INVALID_HANDLE) {
  Print("Expert: iCustom call: Error code=",GetLastError());
  return(INIT_FAILED);
}

Percebam que a chamada não difere muito dos exemplos que utilizamos no indicador com chamadas iMA e iSAR.

A leitura do sinal (obtenção da cor da barra) foi codificada na função GetSignal.

Mas, para ampliar a segurança das operações, a primeira verificação é referente a tentativa de encerrar operações em aberto (m_trade.PositionClose).

int signal=GetSignal();

if (signal==0 || close_trade) {
   if (count_buy>0 || count_sell>0) {
      int close_pos=0;
      for(int i=PositionsTotal()-1;i>=0;i--)
         if(m_position.SelectByIndex(i))
           if(m_position.Symbol()==Symbol() && m_position.Magic()==m_magic) {
              close_pos=0;
              if (signal==0 || close_trade) {
                  m_trade.PositionClose(m_position.Ticket());
                  close_pos=1;
              }
           }
   }
   return;
}

A função GetSignal retornará a cor da barra: sendo 0 (branco), 1 (verde/long) e 2 (vermelho/short) – vide indicador!

Quando count_buy ou count_sell for maior que 0, certamente existirá uma operação em aberto (Long ou Short). Neste caso, a posição será fechada caso GetSignal retorne 0 (a barra mudou de cor – para branco) ou close_trade seja diferente de zero (para forçar o fechamento).

Confiram o código da função GetSignal:

int GetSignal()
  {
      
      //--- load buf_color_line
      if (CopyBuffer(hAPF,4,0,2,buf_APF) < 0){
         Print("CopyBuffer APF error =",GetLastError());
         return(0);
      }
      
      int vSignal=0;
      if ((buf_APF[0]==1 && buf_APF[1]==0) || (count_buy>0 && buf_APF[0]==1 && buf_APF[1]==1))  vSignal=1;
      if ((buf_APF[0]==2 && buf_APF[1]==0) || (count_sell>0 && buf_APF[0]==2 && buf_APF[1]==2))  vSignal=2;

      return (vSignal);
  }

A cor dos dois últimos candles é obtida através da função do MQL5 CopyBuffer: o primeiro parâmetro identifica o handle do indicador (hAPF), o segundo parâmetro a posição do buffer do indicador (4 é o índice que representa buf_color_line – consulte os mapeamentos feitos com SetIndexBuffer), o terceiro a posição inicial (0 – última barra) e o último corresponde ao número de elementos para copiar (2 – duas barras).

A leitura dos dois últimos candles se faz necessário para comparar uma possível mudança de cor

Já a abertura de posição foi codificada na função OpenBuy (posição comprada) e OpenSell (posição vendida). Conforme exposto anteriormente, utilizamos a biblioteca CTrade para controlar a abertura de posição (m_trade.PositionOpen):

void OpenBuy(double sl,double tp)
  {
   sl=m_symbol.NormalizePrice(sl);
   tp=m_symbol.NormalizePrice(tp);
   int aux_Lots=InpLots;
   
//--- check volume before OrderSend to avoid "not enough money" error (CTrade)
   double check_volume_lot=m_trade.CheckVolume(m_symbol.Name(),aux_Lots,m_symbol.Ask(),ORDER_TYPE_BUY);

   if (count_buy>0) return;
   
   if(check_volume_lot!=0.0) {
      if(m_trade.PositionOpen(m_symbol.Name(),ORDER_TYPE_BUY,aux_Lots,m_symbol.Ask(),sl,tp,"LONG"))
      {
         if (trade_maxgain==0) {
            count_buy++;
            max_trades++;
         }
         Print("PositionOpen() BUY method executed SUCCESSFULLY. Return code=",m_trade.ResultRetcode(),
               " (",m_trade.ResultRetcodeDescription(),")");
         PrintResultTrade(m_trade,m_symbol);

         // preço confirmado pela corretora
         trade_open=m_trade.ResultPrice();
      }
...

   }
...

//---
  }

Cada ordem será enviada à mercado (ORDER_TYPE_BUY). Sendo assim, logo que o indicador sinalizar a mudança de cor, o robô fará a negociação pelo preço negociado naquele instante!

Caso tenha ficado alguma dúvida referente a lógica básica de construção de um EA, também recomendo acessar o seguinte vídeo:

No vídeo anterior, algumas estrategias foram escritas de maneira um pouco diferente (até porque abordou uma codificação em MQL4). Mas a lógica padrão é a mesma.

Espero que o artigo seja útil e até a próxima! 😉

Indicadores-parte final: Programação de robôs de trade (videoaula)

Para finalizar a série de artigos sobre a codificação de indicadores no MT5, resolvi compartilhar mais um vídeo explicando as razões que nos levaram modificar o código para abertura de posição simulado pelo indicador.

Quanto maior o número de comparações dos preços do candlestick, menos preciso o algoritmo se mostrava em relação ao “histórico” (quando prev_calculated é igual a 0) e o “testador de estratégia” (a cada negócio) – por incrível que pareça, em um segundo, a estimativa de volume ou a diferença do preço máximo pelo fechamento pode mudar algum critério de decisão.

A única forma de coincidir as comparações históricas com o processamento online (no testador de estratégia ou durante o trade real), é validando os critérios para abertura de posição assim que a nova barra for desenhada e comparar os valores da barra anterior.

A última versão do projeto está disponível no link:
http://aprendizfinanceiro.com.br/APF-Color-Base.zip

Outro indicador que foi adicionado ao código foi o StdDev (desvio padrão). O objetivo é capturar a volatilidade do mercado – o valor do indicador aumenta na medida em que os preços se distanciam da média apurada (período).”

A variável “i” é o índice que representa cada barra processada. Para que possamos “identificar a barra atual (i)” e “comparar a anterior (i-1)“, podemos incluir outro índice (“k“) que será igual a “i-1” apenas quando a operação não estiver aberta – quando trade_open for igual a 0.

    for (int i=start; i < rates_total; i++) {
        HighBuf[i]=high[i];
        CloseBuf[i]=close[i];
        OpenBuf[i]=open[i];
        LowBuf[i]=low[i];
...
             int k=i;
             if (!trade_open) k=i-1;
...
             // Identificação da barra
             bool CANDLE_0          = (open[k]-close[k] == 0);
             bool CANDLE_UP       = (close[k]>open[k] && close[k]-open[k]>=1);
             bool CANDLE_DOWN  = (close[k]=1);
...

O ajuste anterior resolve a questão da comparação da barra anterior, mas precisamos alterar o momento em que as comparações serão liberadas. Este controle é feito pela função isNewBar.

bool isNewBar(const datetime lastbar_time, const int op_type, const int prev_calc)
  {
//--- memorize the time of opening of the last bar in the static variable
   static datetime last_time=0;
   static datetime init_time=0;
   
   datetime init_auxtime=TimeCurrent();

   int limit_time=0;
   long time_match=0;
   
   limit_time=300;
   time_match=(limit_time-(init_auxtime-init_time));
   if (time_match<0) time_match=0;
   
   string label_name1="Seconds", label_text="Seconds... "+(string) (long)time_match;
   ObjectDelete(0, label_name1);
   ObjectCreate(0, label_name1, OBJ_LABEL, 0, 0, 0);
   ObjectSetInteger(0,label_name1,OBJPROP_XDISTANCE,ChartGetInteger(0,CHART_WIDTH_IN_PIXELS,0)-100);
   ObjectSetInteger(0,label_name1,OBJPROP_YDISTANCE,30);
   ObjectSetInteger(0,label_name1,OBJPROP_COLOR,YellowGreen);
   ObjectSetString(0,label_name1,OBJPROP_TEXT,label_text);
   
   if (last_time==0 || init_time==0 || last_time!=lastbar_time) {
      last_time=lastbar_time;
      init_time=init_auxtime;
      if (last_time==0) return(false);
      if (prev_calc==0 || op_type==1) return(true);
      return(false);
   }

   if (op_type==2 && time_match<=2) return(true);
   
   return(false);
  }

Todas as atualizações do projeto serão disponibilizadas no github:
https://github.com/betolj/Trade-MT5

Para quem ainda não estiver muito confortável com a codificação em MQL5, recomendo dedicar tempinho para acessar o canal do Vilela One (bastante didático):
https://www.youtube.com/watch?v=lRWTQTllYQU&list=PLpAIvw0R8TvOBB3FVRZgmw_khMtr45oEL

Em breve, começaremos abordar a codificação do Expert Advisor!

Indicadores-parte3: Programação de robôs de trade (videoaula)

Na terceira e última parte da programação de indicadores (nos próximos falaremos sobre o EA – Expert Advisor), veremos uma versão evoluída do exemplo anterior (baseado na Média Móvel), incluindo controles de tradenúmero de operações com ganho, número máximo de trades, prejuízo máximo, estimativa de ganho e etc.

A base para escolha de uma posição (comprada ou vendida) é bastante semelhante, mas incluímos algumas opções mais avançadas.

O exemplo demonstrado está disponíveis através da url:
http://aprendizfinanceiro.com.br/indicador-aulas3.zip

Conforme exposto no vídeo, a primeira diferença foi a codificação de um controle de trade (basicamente um controle de risco):

// Controle de risco para novas aberturas de posição - por isto !trade_open ou trade_open==0
if (!trade_open){
   //--- Critérios principais e globais
   // 1. Encerra ao atingir 20 pts
   if (trade_sum>20) close_trades=1;
   // 2. Encerra ao atingir o limite diário de trades
   else if (trade_ct>max_daytrades-1) close_trades=1;
   // 3. Encerra ao atingir o prejuízo diário máximo
   else if (trade_sum<=max_tradeloss) close_trades=1;
   //--- Critérios a partir de 3 pts
   else if (trade_ct>=3) {
      if (trade_ct>fail_trades-1 && gain_ct<1) close_trades=1;
      else if (trade_ct>gain_ct && trade_sum>=5) close_trades=1;
      else if (trade_ct==3 && gain_ct==3) close_trades=1;
   }
}

Em seguida, a base do código está na identificação do momento “ideal” para abertura ou fechamento de posição…

Este controle foi implementado através da variável trade_open. Quando trade_open for 0, verificaremos a possibilidade de abrir uma nova posição. Por outro lado, caso seja 1, avaliaremos as possibilidades de fechar a posição (desviando o processamento para o bloco else).

Também limitamos a capacidade de abrir novas operações através da variável close_trades – ao atribuir o valor 1, encerramos as operações no dia e fechamos qualquer posição em aberto.

//--- Verifica se existe um trade em aberto (trade_open):
// 1. Caso não exista operação em aberto, verifica se a próxima barra está prestes a ser desenha e libera o processamento (isNewBar)
// 2. Caso exista, verifica a possibilidade de fechar a posição (desviará para o bloco "else")
if (!trade_open && !close_trades) { 
    // Código para abertura de posição
    if (isNewBar(time[i], start, LM_OPEN)==true) {
       trade_dir=0;
       bars_trade=0;
       buf_color_line[i]=0;
       ...

       //--- Coloque aqui seu código para abertura de posição

    }
}
else {
    // Código para fechamento de posição
              
    // atualiza buf_color_line pelo último valor de trade_dir
    buf_color_line[i]=trade_dir;
    ...
    if (isNewBar(time[i], start, LM_CLOSE)==true && buf_color_line[i]>0) {
        ...

        //--- Coloque aqui os critérios para fechar a posição

        // 1. Fecha posição depois de 5 barras sem ganho superior a 2 pts
        // 2. Atualiza buf_color_line pelo valor de trade_dir
        if (close_trades) trade_dir=0;
        else if (bars_trade>5 && trade_maxgain<2) trade_dir=0;
        buf_color_line[i]=trade_dir;
        ...
    } // encerramento isNewBar
} // encerramento do bloco else (tenta fechar o trade)

Para facilitar no entendimento, coloquei vários comentários em todo código. Acredito que qualquer ajuste possa ser feito sem grandes dificuldades.

Caso você perceba algum bug ou tenha alguma ideia para acrescentar, por favor entre em contato!

Tenham consciência de que poucos *investidores* sobrevivem aos trades. Vende-se muita ilusão na Internet. Seja qual for a sua escolha, faça consciente!

Indicadores-parte2: Programação de robôs de trade (videoaula)

Nesta segunda parte, da série de vídeos sobre indicadores, optei por tratar sobre a codificação da mudança de cor do candlestick em função da média móvel exponencial.

Conforme exposto anteriormente, meu primeiro contato com a codificação do indicador foi através de um vídeo da DeltaTrader. Mas, a base para manipular as cores do candlestick foi a partir de um projeto gratuito, desenvolvido por Kourosh Davallou:
https://www.mql5.com/pt/code/1349

Confiram a segunda parte:

Os exemplos demonstrados estão disponíveis através da url:
http://aprendizfinanceiro.com.br/indicador-aulas2.zip

Conforme prometido, também disponibilizarei para download o código para implementação da VWAP

A VWAP é a representação do Preço Médio Ponderado por Volume (Volume Weighted Average Price) e costuma ser vista como uma opção para visualizar como os grandes players estão agindo.

Em relação aos trades, a VWAP pode ser utilizada como uma referência de suporte ou resistência. Existem várias observações. É fácil perceber que uma reversão pode acontecer quando o preço toca a VWAP. Porém, caso o preço rompa de forma expressiva (rompendo um suporte ou resistência), o movimento dentro da tendência pode acontecer de forma mais expressiva (ao acionar stops, por exemplo).

Compreendi melhor a formula da VWAP através deste artigo (em inglês):
https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:vwap_intraday

O bloco de código é basicamente este:

   sumPrice    += (double) (((high[i]+low[i]+close[i])/3) * volume[i]);
   sumVol      += (double) volume[i];
   buf_VWAP[i] = NormalizeDouble(sumPrice/sumVol,2);

A seguir, o link para download:
http://aprendizfinanceiro.com.br/vwap.zip

No momento, é a última versão que tenho utilizado. Caso você tenha alguma sugestão ou faça alterações, por favor nos informe e compartilhe o código!

Gostaria de deixar claro que minha atuação principal permanece como holder. O que estou compartilhando é uma experiência pessoal e, caso bem sucedido, pretendo apenas reforçar os aportes mensais. Não estou muito convicto de que realmente vale a pena.

Tenham consciência de que poucos *investidores* sobrevivem aos trades. Vende-se muita ilusão na Internet. Seja qual for a sua escolha, faça consciente!

Desejo sucesso a todos… infelizmente, sei que serão poucos! 😉