Exponentially weighted moving average algorithm


Eu estou tentando calcular a média móvel de um sinal. O valor do sinal (um duplo) é atualizado em tempos aleatórios. Eu estou procurando uma maneira eficiente de calcular sua média ponderada de tempo ao longo de uma janela de tempo, em tempo real. Eu poderia fazer isso sozinho, mas é mais desafiador do que eu pensava. A maioria dos recursos que encontrei pela internet está calculando a média móvel do sinal periódico, mas atualizo as minhas em tempo aleatório. Alguém sabe bons recursos para isso O truque é o seguinte: Você recebe atualizações em horários aleatórios via void update (int time, float value). No entanto, você também precisa rastrear quando uma atualização cai da janela de tempo, para que você defina um alarme que é chamado na hora N, o que impede que a atualização anterior seja considerada novamente no cálculo. Se isso acontecer em tempo real, você pode solicitar que o sistema operacional faça uma chamada para um método void dropoffoldestupdate (int time) a ser chamado na hora N Se for uma simulação, você não poderá obter ajuda do sistema operacional e precisará faça isso manualmente. Em uma simulação, você chamaria métodos com o tempo fornecido como um argumento (que não se correlaciona com o tempo real). No entanto, uma suposição razoável é que as chamadas têm a garantia de que os argumentos de tempo estão aumentando. Nesse caso, você precisa manter uma lista ordenada de valores de hora do alarme e, para cada chamada de atualização e leitura, você verifica se o argumento de hora é maior que o da lista de alarmes. Embora seja maior o processamento relacionado ao alarme (desative a atualização mais antiga), remova a cabeça e verifique novamente até que todos os alarmes anteriores ao tempo determinado sejam processados. Então faça a chamada de atualização. Eu até agora assumi que é óbvio o que você faria para o cálculo real, mas vou elaborar apenas no caso. Eu suponho que você tenha um método float read (int time) que você usa para ler os valores. O objetivo é tornar essa chamada o mais eficiente possível. Portanto, você não calcula a média móvel toda vez que o método de leitura é chamado. Em vez disso, você pré-calcula o valor a partir da última atualização ou do último alarme e ajusta esse valor por algumas operações de ponto flutuante para considerar a passagem do tempo desde a última atualização. (isto é, um número constante de operações, exceto para talvez processar uma lista de alarmes empilhados). Espero que isso esteja claro - este deve ser um algoritmo bastante simples e bastante eficiente. Otimização adicional. Um dos problemas remanescentes é se um grande número de atualizações acontecer dentro da janela de tempo, então há um longo tempo para o qual não há leituras nem atualizações, e então uma leitura ou atualização aparece. Nesse caso, o algoritmo acima será ineficiente para atualizar incrementalmente o valor de cada uma das atualizações que está caindo. Isso não é necessário porque apenas nos preocupamos com a última atualização além da janela de tempo, portanto, se houver uma maneira de descartar todas as atualizações mais antigas, isso ajudará. Para fazer isso, podemos modificar o algoritmo para fazer uma pesquisa binária de atualizações para encontrar a atualização mais recente antes da janela de tempo. Se houver relativamente poucas atualizações que precisem ser descartadas, é possível atualizar incrementalmente o valor de cada atualização descartada. Mas, se houver muitas atualizações que precisem ser descartadas, será possível recomputar o valor desde o início, depois de deixar as atualizações antigas. Apêndice sobre Computação Incremental: Eu deveria esclarecer o que quero dizer com cálculo incremental acima na sentença ajustar este valor por um par de operações de ponto flutuante para explicar a passagem do tempo desde a última atualização. Cálculo inicial não-incremental: em seguida, iterar sobre as atualizações relevantes em ordem crescente de tempo: movingaverage (soma lastupdate timesincelastupdate) / windowlength. Agora, se exatamente uma atualização cair fora da janela, mas nenhuma nova atualização chegar, ajuste a soma como: (observe que é previousupdate que tem seu registro de data e hora modificado para iniciar o último início da janela). E se exatamente uma atualização entrar na janela, mas nenhuma nova atualização cair, ajuste a soma como: Como deve ser óbvio, este é um esboço, mas mostra como você pode manter a média de modo que seja O (1) operações por atualização em uma base amortizada. Mas observe a otimização adicional no parágrafo anterior. Observe também os problemas de estabilidade aludidos em uma resposta mais antiga, o que significa que os erros de ponto flutuante podem se acumular em um grande número dessas operações incrementais, de modo que haja uma divergência em relação ao resultado da computação completa que é significativa para o aplicativo. Se uma aproximação estiver correta e houver um tempo mínimo entre as amostras, você poderá tentar super-amostragem. Ter uma matriz que represente intervalos de tempo espaçados uniformemente menores que o mínimo e, a cada período de tempo, armazene a amostra mais recente que foi recebida. Quanto menor o intervalo, mais próxima a média será do valor real. O período não deve ser maior do que a metade do mínimo ou há uma chance de perder uma amostra. respondido Dez 15 11 at 18:12 respondido Dez 15 11 at 22:38 Obrigado pela resposta. Uma melhoria que seria necessária para realmente citar o valor da média total, de modo que não fiquemos em loop o tempo todo. Além disso, pode ser um ponto de menor importância, mas não seria mais eficiente usar um deque ou uma lista para armazenar o valor, uma vez que assumimos que a atualização virá na ordem correta. A inserção seria mais rápida do que no mapa. ndash Arthur Dec 16 11 at 8:55 Sim, você poderia armazenar em cache o valor da soma. Subtraia os valores das amostras que você apagar, adicione os valores das amostras inseridas. Além disso, sim, um dequeltpairltSample, Dategtgt pode ser mais eficiente. Eu escolhi o mapa para facilitar a leitura e a facilidade de invocar o map :: upperbound. Como sempre, escreva primeiro o código correto, depois faça o perfil e meça as alterações incrementais. ndash Rob Dez 16 11 às 15:00 Nota: Aparentemente, esta não é a maneira de abordar isso. Deixá-lo aqui para referência sobre o que está errado com essa abordagem. Confira os comentários. ATUALIZADO - baseado no comentário de Olis. Não tenho certeza sobre a instabilidade que ele está falando embora. Use um mapa ordenado dos tempos de chegada em relação aos valores. Após a chegada de um valor, adicione o horário de chegada ao mapa ordenado junto com seu valor e atualize a média móvel. aviso isso é pseudo-código: lá. Não totalmente elaborado, mas você entendeu. Coisas para notar. Como eu disse acima, é o pseudo código. Você precisará escolher um mapa apropriado. Não remova os pares enquanto faz a iteração, pois você invalidará o iterador e terá que começar novamente. Veja o comentário de Olis abaixo também. O que não funciona? Não leva em conta a proporção do tamanho da janela para a qual cada valor existe. Além disso, essa abordagem de adição e subtração é apenas estável para tipos inteiros, não flutuantes. Oliver Charlesworth Dez 15 11 at 12:29 OliCharlesworth - desculpe, eu perdi alguns pontos-chave na descrição (dupla e ponderada no tempo). Vou atualizar. Obrigado. ndash Dennis Dez 15 11 at 12:33 A ponderação de tempo é outro problema. Mas isso não é do que estou falando. Eu estava me referindo ao fato de que quando um novo valor entra pela primeira vez na janela de tempo, sua contribuição para a média é mínima. Sua contribuição continua aumentando até que um novo valor entre. Oliver Charlesworth Dec 15 11 at 12: 35Este repo fornece algoritmos da Média Móvel Ponderada Exponencialmente, ou EWMAs, com base na nossa palestra Quantifying Anormal Behavior. Média móvel ponderada exponencialmente Uma média móvel exponencialmente ponderada é uma maneira de calcular continuamente um tipo de média para uma série de números, à medida que os números chegam. Depois que um valor na série é adicionado à média, seu peso na média diminui exponencialmente ao longo do tempo. Isso distorce a média em relação aos dados mais recentes. Os EWMAs são úteis por várias razões, principalmente pelo seu baixo custo computacional e de memória, bem como pelo fato de representarem a recente tendência central da série de valores. O algoritmo EWMA requer um fator de decaimento alfa. Quanto maior o alfa, mais a média é tendenciosa em relação à história recente. O alfa deve estar entre 0 e 1 e normalmente é um número bastante pequeno, como 0,04. Vamos discutir a escolha do alfa depois. O algoritmo funciona assim, no pseudocódigo: Multiplique o próximo número da série por alfa. Multiplique o valor atual da média por 1 menos alfa. Adicione o resultado das etapas 1 e 2 e armazene-o como o novo valor atual da média. Repita para cada número da série. Existem comportamentos de casos especiais para como inicializar o valor atual, e estes variam entre as implementações. Uma abordagem é começar com o primeiro valor na série, outra é calcular a média dos primeiros 10 ou mais valores da série usando uma média aritmética e, em seguida, iniciar a atualização incremental da média. Cada método tem vantagens e desvantagens. Pode ajudar a olhar para ela pictoricamente. Suponha que a série tenha cinco números e escolhamos alfa como 0,50 para simplificar. Heres a série, com números na vizinhança de 300. Agora vamos pegar a média móvel desses números. Primeiro, definimos a média para o valor do primeiro número. Em seguida, multiplicamos o próximo número por alfa, multiplicamos o valor atual por 1-alfa e os adicionamos para gerar um novo valor. Isso continua até que tenhamos terminado. Observe como cada um dos valores da série decai pela metade toda vez que um novo valor é adicionado e a parte superior das barras na parte inferior da imagem representa o tamanho da média móvel. É uma média suavizada ou de baixa passagem da série original. Considere uma média móvel de janela deslizante de tamanho fixo (não uma média móvel exponencialmente ponderada) que tenha uma média sobre as N amostras anteriores. Qual é a idade média de cada amostra? É N / 2. Agora, suponha que você deseje construir um EWMA cujas amostras tenham a mesma idade média. A fórmula para calcular o alfa necessário para isso é: alpha 2 / (N1). A prova está no livro Production and Operations Analysis, de Steven Nahmias. Por exemplo, se você tiver uma série temporal com amostras uma vez por segundo e quiser obter a média móvel do minuto anterior, use um alfa de .032786885. Este, aliás, é o alfa constante usado para este repositório do SimpleEWMA. Este repositório contém duas implementações do algoritmo EWMA, com diferentes propriedades. Todas as implementações estão em conformidade com a interface MovingAverage e o construtor retorna esse tipo. Implementações atuais assumem um intervalo de tempo implícito de 1,0 entre cada amostra adicionada. Ou seja, a passagem do tempo é tratada como se fosse a mesma que a chegada das amostras. Se você precisar de decaimento com base no tempo quando as amostras não chegarem precisamente em intervalos definidos, este pacote não suportará suas necessidades no momento. Um SimpleEWMA é projetado para baixo consumo de CPU e memória. Ele terá um comportamento diferente do VariableEWMA por vários motivos. Não tem período de aquecimento e usa um decaimento constante. Essas propriedades permitem usar menos memória. Ele também se comportará de maneira diferente quando for igual a zero, o que é assumido como não inicializado, portanto, se um valor provavelmente se tornar zero ao longo do tempo, qualquer valor diferente de zero causará um salto acentuado em vez de uma pequena alteração. Ao contrário do SimpleEWMA, isso suporta uma idade personalizada que deve ser armazenada e, portanto, usa mais memória. Ele também tem um tempo de aquecimento quando você começa a adicionar valores a ele. Ele reportará um valor de 0.0 até você ter adicionado o número necessário de amostras a ele. Ele usa alguma memória para armazenar o número de amostras adicionadas a ele. Como resultado, usa um pouco mais de duas vezes a memória do SimpleEWMA. Veja a documentação gerada pelo GoDoc aqui. Aceitamos apenas solicitações de solicitação para pequenas correções ou melhorias. Isso inclui: Pequenas correções de bugs Typos Documentação ou comentários Por favor, abra questões para discutir novos recursos. Os pedidos de pull de novos recursos serão rejeitados, por isso recomendamos que você bifurque o repositório e faça alterações em seu fork para o seu caso de uso. Este repositório é Copyright (c) 2013 VividCortex, Inc. Todos os direitos reservados. Está licenciado sob a licença do MIT. Por favor, consulte o arquivo LICENSE para os termos de licença aplicáveis. A abordagem EWMA possui um recurso atrativo: requer relativamente poucos dados armazenados. Para atualizar nossa estimativa a qualquer momento, precisamos apenas de uma estimativa prévia da taxa de variação e do valor de observação mais recente. Um objetivo secundário da EWMA é rastrear mudanças na volatilidade. Para valores pequenos, observações recentes afetam a estimativa prontamente. Para valores mais próximos de um, a estimativa muda lentamente com base em mudanças recentes nos retornos da variável subjacente. O banco de dados RiskMetrics (produzido pelo JP Morgan e disponibilizado ao público) usa o EWMA para atualizar a volatilidade diária. IMPORTANTE: A fórmula do EWMA não pressupõe um nível de variação médio de longo prazo. Assim, o conceito de reversão à média da volatilidade não é capturado pelo EWMA. Os modelos ARCH / GARCH são mais adequados para esse propósito. Um objetivo secundário do EWMA é rastrear mudanças na volatilidade, portanto, para valores pequenos, a observação recente afeta a estimativa prontamente e, para valores mais próximos de um, a estimativa muda lentamente para mudanças recentes nos retornos da variável subjacente. O banco de dados RiskMetrics (produzido pelo JP Morgan) e disponibilizado ao público em 1994, usa o modelo EWMA para atualizar a estimativa de volatilidade diária. A empresa descobriu que, em uma série de variáveis ​​de mercado, esse valor fornece a previsão da variância que mais se aproxima da taxa de variação realizada. As taxas de variação realizadas em um determinado dia foram calculadas como uma média ponderada igualmente nos 25 dias subseqüentes. Da mesma forma, para calcular o valor ideal de lambda para nosso conjunto de dados, precisamos calcular a volatilidade realizada em cada ponto. Existem vários métodos, então escolha um. Em seguida, calcule a soma dos erros quadrados (SSE) entre a estimativa do EWMA e a volatilidade realizada. Finalmente, minimize o SSE variando o valor de lambda. Parece simples. O maior desafio é concordar com um algoritmo para calcular a volatilidade realizada. Por exemplo, o pessoal da RiskMetrics escolheu os 25 dias subsequentes para calcular a taxa de variação realizada. No seu caso, você pode escolher um algoritmo que utilize os preços Daily Volume, HI / LO e / ou OPEN-CLOSE. Q 1: Podemos usar o EWMA para estimar (ou prever) a volatilidade mais de um passo à frente A representação de volatilidade do EWMA não assume uma volatilidade média de longo prazo e, portanto, para qualquer horizonte de previsão além de um passo, o EWMA retorna uma constante valor:

Comments