Report where the snap indicator is drawn, not just what it computed

Diagnostic mode proved the arithmetic: on a 30m chart every sample snapped to
the correct bar and to exactly that bar's low, while the user still saw the
indicator sitting off the bars. That leaves the half never measured in their
browser — whether the dot is drawn where the price says it should be.

The report now carries the cursor's y, the dot's rendered y, the y the snapped
price maps to, and the y coordinates of the snapped bar's high and low. A
correctly computed answer drawn in the wrong place and a wrong answer drawn
faithfully look identical on a screenshot; these four numbers separate them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Chris Amow 2026-08-10 23:32:39 -05:00
parent fa577bacb7
commit 3f677a333c
2 changed files with 26 additions and 0 deletions

View file

@ -213,6 +213,15 @@ class SnapReport(BaseModel):
last_bar_t: int | None = None
tf: str | None = None
chart_w: float | None = None
chart_h: float | None = None
cursor_y: float | None = None
# Where the indicator actually landed versus where the price says it should
# — the only way to tell a wrong answer from a correctly-computed one drawn
# in the wrong place.
dot_y: float | None = None
expected_y: float | None = None
bar_low_y: float | None = None
bar_high_y: float | None = None
note: str | None = None

View file

@ -642,6 +642,23 @@ class ConfluenceChart {
bars_held: this.bars.length,
first_bar_t: this.bars[0].t, last_bar_t: this.bars[this.bars.length - 1].t,
chart_w: this.chartEl.clientWidth,
chart_h: this.chartEl.clientHeight,
cursor_y: Math.round(point.y),
dot_y: this.snapDot && !this.snapDot.hidden
? Math.round(this.snapDot.getBoundingClientRect().top
- this.chartEl.getBoundingClientRect().top) + 5
: null,
expected_y: Math.round(y),
bar_low_y: (() => {
const bar = this.bars.find(candle => candle.t === snapped.t);
const at = bar && this.candles.priceToCoordinate(bar.l);
return at == null ? null : Math.round(at);
})(),
bar_high_y: (() => {
const bar = this.bars.find(candle => candle.t === snapped.t);
const at = bar && this.candles.priceToCoordinate(bar.h);
return at == null ? null : Math.round(at);
})(),
note: point.t == null
? 'coordinateToTime returned null'
: `drift ${drift}s (${Math.round(drift / step)} bars), step ${step}s`,