Sunday 10 February 2019

Média móvel exponencial do código php


Eu quero calcular o valor EMA (Exponential Moving Average) em PHP. Eu tentei com o código seguinte, mas está me dando 500 erros. PHP: função de cálculo da EMA trader-ema Tentou com o google longo tempo, mas não obteve nenhuma ajuda sobre isso no PHP. Então, não tenho idéia do que precisa ser feito para calcular o valor EMA. Edit-1: Extensões instaladas Eu instalei todas as extensões necessárias, agora estou obtendo a saída. Mas isso não parece dar uma saída adequada. Eu acho que a função PHP para calcular EMA não está funcionando corretamente. Qualquer ajuda nessa seria muito apreciada. Estou tentando recuperar o último EMA de um grande conjunto de dados (15000 valores). É um algoritmo muito com recursos hambrientos, uma vez que cada valor depende do anterior. Aqui está o meu código: o que eu já fiz: isole k por isso não é calculado 10000 vezes. Mantenha apenas o EMA computado mais recente, e não mantenha todos eles em um uso de matriz para () em vez de foreach () a matriz de dados não possui chaves É uma matriz básica Isso me permitiu reduzir o tempo de execução de 2000ms para cerca de 500ms para 15000 valores O que não funcionou: Use SplFixedArray (), este raspou apenas 10ms executando 1.000.000 de valores Use a extensão PHPTrader. Isso retorna uma matriz contendo todos os EMAs em vez de apenas o mais recente, e é mais lento Escrevendo e executando o mesmo algoritmo em C e executando-o em mais de 2.000.000 de valores leva apenas 13ms Então, obviamente, usando uma linguagem de nível inferior compilada parece ajudar P Onde Devo ir daqui. O código será executado no Ubuntu, então qual idioma eu escolher? Será que o PHP poderá ligar e passar um argumento tão grande para o roteiro perguntado 11 de julho 14 às 19:21 Estabelecer uma implementação com uma extensão oferece uma Impulso significativo. Além disso, o cálculo pode ser melhorado em si mesmo e esse ganho você pode adicionar em qualquer idioma que você escolher. É fácil ver que lastEMA pode ser calculado da seguinte maneira: Isso pode ser reescrito da seguinte forma para tirar o loop o máximo possível: Para explicar a extração do k pense que na formulação anterior é como se todos os Os dados brutos originais são multiplicados por k, de modo que praticamente você pode, em vez disso, multiplicar o resultado final. Observe que, reescrito desta maneira, você tem 2 operações dentro do loop ao invés de 3 (para ser preciso dentro do loop, também estou incrementando, eu comparado com a atribuição de tamanho e atribuição de valores de lastema), de modo que você pode esperar obter um adicional Aceleração no intervalo entre 16 e 33. Além disso, existem outras melhorias que podem ser consideradas pelo menos em algumas circunstâncias: Considere somente os últimos valores. Os primeiros valores são multiplicados várias vezes por k1m 1 - k, portanto a contribuição deles pode ser pequena ou mesmo Sob a precisão de ponto flutuante (ou o erro aceitável). Esta ideia é particularmente útil se você pode assumir o pressuposto de que os dados mais antigos são da mesma ordem de grandeza que os mais novos porque, se você considerar apenas os últimos valores n, o erro que você faz é err EMAofdiscardeddata (1-k) n. Então, se a ordem de grandeza for amplamente igual, podemos dizer que o erro relativo feito é relerr err lastEMA EMAofdiscardeddata (1-k) n lastEMA que é quase igual a (1-k) n. Sob o pressuposto de que lastEMA é quase igual a EMAdddiscardeddata: Digamos que você pode aceitar um erro relativo de relerr, você pode considerar com segurança apenas os últimos n valores onde (1 - k) e lt relerr. Significa que você pode pré-calcular (antes do loop) n log (relerr) log (1-k) e calcular tudo apenas considerando os últimos n valores. Se o conjunto de dados for muito grande, isso pode dar uma velocidade sensível. Considere que para números de ponto flutuante de 64 bits você tem uma precisão relativa (relacionada à mantisa) que é 2-53 (cerca de 1.1e-16 e apenas 2-24 5.96e-8 para números de ponto flutuante de 32 bits) para que você não possa obter Melhor do que este erro relativo, então, basicamente, você nunca deve ter uma vantagem ao calcular mais que n log (1.1e-16) log (1-k) valores. Para dar um exemplo se range 2000 then n log (1.1e-16) log (1-22001) 36746. Eu acho que é interessante saber que os cálculos extras se perderiam dentro dos arredondamentos é inútil é melhor não fazer. Agora um exemplo para o caso em que você pode aceitar um erro relativo maior do que o ponto flutuante precisão relerr 1ppm 1e-6 0.00001 6 dígitos decimais significativos você tem registro n log (1.1e-16) (1-22001) 13815 Eu acho que é bastante Pequeno número em comparação com os seus últimos números de amostras, então, nesse caso, a aceleração pode ser evidente (Im assumindo que o alcance 2000 é significativo ou alto para a sua aplicação, mas que eu não posso saber). Apenas outros poucos números porque não sei quais são as suas figuras típicas: relerr 1e-3 range 2000 n 6907 relerr 1e-3 range 200 n 691 relerr 1e-3 range 20 n 69 relerr 1e-6 range 2000 n 13815 relerr 1e - 6 gama 200 n 1381 relerr 1e-6 range 20 n 138 Se o pressuposto lastEMA quase igual a EMA de dados perdidos não pode ser tomado, as coisas são menos fáceis, mas como a cam vantajosa é significativa, pode ser significativo continuar: precisamos repensar a Fórmula completa: relerr EMAofdiscardeddata (1-k) n lastEMA assim n log (relerr lastEMA EMAdediscardeddata) log (1-k) (registro log (relerr) (lastEMA EMAdediscardeddata)) log (1-k) o ponto central é calcular lastEMA EMAdediscardeddata (sem realmente calcular lastEMA nem EMAofdiscardeddata, é claro) um caso é quando sabemos a priori que, por exemplo, EMAdediscardeddata lastema lt M (por exemplo, M 1000 ou M 1e6) nesse caso n lt (log (relerrM)) log (1 - k) se você não pode dar qualquer número M você tem que encontrar uma boa ID E para estimar excessivamente EMAdediscardeddata lastEMA uma maneira rápida poderia ser tomar M max (dados) min (dados) Paralelização O cálculo pode ser reescrito de uma forma onde é uma simples adição de termos independentes: então, se o idioma de implementação suportar A paralelização do conjunto de dados pode ser dividida em 4 (ou 8 ou n. Basicamente o número de núcleos de CPU disponíveis), e pode-se calcular a soma de termos em cada pedaço em paralelo, resumindo os resultados individuais no final. Eu não vou em detalhes com isso, uma vez que esta resposta já é terrivelmente longa e acho que o conceito já está expresso. Obrigado por este I39m usando isso em dados do mercado de ações, então o fato de que os dados mais antigos estão na mesma ordem de grandeza que os dados mais recentes dependem do período de tempo utilizado. Suponhamos uma gama de 200, haverá uma variação muito maior nos preços em um período de tempo diário (200 dias) do que um período de tempo de 5 minutos (16 horas). Vou experimentar diferentes cenários em dados reais e simulados. Em novos dados, com um intervalo de 200, uso um conjunto de dados de 1000 elementos. Mas também faço alguns testes ao longo dos últimos anos, então eu ainda preciso carregar todo o conjunto de dados. Você ajudou para ambas as situações, obrigado ndash Lykegenes 16 de julho 14 às 15:11 Construir sua própria extensão definitivamente melhora o desempenho. Heres um bom tutorial do site Zend. Alguns números de desempenho: Hardware: Ubuntu 14.04, PHP 5.5.9, Intel Core3.3Ghz de 1 núcleo, 128 MB de RAM (é um VPS). Antes (somente PHP, 16.000 valores). Extensão de 500ms C, 16.000 valores. Extensão de 0,3 ms (100 000 valores). Extensão C de 3.7ms (500.000 valores). 28,0 ms Mas memória Im limitada neste momento, usando 70 MB. Vou consertar isso e atualizar os números de acordo. A média móvel exponencial é um tipo de filtro IIR que é fácil de implementar em C e usa recursos mínimos. Ao contrário de uma média móvel simples, não requer uma memória RAM para armazenar amostras anteriores. Apenas tem que armazenar um valor (a média anterior). Uma média móvel exponencial é expressa como a seguinte equação: avgn (em alfa) avgn-1 (1-alfa). Implementar esta equação usando matemática de ponto flutuante é direto, mas usar variáveis ​​de ponto fixo é um pouco complicado. O trecho de código aqui usa inteiros assinados de 32 bits para a média e os valores de entrada. Os valores intermediários precisam usar matemática de 64 bits para evitar erros de transbordamento. Os valores alfa próximos a zero representam uma média pesada, enquanto um valor alfa de um não possui uma média. Na linha em que o temp0 é calculado, acredito que o fim da linha deve ser lido (65535 - alfa) Caso contrário, um alfa de 1 incluiria incorretamente a média anterior e o novo valor.

No comments:

Post a Comment