Индикатор разворота
unknown
javascript
4 years ago
3.5 kB
13
Indexable
// Класс индикатора
class ReverseMeter {
constructor(period = 400, area = 0.01) {
this.period = period;
// погрешность для расчетов (если будем считать по коэфициентам линий K)
this.area = area;
this.dataset = new Extremums(Math.floor(period) / 4, 'max'); // Детектор экстремумов
this.hExtremums = new CircularBuffer(period); // Коллекция только экстремумов
}
nextValue(o, h, l, c) {
let result = null;
// Если экстремумы заполнены
if (this.hExtremums.filled()) {
result = this.calculate(o, h, l, c);
}
// Возвращает либо новый максимальный экстремум либо null
const extremum = this.dataset.push(h);
if (extremum) {
this.hExtremums.push(extremum);
}
return result;
}
calculate(o, h, l, c) {
let score = 0;
// Массив коэфициентов K всех линий между текущей точкой цены и всеми предыдущими экстремумами
const kList = [];
// Изза подобия треугольников подберем числа в координатах чтобы tan(Alpha) = K был примерно такой же
// как если бы мы считали x координаты почестному
const x1 = 0.01;
const y1 = h;
this.hExtremums.forEach((y0) => {
// x0 - всегда 0
const x0 = 0;
// Из уравнения канонической прямой, чтобы вычислить K - угловой коэфициент
// воспользуемся формулой (где 1 = x в формуле), если подставим вместо x = 1 то получим K
const k = ((1 - x0) * (y1 - y0)) / (x1 - x0);
kList.push(k);
});
// Карта кластирезаций
// Для расчета сколько примерно одинаковых угловых коэфициентов есть
const clustering = new Map();
let score = 0;
kList.forEach((k) => {
// Округляем все k до точности 0.01
const fixation = 10 ** 2;
k = Math.round((k + Number.EPSILON) * fixation) / fixation;
// Сохраняем k в Map, и првоеряем было ли такое же значение
// Если было увеличиваем счетчик в кол-ве прямых с таким коэффициентом
const next = (clustering.get(k) || 0) + 1;
// Если очков больше 1, запишем максимальное значение в очки
// Так получится на выходе самый большой кластер с одинаковыми коэфициантами k
if (next > 1 && next > score) {
score = next;
}
clustering.set(k, next);
});
// Нормализуем выходное значение
return 1 - 1 / (1 + score);
// return score;
}
}
Editor is loading...