Refactor: Convert indicators to self-contained files

- Created moving_average.js consolidating ma.js, ma_indicator.js, sma.js, ema.js
- Made all indicators self-contained with embedded:
  * Math logic (no external dependencies)
  * Metadata (getMetadata())
  * Signal calculation (calculateXXXSignal)
  * Base class (inline BaseIndicator)
- Updated macd.js, hts.js to inline EMA/MA calculations
- Added signal functions to RSI, BB, Stochastic, ATR indicators
- Updated indicators/index.js to export both classes and signal functions
- Simplified signals-calculator.js to orchestrate using indicator signal functions
- Removed obsolete files: ma.js, base.js, ma_indicator.js, sma.js, ema.js

All indicators now fully self-contained with no external file dependencies
for math, signal calculation, or base class.
This commit is contained in:
DiTus
2026-03-01 19:39:28 +01:00
parent fdab0a3faa
commit a344a7f0da
14 changed files with 883 additions and 644 deletions

View File

@ -1,6 +1,70 @@
import { BaseIndicator } from './base.js';
// Self-contained ATR indicator
// Includes math, metadata, signal calculation, and base class
// Signal constants (defined in each indicator file)
const SIGNAL_TYPES = {
BUY: 'buy',
SELL: 'sell',
HOLD: 'hold'
};
const SIGNAL_COLORS = {
buy: '#26a69a',
hold: '#787b86',
sell: '#ef5350'
};
// Base class (inline replacement for BaseIndicator)
class BaseIndicator {
constructor(config) {
this.id = config.id;
this.type = config.type;
this.name = config.name;
this.params = config.params || {};
this.timeframe = config.timeframe || '1m';
this.series = [];
this.visible = config.visible !== false;
this.cachedResults = null;
this.cachedMeta = null;
this.lastSignalTimestamp = null;
this.lastSignalType = null;
}
}
// Signal calculation for ATR
function calculateATRSignal(indicator, lastCandle, prevCandle, values) {
const atr = values?.atr;
const close = lastCandle.close;
const prevClose = prevCandle?.close;
if (!atr || atr === null || !prevClose) {
return null;
}
const atrPercent = atr / close * 100;
const priceChange = Math.abs(close - prevClose);
const atrRatio = priceChange / atr;
if (atrRatio > 1.5) {
return {
type: SIGNAL_TYPES.HOLD,
strength: 70,
value: atr,
reasoning: `High volatility: ATR (${atr.toFixed(2)}, ${atrPercent.toFixed(2)}%)`
};
}
return null;
}
// ATR Indicator class
export class ATRIndicator extends BaseIndicator {
constructor(config) {
super(config);
this.lastSignalTimestamp = null;
this.lastSignalType = null;
}
calculate(candles) {
const period = this.params.period || 14;
const results = new Array(candles.length).fill(null);
@ -23,16 +87,32 @@ export class ATRIndicator extends BaseIndicator {
atr = (atr * (period - 1) + tr[i]) / period;
results[i] = atr;
}
return results;
return results.map(atr => ({ atr }));
}
getMetadata() {
return {
name: 'ATR',
description: 'Average True Range - measures market volatility',
inputs: [{ name: 'period', label: 'Period', type: 'number', default: 14, min: 1, max: 100 }],
plots: [{ id: 'value', color: '#795548', title: 'ATR' }],
inputs: [{
name: 'period',
label: 'Period',
type: 'number',
default: 14,
min: 1,
max: 100,
description: 'Period for ATR calculation'
}],
plots: [{
id: 'value',
color: '#795548',
title: 'ATR',
lineWidth: 1
}],
displayMode: 'pane'
};
}
}
export { calculateATRSignal };