* new akka module split from akka-cluster * provide sigar provisioning * fix ewma usage * resolve #16121 * see #16354
68 lines
2.5 KiB
Scala
68 lines
2.5 KiB
Scala
/**
|
||
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
|
||
*/
|
||
package akka.cluster.metrics
|
||
|
||
import scala.concurrent.duration.FiniteDuration
|
||
|
||
/**
|
||
* The exponentially weighted moving average (EWMA) approach captures short-term
|
||
* movements in volatility for a conditional volatility forecasting model. By virtue
|
||
* of its alpha, or decay factor, this provides a statistical streaming data model
|
||
* that is exponentially biased towards newer entries.
|
||
*
|
||
* http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
|
||
*
|
||
* An EWMA only needs the most recent forecast value to be kept, as opposed to a standard
|
||
* moving average model.
|
||
*
|
||
* @param alpha decay factor, sets how quickly the exponential weighting decays for past data compared to new data,
|
||
* see http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
|
||
*
|
||
* @param value the current exponentially weighted moving average, e.g. Y(n - 1), or,
|
||
* the sampled value resulting from the previous smoothing iteration.
|
||
* This value is always used as the previous EWMA to calculate the new EWMA.
|
||
*
|
||
*/
|
||
@SerialVersionUID(1L)
|
||
final case class EWMA(value: Double, alpha: Double) {
|
||
|
||
require(0.0 <= alpha && alpha <= 1.0, "alpha must be between 0.0 and 1.0")
|
||
|
||
/**
|
||
* Calculates the exponentially weighted moving average for a given monitored data set.
|
||
*
|
||
* @param xn the new data point
|
||
* @return a new [[akka.cluster.EWMA]] with the updated value
|
||
*/
|
||
def :+(xn: Double): EWMA = {
|
||
val newValue = (alpha * xn) + (1 - alpha) * value
|
||
if (newValue == value) this // no change
|
||
else copy(value = newValue)
|
||
}
|
||
|
||
}
|
||
|
||
object EWMA {
|
||
|
||
/**
|
||
* math.log(2)
|
||
*/
|
||
private val LogOf2 = 0.69315
|
||
|
||
/**
|
||
* Calculate the alpha (decay factor) used in [[akka.cluster.EWMA]]
|
||
* from specified half-life and interval between observations.
|
||
* Half-life is the interval over which the weights decrease by a factor of two.
|
||
* The relevance of each data sample is halved for every passing half-life duration,
|
||
* i.e. after 4 times the half-life, a data sample’s relevance is reduced to 6% of
|
||
* its original relevance. The initial relevance of a data sample is given by
|
||
* 1 – 0.5 ^ (collect-interval / half-life).
|
||
*/
|
||
def alpha(halfLife: FiniteDuration, collectInterval: FiniteDuration): Double = {
|
||
val halfLifeMillis = halfLife.toMillis
|
||
require(halfLife.toMillis > 0, "halfLife must be > 0 s")
|
||
val decayRate = LogOf2 / halfLifeMillis
|
||
1 - math.exp(-decayRate * collectInterval.toMillis)
|
||
}
|
||
}
|