Implement Strategy tab with Ping-Pong backtesting and crossover-based signal logic

- Add 'Strategy' tab to sidebar for backtesting simulations
- Create strategy-panel.js for Ping-Pong and Accumulation mode simulations
- Refactor all indicators (MA, HTS, RSI, MACD, BB, STOCH, Hurst) to use strict crossover-based signal calculation
- Update chart.js with setSimulationMarkers and clearSimulationMarkers support
- Implement single-entry rule in Ping-Pong simulation mode
This commit is contained in:
DiTus
2026-03-03 13:15:29 +01:00
parent 73f325ce19
commit d92af6903d
13 changed files with 626 additions and 104 deletions

View File

@ -50,32 +50,37 @@ function calculateEMAInline(data, period) {
}
// Signal calculation for MACD
function calculateMACDSignal(indicator, lastCandle, prevCandle, values) {
function calculateMACDSignal(indicator, lastCandle, prevCandle, values, prevValues) {
const macd = values?.macd;
const signal = values?.signal;
const histogram = values?.histogram;
const prevMacd = prevValues?.macd;
const prevSignal = prevValues?.signal;
if (!macd || macd === null || !signal || signal === null) {
if (macd === undefined || macd === null || signal === undefined || signal === null ||
prevMacd === undefined || prevMacd === null || prevSignal === undefined || prevSignal === null) {
return null;
}
let signalType, strength, reasoning;
const prevCandleHistogram = prevCandle ? values?.histogram : null;
if (macd > signal) {
signalType = SIGNAL_TYPES.BUY;
strength = Math.min(50 + histogram * 500, 100);
reasoning = `MACD (${macd.toFixed(2)}) is above Signal (${signal.toFixed(2)})`;
} else if (macd < signal) {
signalType = SIGNAL_TYPES.SELL;
strength = Math.min(50 + Math.abs(histogram) * 500, 100);
reasoning = `MACD (${macd.toFixed(2)}) is below Signal (${signal.toFixed(2)})`;
} else {
return null;
// BUY: MACD crosses UP through Signal line
if (prevMacd <= prevSignal && macd > signal) {
return {
type: SIGNAL_TYPES.BUY,
strength: 80,
value: macd,
reasoning: `MACD crossed UP through Signal line`
};
}
// SELL: MACD crosses DOWN through Signal line
else if (prevMacd >= prevSignal && macd < signal) {
return {
type: SIGNAL_TYPES.SELL,
strength: 80,
value: macd,
reasoning: `MACD crossed DOWN through Signal line`
};
}
return { type: signalType, strength, value: macd, reasoning };
return null;
}
// MACD Indicator class