Skip to content

fix: remove sign-guarded symlog from logarithm axis to fix negative labels for sub-1 prices - #837

Open
NemeZZiZZ wants to merge 1 commit into
klinecharts:mainfrom
NemeZZiZZ:fix/log-axis-sub-1-prices
Open

fix: remove sign-guarded symlog from logarithm axis to fix negative labels for sub-1 prices#837
NemeZZiZZ wants to merge 1 commit into
klinecharts:mainfrom
NemeZZiZZ:fix/log-axis-sub-1-prices

Conversation

@NemeZZiZZ

Copy link
Copy Markdown
Contributor

Problem

The built-in logarithm y-axis template maps values through a sign-guarded symlog:

valueToRealValue: (value) => (value < 0 ? -log10(Math.abs(value)) : log10(value))
realValueToDisplayValue: (value) => (value < 0 ? -index10(Math.abs(value)) : index10(value))

For any price in (0, 1) — e.g. an altcoin trading at 0.0000123 — log10(value) is negative, so the real-space coordinate is negative while the price is positive. The inverse functions then take that negative real value to mean "negative price" and return -index10(|real|), a huge negative number.

Verified against current main (replicating YAxis.createRangeImp + createTicksImp with the template installed), visible range [0.000008, 0.000023]:

Path Result
displayFrom / displayTo after range gap -138922.89 / -35200.16
Rendered axis tick labels -130000, -120000, …, -80000
Crosshair label (CrosshairHorizontalLabelView.getTextconvertFromPixel) -69929.30 (should be ≈ 0.0000143)
Overlay point value stored on draw (OverlayViewconvertFromPixel) -64399.94 (should be 0.0000155)
Public chart.convertFromPixel() API same garbage

Any instrument priced below 1 is affected (a [0.081, 0.119] range renders ticks -12.6 … -9.6). Prices above 1 work because log10(v) > 0 keeps the sign guard on the consistent branch.

The symlog is also not injective: valueToRealValue(10) === valueToRealValue(-0.1) === 1, so no sign-guard variant can be made invertible — the guards cannot be repaired, only removed.

Fix

Make the template a pure logarithmic axis: real = log10(value), value = index10(real), unconditionally. 4 functions + createRange, one file.

After the fix, same scenarios: tick labels 0.000009, 0.000012, …, crosshair 0.0000143, overlay round-trip exact (0.0000155 → 0.0000155). Prices above 1 are bit-for-bit unaffected (the sign guards were already taking the positive branch there).

Behavior note

Ranges containing values ≤ 0 previously rendered through the quasi-symlog (approximately correct only for purely negative ranges, wrong for mixed ones: a [-5, 100] range produced tick labels 0, 40, 80…). After the fix such ranges produce NaN coordinates — the axis renders no ticks instead of wrong ones, matching the mathematical domain of a log scale (same behavior as other charting libraries, e.g. TradingView treats non-positive values as invalid on log scale).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant