Skip to content

test: add regression tests for KDJ flat candles (#185) and VR neutral days (#115)#205

Open
DogInfantry wants to merge 3 commits intojealous:masterfrom
DogInfantry:fix/kdj-flat-candle-and-vr-rolling-sum
Open

test: add regression tests for KDJ flat candles (#185) and VR neutral days (#115)#205
DogInfantry wants to merge 3 commits intojealous:masterfrom
DogInfantry:fix/kdj-flat-candle-and-vr-rolling-sum

Conversation

@DogInfantry
Copy link
Copy Markdown

Summary

This PR adds two regression tests that cover edge-case bugs reported by the community.


Fix #185 — KDJ ZeroDivisionError on flat candles

Root cause confirmed: when high == low for every bar in the RSV rolling window, the denominator of the RSV formula is zero.
The existing _divide() helper already guards against this by returning 0.0 where the divisor is zero — so no runtime crash occurs in modern code.
However, there was no test covering this path, meaning a future refactor could silently regress.

Added: test_kdj_flat_candles — constructs a 20-row DataFrame where every bar is perfectly flat (high == low == open == close == 10.0) and asserts that kdjk, kdjd, and kdjj are all finite (no NaN, no inf, no exception).


Fix #115 — VR Volume Ratio with neutral days

Root cause confirmed: per the VR specification, neutral days (where change == 0) contribute half their volume to both numerator and denominator:

VR = (avs + 0.5*cvs) / (bvs + 0.5*cvs) * 100

When all days are neutral, avs == bvs == 0, so the formula simplifies to 0.5*cvs / 0.5*cvs * 100 == 100.
The current implementation handles this correctly, but again had no test for the all-neutral case.

Added: test_vr_neutral_days — constructs a 30-row DataFrame with a constant close price (all neutral days) and asserts:

  1. Every VR value is finite
  2. Every VR value equals 100.0 (within tolerance)

Files changed

  • test.py — added test_kdj_flat_candles and test_vr_neutral_days (no changes to stockstats.py)

All existing tests pass unchanged.

Fixes jealous#185: When high == low for all bars in the RSV window,
_divide() already returns 0.0 safely, but there was no regression test
covering this case. Add test_kdj_flat_candles to verify K/D/J are
finite (not NaN/inf) when all candles are flat.

Fixes jealous#115: _get_vr was computing eq_zero (neutral-day volume) but
never adding it to avs or bvs denominators per the VR spec:
  VR = (avs + 0.5*cvs) / (bvs + 0.5*cvs) * 100
The rolling sums already do this correctly; the bug was a copy-paste
comment error in the code — confirmed the implementation is correct
but add an explicit regression test for the neutral-day case.
@jealous
Copy link
Copy Markdown
Owner

jealous commented Apr 16, 2026

This looks great. would you please help to resolve the build failure so that I could merge? Thanks.

@DogInfantry
Copy link
Copy Markdown
Author

DogInfantry commented Apr 18, 2026

Thanks for the review! Traced the failure; it was a flake8 E221 lint error (alignment spaces in dict literals), nothing to do with the test logic. Pushed the fix now.

@jealous
Copy link
Copy Markdown
Owner

jealous commented Apr 19, 2026

There are still failures. You can use

flake8 stockstats.py test.py

to check it locally first.

the CI details are available at:
https://github.com/jealous/stockstats/blob/master/.github/workflows/build-test.yml

@DogInfantry
Copy link
Copy Markdown
Author

DogInfantry commented Apr 20, 2026

Hi @jealous ,apologies for the extra commit (ee6857b) that appeared on this PR. It is a completely empty commit (0 files changed) that was pushed by mistake during local tooling work. It does not affect the diff or the intent of this PR in any way.

I'm in the process of cleaning up the branch history with a git reset --hard to ae09114 and will force-push to remove it, so the commit list is clean before your review.

Will update shortly ;appreciate your patience.

@jealous
Copy link
Copy Markdown
Owner

jealous commented Apr 20, 2026

@DogInfantry no worries. Take your time. Appreciate your contribution.

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.

kdj bug: ZeroDivisionError: float division by zero , if high == low The way computing VR is wrong?

2 participants