simplified crossover detection: find first candle where price crosses MA

This commit is contained in:
DiTus
2026-03-01 22:16:12 +01:00
parent 12689ad8f3
commit af79268621

View File

@ -94,9 +94,6 @@ export function calculateSummarySignal(signals) {
function calculateHistoricalCrossovers(activeIndicators, candles) {
activeIndicators.forEach(indicator => {
const indicatorType = indicator.type || indicator.indicatorType;
const SignalFunction = getSignalFunction(indicatorType);
if (!SignalFunction) return;
// Recalculate indicator values for all candles
const IndicatorClass = IndicatorRegistry[indicatorType];
@ -107,46 +104,43 @@ function calculateHistoricalCrossovers(activeIndicators, candles) {
if (!results || results.length === 0) return;
// Track the last crossover timestamp
let lastCrossoverTimestamp = indicator.lastSignalTimestamp || null;
let crossoverCount = 0;
// Find the most recent crossover by going backwards from the newest candle
// candles are sorted oldest first, newest last
let lastCrossoverTimestamp = null;
// Iterate through candles to find crossovers (from newest to oldest)
// We start from the end and go backwards to find the most recent crossover
for (let i = candles.length - 2; i >= 0; i--) {
// Skip if we don't have data for these candles
if (!results[i] || !results[i + 1]) continue;
for (let i = candles.length - 1; i > 0; i--) {
const candle = candles[i]; // newer candle
const prevCandle = candles[i-1]; // older candle
const candle = candles[i];
const prevCandle = candles[i + 1];
const result = results[i];
const prevResult = results[i-1];
const valuesThis = typeof results[i] === 'object' ? results[i] : { ma: results[i] };
const valuesPrev = typeof results[i + 1] === 'object' ? results[i + 1] : { ma: results[i + 1] };
if (!result || !prevResult) continue;
const closeThis = candles[i].close;
const closePrev = candles[i + 1].close;
const maThis = valuesThis.ma;
const maPrev = valuesPrev.ma;
// Get MA value (handle both object and number formats)
const ma = result.ma !== undefined ? result.ma : result;
const prevMa = prevResult.ma !== undefined ? prevResult.ma : prevResult;
// Check for BUY→SELL crossover (was above, now below)
if (closePrev > maPrev && closeThis < maThis) {
console.log(`[HistoricalCross] ${indicatorType} BUY→SELL crossover at candle ${i}, time: ${prevCandle.time}`);
lastCrossoverTimestamp = prevCandle.time;
crossoverCount++;
break; // Found most recent crossover
if (ma === undefined || prevMa === undefined) continue;
// Check crossover: price was on one side of MA, now on the other side
const priceAbovePrev = prevCandle.close > prevMa;
const priceAboveNow = candle.close > ma;
// SELL signal: price crossed from above to below MA
if (priceAbovePrev && !priceAboveNow) {
lastCrossoverTimestamp = candle.time;
break;
}
// Check for SELL→BUY crossover (was below, now above)
else if (closePrev < maPrev && closeThis > maThis) {
console.log(`[HistoricalCross] ${indicatorType} SELL→BUY crossover at candle ${i}, time: ${prevCandle.time}`);
lastCrossoverTimestamp = prevCandle.time;
crossoverCount++;
break; // Found most recent crossover
// BUY signal: price crossed from below to above MA
if (!priceAbovePrev && priceAboveNow) {
lastCrossoverTimestamp = candle.time;
break;
}
}
if (crossoverCount > 0) {
if (lastCrossoverTimestamp) {
console.log(`[HistoricalCross] ${indicatorType}: Found crossover at ${new Date(lastCrossoverTimestamp * 1000).toLocaleString()}`);
// Update the indicator's lastSignalTimestamp
indicator.lastSignalTimestamp = lastCrossoverTimestamp;
}
});