Skip to content

Instantly share code, notes, and snippets.

@dkatz23238
Created January 13, 2022 21:20
Show Gist options
  • Save dkatz23238/7803f12d61e99bb988c1b3315b0dda13 to your computer and use it in GitHub Desktop.
Save dkatz23238/7803f12d61e99bb988c1b3315b0dda13 to your computer and use it in GitHub Desktop.
Timeseries.js
/*
* @param {DateRange} index
*/
let invertIndex = (index) => {
let invIndex = {};
for (let i = 0; i < index.values.length; i++) {
invIndex[index.values[i]] = i;
}
return invIndex;
};
// a and b must have a shape and get method
let sumVectors = (a, b) => {
if (a.shape != b.shape) {
throw `Can't sum vector ${a.shape} with vector ${b.shape}`;
}
let results = [];
for (let i = 0; i < a.shape; i++) {
results.push(a.get(i) + b.get(i));
}
return new Vector(results);
};
let vectorScalarProduct = (s, v) => {
return v.getValues().map((i) => s * i);
};
// v must hold an array with summable values
let averageVector = (v) => {
return v.values.reduce((i, j) => i + j, 0) / v.values.length;
};
// Mixins
let summableMixin = (Base) =>
class extends Base {
sum(vector) {
return sumVectors(this, vector);
}
};
let meanableMixin = (Base) =>
class extends Base {
mean() {
return averageVector(this);
}
};
let pushableMixin = (Base) =>
class extends Base {
push(v) {
this.values.push(v);
this.shape++;
}
};
let valueablesMixin = (Base) =>
class extends Base {
getValues() {
return this.values;
}
};
let scalarProductableMixin = (Base) =>
class extends Base {
prod(s) {
return new Vector(vectorScalarProduct(s, this));
}
};
let scalarSummableMixin = (Base) =>
class extends Base {
scalarSum(s) {
return new Vector(s.getValues().map((i) => i + s));
}
};
class VectorBase {
constructor(array) {
this.values = array;
this.shape = array.length;
}
set(pos, val) {
// Positional set
this.values[pos] = val;
}
get(pos) {
// Positional get
return this.values[pos];
}
}
//
//
class Vector extends scalarSummableMixin(
scalarProductableMixin(
//
valueablesMixin(
//
pushableMixin(
//
meanableMixin(
//
summableMixin(
//
VectorBase
)
)
)
)
)
) {}
class DateRange extends valueablesMixin(
//
pushableMixin(
//
VectorBase
)
) {}
class TimeSeries {
#index;
#vector;
#invIndex;
constructor(index, values) {
if (!(index instanceof DateRange) || !(values instanceof Vector)) {
throw "index must be DateRange and values must be Vector";
}
this.#index = new DateRange(index.getValues());
this.#vector = new Vector(values.getValues());
this.#invIndex = invertIndex(this.#index);
}
values() {
return new Vector(this.#vector.getValues());
}
index() {
return new DateRange(this.#index.getValues());
}
invIndex() {
return invertIndex(this.#index);
}
setValueByPos(pos, value) {
this.#vector.set(pos, value);
}
setValueByIndex(date, value) {
let pos = this.#invIndex[date];
if (pos === undefined) {
throw date + " Not in index";
}
this.#vector.set(pos, value);
}
setIndexByPos(index, position) {
if (position == null) {
throw "position can't be null";
}
this.#index.set(position, index);
this.#invIndex = invertIndex(this.#index);
}
push(date, value) {
this.#vector.push(value);
this.#index.push(date);
this.#invIndex = invertIndex(this.#index);
}
sum(ts) {
if (ts.index().getValues() !== this.#index.getValues()) {
throw "Indexes don't much";
}
return new TimeSeries(this.index(), this.values().sum(ts.values()));
}
prod(s) {
return new TimeSeries(this.index(), this.values().prod(s));
}
copy() {
return new TimeSeries(this.index(), this.values());
}
records() {
let records = [];
for (let i = 0; i < this.#vector.shape; i++) {
records.push({
date: this.#index.get(i),
value: this.#vector.get(i),
});
}
return records;
}
}
let d = new DateRange([
"2020-01-01T00:00:00",
"2020-02-01T00:00:00",
"2020-03-01T00:00:00",
]);
let v = new Vector([1, 2, 3]);
let t = new TimeSeries(d, v);
let t1 = new TimeSeries(d, v);
let t3 = t1.copy();
// Setting index by position
t.setIndexByPos("2020-01-02T00:00:00", 0);
// Setting value by
t.setValueByIndex("2020-01-02T00:00:00", 23);
// Throws error
// et series = t.sum(t1);
// Works because indices match
let series = t.sum(t);
let vector = series.values();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment