Files
personal_TV/static/candle-aggregator.js
2025-07-17 00:12:33 +02:00

62 lines
2.7 KiB
JavaScript

/**
* Aggregates fine-grained candle data into a larger timeframe.
* For example, it can convert 1-minute candles into 5-minute candles.
*
* @param {Array<Object>} data - An array of candle objects, sorted by time.
* Each object must have { time, open, high, low, close }.
* @param {number} intervalMinutes - The desired new candle interval in minutes (e.g., 5 for 5m).
* @returns {Array<Object>} A new array of aggregated candle objects.
*/
function aggregateCandles(data, intervalMinutes) {
if (!data || data.length === 0 || !intervalMinutes || intervalMinutes < 1) {
return [];
}
const intervalSeconds = intervalMinutes * 60;
const aggregated = [];
let currentAggCandle = null;
data.forEach(candle => {
// Validate candle data
if (!candle || !candle.time ||
isNaN(candle.open) || isNaN(candle.high) ||
isNaN(candle.low) || isNaN(candle.close) ||
candle.open <= 0 || candle.high <= 0 ||
candle.low <= 0 || candle.close <= 0) {
console.warn('Skipping invalid candle during aggregation:', candle);
return; // Skip this candle
}
// Calculate the timestamp for the start of the interval bucket
// Properly align to interval boundaries (e.g., 5-min intervals start at :00, :05, :10, etc.)
const bucketTimestamp = Math.floor(candle.time / intervalSeconds) * intervalSeconds;
if (!currentAggCandle || bucketTimestamp !== currentAggCandle.time) {
// If a previous aggregated candle exists, push it to the results
if (currentAggCandle) {
aggregated.push(currentAggCandle);
}
// Start a new aggregated candle
currentAggCandle = {
time: bucketTimestamp,
open: candle.open,
high: candle.high,
low: candle.low,
close: candle.close,
};
} else {
// This candle belongs to the current aggregated candle, so update it
currentAggCandle.high = Math.max(currentAggCandle.high, candle.high);
currentAggCandle.low = Math.min(currentAggCandle.low, candle.low);
currentAggCandle.close = candle.close; // The close is always the latest one
}
});
// Add the last aggregated candle if it exists
if (currentAggCandle) {
aggregated.push(currentAggCandle);
}
return aggregated;
}