refactor: Review-Fixes Strategie (unbenutzter Param, Range-Guard, Ratchet-Test)

This commit is contained in:
2026-06-09 20:28:43 +00:00
parent b4388c959c
commit d54b11293d
3 changed files with 13 additions and 5 deletions

View File

@@ -20,3 +20,10 @@ test('NaN-ATR lässt Stop unverändert', () => {
expect(r.highestHigh).toBe(120);
expect(r.stop).toBe(104);
});
test('Stop ratchtet hoch wenn ATR schrumpft, auch ohne neues Hoch', () => {
// hh bleibt 110, ATR schrumpft von 3 auf 1 → Stop 1103 = 107 > vorher 104
const r = updateChandelier({ highestHigh: 110, stop: 104 }, 105, 1, 3);
expect(r.highestHigh).toBe(110);
expect(r.stop).toBe(107);
});

View File

@@ -19,7 +19,7 @@ function breakoutSeries(): Candle[] {
test('Long-Signal bei Donchian-Breakout über Trend-EMA', () => {
const c4h = breakoutSeries();
const ev = evaluateAt(c4h, computeIndicators(c4h, P), c4h.length - 1, P);
const ev = evaluateAt(c4h, computeIndicators(c4h, P), c4h.length - 1);
expect(ev.signal).toBe('long');
expect(ev.blockedBy).toBeNull();
expect(ev.donchianHigh).toBe(17);
@@ -29,7 +29,7 @@ test('Long-Signal bei Donchian-Breakout über Trend-EMA', () => {
test('blockiert unter Donchian-High', () => {
const c4h = breakoutSeries();
c4h[c4h.length - 1].close = 16.9; // unter 17
const ev = evaluateAt(c4h, computeIndicators(c4h, P), c4h.length - 1, P);
const ev = evaluateAt(c4h, computeIndicators(c4h, P), c4h.length - 1);
expect(ev.signal).toBeNull();
expect(ev.blockedBy).toBe('below_donchian');
});
@@ -46,14 +46,14 @@ test('blockiert unter Trend-EMA (Bärenmarkt-Filter)', () => {
s.push(c(75, 76, 74, 75, 6));
// Index 7: Donchian[7] = max(76,76,76) = 76, EMA5 ≈ 80, Close 77 > Donchian aber < EMA
s.push(c(77, 80, 76, 77, 7));
const ev = evaluateAt(s, computeIndicators(s, P), s.length - 1, P);
const ev = evaluateAt(s, computeIndicators(s, P), s.length - 1);
expect(ev.signal).toBeNull();
expect(ev.blockedBy).toBe('below_trend_ema');
});
test('blockiert bei zu wenig Daten', () => {
const c4h = breakoutSeries().slice(0, 4);
const ev = evaluateAt(c4h, computeIndicators(c4h, P), c4h.length - 1, P);
const ev = evaluateAt(c4h, computeIndicators(c4h, P), c4h.length - 1);
expect(ev.blockedBy).toBe('insufficient_data');
});

View File

@@ -42,11 +42,12 @@ export function computeIndicators(c4h: Candle[], p: StrategyParams): IndicatorSe
}
/** Bewertet die (abgeschlossene) 4h-Candle an Index i. */
export function evaluateAt(c4h: Candle[], ind: IndicatorSet, i: number, p: StrategyParams): Evaluation {
export function evaluateAt(c4h: Candle[], ind: IndicatorSet, i: number): Evaluation {
const close = c4h[i]?.close ?? NaN;
const base = { close, atr: ind.atr[i], donchianHigh: ind.donchianHigh[i], trendEma: ind.trendEma[i] };
if (
i < 0 ||
i >= c4h.length ||
Number.isNaN(ind.trendEma[i]) ||
Number.isNaN(ind.donchianHigh[i]) ||
Number.isNaN(ind.atr[i])