mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
71 lines
2.4 KiB
JavaScript
71 lines
2.4 KiB
JavaScript
//#region src/network/ewma.ts
|
|
/**
|
|
* Exponentially Weighted Moving Average (EWMA)
|
|
*
|
|
* Pure functional implementation of EWMA calculations.
|
|
* Based on Shaka Player's EWMA algorithm.
|
|
*/
|
|
/**
|
|
* Calculate alpha (decay factor) from half-life.
|
|
*
|
|
* Alpha determines how quickly old data "expires":
|
|
* - alpha close to 1 = slow decay (long memory)
|
|
* - alpha close to 0 = fast decay (short memory)
|
|
*
|
|
* @param halfLife - The quantity of prior samples (by weight) that make up
|
|
* half of the new estimate. Must be positive.
|
|
* @returns Alpha value between 0 and 1
|
|
*
|
|
* @example
|
|
* const alpha = calculateAlpha(2); // ≈ 0.7071 for 2-second half-life
|
|
*/
|
|
function calculateAlpha(halfLife) {
|
|
return Math.exp(Math.log(.5) / halfLife);
|
|
}
|
|
/**
|
|
* Calculate exponentially weighted moving average.
|
|
*
|
|
* Updates an estimate by blending a new value with the previous estimate,
|
|
* weighted by the sample duration. Longer samples have more influence.
|
|
*
|
|
* @param prevEstimate - Previous EWMA estimate
|
|
* @param value - New sample value to incorporate
|
|
* @param weight - Sample weight (typically duration in seconds)
|
|
* @param halfLife - Half-life for decay (typically 2-5 seconds)
|
|
* @returns Updated EWMA estimate
|
|
*
|
|
* @example
|
|
* let estimate = 0;
|
|
* estimate = calculateEwma(estimate, 1_000_000, 1, 2); // First sample
|
|
* estimate = calculateEwma(estimate, 2_000_000, 1, 2); // Second sample
|
|
*/
|
|
function calculateEwma(prevEstimate, value, weight, halfLife) {
|
|
const adjAlpha = calculateAlpha(halfLife) ** weight;
|
|
return value * (1 - adjAlpha) + adjAlpha * prevEstimate;
|
|
}
|
|
/**
|
|
* Apply zero-factor correction to EWMA estimate.
|
|
*
|
|
* The zero-factor correction compensates for bias when starting from zero.
|
|
* Without this correction, early estimates would be artificially low.
|
|
*
|
|
* As totalWeight increases, the correction factor approaches 1, meaning
|
|
* the estimate becomes more reliable and needs less correction.
|
|
*
|
|
* @param estimate - Raw EWMA estimate (uncorrected)
|
|
* @param totalWeight - Accumulated weight from all samples
|
|
* @param halfLife - Half-life used in EWMA calculation
|
|
* @returns Corrected estimate, or 0 if totalWeight is 0
|
|
*
|
|
* @example
|
|
* const raw = calculateEwma(0, 1_000_000, 1, 2);
|
|
* const corrected = applyZeroFactor(raw, 1, 2); // ≈ 1_000_000
|
|
*/
|
|
function applyZeroFactor(estimate, totalWeight, halfLife) {
|
|
if (totalWeight === 0) return 0;
|
|
return estimate / (1 - calculateAlpha(halfLife) ** totalWeight);
|
|
}
|
|
//#endregion
|
|
export { applyZeroFactor, calculateAlpha, calculateEwma };
|
|
|
|
//# sourceMappingURL=ewma.js.map
|