Qualquer um que já tenha se interessado por ações ou criptomoedas viu essas linhas adicionais nos gráficos. Você pode ter ouvido as opiniões de que eles não funcionam. Mas eles melhoram muito minha capacidade de negociação, enquanto exibem muitos dados importantes. Mas como eles realmente funcionam? E para quem pode ser útil?
Você definitivamente deve ler isso se:
- Você os usa no dia de negociação
- Você está planejando escrever um bot de negociação
- Se você deseja implementar uma estratégia de negociação ou indicadores por si mesmo

Na maioria das vezes,
os indicadores técnicos são uma função de janela, função recursiva ou função ponderada de preços / volumes extraídos da bolsa de valores no formato UOHLCV (tempo unix, aberto, alto, baixo, fechado, volume). Não é incomum que os indicadores usem diferentes filtros, mínimos e máximos ou outros indicadores como base para cálculos subsequentes.
Média móvel simples (SMA)
Ao codificar indicadores, é muito conveniente usar a abordagem funcional. Por exemplo, a média móvel é apenas a média de cada valor da janela rolante.
function sma($close, window) { return rolling(x => mean(x), window, $close); }
onde
mean é a operação que calcula a média da matriz e a
rolagem é a combinação da função de janela que, para cada elemento existente na matriz, produz uma matriz dos últimos n elementos e a
operação que dobra essa janela em um número.
function rolling(operation, window, array) { let result = []; for (let i = 0; i < array.length; i++) { if (i + 1 < window) { result.push(NaN); } else { result.push(operation(array.slice(i + 1 - window, i + 1))); } } return result; }
O
SMA é um indicador de atraso e ajuda a determinar a tendência. Ele é desenhado como sobreposição no gráfico e os primeiros valores geralmente são descartados. Duas médias móveis podem ser usadas juntas para gerar sinais de cruzamento.

Um cruzamento de alta ocorre quando uma média móvel relativamente curta rompe a média móvel longa. A média móvel ponderada exponencialmente é mais usada na prática, porque uma função de janela ponderada reduz o efeito de atraso.
Desvio padrão (DESVPAD)
Se substituirmos a função
média no SMA pelo desvio padrão, obteremos um desvio padrão deslizante
function stdev($close, window) { return rolling(x => sd(x), window, $close); }
Onde
sd é considerado raiz quadrada de variância e comumente sem correção de Bessel. Vamos assumir que todo mundo entende como implementar
sd
A raiz quadrada da variação é usada porque a variação em si é medida em dólares suqare em termos de teoria das dimensões e não porque alguém registrou marca comercial ou qualquer outra coisa.
Bandas de Bollinger (BBAND)
Assim, já implementamos dois indicadores básicos que podemos combinar e obter novos. Por exemplo, se considerarmos a adição pontual da média móvel e do desvio padrão multiplicado por 2, obteremos a parte superior da banda de Bollinger e a parte inferior, se subtrairmos.
function bb($close, window, mult) { let middle = sma($close, window); let upper = pointwise((a, b) => a + b * mult, middle, stdev($close, window)); let lower = pointwise((a, b) => a - b * mult, middle, stdev($close, window)); return { lower : lower, upper : upper}; }
onde a função
pointwise é outra função útil
export function pointwise(operation, ...arrays) { let result = []; for (let i = 0, len = arrays[0].length; i < len; i++) { let iarr = (i) => arrays.map(x => x[i]); result[i] = operation(...iarr(i)); } return result; }
e é só executar a
operação com várias matrizes

As bandas de Bollinger ajudam a determinar a calma antes do grande movimento de preços e são usadas como uma ferramenta para demonstrar a volatilidade diretamente no gráfico, o desvio padrão subtraído / adicionado da média móvel para ser exibido como sobreposição em um gráfico com o preço.
Média móvel exponencial (EMA)
Como podemos reduzir o atraso da média móvel simples? Como calcula a média dos últimos n preços de fechamento, podemos entender que podemos realizar a soma com algum peso e reduzir a contribuição dos preços antigos.
Por exemplo, se escolhermos
e uma constante
se for menor que um, obteremos um peso infinitamente menor, se adicionarmos os preços começando pelo mais novo.

Também é possível aproximar cálculos e obter equação recursiva se expandirmos a janela para o comprimento total e assumirmos que a contribuição das caudas é pequena.
Por fim, precisamos de algum valor α = 1 - q como uma constante de suavização. É possível
provar que, quando escolhemos
o centro de massa das tabelas de pesos EMA e SMA acima se iguala. No código, isso parece muito mais simples.
function ema($close, window, weight = null) { weight = weight ? weight : 2 / (window + 1); let ema = [ mean($close.slice(0, window)) ]; for (let i = 1; i < $close.length; i++) { ema.push($close[i] * weight + ema[i - 1] * (1 - weight)); }; return ema; }
Em geral, essa é a mesma média móvel, mas mais sensível.

A eficácia do uso depende da sua experiência e das configurações usadas. Por exemplo,
neste site, os parâmetros são escolhidos muito bem.
Divergência da convergência média móvel (MACD)
Gerald Appel, em 1979, apresentou um dos indicadores mais simples e eficazes disponíveis. Ele transforma dois indicadores de tendência EMA em um oscilador de momento e oferece o melhor dos dois mundos: acompanhamento de tendência e momento. Grosso modo, o histograma MACD é um derivado do preço. Ele é desenhado em um novo sistema de coordenadas, em vez de sobreposto, e representa com duas linhas e um histograma.

Para calcular a linha MACD, precisamos subtrair EMA longa de curta, isso é tudo. Outra EMA desta linha com janela minúscula produzirá a linha de sinal. O histograma é obtido pela diferença entre os dois resultados anteriores.
function macd($close, wshort, wlong, wsig) { let line = pointwise((a, b) => a - b, ema($close, wshort), ema($close, wlong)); let signal = ema(line, wsig); let hist = pointwise((a, b) => a - b, line, signal); return { line : line, signal : signal, hist : hist }; }
Matriz de correlação
Se você se interessou por análises de investimento e portfólio de longo prazo, encontrará útil a matriz de correlação.
function cor(f, g) { let Ef = mean(f), Eg = mean(g); let Ef2 = mean(pointwise((a) => a * a, f)); let Eg2 = mean(pointwise((a) => a * a, g)); let Efg = mean(pointwise((a, b) => a * b, f, g)); return (Efg - Ef * Eg) / Math.sqrt((Ef2 - Ef * Ef) * (Eg2 - Eg * Eg)); }
Aqui matriz de correlação de diferentes criptoativos em 2 meses.

Teste de unidade de indicador
Se tivermos tabelas precisas de valores de indicadores, podemos testar com precisão nosso cálculo. Existem várias maneiras de determinar a medida do erro entre as duas funções, mas, neste caso, o erro quadrático médio normalizado é mais adequado porque é uma quantidade adimensional em contraste com o RMSE e é relativo.
Por exemplo, o bitcoin pode custar US $ 20.000 e uma diferença de US $ 10 é pequena, enquanto quando o altcoin inteiro pode custar US $ 1 e a diferença de US $ 10 é enorme.
function nrmse(f, g) { let sqrDiff = pointwise((a, b) => (a - b) * (a - b), f, g); return Math.sqrt(mean(sqrDiff)) / (Math.max(...f) - Math.min(...f)); }
Também podemos usar o MAPE, mas não é alternativo e tem um problema próximo de zero.
Conclusão
Então é isso. Em algumas linhas de código, podemos expressar os indicadores técnicos básicos, se você gosta dessa explicação, consulte minha biblioteca no github. Lá você pode encontrar muito mais. Se você quiser usar alguns algoritmos de aprendizado de máquina para o seu bot, verifique o indicador Zig-Zag como pontos de entrada.
Referências
1.
StockCharts - uma lista de algoritmos com dados de teste nas tabelas.
2.
Cryptowatch - parâmetros bem ajustados dos indicadores.
3.
Github - meu código fonte.
PS Se você encontrar algum erro no texto, informe-me diretamente.