Publicado como Ideia TradingView sobre ETHUSDT. Ver o gráfico no TradingView
Se alguma vez transpôs um indicador para Python para lhe fazer um backtest, ou confiou num script porque vinha com uma verificação, é da lacuna que essas duas coisas deixam aberta que aqui se fala.
Reconstruímos três dos nossos próprios indicadores para que um backtest pudesse correr sobre eles. As três reconstruções tinham lá dentro uma constante errada. As três passaram a sua validação. Nenhuma foi apanhada por um teste.
Porquê reconstruir sequer um indicador
Um script Pine corre no seu gráfico. Não percorre seis anos de histórico em ciclo, e não responde se um sinal compensa realmente. Para fazer essa pergunta, reconstrói-se em algo que se possa correr milhares de vezes.
É nessa reconstrução que um indicador deixa de ser, sem alarido, o mesmo indicador.
O erro que mais custou, e é uma barra
Um dos comprimentos dentro do Volume Oracle é derivado do período:
target bars = 36 hours × 60 / 240 minutes = 9
regime length = round(9 × 2.5) = round(22.5)
O math.round do Pine resolve os empates afastando-se do zero. Dá 23. O round() do Python 3 usa o arredondamento bancário, que resolve os empates para o número par. Dá 22.
Ambas são implementações corretas do arredondamento. São simplesmente convenções diferentes, e nada o avisa de que passou de uma para a outra.
Todas as retrospeções derivadas desse número se moveram com ele. O resultado na linha mais bem sustentada de uma varredura de 36 sinais:
| versão | vantagem a 48 h | taxa de acerto | n |
|---|---|---|---|
| reconstruído, comprimento 22 | +0,423 % | 51 | 1216 |
| correto, comprimento 23 | +0,260 % | 50 | 1223 |
Um corte de 38 % por causa de uma convenção de arredondamento.
Depois registámos a lição de forma errada
A nota que escrevemos dizia que acontecia apenas em 4H. Foi escrita a partir do único período que estava então em teste, e assim ficou durante dois meses.
A correr a mesma aritmética em todos os períodos:
| período | comprimento de regime | comprimento de fluxo | resultado |
|---|---|---|---|
| 5m | 45 contra 45 | 23 contra 22 | diverge |
| 2H | 45 contra 45 | 23 contra 22 | diverge |
| 4H | 23 contra 22 | 12 contra 11 | diverge |
| 8H | 53 contra 52 | 27 contra 26 | diverge |
| 1D | 18 contra 18 | 9 contra 9 | empata, concorda |
| 3D, 1W | 15 contra 15 | 8 contra 8 | empata, concorda |
Quatro em dezasseis, não um.
Dessa tabela caem duas coisas que raciocínio nenhum produziu.
Um empate não chega. 1D, 3D e 1W caem todos exatamente em ,5 e concordam. O arredondamento bancário só move um empate cuja resposta arredondada para cima é ímpar, por isso round(17.5) dá 18 de qualquer das formas. Cerca de metade de todos os empates são inofensivos, e é precisamente por isso que verificar um por amostragem não prova nada.
A divergência pode chegar um passo mais tarde. Em 5m e 2H o primeiro comprimento concorda em 45. A linha seguinte, round(45 × 0.5), volta a ser 22,5, e essa divide-se. Se verificar a primeira constante e seguir em frente, dá por bons os dois períodos sem razão.
Os outros dois, em breve
Harmonic normaliza um oscilador recortando-o para uma banda móvel. No código fonte, cada barra é recortada pela sua própria banda. A reconstrução recortava uma janela inteira de 200 barras usando a banda da barra atual, o que é uma função diferente. Diferença medida em 11.497 barras: 0,47 pontos em média. Um erro de transcrição real sem efeito material.
Esse, ainda por cima, inflacionámo-lo antes de o medir. Foi anunciado, só de ler o código, como sendo quase de certeza o desvio de 9 %. O número era 0,47. Um erro real e um erro material são afirmações diferentes, e mede-se a grandeza antes de dar nome ao impacto.
Plutus Flow faz a média do volume ao longo de 50 barras para detetar picos. A reconstrução usou 20, porque era esse o número que julgávamos saber. Efeito: menos de um décimo de ponto percentual, sem mudanças de sinal. O veredito não se mexeu, mas o número estava errado e agora está certo, que é o único critério que conta.
A parte que é, de facto, a lição
Eis o que a validação de cada reconstrução comunicou na altura.
| reconstrução | a sua própria verificação | o que isso significava |
|---|---|---|
| Volume Oracle | 3 em 3 antes, 3 em 3 depois | não conseguiu distingui-las |
| Harmonic | 6 em 8 antes, 5 em 8 depois | pontuou mais alto a versão com o erro |
| Plutus Flow | nunca foi executada | — |
É na linha do meio que vale a pena demorar-se. A validação preferiu o código errado. Se tivéssemos deixado a verificação decidir, ter-nos-ia convencido a voltar ao erro.
Uma validação que compara um único valor de saída não consegue detetar uma constante de entrada errada. A saída é um crivo demasiado grosseiro. Muitos conjuntos de parâmetros errados e diferentes produzem hoje a mesma etiqueta de regime, o mesmo estado de cruzamento, a mesma cor no gráfico. Diferem em barras para as quais não está a olhar neste momento, e é exatamente aí que vive um backtest.
O que fazer em vez disso
Imprima todos os parâmetros derivados. Todos os comprimentos, todos os limiares, todos os multiplicadores. Compare-os com o código fonte linha a linha, antes de classificar o que quer que seja.
Mantenha a verificação da saída. Apanha outra classe de erros e é necessária. Apenas está muito longe de ser suficiente, e estes três passaram-lhe à frente sem serem incomodados.
O âmbito honesto
O código Pine estava correto nos três casos. O que estava errado era o aparelho construído para o testar, e essa é a versão mais incómoda do problema: o instrumento derivou, e a autoverificação do próprio instrumento dizia que não.
O número de 38 % é uma linha, uma varredura, um período, dentro da amostra, e está citado a partir do nosso próprio registo em vez de recalculado. O resultado do arredondamento é reproduzível com um único comando, e foi ao corrigi-lo que se descobriu que a nossa própria nota sobre o assunto estava errada havia dois meses.
Publicado como Ideia TradingView sobre ETHUSDT. Ver o gráfico no TradingView
Medição passada das nossas próprias ferramentas, descrita a posteriori. Nada aqui é uma recomendação nem uma indicação de resultados futuros.