@lodestar/beacon-node
Version:
A Typescript implementation of the beacon chain
96 lines • 3.44 kB
JavaScript
export class TimeSeries {
constructor(opts) {
this.points = [];
this.maxPoints = opts?.maxPoints ?? 1000;
this.startTimeSec = Date.now() / 1000;
}
/** Add TimeSeries entry for value at current time */
addPoint(value, timeSec = Math.floor(Date.now() / 1000)) {
// Substract initial time so x values are not big and cause rounding errors
const time = timeSec - this.startTimeSec;
this.points.push([time, value]);
// Limit length by removing old entries
while (this.points.length > this.maxPoints) {
this.points.shift();
}
}
/** Compute the slope of all registered points assuming linear regression */
computeLinearSpeed() {
return linearRegression(this.points).m;
}
/**
* Compute x point at which y = 0.
* From eq `y = b + m*x` then solve for `0 = b + m*x`
*/
computeY0Point() {
const { m, b } = linearRegression(this.points);
// The X cordinate system has been shifted left by startTimeSec, so return the
// projection in original coordinated system
return -b / m + this.startTimeSec;
}
/** Remove all entries */
clear() {
this.points = [];
}
numPoints() {
return this.points.length;
}
}
/**
* From https://github.com/simple-statistics/simple-statistics/blob/d0d177baf74976a2421638bce98ab028c5afb537/src/linear_regression.js
*
* [Simple linear regression](http://en.wikipedia.org/wiki/Simple_linear_regression)
* is a simple way to find a fitted line between a set of coordinates.
* This algorithm finds the slope and y-intercept of a regression line
* using the least sum of squares.
*
* @param data an array of two-element of arrays,
* like `[[0, 1], [2, 3]]`
* @returns object containing slope and intersect of regression line
* @example
* linearRegression([[0, 0], [1, 1]]); // => { m: 1, b: 0 }
*/
function linearRegression(data) {
let m, b;
// Store data length in a local variable to reduce
// repeated object property lookups
const dataLength = data.length;
//if there's only one point, arbitrarily choose a slope of 0
//and a y-intercept of whatever the y of the initial point is
if (dataLength === 1) {
m = 0;
b = data[0][1];
}
else {
// Initialize our sums and scope the `m` and `b`
// variables that define the line.
let sumX = 0, sumY = 0, sumXX = 0, sumXY = 0;
// Use local variables to grab point values
// with minimal object property lookups
let point, x, y;
// Gather the sum of all x values, the sum of all
// y values, and the sum of x^2 and (x*y) for each
// value.
//
// In math notation, these would be SS_x, SS_y, SS_xx, and SS_xy
for (let i = 0; i < dataLength; i++) {
point = data[i];
x = point[0];
y = point[1];
sumX += x;
sumY += y;
sumXX += x * x;
sumXY += x * y;
}
// `m` is the slope of the regression line
m = (dataLength * sumXY - sumX * sumY) / (dataLength * sumXX - sumX * sumX);
// `b` is the y-intercept of the line.
b = sumY / dataLength - (m * sumX) / dataLength;
}
// Return both values as an object.
return {
m: m,
b: b,
};
}
//# sourceMappingURL=timeSeries.js.map